mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Code reformat.
This commit is contained in:
3290
ATA/Identify.cs
3290
ATA/Identify.cs
File diff suppressed because it is too large
Load Diff
@@ -66,8 +66,8 @@ namespace DiscImageChef.Decoders.ATA
|
||||
public ushort LbaLow;
|
||||
public ushort LbaMid;
|
||||
public ushort LbaHigh;
|
||||
public byte DeviceHead;
|
||||
public byte Command;
|
||||
public byte DeviceHead;
|
||||
public byte Command;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||
@@ -97,12 +97,12 @@ namespace DiscImageChef.Decoders.ATA
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
|
||||
public struct AtaErrorRegistersLba48
|
||||
{
|
||||
public byte Status;
|
||||
public byte Error;
|
||||
public byte Status;
|
||||
public byte Error;
|
||||
public ushort SectorCount;
|
||||
public ushort LbaLow;
|
||||
public ushort LbaMid;
|
||||
public ushort LbaHigh;
|
||||
public byte DeviceHead;
|
||||
public byte DeviceHead;
|
||||
}
|
||||
}
|
||||
@@ -38,44 +38,45 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class BCA
|
||||
{
|
||||
#region Public structures
|
||||
public struct BurstCuttingArea
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Always 66</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4 to 67 BCA data</summary>
|
||||
public byte[] BCA;
|
||||
}
|
||||
#endregion Public structures
|
||||
#region Public methods
|
||||
public static BurstCuttingArea? Decode(byte[] BCAResponse)
|
||||
{
|
||||
if(BCAResponse == null) return null;
|
||||
if(BCAResponse == null)
|
||||
return null;
|
||||
|
||||
if(BCAResponse.Length != 68)
|
||||
{
|
||||
DicConsole.DebugWriteLine("BD BCA decoder", "Found incorrect Blu-ray BCA size ({0} bytes)",
|
||||
BCAResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
BurstCuttingArea decoded = new BurstCuttingArea
|
||||
var decoded = new BurstCuttingArea
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0),
|
||||
Reserved1 = BCAResponse[2],
|
||||
Reserved2 = BCAResponse[3],
|
||||
BCA = new byte[64]
|
||||
DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0), Reserved1 = BCAResponse[2],
|
||||
Reserved2 = BCAResponse[3], BCA = new byte[64]
|
||||
};
|
||||
|
||||
Array.Copy(BCAResponse, 4, decoded.BCA, 0, 64);
|
||||
@@ -85,16 +86,20 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(BurstCuttingArea? BCAResponse)
|
||||
{
|
||||
if(BCAResponse == null) return null;
|
||||
if(BCAResponse == null)
|
||||
return null;
|
||||
|
||||
BurstCuttingArea response = BCAResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
|
||||
sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.BCA, 80));
|
||||
@@ -104,31 +109,5 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(byte[] BCAResponse) => Prettify(Decode(BCAResponse));
|
||||
#endregion Public methods
|
||||
|
||||
#region Public structures
|
||||
public struct BurstCuttingArea
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Always 66
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4 to 67
|
||||
/// BCA data
|
||||
/// </summary>
|
||||
public byte[] BCA;
|
||||
}
|
||||
#endregion Public structures
|
||||
}
|
||||
}
|
||||
@@ -38,53 +38,72 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global"),
|
||||
SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
public static class Cartridge
|
||||
{
|
||||
#region Public structures
|
||||
public struct CartridgeStatus
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Always 6</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4, bit 7 Medium is inserted in a cartridge</summary>
|
||||
public bool Cartridge;
|
||||
/// <summary>Byte 4, bit 6 Medium taken out / put in a cartridge</summary>
|
||||
public bool OUT;
|
||||
/// <summary>Byte 4, bits 5 to 3 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 4, bit 2 Cartridge sets write protection</summary>
|
||||
public bool CWP;
|
||||
/// <summary>Byte 4, bits 1 to 0 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved7;
|
||||
}
|
||||
#endregion Public structures
|
||||
#region Public methods
|
||||
public static CartridgeStatus? Decode(byte[] CSResponse)
|
||||
{
|
||||
if(CSResponse == null) return null;
|
||||
if(CSResponse == null)
|
||||
return null;
|
||||
|
||||
if(CSResponse.Length != 8)
|
||||
{
|
||||
DicConsole.DebugWriteLine("BD Cartridge Status decoder",
|
||||
"Found incorrect Blu-ray Cartridge Status size ({0} bytes)",
|
||||
CSResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
CartridgeStatus decoded = new CartridgeStatus
|
||||
var decoded = new CartridgeStatus
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0),
|
||||
Reserved1 = CSResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0), Reserved1 = CSResponse[2],
|
||||
Reserved2 = CSResponse[3],
|
||||
Cartridge = Convert.ToBoolean(CSResponse[4] & 0x80),
|
||||
OUT = Convert.ToBoolean(CSResponse[4] & 0x40),
|
||||
Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3),
|
||||
CWP = Convert.ToBoolean(CSResponse[4] & 0x04),
|
||||
Reserved4 = (byte)(CSResponse[4] & 0x03),
|
||||
Reserved5 = CSResponse[5],
|
||||
Reserved6 = CSResponse[6],
|
||||
Reserved7 = CSResponse[7]
|
||||
OUT =
|
||||
Convert.ToBoolean(CSResponse[4] & 0x40),
|
||||
Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3),
|
||||
CWP =
|
||||
Convert.ToBoolean(CSResponse[4] & 0x04),
|
||||
Reserved4 = (byte)(CSResponse[4] & 0x03),
|
||||
Reserved5 = CSResponse[5],
|
||||
Reserved6 =
|
||||
CSResponse[6],
|
||||
Reserved7 = CSResponse[7]
|
||||
};
|
||||
|
||||
return decoded;
|
||||
@@ -92,36 +111,57 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(CartridgeStatus? CSResponse)
|
||||
{
|
||||
if(CSResponse == null) return null;
|
||||
if(CSResponse == null)
|
||||
return null;
|
||||
|
||||
CartridgeStatus response = CSResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
|
||||
if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine();
|
||||
if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
|
||||
if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
|
||||
if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
|
||||
if(response.Reserved3 != 0)
|
||||
sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
|
||||
|
||||
if(response.Reserved4 != 0)
|
||||
sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine();
|
||||
|
||||
if(response.Reserved5 != 0)
|
||||
sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
|
||||
|
||||
if(response.Reserved6 != 0)
|
||||
sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
|
||||
|
||||
if(response.Reserved7 != 0)
|
||||
sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine();
|
||||
#endif
|
||||
|
||||
if(response.Cartridge)
|
||||
{
|
||||
sb.AppendLine("Media is inserted in a cartridge");
|
||||
if(response.OUT) sb.AppendLine("Media has been taken out, or inserted in, the cartridge");
|
||||
if(response.CWP) sb.AppendLine("Media is write protected");
|
||||
|
||||
if(response.OUT)
|
||||
sb.AppendLine("Media has been taken out, or inserted in, the cartridge");
|
||||
|
||||
if(response.CWP)
|
||||
sb.AppendLine("Media is write protected");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Media is not in a cartridge");
|
||||
|
||||
#if DEBUG
|
||||
if(response.OUT) sb.AppendLine("Media has out bit marked, shouldn't");
|
||||
if(response.CWP) sb.AppendLine("Media has write protection bit marked, shouldn't");
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.OUT)
|
||||
sb.AppendLine("Media has out bit marked, shouldn't");
|
||||
|
||||
if(response.CWP)
|
||||
sb.AppendLine("Media has write protection bit marked, shouldn't");
|
||||
#endif
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
@@ -129,66 +169,5 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(byte[] CSResponse) => Prettify(Decode(CSResponse));
|
||||
#endregion Public methods
|
||||
|
||||
#region Public structures
|
||||
public struct CartridgeStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Always 6
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 7
|
||||
/// Medium is inserted in a cartridge
|
||||
/// </summary>
|
||||
public bool Cartridge;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 6
|
||||
/// Medium taken out / put in a cartridge
|
||||
/// </summary>
|
||||
public bool OUT;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 5 to 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 2
|
||||
/// Cartridge sets write protection
|
||||
/// </summary>
|
||||
public bool CWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 1 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved7;
|
||||
}
|
||||
#endregion Public structures
|
||||
}
|
||||
}
|
||||
266
Blu-ray/DDS.cs
266
Blu-ray/DDS.cs
@@ -38,42 +38,84 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class DDS
|
||||
{
|
||||
#region Private constants
|
||||
/// <summary>
|
||||
/// Disc Definition Structure Identifier "DS"
|
||||
/// </summary>
|
||||
/// <summary>Disc Definition Structure Identifier "DS"</summary>
|
||||
const ushort DDSIdentifier = 0x4453;
|
||||
#endregion Private constants
|
||||
|
||||
#region Public structures
|
||||
public struct DiscDefinitionStructure
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data Length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 5 "DS"</summary>
|
||||
public ushort Signature;
|
||||
/// <summary>Byte 6 DDS format</summary>
|
||||
public byte Format;
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Bytes 8 to 11 DDS update count</summary>
|
||||
public uint UpdateCount;
|
||||
/// <summary>Bytes 12 to 19 Reserved</summary>
|
||||
public ulong Reserved4;
|
||||
/// <summary>Bytes 20 to 23 First PSN of Drive Area</summary>
|
||||
public uint DriveAreaPSN;
|
||||
/// <summary>Bytes 24 to 27 Reserved</summary>
|
||||
public uint Reserved5;
|
||||
/// <summary>Bytes 28 to 31 First PSN of Defect List</summary>
|
||||
public uint DefectListPSN;
|
||||
/// <summary>Bytes 32 to 35 Reserved</summary>
|
||||
public uint Reserved6;
|
||||
/// <summary>Bytes 36 to 39 PSN of LSN 0 of user data area</summary>
|
||||
public uint PSNofLSNZero;
|
||||
/// <summary>Bytes 40 to 43 Last LSN of user data area</summary>
|
||||
public uint LastUserAreaLSN;
|
||||
/// <summary>Bytes 44 to 47 ISA0 size</summary>
|
||||
public uint ISA0;
|
||||
/// <summary>Bytes 48 to 51 OSA size</summary>
|
||||
public uint OSA;
|
||||
/// <summary>Bytes 52 to 55 ISA1 size</summary>
|
||||
public uint ISA1;
|
||||
/// <summary>Byte 56 Spare Area full flags</summary>
|
||||
public byte SpareAreaFullFlags;
|
||||
/// <summary>Byte 57 Reserved</summary>
|
||||
public byte Reserved7;
|
||||
/// <summary>Byte 58 Disc type specific field</summary>
|
||||
public byte DiscTypeSpecificField1;
|
||||
/// <summary>Byte 59 Reserved</summary>
|
||||
public byte Reserved8;
|
||||
/// <summary>Byte 60 to 63 Disc type specific field</summary>
|
||||
public uint DiscTypeSpecificField2;
|
||||
/// <summary>Byte 64 to 67 Reserved</summary>
|
||||
public uint Reserved9;
|
||||
/// <summary>Bytes 68 to 99 Status bits of INFO1/2 and PAC1/2 on L0 and L1</summary>
|
||||
public byte[] StatusBits;
|
||||
/// <summary>Bytes 100 to end Disc type specific data</summary>
|
||||
public byte[] DiscTypeSpecificData;
|
||||
}
|
||||
#endregion Public structures
|
||||
|
||||
#region Public methods
|
||||
public static DiscDefinitionStructure? Decode(byte[] DDSResponse)
|
||||
{
|
||||
if(DDSResponse == null) return null;
|
||||
if(DDSResponse == null)
|
||||
return null;
|
||||
|
||||
DiscDefinitionStructure decoded = new DiscDefinitionStructure
|
||||
var decoded = new DiscDefinitionStructure
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0),
|
||||
Reserved1 = DDSResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0), Reserved1 = DDSResponse[2],
|
||||
Reserved2 = DDSResponse[3],
|
||||
Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4)
|
||||
};
|
||||
@@ -82,6 +124,7 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
DicConsole.DebugWriteLine("BD DDS decoder", "Found incorrect DDS signature (0x{0:X4})",
|
||||
decoded.Signature);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -114,11 +157,12 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(DiscDefinitionStructure? DDSResponse)
|
||||
{
|
||||
if(DDSResponse == null) return null;
|
||||
if(DDSResponse == null)
|
||||
return null;
|
||||
|
||||
DiscDefinitionStructure response = DDSResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("DDS Format: 0x{0:X2}", response.Format).AppendLine();
|
||||
sb.AppendFormat("DDS has ben updated {0} times", response.UpdateCount).AppendLine();
|
||||
@@ -137,153 +181,39 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
sb.AppendFormat("Blu-ray DDS Disc Type Specific Data in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80));
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine();
|
||||
if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine();
|
||||
if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
|
||||
if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
|
||||
if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine();
|
||||
if(response.Reserved8 != 0) sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine();
|
||||
if(response.Reserved9 != 0) sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
|
||||
if(response.Reserved3 != 0)
|
||||
sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine();
|
||||
|
||||
if(response.Reserved4 != 0)
|
||||
sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine();
|
||||
|
||||
if(response.Reserved5 != 0)
|
||||
sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
|
||||
|
||||
if(response.Reserved6 != 0)
|
||||
sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
|
||||
|
||||
if(response.Reserved7 != 0)
|
||||
sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine();
|
||||
|
||||
if(response.Reserved8 != 0)
|
||||
sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine();
|
||||
|
||||
if(response.Reserved9 != 0)
|
||||
sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine();
|
||||
#endif
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string Prettify(byte[] DDSResponse) => Prettify(Decode(DDSResponse));
|
||||
#endregion Public methods
|
||||
|
||||
#region Public structures
|
||||
public struct DiscDefinitionStructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data Length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 5
|
||||
/// "DS"
|
||||
/// </summary>
|
||||
public ushort Signature;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// DDS format
|
||||
/// </summary>
|
||||
public byte Format;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// DDS update count
|
||||
/// </summary>
|
||||
public uint UpdateCount;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 19
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public ulong Reserved4;
|
||||
/// <summary>
|
||||
/// Bytes 20 to 23
|
||||
/// First PSN of Drive Area
|
||||
/// </summary>
|
||||
public uint DriveAreaPSN;
|
||||
/// <summary>
|
||||
/// Bytes 24 to 27
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public uint Reserved5;
|
||||
/// <summary>
|
||||
/// Bytes 28 to 31
|
||||
/// First PSN of Defect List
|
||||
/// </summary>
|
||||
public uint DefectListPSN;
|
||||
/// <summary>
|
||||
/// Bytes 32 to 35
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public uint Reserved6;
|
||||
/// <summary>
|
||||
/// Bytes 36 to 39
|
||||
/// PSN of LSN 0 of user data area
|
||||
/// </summary>
|
||||
public uint PSNofLSNZero;
|
||||
/// <summary>
|
||||
/// Bytes 40 to 43
|
||||
/// Last LSN of user data area
|
||||
/// </summary>
|
||||
public uint LastUserAreaLSN;
|
||||
/// <summary>
|
||||
/// Bytes 44 to 47
|
||||
/// ISA0 size
|
||||
/// </summary>
|
||||
public uint ISA0;
|
||||
/// <summary>
|
||||
/// Bytes 48 to 51
|
||||
/// OSA size
|
||||
/// </summary>
|
||||
public uint OSA;
|
||||
/// <summary>
|
||||
/// Bytes 52 to 55
|
||||
/// ISA1 size
|
||||
/// </summary>
|
||||
public uint ISA1;
|
||||
/// <summary>
|
||||
/// Byte 56
|
||||
/// Spare Area full flags
|
||||
/// </summary>
|
||||
public byte SpareAreaFullFlags;
|
||||
/// <summary>
|
||||
/// Byte 57
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved7;
|
||||
/// <summary>
|
||||
/// Byte 58
|
||||
/// Disc type specific field
|
||||
/// </summary>
|
||||
public byte DiscTypeSpecificField1;
|
||||
/// <summary>
|
||||
/// Byte 59
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved8;
|
||||
/// <summary>
|
||||
/// Byte 60 to 63
|
||||
/// Disc type specific field
|
||||
/// </summary>
|
||||
public uint DiscTypeSpecificField2;
|
||||
/// <summary>
|
||||
/// Byte 64 to 67
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public uint Reserved9;
|
||||
/// <summary>
|
||||
/// Bytes 68 to 99
|
||||
/// Status bits of INFO1/2 and PAC1/2 on L0 and L1
|
||||
/// </summary>
|
||||
public byte[] StatusBits;
|
||||
/// <summary>
|
||||
/// Bytes 100 to end
|
||||
/// Disc type specific data
|
||||
/// </summary>
|
||||
public byte[] DiscTypeSpecificData;
|
||||
}
|
||||
#endregion Public structures
|
||||
}
|
||||
}
|
||||
347
Blu-ray/DI.cs
347
Blu-ray/DI.cs
@@ -39,54 +39,64 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class DI
|
||||
{
|
||||
public enum BluSize : byte
|
||||
{
|
||||
/// <summary>120mm</summary>
|
||||
OneTwenty = 0, /// <summary>80mm</summary>
|
||||
Eighty = 1
|
||||
}
|
||||
|
||||
public enum ChannelLength : byte
|
||||
{
|
||||
/// <summary>74.5nm channel or 25Gb/layer</summary>
|
||||
Seventy = 1, /// <summary>69.0nm channel or 27Gb/layer</summary>
|
||||
Sixty = 2
|
||||
}
|
||||
|
||||
public enum HybridLayer : byte
|
||||
{
|
||||
/// <summary>No hybrid layer</summary>
|
||||
None = 0, /// <summary>-ROM layer</summary>
|
||||
ReadOnly = 1, /// <summary>-R layer</summary>
|
||||
Recordable = 2, /// <summary>-RW layer</summary>
|
||||
Rewritable = 3
|
||||
}
|
||||
|
||||
#region Private constants
|
||||
const string DiscTypeBDROM = "BDO";
|
||||
const string DiscTypeBDRE = "BDW";
|
||||
const string DiscTypeBDR = "BDR";
|
||||
|
||||
/// <summary>
|
||||
/// Disc Information Unit Identifier "DI"
|
||||
/// </summary>
|
||||
/// <summary>Disc Information Unit Identifier "DI"</summary>
|
||||
const ushort DIUIdentifier = 0x4449;
|
||||
#endregion Private constants
|
||||
|
||||
#region Public methods
|
||||
public static DiscInformation? Decode(byte[] DIResponse)
|
||||
{
|
||||
if(DIResponse == null) return null;
|
||||
if(DIResponse == null)
|
||||
return null;
|
||||
|
||||
if(DIResponse.Length != 4100)
|
||||
{
|
||||
DicConsole.DebugWriteLine("BD Disc Information decoder",
|
||||
"Found incorrect Blu-ray Disc Information size ({0} bytes)",
|
||||
DIResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
DiscInformation decoded = new DiscInformation
|
||||
var decoded = new DiscInformation
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0),
|
||||
Reserved1 = DIResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0), Reserved1 = DIResponse[2],
|
||||
Reserved2 = DIResponse[3]
|
||||
};
|
||||
|
||||
@@ -95,14 +105,16 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(offset >= 4100) break;
|
||||
if(offset >= 4100)
|
||||
break;
|
||||
|
||||
DiscInformationUnits unit = new DiscInformationUnits
|
||||
var unit = new DiscInformationUnits
|
||||
{
|
||||
Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset)
|
||||
};
|
||||
|
||||
if(unit.Signature != DIUIdentifier) break;
|
||||
if(unit.Signature != DIUIdentifier)
|
||||
break;
|
||||
|
||||
unit.Format = DIResponse[2 + offset];
|
||||
unit.UnitsPerBlock = (byte)((DIResponse[3 + offset] & 0xF8) >> 3);
|
||||
@@ -125,19 +137,24 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
unit.RecordedPolarity = DIResponse[14 + offset];
|
||||
unit.Bca = (byte)(DIResponse[16 + offset] & 0x0F);
|
||||
unit.MaxTransfer = DIResponse[17 + offset];
|
||||
|
||||
unit.LastPsn = (uint)((DIResponse[20 + offset] << 24) + (DIResponse[21 + offset] << 16) +
|
||||
(DIResponse[22 + offset] << 8) + DIResponse[23 + offset]);
|
||||
|
||||
// TODO: In -R/-RE how does this relate to layer size???
|
||||
unit.FirstAun = (uint)((DIResponse[24 + offset] << 24) + (DIResponse[25 + offset] << 16) +
|
||||
(DIResponse[26 + offset] << 8) + DIResponse[27 + offset]);
|
||||
|
||||
unit.LastAun = (uint)((DIResponse[28 + offset] << 24) + (DIResponse[29 + offset] << 16) +
|
||||
(DIResponse[30 + offset] << 8) + DIResponse[31 + offset]);
|
||||
|
||||
switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier))
|
||||
{
|
||||
case DiscTypeBDROM:
|
||||
{
|
||||
unit.FormatDependentContents = new byte[32];
|
||||
Array.Copy(DIResponse, 32 + offset, unit.FormatDependentContents, 0, 32);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -154,6 +171,7 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
unit.ProductRevisionNumber = DIResponse[111 + offset];
|
||||
|
||||
offset += 14;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -162,6 +180,7 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
DicConsole.DebugWriteLine("BD Disc Information decoder",
|
||||
"Found unknown disc type identifier \"{0}\"",
|
||||
Encoding.ASCII.GetString(unit.DiscTypeIdentifier));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -171,21 +190,25 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
offset += unit.Length;
|
||||
}
|
||||
|
||||
if(units.Count <= 0) return decoded;
|
||||
if(units.Count <= 0)
|
||||
return decoded;
|
||||
|
||||
decoded.Units = new DiscInformationUnits[units.Count];
|
||||
for(int i = 0; i < units.Count; i++) decoded.Units[i] = units[i];
|
||||
|
||||
for(int i = 0; i < units.Count; i++)
|
||||
decoded.Units[i] = units[i];
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
public static string Prettify(DiscInformation? DIResponse)
|
||||
{
|
||||
if(DIResponse == null) return null;
|
||||
if(DIResponse == null)
|
||||
return null;
|
||||
|
||||
DiscInformation response = DIResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
foreach(DiscInformationUnits unit in response.Units)
|
||||
{
|
||||
@@ -193,41 +216,53 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
sb.AppendFormat("DI Unit Format: 0x{0:X2}", unit.Format).AppendLine();
|
||||
sb.AppendFormat("There are {0} per block", unit.UnitsPerBlock).AppendLine();
|
||||
sb.AppendFormat("This DI refers to layer {0}", unit.Layer).AppendLine();
|
||||
|
||||
if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE)
|
||||
sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine();
|
||||
|
||||
sb.AppendLine(unit.Continuation ? "This DI continues previous unit" : "This DI starts a new unit");
|
||||
sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine();
|
||||
sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier))
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)).
|
||||
AppendLine();
|
||||
|
||||
switch(unit.DiscSize)
|
||||
{
|
||||
case BluSize.OneTwenty:
|
||||
sb.AppendLine("Disc size: 120mm");
|
||||
|
||||
break;
|
||||
case BluSize.Eighty:
|
||||
sb.AppendLine("Disc size: 80mm");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc size: Unknown code {0}", (byte)unit.DiscSize).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("Disc class: {0}", unit.DiscClass).AppendLine();
|
||||
sb.AppendFormat("Disc version: {0}", unit.DiscVersion).AppendLine();
|
||||
sb.AppendFormat("This disc has {0} layers", unit.Layers).AppendLine();
|
||||
|
||||
switch(unit.DvdLayer)
|
||||
{
|
||||
case HybridLayer.None:
|
||||
sb.AppendLine("This disc does not contain a DVD layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.ReadOnly:
|
||||
sb.AppendLine("This disc contains a DVD-ROM layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.Recordable:
|
||||
sb.AppendLine("This disc contains a DVD-R layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.Rewritable:
|
||||
sb.AppendLine("This disc contains a DVD-RW layer.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -235,15 +270,19 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
case HybridLayer.None:
|
||||
sb.AppendLine("This disc does not contain a CD layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.ReadOnly:
|
||||
sb.AppendLine("This disc contains a CD-ROM layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.Recordable:
|
||||
sb.AppendLine("This disc contains a CD-R layer.");
|
||||
|
||||
break;
|
||||
case HybridLayer.Rewritable:
|
||||
sb.AppendLine("This disc contains a CD-RW layer.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -251,13 +290,16 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
case ChannelLength.Seventy:
|
||||
sb.AppendLine("Disc uses a 74.5nm channel giving 25 Gb per layer.");
|
||||
|
||||
break;
|
||||
case ChannelLength.Sixty:
|
||||
sb.AppendLine("Disc uses a 69.0nm channel giving 27 Gb per layer.");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc uses unknown channel length with code {0}", (byte)unit.ChannelLength)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Disc uses unknown channel length with code {0}", (byte)unit.ChannelLength).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -265,12 +307,15 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc uses positive polarity.");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc uses negative polarity.");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc uses unknown polarity with code {0}", unit.Polarity).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -279,13 +324,16 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Recorded marks have a lower reflectivity than unrecorded ones (HTL disc).");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Recorded marks have a higher reflectivity than unrecorded ones (LTH disc).");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc uses unknown recorded reflectivity polarity with code {0}",
|
||||
unit.RecordedPolarity).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -293,31 +341,39 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc doesn't have a BCA.");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc has a BCA.");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc uses unknown BCA code {0}", unit.Bca).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(unit.MaxTransfer > 0)
|
||||
sb.AppendFormat("Disc has a maximum transfer rate of {0} Mbit/sec.", unit.MaxTransfer).AppendLine();
|
||||
else sb.AppendLine("Disc does not specify a maximum transfer rate.");
|
||||
else
|
||||
sb.AppendLine("Disc does not specify a maximum transfer rate.");
|
||||
|
||||
sb.AppendFormat("Last user data PSN for disc: {0}", unit.LastPsn).AppendLine();
|
||||
sb.AppendFormat("First address unit number of data zone in this layer: {0}", unit.FirstAun)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("First address unit number of data zone in this layer: {0}", unit.FirstAun).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("Last address unit number of data zone in this layer: {0}", unit.LastAun).AppendLine();
|
||||
|
||||
if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR ||
|
||||
Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE)
|
||||
{
|
||||
sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("Disc timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine();
|
||||
sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine();
|
||||
}
|
||||
@@ -335,219 +391,86 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
#region Public structures
|
||||
public struct DiscInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Always 4098
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Always 4098</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4 to 4099
|
||||
/// Disc information units
|
||||
/// </summary>
|
||||
/// <summary>Byte 4 to 4099 Disc information units</summary>
|
||||
public DiscInformationUnits[] Units;
|
||||
}
|
||||
|
||||
public struct DiscInformationUnits
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// "DI"
|
||||
/// </summary>
|
||||
/// <summary>Byte 0 "DI"</summary>
|
||||
public ushort Signature;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Disc information format
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Disc information format</summary>
|
||||
public byte Format;
|
||||
/// <summary>
|
||||
/// Byte 3, bits 7 to 3
|
||||
/// Number of DI units per block
|
||||
/// </summary>
|
||||
/// <summary>Byte 3, bits 7 to 3 Number of DI units per block</summary>
|
||||
public byte UnitsPerBlock;
|
||||
/// <summary>
|
||||
/// Byte 3, bits 2 to 0
|
||||
/// Layer this DI refers to
|
||||
/// </summary>
|
||||
/// <summary>Byte 3, bits 2 to 0 Layer this DI refers to</summary>
|
||||
public byte Layer;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Reserved for BD-ROM, legacy information for BD-R/-RE
|
||||
/// </summary>
|
||||
/// <summary>Byte 4 Reserved for BD-ROM, legacy information for BD-R/-RE</summary>
|
||||
public byte Legacy;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Sequence number for this DI unit
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Sequence number for this DI unit</summary>
|
||||
public byte Sequence;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 7
|
||||
/// If set this DI is a continuation of the previous one
|
||||
/// </summary>
|
||||
/// <summary>Byte 6, bit 7 If set this DI is a continuation of the previous one</summary>
|
||||
public bool Continuation;
|
||||
/// <summary>
|
||||
/// Byte 6, bits 6 to 0
|
||||
/// Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE
|
||||
/// </summary>
|
||||
/// <summary>Byte 6, bits 6 to 0 Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE</summary>
|
||||
public byte Length;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 10
|
||||
/// Disc type identifier
|
||||
/// </summary>
|
||||
/// <summary>Bytes 8 to 10 Disc type identifier</summary>
|
||||
public byte[] DiscTypeIdentifier;
|
||||
/// <summary>
|
||||
/// Byte 11, bits 7 to 6
|
||||
/// Disc size
|
||||
/// </summary>
|
||||
/// <summary>Byte 11, bits 7 to 6 Disc size</summary>
|
||||
public BluSize DiscSize;
|
||||
/// <summary>
|
||||
/// Byte 11, bits 5 to 4
|
||||
/// Disc class
|
||||
/// </summary>
|
||||
/// <summary>Byte 11, bits 5 to 4 Disc class</summary>
|
||||
public byte DiscClass;
|
||||
/// <summary>
|
||||
/// Byte 11, bits 3 to 0
|
||||
/// Disc version
|
||||
/// </summary>
|
||||
/// <summary>Byte 11, bits 3 to 0 Disc version</summary>
|
||||
public byte DiscVersion;
|
||||
/// <summary>
|
||||
/// Byte 12, bits 7 to 4
|
||||
/// Layers in this disc
|
||||
/// </summary>
|
||||
/// <summary>Byte 12, bits 7 to 4 Layers in this disc</summary>
|
||||
public byte Layers;
|
||||
/// <summary>
|
||||
/// Byte 12, bits 3 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 12, bits 3 to 0 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 13, bits 7 to 6
|
||||
/// DVD layer
|
||||
/// </summary>
|
||||
/// <summary>Byte 13, bits 7 to 6 DVD layer</summary>
|
||||
public HybridLayer DvdLayer;
|
||||
/// <summary>
|
||||
/// Byte 13, bits 5 to 4
|
||||
/// CD layer
|
||||
/// </summary>
|
||||
/// <summary>Byte 13, bits 5 to 4 CD layer</summary>
|
||||
public HybridLayer CdLayer;
|
||||
/// <summary>
|
||||
/// Byte 13, bits 3 to 0
|
||||
/// Channel length
|
||||
/// </summary>
|
||||
/// <summary>Byte 13, bits 3 to 0 Channel length</summary>
|
||||
public ChannelLength ChannelLength;
|
||||
/// <summary>
|
||||
/// Byte 14
|
||||
/// Polarity
|
||||
/// </summary>
|
||||
/// <summary>Byte 14 Polarity</summary>
|
||||
public byte Polarity;
|
||||
/// <summary>
|
||||
/// Byte 15
|
||||
/// Recorded polarity
|
||||
/// </summary>
|
||||
/// <summary>Byte 15 Recorded polarity</summary>
|
||||
public byte RecordedPolarity;
|
||||
/// <summary>
|
||||
/// Byte 16, bits 7 to 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 16, bits 7 to 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 16, bits 3 to 0
|
||||
/// If 0 no BCA, if 1 BCA, rest not defined
|
||||
/// </summary>
|
||||
/// <summary>Byte 16, bits 3 to 0 If 0 no BCA, if 1 BCA, rest not defined</summary>
|
||||
public byte Bca;
|
||||
/// <summary>
|
||||
/// Byte 17
|
||||
/// Maximum transfer speed in megabits/second, 0 if no maximum
|
||||
/// </summary>
|
||||
/// <summary>Byte 17 Maximum transfer speed in megabits/second, 0 if no maximum</summary>
|
||||
public byte MaxTransfer;
|
||||
/// <summary>
|
||||
/// Bytes 18 to 19
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Bytes 18 to 19 Reserved</summary>
|
||||
public ushort Reserved4;
|
||||
/// <summary>
|
||||
/// Bytes 20 to 23
|
||||
/// Last user data PSN for disc
|
||||
/// </summary>
|
||||
/// <summary>Bytes 20 to 23 Last user data PSN for disc</summary>
|
||||
public uint LastPsn;
|
||||
/// <summary>
|
||||
/// Bytes 24 to 27
|
||||
/// First address unit number of data zone in this layer
|
||||
/// </summary>
|
||||
/// <summary>Bytes 24 to 27 First address unit number of data zone in this layer</summary>
|
||||
public uint FirstAun;
|
||||
/// <summary>
|
||||
/// Bytes 28 to 31
|
||||
/// Last address unit number of data zone in this layer
|
||||
/// </summary>
|
||||
/// <summary>Bytes 28 to 31 Last address unit number of data zone in this layer</summary>
|
||||
public uint LastAun;
|
||||
/// <summary>
|
||||
/// Bytes 32 to 63 for BD-ROM, bytes 32 to 99 for BD-R/-RE
|
||||
/// Format dependent contents, disclosed in private blu-ray specifications
|
||||
/// Bytes 32 to 63 for BD-ROM, bytes 32 to 99 for BD-R/-RE Format dependent contents, disclosed in private blu-ray
|
||||
/// specifications
|
||||
/// </summary>
|
||||
public byte[] FormatDependentContents;
|
||||
/// <summary>
|
||||
/// Bytes 100 to 105, BD-R/-RE only
|
||||
/// Manufacturer ID
|
||||
/// </summary>
|
||||
/// <summary>Bytes 100 to 105, BD-R/-RE only Manufacturer ID</summary>
|
||||
public byte[] ManufacturerID;
|
||||
/// <summary>
|
||||
/// Bytes 106 to 108, BD-R/-RE only
|
||||
/// Media type ID
|
||||
/// </summary>
|
||||
/// <summary>Bytes 106 to 108, BD-R/-RE only Media type ID</summary>
|
||||
public byte[] MediaTypeID;
|
||||
/// <summary>
|
||||
/// Bytes 109 to 110, BD-R/-RE only
|
||||
/// Timestamp
|
||||
/// </summary>
|
||||
/// <summary>Bytes 109 to 110, BD-R/-RE only Timestamp</summary>
|
||||
public ushort TimeStamp;
|
||||
/// <summary>
|
||||
/// Byte 111
|
||||
/// Product revision number
|
||||
/// </summary>
|
||||
/// <summary>Byte 111 Product revision number</summary>
|
||||
public byte ProductRevisionNumber;
|
||||
}
|
||||
#endregion Public structures
|
||||
|
||||
public enum BluSize : byte
|
||||
{
|
||||
/// <summary>120mm</summary>
|
||||
OneTwenty = 0,
|
||||
/// <summary>80mm</summary>
|
||||
Eighty = 1
|
||||
}
|
||||
|
||||
public enum HybridLayer : byte
|
||||
{
|
||||
/// <summary>No hybrid layer</summary>
|
||||
None = 0,
|
||||
/// <summary>-ROM layer</summary>
|
||||
ReadOnly = 1,
|
||||
/// <summary>-R layer</summary>
|
||||
Recordable = 2,
|
||||
/// <summary>-RW layer</summary>
|
||||
Rewritable = 3
|
||||
}
|
||||
|
||||
public enum ChannelLength : byte
|
||||
{
|
||||
/// <summary>74.5nm channel or 25Gb/layer</summary>
|
||||
Seventy = 1,
|
||||
/// <summary>69.0nm channel or 27Gb/layer</summary>
|
||||
Sixty = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Blu-ray/Spare.cs
104
Blu-ray/Spare.cs
@@ -37,43 +37,49 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.Bluray
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class Spare
|
||||
{
|
||||
#region Public structures
|
||||
public struct SpareAreaInformation
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Always 14</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 7 Reserved</summary>
|
||||
public uint Reserved3;
|
||||
/// <summary>Bytes 8 to 11 Free spare blocks</summary>
|
||||
public uint FreeSpareBlocks;
|
||||
/// <summary>Bytes 12 to 15 Allocated spare blocks</summary>
|
||||
public uint AllocatedSpareBlocks;
|
||||
}
|
||||
#endregion Public structures
|
||||
#region Public methods
|
||||
public static SpareAreaInformation? Decode(byte[] SAIResponse)
|
||||
{
|
||||
if(SAIResponse == null) return null;
|
||||
if(SAIResponse == null)
|
||||
return null;
|
||||
|
||||
if(SAIResponse.Length != 16)
|
||||
{
|
||||
DicConsole.DebugWriteLine("BD Spare Area Information decoder",
|
||||
"Found incorrect Blu-ray Spare Area Information size ({0} bytes)",
|
||||
SAIResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
SpareAreaInformation decoded = new SpareAreaInformation
|
||||
var decoded = new SpareAreaInformation
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0),
|
||||
Reserved1 = SAIResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0), Reserved1 = SAIResponse[2],
|
||||
Reserved2 = SAIResponse[3],
|
||||
Reserved3 = BigEndianBitConverter.ToUInt32(SAIResponse, 4),
|
||||
FreeSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 8),
|
||||
@@ -85,17 +91,23 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(SpareAreaInformation? SAIResponse)
|
||||
{
|
||||
if(SAIResponse == null) return null;
|
||||
if(SAIResponse == null)
|
||||
return null;
|
||||
|
||||
SpareAreaInformation response = SAIResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
|
||||
if(response.Reserved3 != 0)
|
||||
sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine();
|
||||
sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine();
|
||||
|
||||
@@ -104,41 +116,5 @@ namespace DiscImageChef.Decoders.Bluray
|
||||
|
||||
public static string Prettify(byte[] SAIResponse) => Prettify(Decode(SAIResponse));
|
||||
#endregion Public methods
|
||||
|
||||
#region Public structures
|
||||
public struct SpareAreaInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Always 14
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public uint Reserved3;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// Free spare blocks
|
||||
/// </summary>
|
||||
public uint FreeSpareBlocks;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 15
|
||||
/// Allocated spare blocks
|
||||
/// </summary>
|
||||
public uint AllocatedSpareBlocks;
|
||||
}
|
||||
#endregion Public structures
|
||||
}
|
||||
}
|
||||
575
CD/ATIP.cs
575
CD/ATIP.cs
@@ -38,201 +38,28 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class ATIP
|
||||
{
|
||||
public struct CDATIP
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 1 to 0
|
||||
/// Total size of returned session information minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 7 to 4
|
||||
/// Indicative target writing power
|
||||
/// </summary>
|
||||
public byte ITWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 3
|
||||
/// Set if DDCD
|
||||
/// </summary>
|
||||
public bool DDCD;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 2 to 0
|
||||
/// Reference speed
|
||||
/// </summary>
|
||||
public byte ReferenceSpeed;
|
||||
/// <summary>
|
||||
/// Byte 5, bit 7
|
||||
/// Always unset
|
||||
/// </summary>
|
||||
public bool AlwaysZero;
|
||||
/// <summary>
|
||||
/// Byte 5, bit 6
|
||||
/// Unrestricted media
|
||||
/// </summary>
|
||||
public bool URU;
|
||||
/// <summary>
|
||||
/// Byte 5, bits 5 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 7
|
||||
/// Always set
|
||||
/// </summary>
|
||||
public bool AlwaysOne;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 6
|
||||
/// Set if rewritable (CD-RW or DDCD-RW)
|
||||
/// </summary>
|
||||
public bool DiscType;
|
||||
/// <summary>
|
||||
/// Byte 6, bits 5 to 3
|
||||
/// Disc subtype
|
||||
/// </summary>
|
||||
public byte DiscSubType;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 2
|
||||
/// A1 values are valid
|
||||
/// </summary>
|
||||
public bool A1Valid;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 1
|
||||
/// A2 values are valid
|
||||
/// </summary>
|
||||
public bool A2Valid;
|
||||
/// <summary>
|
||||
/// Byte 6, bit 0
|
||||
/// A3 values are valid
|
||||
/// </summary>
|
||||
public bool A3Valid;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 8
|
||||
/// ATIP Start time of Lead-In (Minute)
|
||||
/// </summary>
|
||||
public byte LeadInStartMin;
|
||||
/// <summary>
|
||||
/// Byte 9
|
||||
/// ATIP Start time of Lead-In (Second)
|
||||
/// </summary>
|
||||
public byte LeadInStartSec;
|
||||
/// <summary>
|
||||
/// Byte 10
|
||||
/// ATIP Start time of Lead-In (Frame)
|
||||
/// </summary>
|
||||
public byte LeadInStartFrame;
|
||||
/// <summary>
|
||||
/// Byte 11
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 12
|
||||
/// ATIP Last possible start time of Lead-Out (Minute)
|
||||
/// </summary>
|
||||
public byte LeadOutStartMin;
|
||||
/// <summary>
|
||||
/// Byte 13
|
||||
/// ATIP Last possible start time of Lead-Out (Second)
|
||||
/// </summary>
|
||||
public byte LeadOutStartSec;
|
||||
/// <summary>
|
||||
/// Byte 14
|
||||
/// ATIP Last possible start time of Lead-Out (Frame)
|
||||
/// </summary>
|
||||
public byte LeadOutStartFrame;
|
||||
/// <summary>
|
||||
/// Byte 15
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Bytes 16 to 18
|
||||
/// A1 values
|
||||
/// </summary>
|
||||
public byte[] A1Values;
|
||||
/// <summary>
|
||||
/// Byte 19
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved7;
|
||||
/// <summary>
|
||||
/// Bytes 20 to 22
|
||||
/// A2 values
|
||||
/// </summary>
|
||||
public byte[] A2Values;
|
||||
/// <summary>
|
||||
/// Byte 23
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved8;
|
||||
/// <summary>
|
||||
/// Bytes 24 to 26
|
||||
/// A3 values
|
||||
/// </summary>
|
||||
public byte[] A3Values;
|
||||
/// <summary>
|
||||
/// Byte 27
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved9;
|
||||
/// <summary>
|
||||
/// Bytes 28 to 30
|
||||
/// S4 values
|
||||
/// </summary>
|
||||
public byte[] S4Values;
|
||||
/// <summary>
|
||||
/// Byte 31
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved10;
|
||||
}
|
||||
|
||||
public static CDATIP? Decode(byte[] CDATIPResponse)
|
||||
{
|
||||
if(CDATIPResponse == null) return null;
|
||||
if(CDATIPResponse == null)
|
||||
return null;
|
||||
|
||||
CDATIP decoded = new CDATIP();
|
||||
var decoded = new CDATIP();
|
||||
|
||||
if(CDATIPResponse.Length != 32 && CDATIPResponse.Length != 28)
|
||||
if(CDATIPResponse.Length != 32 &&
|
||||
CDATIPResponse.Length != 28)
|
||||
{
|
||||
DicConsole.DebugWriteLine("CD ATIP decoder",
|
||||
"Expected CD ATIP size (32 bytes) is not received size ({0} bytes), not decoding",
|
||||
CDATIPResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -275,7 +102,8 @@ namespace DiscImageChef.Decoders.CD
|
||||
decoded.Reserved8 = CDATIPResponse[23];
|
||||
decoded.Reserved9 = CDATIPResponse[27];
|
||||
|
||||
if(CDATIPResponse.Length < 32) return decoded;
|
||||
if(CDATIPResponse.Length < 32)
|
||||
return decoded;
|
||||
|
||||
decoded.S4Values = new byte[3];
|
||||
Array.Copy(CDATIPResponse, 28, decoded.S4Values, 0, 3);
|
||||
@@ -286,72 +114,89 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDATIP? CDATIPResponse)
|
||||
{
|
||||
if(CDATIPResponse == null) return null;
|
||||
if(CDATIPResponse == null)
|
||||
return null;
|
||||
|
||||
CDATIP response = CDATIPResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(response.DDCD)
|
||||
{
|
||||
sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine();
|
||||
sb.AppendLine(response.DiscType ? "Disc is DDCD-RW" : "Disc is DDCD-R");
|
||||
|
||||
switch(response.ReferenceSpeed)
|
||||
{
|
||||
case 2:
|
||||
sb.AppendLine("Reference speed is 4x");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("Reference speed is 8x");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("ATIP Start time of Lead-in: 0x{0:X6}",
|
||||
(response.LeadInStartMin << 16) + (response.LeadInStartSec << 8) +
|
||||
response.LeadInStartFrame).AppendLine();
|
||||
|
||||
sb.AppendFormat("ATIP Last possible start time of Lead-out: 0x{0:X6}",
|
||||
(response.LeadOutStartMin << 16) + (response.LeadOutStartSec << 8) +
|
||||
response.LeadOutStartFrame).AppendLine();
|
||||
|
||||
sb.AppendFormat("S4 value: 0x{0:X6}",
|
||||
(response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2])
|
||||
.AppendLine();
|
||||
(response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).
|
||||
AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP & 0x07).AppendLine();
|
||||
|
||||
if(response.DiscType)
|
||||
{
|
||||
switch(response.DiscSubType)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc is CD-RW");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc is High-Speed CD-RW");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("Disc is Ultra-Speed CD-RW");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("Disc is Ultra-Speed+ CD-RW");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("Disc is medium type B, low beta category (B-) CD-RW");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("Disc is medium type B, high beta category (B+) CD-RW");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("Disc is medium type C, low beta category (C-) CD-RW");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("Disc is medium type C, high beta category (C+) CD-RW");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown CD-RW disc subtype: {0}", response.DiscSubType).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -359,44 +204,56 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("Reference speed is 2x");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("Disc is CD-R");
|
||||
|
||||
switch(response.DiscSubType)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc is normal speed (CLV) CD-R");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc is high speed (CAV) CD-R");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("Disc is medium type A, low beta category (A-) CD-R");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("Disc is medium type A, high beta category (A+) CD-R");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("Disc is medium type B, low beta category (B-) CD-R");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("Disc is medium type B, high beta category (B+) CD-R");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("Disc is medium type C, low beta category (C-) CD-R");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("Disc is medium type C, high beta category (C+) CD-R");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown CD-R disc subtype: {0}", response.DiscSubType).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -405,41 +262,48 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
sb.AppendFormat("ATIP Start time of Lead-in: {0}:{1:D2}:{2:D2}", response.LeadInStartMin,
|
||||
response.LeadInStartSec, response.LeadInStartFrame).AppendLine();
|
||||
|
||||
sb.AppendFormat("ATIP Last possible start time of Lead-out: {0}:{1:D2}:{2:D2}",
|
||||
response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame)
|
||||
.AppendLine();
|
||||
response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame).
|
||||
AppendLine();
|
||||
|
||||
if(response.A1Valid)
|
||||
sb.AppendFormat("A1 value: 0x{0:X6}",
|
||||
(response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2])
|
||||
.AppendLine();
|
||||
(response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]).
|
||||
AppendLine();
|
||||
|
||||
if(response.A2Valid)
|
||||
sb.AppendFormat("A2 value: 0x{0:X6}",
|
||||
(response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2])
|
||||
.AppendLine();
|
||||
(response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]).
|
||||
AppendLine();
|
||||
|
||||
if(response.A3Valid)
|
||||
sb.AppendFormat("A3 value: 0x{0:X6}",
|
||||
(response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2])
|
||||
.AppendLine();
|
||||
(response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]).
|
||||
AppendLine();
|
||||
|
||||
if(response.S4Values != null)
|
||||
sb.AppendFormat("S4 value: 0x{0:X6}",
|
||||
(response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2])
|
||||
.AppendLine();
|
||||
(response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).
|
||||
AppendLine();
|
||||
}
|
||||
|
||||
if(response.LeadInStartMin != 97) return sb.ToString();
|
||||
if(response.LeadInStartMin != 97)
|
||||
return sb.ToString();
|
||||
|
||||
int type = response.LeadInStartFrame % 10;
|
||||
int frm = response.LeadInStartFrame - type;
|
||||
|
||||
if(response.DiscType) sb.AppendLine("Disc uses phase change");
|
||||
if(response.DiscType)
|
||||
sb.AppendLine("Disc uses phase change");
|
||||
else
|
||||
sb.AppendLine(type < 5
|
||||
? "Disc uses long strategy type dye (Cyanine, AZO, etc...)"
|
||||
sb.AppendLine(type < 5 ? "Disc uses long strategy type dye (Cyanine, AZO, etc...)"
|
||||
: "Disc uses short strategy type dye (Phthalocyanine, etc...)");
|
||||
|
||||
string manufacturer = ManufacturerFromATIP(response.LeadInStartSec, frm);
|
||||
|
||||
if(manufacturer != "") sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine();
|
||||
if(manufacturer != "")
|
||||
sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -447,6 +311,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDATIPResponse)
|
||||
{
|
||||
CDATIP? decoded = Decode(CDATIPResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
@@ -457,166 +322,169 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 15:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "TDK Corporation";
|
||||
case 10: return "Ritek Co.";
|
||||
case 20: return "Mitsubishi Chemical Corporation";
|
||||
case 30: return "NAN-YA Plastics Corporation";
|
||||
case 00: return"TDK Corporation";
|
||||
case 10: return"Ritek Co.";
|
||||
case 20: return"Mitsubishi Chemical Corporation";
|
||||
case 30: return"NAN-YA Plastics Corporation";
|
||||
}
|
||||
|
||||
break;
|
||||
case 16:
|
||||
switch(frm)
|
||||
{
|
||||
case 20: return "Shenzen SG&Gast Digital Optical Discs";
|
||||
case 30: return "Grand Advance Technology Ltd.";
|
||||
case 20: return"Shenzen SG&Gast Digital Optical Discs";
|
||||
case 30: return"Grand Advance Technology Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 17:
|
||||
if(frm == 00) return "Moser Baer India Limited";
|
||||
if(frm == 00)
|
||||
return"Moser Baer India Limited";
|
||||
|
||||
break;
|
||||
case 18:
|
||||
switch(frm)
|
||||
{
|
||||
case 10: return "Wealth Fair Investment Ltd.";
|
||||
case 60: return "Taroko International Co. Ltd.";
|
||||
case 10: return"Wealth Fair Investment Ltd.";
|
||||
case 60: return"Taroko International Co. Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 20:
|
||||
if(frm == 10) return "CDA Datenträger Albrechts GmbH";
|
||||
if(frm == 10)
|
||||
return"CDA Datenträger Albrechts GmbH";
|
||||
|
||||
break;
|
||||
case 21:
|
||||
switch(frm)
|
||||
{
|
||||
case 10: return "Grupo Condor S.L.";
|
||||
case 30: return "Bestdisc Technology Corporation";
|
||||
case 40: return "Optical Disc Manufacturing Equipment";
|
||||
case 50: return "Sound Sound Multi-Media Development Ltd.";
|
||||
case 10: return"Grupo Condor S.L.";
|
||||
case 30: return"Bestdisc Technology Corporation";
|
||||
case 40: return"Optical Disc Manufacturing Equipment";
|
||||
case 50: return"Sound Sound Multi-Media Development Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 22:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Woongjin Media Corp.";
|
||||
case 10: return "Seantram Technology Inc.";
|
||||
case 20: return "Advanced Digital Media";
|
||||
case 30: return "EXIMPO";
|
||||
case 40: return "CIS Technology Inc.";
|
||||
case 50: return "Hong Kong Digital Technology Co., Ltd.";
|
||||
case 60: return "Acer Media Technology, Inc.";
|
||||
case 00: return"Woongjin Media Corp.";
|
||||
case 10: return"Seantram Technology Inc.";
|
||||
case 20: return"Advanced Digital Media";
|
||||
case 30: return"EXIMPO";
|
||||
case 40: return"CIS Technology Inc.";
|
||||
case 50: return"Hong Kong Digital Technology Co., Ltd.";
|
||||
case 60: return"Acer Media Technology, Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 23:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Matsushita Electric Industrial Co., Ltd.";
|
||||
case 10: return "Doremi Media Co., Ltd.";
|
||||
case 20: return "Nacar Media s.r.l.";
|
||||
case 30: return "Audio Distributors Co., Ltd.";
|
||||
case 40: return "Victor Company of Japan, Ltd.";
|
||||
case 50: return "Optrom Inc.";
|
||||
case 60: return "Customer Pressing Oosterhout";
|
||||
case 00: return"Matsushita Electric Industrial Co., Ltd.";
|
||||
case 10: return"Doremi Media Co., Ltd.";
|
||||
case 20: return"Nacar Media s.r.l.";
|
||||
case 30: return"Audio Distributors Co., Ltd.";
|
||||
case 40: return"Victor Company of Japan, Ltd.";
|
||||
case 50: return"Optrom Inc.";
|
||||
case 60: return"Customer Pressing Oosterhout";
|
||||
}
|
||||
|
||||
break;
|
||||
case 24:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Taiyo Yuden Company Ltd.";
|
||||
case 10: return "SONY Corporation";
|
||||
case 20: return "Computer Support Italy s.r.l.";
|
||||
case 30: return "Unitech Japan Inc.";
|
||||
case 40: return "kdg mediatech AG";
|
||||
case 50: return "Guann Yinn Co., Ltd.";
|
||||
case 60: return "Harmonic Hall Optical Disc Ltd.";
|
||||
case 00: return"Taiyo Yuden Company Ltd.";
|
||||
case 10: return"SONY Corporation";
|
||||
case 20: return"Computer Support Italy s.r.l.";
|
||||
case 30: return"Unitech Japan Inc.";
|
||||
case 40: return"kdg mediatech AG";
|
||||
case 50: return"Guann Yinn Co., Ltd.";
|
||||
case 60: return"Harmonic Hall Optical Disc Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 25:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "MPO";
|
||||
case 20: return "Hitachi Maxell, Ltd.";
|
||||
case 30: return "Infodisc Technology Co. Ltd.";
|
||||
case 40: return "Vivastar AG";
|
||||
case 50: return "AMS Technology Inc.";
|
||||
case 60: return "Xcitec Inc.";
|
||||
case 00: return"MPO";
|
||||
case 20: return"Hitachi Maxell, Ltd.";
|
||||
case 30: return"Infodisc Technology Co. Ltd.";
|
||||
case 40: return"Vivastar AG";
|
||||
case 50: return"AMS Technology Inc.";
|
||||
case 60: return"Xcitec Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 26:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Fornet International Pte Ltd.";
|
||||
case 10: return "POSTECH Corporation";
|
||||
case 20: return "SKC Co., Ltd.";
|
||||
case 30: return "Optical Disc Corporation";
|
||||
case 40: return "FUJI Photo Film Co., Ltd.";
|
||||
case 50: return "Lead Data Inc.";
|
||||
case 60: return "CMC Magnetics Corporation";
|
||||
case 00: return"Fornet International Pte Ltd.";
|
||||
case 10: return"POSTECH Corporation";
|
||||
case 20: return"SKC Co., Ltd.";
|
||||
case 30: return"Optical Disc Corporation";
|
||||
case 40: return"FUJI Photo Film Co., Ltd.";
|
||||
case 50: return"Lead Data Inc.";
|
||||
case 60: return"CMC Magnetics Corporation";
|
||||
}
|
||||
|
||||
break;
|
||||
case 27:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Digital Storage Technology Co., Ltd.";
|
||||
case 10: return "Plasmon Data systems Ltd.";
|
||||
case 20: return "Princo Corporation";
|
||||
case 30: return "Pioneer Video Corporation";
|
||||
case 40: return "Kodak Japan Ltd.";
|
||||
case 50: return "Mitsui Chemicals, Inc.";
|
||||
case 60: return "Ricoh Company Ltd.";
|
||||
case 00: return"Digital Storage Technology Co., Ltd.";
|
||||
case 10: return"Plasmon Data systems Ltd.";
|
||||
case 20: return"Princo Corporation";
|
||||
case 30: return"Pioneer Video Corporation";
|
||||
case 40: return"Kodak Japan Ltd.";
|
||||
case 50: return"Mitsui Chemicals, Inc.";
|
||||
case 60: return"Ricoh Company Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 28:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Opti.Me.S. S.p.A.";
|
||||
case 10: return "Gigastore Corporation";
|
||||
case 20: return "Multi Media Masters & Machinary SA";
|
||||
case 30: return "Auvistar Industry Co., Ltd.";
|
||||
case 40: return "King Pro Mediatek Inc.";
|
||||
case 50: return "Delphi Technology Inc.";
|
||||
case 60: return "Friendly CD-Tek Co.";
|
||||
case 00: return"Opti.Me.S. S.p.A.";
|
||||
case 10: return"Gigastore Corporation";
|
||||
case 20: return"Multi Media Masters & Machinary SA";
|
||||
case 30: return"Auvistar Industry Co., Ltd.";
|
||||
case 40: return"King Pro Mediatek Inc.";
|
||||
case 50: return"Delphi Technology Inc.";
|
||||
case 60: return"Friendly CD-Tek Co.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 29:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Taeil Media Co., Ltd.";
|
||||
case 10: return "Vanguard Disc Inc.";
|
||||
case 20: return "Unidisc Technology Co., Ltd.";
|
||||
case 30: return "Hile Optical Disc Technology Corp.";
|
||||
case 40: return "Viva Magnetics Ltd.";
|
||||
case 50: return "General Magnetics Ltd.";
|
||||
case 00: return"Taeil Media Co., Ltd.";
|
||||
case 10: return"Vanguard Disc Inc.";
|
||||
case 20: return"Unidisc Technology Co., Ltd.";
|
||||
case 30: return"Hile Optical Disc Technology Corp.";
|
||||
case 40: return"Viva Magnetics Ltd.";
|
||||
case 50: return"General Magnetics Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 30:
|
||||
if(frm == 10) return "CDA Datenträger Albrechts GmbH";
|
||||
if(frm == 10)
|
||||
return"CDA Datenträger Albrechts GmbH";
|
||||
|
||||
break;
|
||||
case 31:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Ritek Co.";
|
||||
case 30: return "Grand Advance Technology Ltd.";
|
||||
case 00: return"Ritek Co.";
|
||||
case 30: return"Grand Advance Technology Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 32:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "TDK Corporation";
|
||||
case 10: return "Prodisc Technology Inc.";
|
||||
case 00: return"TDK Corporation";
|
||||
case 10: return"Prodisc Technology Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -624,96 +492,165 @@ namespace DiscImageChef.Decoders.CD
|
||||
switch(frm)
|
||||
{
|
||||
case 20:
|
||||
case 22: return "Mitsubishi Chemical Corporation";
|
||||
case 22: return"Mitsubishi Chemical Corporation";
|
||||
}
|
||||
|
||||
break;
|
||||
case 42:
|
||||
if(frm == 20) return "Advanced Digital Media";
|
||||
if(frm == 20)
|
||||
return"Advanced Digital Media";
|
||||
|
||||
break;
|
||||
case 45:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Fornet International Pte Ltd.";
|
||||
case 10: return "Unitech Japan Inc.";
|
||||
case 20: return "Acer Media Technology, Inc.";
|
||||
case 40: return "CIS Technology Inc.";
|
||||
case 50: return "Guann Yinn Co., Ltd.";
|
||||
case 60: return "Xcitec Inc.";
|
||||
case 00: return"Fornet International Pte Ltd.";
|
||||
case 10: return"Unitech Japan Inc.";
|
||||
case 20: return"Acer Media Technology, Inc.";
|
||||
case 40: return"CIS Technology Inc.";
|
||||
case 50: return"Guann Yinn Co., Ltd.";
|
||||
case 60: return"Xcitec Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 46:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Taiyo Yuden Company Ltd.";
|
||||
case 10: return "Hong Kong Digital Technology Co., Ltd.";
|
||||
case 20: return "Multi Media Masters & Machinary SA";
|
||||
case 30: return "Computer Support Italy s.r.l.";
|
||||
case 40: return "FUJI Photo Film Co., Ltd.";
|
||||
case 50: return "Auvistar Industry Co., Ltd.";
|
||||
case 60: return "CMC Magnetics Corporation";
|
||||
case 00: return"Taiyo Yuden Company Ltd.";
|
||||
case 10: return"Hong Kong Digital Technology Co., Ltd.";
|
||||
case 20: return"Multi Media Masters & Machinary SA";
|
||||
case 30: return"Computer Support Italy s.r.l.";
|
||||
case 40: return"FUJI Photo Film Co., Ltd.";
|
||||
case 50: return"Auvistar Industry Co., Ltd.";
|
||||
case 60: return"CMC Magnetics Corporation";
|
||||
}
|
||||
|
||||
break;
|
||||
case 47:
|
||||
switch(frm)
|
||||
{
|
||||
case 10: return "Hitachi Maxell, Ltd.";
|
||||
case 20: return "Princo Corporation";
|
||||
case 40: return "POSTECH Corporation";
|
||||
case 50: return "Ritek Co.";
|
||||
case 60: return "Prodisc Technology Inc.";
|
||||
case 10: return"Hitachi Maxell, Ltd.";
|
||||
case 20: return"Princo Corporation";
|
||||
case 40: return"POSTECH Corporation";
|
||||
case 50: return"Ritek Co.";
|
||||
case 60: return"Prodisc Technology Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 48:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "Ricoh Company Ltd.";
|
||||
case 10: return "Kodak Japan Ltd.";
|
||||
case 20: return "Plasmon Data systems Ltd.";
|
||||
case 30: return "Pioneer Video Corporation";
|
||||
case 40: return "Digital Storage Technology Co., Ltd.";
|
||||
case 50: return "Mitsui Chemicals, Inc.";
|
||||
case 60: return "Lead Data Inc.";
|
||||
case 00: return"Ricoh Company Ltd.";
|
||||
case 10: return"Kodak Japan Ltd.";
|
||||
case 20: return"Plasmon Data systems Ltd.";
|
||||
case 30: return"Pioneer Video Corporation";
|
||||
case 40: return"Digital Storage Technology Co., Ltd.";
|
||||
case 50: return"Mitsui Chemicals, Inc.";
|
||||
case 60: return"Lead Data Inc.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 49:
|
||||
switch(frm)
|
||||
{
|
||||
case 00: return "TDK Corporation";
|
||||
case 10: return "Gigastore Corporation";
|
||||
case 20: return "King Pro Mediatek Inc.";
|
||||
case 30: return "Opti.Me.S. S.p.A.";
|
||||
case 40: return "Victor Company of Japan, Ltd.";
|
||||
case 60: return "Matsushita Electric Industrial Co., Ltd.";
|
||||
case 00: return"TDK Corporation";
|
||||
case 10: return"Gigastore Corporation";
|
||||
case 20: return"King Pro Mediatek Inc.";
|
||||
case 30: return"Opti.Me.S. S.p.A.";
|
||||
case 40: return"Victor Company of Japan, Ltd.";
|
||||
case 60: return"Matsushita Electric Industrial Co., Ltd.";
|
||||
}
|
||||
|
||||
break;
|
||||
case 50:
|
||||
switch(frm)
|
||||
{
|
||||
case 10: return "Vanguard Disc Inc.";
|
||||
case 20: return "Mitsubishi Chemical Corporation";
|
||||
case 30: return "CDA Datenträger Albrechts GmbH";
|
||||
case 10: return"Vanguard Disc Inc.";
|
||||
case 20: return"Mitsubishi Chemical Corporation";
|
||||
case 30: return"CDA Datenträger Albrechts GmbH";
|
||||
}
|
||||
|
||||
break;
|
||||
case 51:
|
||||
switch(frm)
|
||||
{
|
||||
case 10: return "Grand Advance Technology Ltd.";
|
||||
case 20: return "Infodisc Technology Co. Ltd.";
|
||||
case 50: return "Hile Optical Disc Technology Corp.";
|
||||
case 10: return"Grand Advance Technology Ltd.";
|
||||
case 20: return"Infodisc Technology Co. Ltd.";
|
||||
case 50: return"Hile Optical Disc Technology Corp.";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
return"";
|
||||
}
|
||||
|
||||
public struct CDATIP
|
||||
{
|
||||
/// <summary>Bytes 1 to 0 Total size of returned session information minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4, bits 7 to 4 Indicative target writing power</summary>
|
||||
public byte ITWP;
|
||||
/// <summary>Byte 4, bit 3 Set if DDCD</summary>
|
||||
public bool DDCD;
|
||||
/// <summary>Byte 4, bits 2 to 0 Reference speed</summary>
|
||||
public byte ReferenceSpeed;
|
||||
/// <summary>Byte 5, bit 7 Always unset</summary>
|
||||
public bool AlwaysZero;
|
||||
/// <summary>Byte 5, bit 6 Unrestricted media</summary>
|
||||
public bool URU;
|
||||
/// <summary>Byte 5, bits 5 to 0 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 6, bit 7 Always set</summary>
|
||||
public bool AlwaysOne;
|
||||
/// <summary>Byte 6, bit 6 Set if rewritable (CD-RW or DDCD-RW)</summary>
|
||||
public bool DiscType;
|
||||
/// <summary>Byte 6, bits 5 to 3 Disc subtype</summary>
|
||||
public byte DiscSubType;
|
||||
/// <summary>Byte 6, bit 2 A1 values are valid</summary>
|
||||
public bool A1Valid;
|
||||
/// <summary>Byte 6, bit 1 A2 values are valid</summary>
|
||||
public bool A2Valid;
|
||||
/// <summary>Byte 6, bit 0 A3 values are valid</summary>
|
||||
public bool A3Valid;
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>Byte 8 ATIP Start time of Lead-In (Minute)</summary>
|
||||
public byte LeadInStartMin;
|
||||
/// <summary>Byte 9 ATIP Start time of Lead-In (Second)</summary>
|
||||
public byte LeadInStartSec;
|
||||
/// <summary>Byte 10 ATIP Start time of Lead-In (Frame)</summary>
|
||||
public byte LeadInStartFrame;
|
||||
/// <summary>Byte 11 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>Byte 12 ATIP Last possible start time of Lead-Out (Minute)</summary>
|
||||
public byte LeadOutStartMin;
|
||||
/// <summary>Byte 13 ATIP Last possible start time of Lead-Out (Second)</summary>
|
||||
public byte LeadOutStartSec;
|
||||
/// <summary>Byte 14 ATIP Last possible start time of Lead-Out (Frame)</summary>
|
||||
public byte LeadOutStartFrame;
|
||||
/// <summary>Byte 15 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>Bytes 16 to 18 A1 values</summary>
|
||||
public byte[] A1Values;
|
||||
/// <summary>Byte 19 Reserved</summary>
|
||||
public byte Reserved7;
|
||||
/// <summary>Bytes 20 to 22 A2 values</summary>
|
||||
public byte[] A2Values;
|
||||
/// <summary>Byte 23 Reserved</summary>
|
||||
public byte Reserved8;
|
||||
/// <summary>Bytes 24 to 26 A3 values</summary>
|
||||
public byte[] A3Values;
|
||||
/// <summary>Byte 27 Reserved</summary>
|
||||
public byte Reserved9;
|
||||
/// <summary>Bytes 28 to 30 S4 values</summary>
|
||||
public byte[] S4Values;
|
||||
/// <summary>Byte 31 Reserved</summary>
|
||||
public byte Reserved10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,178 +38,57 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class CDTextOnLeadIn
|
||||
{
|
||||
public enum PackTypeIndicator : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Title of the track (or album if track == 0)
|
||||
/// </summary>
|
||||
Title = 0x80,
|
||||
/// <summary>
|
||||
/// Performer
|
||||
/// </summary>
|
||||
Performer = 0x81,
|
||||
/// <summary>
|
||||
/// Songwriter
|
||||
/// </summary>
|
||||
Songwriter = 0x82,
|
||||
/// <summary>
|
||||
/// Composer
|
||||
/// </summary>
|
||||
Composer = 0x83,
|
||||
/// <summary>
|
||||
/// Arranger
|
||||
/// </summary>
|
||||
Arranger = 0x84,
|
||||
/// <summary>
|
||||
/// Message from the content provider or artist
|
||||
/// </summary>
|
||||
Message = 0x85,
|
||||
/// <summary>
|
||||
/// Disc identification information
|
||||
/// </summary>
|
||||
DiscIdentification = 0x86,
|
||||
/// <summary>
|
||||
/// Genre identification
|
||||
/// </summary>
|
||||
GenreIdentification = 0x87,
|
||||
/// <summary>
|
||||
/// Table of content information
|
||||
/// </summary>
|
||||
TOCInformation = 0x88,
|
||||
/// <summary>
|
||||
/// Second table of content information
|
||||
/// </summary>
|
||||
SecondTOCInformation = 0x89,
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
Reserved1 = 0x8A,
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
Reserved2 = 0x8B,
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
Reserved3 = 0x8C,
|
||||
/// <summary>
|
||||
/// Reserved for content provider only
|
||||
/// </summary>
|
||||
ReservedForContentProvider = 0x8D,
|
||||
/// <summary>
|
||||
/// UPC of album or ISRC of track
|
||||
/// </summary>
|
||||
UPCorISRC = 0x8E,
|
||||
/// <summary>
|
||||
/// Size information of the block
|
||||
/// </summary>
|
||||
/// <summary>Title of the track (or album if track == 0)</summary>
|
||||
Title = 0x80, /// <summary>Performer</summary>
|
||||
Performer = 0x81, /// <summary>Songwriter</summary>
|
||||
Songwriter = 0x82, /// <summary>Composer</summary>
|
||||
Composer = 0x83, /// <summary>Arranger</summary>
|
||||
Arranger = 0x84, /// <summary>Message from the content provider or artist</summary>
|
||||
Message = 0x85, /// <summary>Disc identification information</summary>
|
||||
DiscIdentification = 0x86, /// <summary>Genre identification</summary>
|
||||
GenreIdentification = 0x87, /// <summary>Table of content information</summary>
|
||||
TOCInformation = 0x88, /// <summary>Second table of content information</summary>
|
||||
SecondTOCInformation = 0x89, /// <summary>Reserved</summary>
|
||||
Reserved1 = 0x8A, /// <summary>Reserved</summary>
|
||||
Reserved2 = 0x8B, /// <summary>Reserved</summary>
|
||||
Reserved3 = 0x8C, /// <summary>Reserved for content provider only</summary>
|
||||
ReservedForContentProvider = 0x8D, /// <summary>UPC of album or ISRC of track</summary>
|
||||
UPCorISRC = 0x8E, /// <summary>Size information of the block</summary>
|
||||
BlockSizeInformation = 0x8F
|
||||
}
|
||||
|
||||
public struct CDText
|
||||
{
|
||||
/// <summary>
|
||||
/// Total size of returned CD-Text information minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// CD-Text data packs
|
||||
/// </summary>
|
||||
public CDTextPack[] DataPacks;
|
||||
}
|
||||
|
||||
public struct CDTextPack
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// Pack ID1 (Pack Type)
|
||||
/// </summary>
|
||||
public byte HeaderID1;
|
||||
/// <summary>
|
||||
/// Byte 1
|
||||
/// Pack ID2 (Track number)
|
||||
/// </summary>
|
||||
public byte HeaderID2;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Pack ID3
|
||||
/// </summary>
|
||||
public byte HeaderID3;
|
||||
/// <summary>
|
||||
/// Byte 3, bit 7
|
||||
/// Double Byte Character Code
|
||||
/// </summary>
|
||||
public bool DBCC;
|
||||
/// <summary>
|
||||
/// Byte 3, bits 6 to 4
|
||||
/// Block number
|
||||
/// </summary>
|
||||
public byte BlockNumber;
|
||||
/// <summary>
|
||||
/// Byte 3, bits 3 to 0
|
||||
/// Character position
|
||||
/// </summary>
|
||||
public byte CharacterPosition;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 15
|
||||
/// Text data
|
||||
/// </summary>
|
||||
public byte[] TextDataField;
|
||||
/// <summary>
|
||||
/// Bytes 16 to 17
|
||||
/// CRC16
|
||||
/// </summary>
|
||||
public ushort CRC;
|
||||
}
|
||||
|
||||
public static CDText? Decode(byte[] CDTextResponse)
|
||||
{
|
||||
if(CDTextResponse == null) return null;
|
||||
if(CDTextResponse == null)
|
||||
return null;
|
||||
|
||||
CDText decoded = new CDText
|
||||
var decoded = new CDText
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0),
|
||||
Reserved1 = CDTextResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0), Reserved1 = CDTextResponse[2],
|
||||
Reserved2 = CDTextResponse[3]
|
||||
};
|
||||
|
||||
decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18];
|
||||
|
||||
if(decoded.DataLength == 2) return null;
|
||||
if(decoded.DataLength == 2)
|
||||
return null;
|
||||
|
||||
if(decoded.DataLength + 2 != CDTextResponse.Length)
|
||||
{
|
||||
DicConsole.DebugWriteLine("CD-TEXT decoder",
|
||||
"Expected CD-TEXT size ({0} bytes) is not received size ({1} bytes), not decoding",
|
||||
decoded.DataLength + 2, CDTextResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -231,23 +110,27 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDText? CDTextResponse)
|
||||
{
|
||||
if(CDTextResponse == null) return null;
|
||||
if(CDTextResponse == null)
|
||||
return null;
|
||||
|
||||
CDText response = CDTextResponse.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CDText response = CDTextResponse.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
|
||||
foreach(CDTextPack descriptor in response.DataPacks)
|
||||
if((descriptor.HeaderID1 & 0x80) != 0x80)
|
||||
{
|
||||
// Ignore NOPs
|
||||
if((descriptor.HeaderID1 & 0x80) != 0)
|
||||
sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1).
|
||||
AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -256,71 +139,98 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 0x80:
|
||||
{
|
||||
sb.Append("CD-Text pack contains title for ");
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x81:
|
||||
{
|
||||
sb.Append("CD-Text pack contains performer for ");
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x82:
|
||||
{
|
||||
sb.Append("CD-Text pack contains songwriter for ");
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x83:
|
||||
{
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x84:
|
||||
{
|
||||
sb.Append("CD-Text pack contains arranger for ");
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x85:
|
||||
{
|
||||
sb.Append("CD-Text pack contains content provider's message for ");
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("album");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x86:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains disc identification information");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x87:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains genre identification information");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x88:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains table of contents information");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x89:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains second table of contents information");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -329,25 +239,31 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 0x8C:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains reserved data");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8D:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains data reserved for content provider only");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8E:
|
||||
{
|
||||
if(descriptor.HeaderID2 == 0x00) sb.AppendLine("CD-Text pack contains UPC");
|
||||
else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
if(descriptor.HeaderID2 == 0x00)
|
||||
sb.AppendLine("CD-Text pack contains UPC");
|
||||
else
|
||||
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x8F:
|
||||
{
|
||||
sb.AppendLine("CD-Text pack contains size block information");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -364,20 +280,25 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 0x87:
|
||||
case 0x8E:
|
||||
{
|
||||
if(descriptor.DBCC) sb.AppendLine("Double Byte Character Code is used");
|
||||
if(descriptor.DBCC)
|
||||
sb.AppendLine("Double Byte Character Code is used");
|
||||
|
||||
sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine();
|
||||
sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine();
|
||||
|
||||
sb.AppendFormat("Text field: \"{0}\"",
|
||||
StringHandlers.CToString(descriptor.TextDataField,
|
||||
Encoding.GetEncoding("iso-8859-1"))).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
sb.AppendFormat("Binary contents: {0}",
|
||||
PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28))
|
||||
.AppendLine();
|
||||
PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -391,7 +312,40 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDTextResponse)
|
||||
{
|
||||
CDText? decoded = Decode(CDTextResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
public struct CDText
|
||||
{
|
||||
/// <summary>Total size of returned CD-Text information minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>CD-Text data packs</summary>
|
||||
public CDTextPack[] DataPacks;
|
||||
}
|
||||
|
||||
public struct CDTextPack
|
||||
{
|
||||
/// <summary>Byte 0 Pack ID1 (Pack Type)</summary>
|
||||
public byte HeaderID1;
|
||||
/// <summary>Byte 1 Pack ID2 (Track number)</summary>
|
||||
public byte HeaderID2;
|
||||
/// <summary>Byte 2 Pack ID3</summary>
|
||||
public byte HeaderID3;
|
||||
/// <summary>Byte 3, bit 7 Double Byte Character Code</summary>
|
||||
public bool DBCC;
|
||||
/// <summary>Byte 3, bits 6 to 4 Block number</summary>
|
||||
public byte BlockNumber;
|
||||
/// <summary>Byte 3, bits 3 to 0 Character position</summary>
|
||||
public byte CharacterPosition;
|
||||
/// <summary>Bytes 4 to 15 Text data</summary>
|
||||
public byte[] TextDataField;
|
||||
/// <summary>Bytes 16 to 17 CRC16</summary>
|
||||
public ushort CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
CD/Enums.cs
68
CD/Enums.cs
@@ -37,65 +37,25 @@ namespace DiscImageChef.Decoders.CD
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum TocAdr : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Q Sub-channel mode information not supplied
|
||||
/// </summary>
|
||||
NoInformation = 0x00,
|
||||
/// <summary>
|
||||
/// Q Sub-channel encodes current position data
|
||||
/// </summary>
|
||||
CurrentPosition = 0x01,
|
||||
/// <summary>
|
||||
/// Q Sub-channel encodes the media catalog number
|
||||
/// </summary>
|
||||
MediaCatalogNumber = 0x02,
|
||||
/// <summary>
|
||||
/// Q Sub-channel encodes the ISRC
|
||||
/// </summary>
|
||||
ISRC = 0x03,
|
||||
/// <summary>
|
||||
/// Q Sub-channel encodes the start of an audio/data track (if found in TOC)
|
||||
/// </summary>
|
||||
TrackPointer = 0x01,
|
||||
/// <summary>
|
||||
/// Q Sub-channel encodes the start of a video track (if found in TOC) for CD-V
|
||||
/// </summary>
|
||||
/// <summary>Q Sub-channel mode information not supplied</summary>
|
||||
NoInformation = 0x00, /// <summary>Q Sub-channel encodes current position data</summary>
|
||||
CurrentPosition = 0x01, /// <summary>Q Sub-channel encodes the media catalog number</summary>
|
||||
MediaCatalogNumber = 0x02, /// <summary>Q Sub-channel encodes the ISRC</summary>
|
||||
ISRC = 0x03, /// <summary>Q Sub-channel encodes the start of an audio/data track (if found in TOC)</summary>
|
||||
TrackPointer = 0x01, /// <summary>Q Sub-channel encodes the start of a video track (if found in TOC) for CD-V</summary>
|
||||
VideoTrackPointer = 0x04
|
||||
}
|
||||
|
||||
public enum TocControl : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Stereo audio, no pre-emphasis
|
||||
/// </summary>
|
||||
TwoChanNoPreEmph = 0x00,
|
||||
/// <summary>
|
||||
/// Stereo audio with pre-emphasis
|
||||
/// </summary>
|
||||
TwoChanPreEmph = 0x01,
|
||||
/// <summary>
|
||||
/// If mask applied, track can be copied
|
||||
/// </summary>
|
||||
CopyPermissionMask = 0x02,
|
||||
/// <summary>
|
||||
/// Data track, recorded uninterrumpted
|
||||
/// </summary>
|
||||
DataTrack = 0x04,
|
||||
/// <summary>
|
||||
/// Data track, recorded incrementally
|
||||
/// </summary>
|
||||
DataTrackIncremental = 0x05,
|
||||
/// <summary>
|
||||
/// Quadraphonic audio, no pre-emphasis
|
||||
/// </summary>
|
||||
FourChanNoPreEmph = 0x08,
|
||||
/// <summary>
|
||||
/// Quadraphonic audio with pre-emphasis
|
||||
/// </summary>
|
||||
FourChanPreEmph = 0x09,
|
||||
/// <summary>
|
||||
/// Reserved mask
|
||||
/// </summary>
|
||||
/// <summary>Stereo audio, no pre-emphasis</summary>
|
||||
TwoChanNoPreEmph = 0x00, /// <summary>Stereo audio with pre-emphasis</summary>
|
||||
TwoChanPreEmph = 0x01, /// <summary>If mask applied, track can be copied</summary>
|
||||
CopyPermissionMask = 0x02, /// <summary>Data track, recorded uninterrumpted</summary>
|
||||
DataTrack = 0x04, /// <summary>Data track, recorded incrementally</summary>
|
||||
DataTrackIncremental = 0x05, /// <summary>Quadraphonic audio, no pre-emphasis</summary>
|
||||
FourChanNoPreEmph = 0x08, /// <summary>Quadraphonic audio with pre-emphasis</summary>
|
||||
FourChanPreEmph = 0x09, /// <summary>Reserved mask</summary>
|
||||
ReservedMask = 0x0C
|
||||
}
|
||||
}
|
||||
301
CD/FullTOC.cs
301
CD/FullTOC.cs
@@ -37,25 +37,13 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ISO/IEC 61104: Compact disc video system - 12 cm CD-V
|
||||
/// ISO/IEC 60908: Audio recording - Compact disc digital audio system
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ISO/IEC 61104: Compact
|
||||
/// disc video system - 12 cm CD-V ISO/IEC 60908: Audio recording - Compact disc digital audio system
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class FullTOC
|
||||
{
|
||||
const string StereoNoPre = "Stereo audio track with no pre-emphasis";
|
||||
@@ -65,98 +53,15 @@ namespace DiscImageChef.Decoders.CD
|
||||
const string DataUnintrp = "Data track, recorded uninterrupted";
|
||||
const string DataIncrtly = "Data track, recorded incrementally";
|
||||
|
||||
public struct CDFullTOC
|
||||
{
|
||||
/// <summary>
|
||||
/// Total size of returned session information minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// First complete session number in hex
|
||||
/// </summary>
|
||||
public byte FirstCompleteSession;
|
||||
/// <summary>
|
||||
/// Last complete session number in hex
|
||||
/// </summary>
|
||||
public byte LastCompleteSession;
|
||||
/// <summary>
|
||||
/// Track descriptors
|
||||
/// </summary>
|
||||
public TrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct TrackDataDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// Session number in hex
|
||||
/// </summary>
|
||||
public byte SessionNumber;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 7 to 4
|
||||
/// Type of information in Q subchannel of block where this TOC entry was found
|
||||
/// </summary>
|
||||
public byte ADR;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 3 to 0
|
||||
/// Track attributes
|
||||
/// </summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// </summary>
|
||||
public byte TNO;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// </summary>
|
||||
public byte POINT;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// </summary>
|
||||
public byte Min;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// </summary>
|
||||
public byte Sec;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// </summary>
|
||||
public byte Frame;
|
||||
/// <summary>
|
||||
/// Byte 7, CD only
|
||||
/// </summary>
|
||||
public byte Zero;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 7 to 4, DDCD only
|
||||
/// </summary>
|
||||
public byte HOUR;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 3 to 0, DDCD only
|
||||
/// </summary>
|
||||
public byte PHOUR;
|
||||
/// <summary>
|
||||
/// Byte 8
|
||||
/// </summary>
|
||||
public byte PMIN;
|
||||
/// <summary>
|
||||
/// Byte 9
|
||||
/// </summary>
|
||||
public byte PSEC;
|
||||
/// <summary>
|
||||
/// Byte 10
|
||||
/// </summary>
|
||||
public byte PFRAME;
|
||||
}
|
||||
|
||||
public static CDFullTOC? Decode(byte[] CDFullTOCResponse)
|
||||
{
|
||||
if(CDFullTOCResponse == null) return null;
|
||||
if(CDFullTOCResponse == null)
|
||||
return null;
|
||||
|
||||
CDFullTOC decoded = new CDFullTOC
|
||||
var decoded = new CDFullTOC
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDFullTOCResponse, 0),
|
||||
FirstCompleteSession = CDFullTOCResponse[2],
|
||||
LastCompleteSession = CDFullTOCResponse[3]
|
||||
FirstCompleteSession = CDFullTOCResponse[2], LastCompleteSession = CDFullTOCResponse[3]
|
||||
};
|
||||
|
||||
decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 11];
|
||||
@@ -166,6 +71,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
DicConsole.DebugWriteLine("CD full TOC decoder",
|
||||
"Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding",
|
||||
decoded.DataLength + 2, CDFullTOCResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -192,16 +98,18 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDFullTOC? CDFullTOCResponse)
|
||||
{
|
||||
if(CDFullTOCResponse == null) return null;
|
||||
if(CDFullTOCResponse == null)
|
||||
return null;
|
||||
|
||||
CDFullTOC response = CDFullTOCResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
int lastSession = 0;
|
||||
|
||||
sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine();
|
||||
sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine();
|
||||
|
||||
foreach(TrackDataDescriptor descriptor in response.TrackDescriptors)
|
||||
if((descriptor.CONTROL & 0x08) == 0x08 ||
|
||||
descriptor.ADR != 1 && descriptor.ADR != 5 && descriptor.ADR != 4 && descriptor.ADR != 6 ||
|
||||
@@ -240,31 +148,40 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 0xA0 when descriptor.ADR == 4:
|
||||
{
|
||||
sb.AppendFormat("First video track number: {0}", descriptor.PMIN).AppendLine();
|
||||
|
||||
switch(descriptor.PSEC)
|
||||
{
|
||||
case 0x10:
|
||||
sb.AppendLine("CD-V single in NTSC format with digital stereo sound");
|
||||
|
||||
break;
|
||||
case 0x11:
|
||||
sb.AppendLine("CD-V single in NTSC format with digital bilingual sound");
|
||||
|
||||
break;
|
||||
case 0x12:
|
||||
sb.AppendLine("CD-V disc in NTSC format with digital stereo sound");
|
||||
|
||||
break;
|
||||
case 0x13:
|
||||
sb.AppendLine("CD-V disc in NTSC format with digital bilingual sound");
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine("CD-V single in PAL format with digital stereo sound");
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
sb.AppendLine("CD-V single in PAL format with digital bilingual sound");
|
||||
|
||||
break;
|
||||
case 0x22:
|
||||
sb.AppendLine("CD-V disc in PAL format with digital stereo sound");
|
||||
|
||||
break;
|
||||
case 0x23:
|
||||
sb.AppendLine("CD-V disc in PAL format with digital bilingual sound");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -274,63 +191,80 @@ namespace DiscImageChef.Decoders.CD
|
||||
case 0xA0 when descriptor.ADR == 1:
|
||||
{
|
||||
sb.AppendFormat("First track number: {0} (", descriptor.PMIN);
|
||||
|
||||
switch((TocControl)(descriptor.CONTROL & 0x0D))
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.Append(StereoNoPre);
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.Append(StereoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.Append(QuadNoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.Append(QuadPreEmph);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.Append(DataUnintrp);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.Append(DataIncrtly);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendLine(")");
|
||||
sb.AppendFormat("Disc type: {0}", descriptor.PSEC).AppendLine();
|
||||
|
||||
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA1 when descriptor.ADR == 4:
|
||||
sb.AppendFormat("Last video track number: {0}", descriptor.PMIN).AppendLine();
|
||||
|
||||
break;
|
||||
case 0xA1 when descriptor.ADR == 1:
|
||||
{
|
||||
sb.AppendFormat("Last track number: {0} (", descriptor.PMIN);
|
||||
|
||||
switch((TocControl)(descriptor.CONTROL & 0x0D))
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.Append(StereoNoPre);
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.Append(StereoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.Append(QuadNoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.Append(QuadPreEmph);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.Append(DataUnintrp);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.Append(DataIncrtly);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendLine(")");
|
||||
|
||||
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
|
||||
break;
|
||||
}
|
||||
@@ -343,8 +277,9 @@ namespace DiscImageChef.Decoders.CD
|
||||
descriptor.PHOUR).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Lead-out start position: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
|
||||
.AppendLine();
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).
|
||||
AppendLine();
|
||||
|
||||
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
|
||||
|
||||
switch((TocControl)(descriptor.CONTROL & 0x0D))
|
||||
@@ -354,10 +289,12 @@ namespace DiscImageChef.Decoders.CD
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.AppendLine("Lead-out is audio type");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.AppendLine("Lead-out is data type");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -366,21 +303,24 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
case 0xF0:
|
||||
{
|
||||
sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN);
|
||||
sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC);
|
||||
sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN);
|
||||
sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC);
|
||||
sb.AppendFormat("Moment of inertia: 0x{0:X2}", descriptor.PFRAME);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min,
|
||||
descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Absolute time: {0:D2}:{1:D2}:{2:D2}", descriptor.Min,
|
||||
descriptor.Sec, descriptor.Frame).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x63)
|
||||
if(descriptor.POINT >= 0x01 &&
|
||||
descriptor.POINT <= 0x63)
|
||||
if(descriptor.ADR == 4)
|
||||
sb.AppendFormat("Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
|
||||
@@ -391,7 +331,8 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
if((TocControl)(descriptor.CONTROL & 0x0D) == TocControl.DataTrack ||
|
||||
(TocControl)(descriptor.CONTROL & 0x0D) ==
|
||||
TocControl.DataTrackIncremental) type = "Data";
|
||||
TocControl.DataTrackIncremental)
|
||||
type = "Data";
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (",
|
||||
@@ -406,21 +347,27 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.Append(StereoNoPre);
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.Append(StereoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.Append(QuadNoPreEm);
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.Append(QuadPreEmph);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.Append(DataUnintrp);
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.Append(DataIncrtly);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -457,24 +404,26 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
if(descriptor.PHOUR > 0)
|
||||
{
|
||||
sb
|
||||
.AppendFormat("Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.Min, descriptor.Sec, descriptor.Frame,
|
||||
descriptor.HOUR).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
|
||||
sb.
|
||||
AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
|
||||
descriptor.PHOUR).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb
|
||||
.AppendFormat("Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
|
||||
.AppendLine();
|
||||
|
||||
sb.
|
||||
AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).
|
||||
AppendLine();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -482,9 +431,11 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
case 0xB1:
|
||||
{
|
||||
sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("Number of skip track pointers: {0}", descriptor.PSEC).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -499,22 +450,25 @@ namespace DiscImageChef.Decoders.CD
|
||||
sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine();
|
||||
sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine();
|
||||
sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xC0:
|
||||
{
|
||||
sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine();
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb
|
||||
.AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
|
||||
descriptor.PHOUR).AppendLine();
|
||||
else
|
||||
sb
|
||||
.AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
|
||||
.AppendLine();
|
||||
sb.
|
||||
AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -528,6 +482,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
|
||||
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
|
||||
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -535,23 +490,25 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
if(descriptor.PHOUR > 0)
|
||||
{
|
||||
sb
|
||||
.AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
|
||||
descriptor.PHOUR).AppendLine();
|
||||
sb
|
||||
.AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
|
||||
sb.
|
||||
AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.Min, descriptor.Sec, descriptor.Frame,
|
||||
descriptor.HOUR).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
sb
|
||||
.AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
|
||||
.AppendLine();
|
||||
sb
|
||||
.AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).
|
||||
AppendLine();
|
||||
|
||||
sb.
|
||||
AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine();
|
||||
}
|
||||
|
||||
@@ -560,14 +517,16 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
default:
|
||||
{
|
||||
if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x40)
|
||||
if(descriptor.POINT >= 0x01 &&
|
||||
descriptor.POINT <= 0x40)
|
||||
{
|
||||
sb
|
||||
.AppendFormat("Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
|
||||
.AppendLine();
|
||||
sb
|
||||
.AppendFormat("Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}",
|
||||
sb.
|
||||
AppendFormat("Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).
|
||||
AppendLine();
|
||||
|
||||
sb.
|
||||
AppendFormat("Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}",
|
||||
descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine();
|
||||
}
|
||||
else
|
||||
@@ -597,6 +556,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame);
|
||||
sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -608,7 +568,52 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDFullTOCResponse)
|
||||
{
|
||||
CDFullTOC? decoded = Decode(CDFullTOCResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
public struct CDFullTOC
|
||||
{
|
||||
/// <summary>Total size of returned session information minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>First complete session number in hex</summary>
|
||||
public byte FirstCompleteSession;
|
||||
/// <summary>Last complete session number in hex</summary>
|
||||
public byte LastCompleteSession;
|
||||
/// <summary>Track descriptors</summary>
|
||||
public TrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct TrackDataDescriptor
|
||||
{
|
||||
/// <summary>Byte 0 Session number in hex</summary>
|
||||
public byte SessionNumber;
|
||||
/// <summary>Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found</summary>
|
||||
public byte ADR;
|
||||
/// <summary>Byte 1, bits 3 to 0 Track attributes</summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>Byte 2</summary>
|
||||
public byte TNO;
|
||||
/// <summary>Byte 3</summary>
|
||||
public byte POINT;
|
||||
/// <summary>Byte 4</summary>
|
||||
public byte Min;
|
||||
/// <summary>Byte 5</summary>
|
||||
public byte Sec;
|
||||
/// <summary>Byte 6</summary>
|
||||
public byte Frame;
|
||||
/// <summary>Byte 7, CD only</summary>
|
||||
public byte Zero;
|
||||
/// <summary>Byte 7, bits 7 to 4, DDCD only</summary>
|
||||
public byte HOUR;
|
||||
/// <summary>Byte 7, bits 3 to 0, DDCD only</summary>
|
||||
public byte PHOUR;
|
||||
/// <summary>Byte 8</summary>
|
||||
public byte PMIN;
|
||||
/// <summary>Byte 9</summary>
|
||||
public byte PSEC;
|
||||
/// <summary>Byte 10</summary>
|
||||
public byte PFRAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
254
CD/PMA.cs
254
CD/PMA.cs
@@ -37,112 +37,22 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class PMA
|
||||
{
|
||||
public struct CDPMA
|
||||
{
|
||||
/// <summary>
|
||||
/// Total size of returned session information minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Track descriptors
|
||||
/// </summary>
|
||||
public CDPMADescriptors[] PMADescriptors;
|
||||
}
|
||||
|
||||
public struct CDPMADescriptors
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 7 to 4
|
||||
/// Type of information in Q subchannel of block where this TOC entry was found
|
||||
/// </summary>
|
||||
public byte ADR;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 3 to 0
|
||||
/// Track attributes
|
||||
/// </summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// </summary>
|
||||
public byte TNO;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// </summary>
|
||||
public byte POINT;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// </summary>
|
||||
public byte Min;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// </summary>
|
||||
public byte Sec;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// </summary>
|
||||
public byte Frame;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 7 to 4
|
||||
/// </summary>
|
||||
public byte HOUR;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 3 to 0
|
||||
/// </summary>
|
||||
public byte PHOUR;
|
||||
/// <summary>
|
||||
/// Byte 8
|
||||
/// </summary>
|
||||
public byte PMIN;
|
||||
/// <summary>
|
||||
/// Byte 9
|
||||
/// </summary>
|
||||
public byte PSEC;
|
||||
/// <summary>
|
||||
/// Byte 10
|
||||
/// </summary>
|
||||
public byte PFRAME;
|
||||
}
|
||||
|
||||
public static CDPMA? Decode(byte[] CDPMAResponse)
|
||||
{
|
||||
if(CDPMAResponse == null) return null;
|
||||
if(CDPMAResponse == null)
|
||||
return null;
|
||||
|
||||
CDPMA decoded = new CDPMA
|
||||
var decoded = new CDPMA
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0),
|
||||
Reserved1 = CDPMAResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0), Reserved1 = CDPMAResponse[2],
|
||||
Reserved2 = CDPMAResponse[3]
|
||||
};
|
||||
|
||||
@@ -153,6 +63,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
DicConsole.DebugWriteLine("CD PMA decoder",
|
||||
"Expected CDPMA size ({0} bytes) is not received size ({1} bytes), not decoding",
|
||||
decoded.DataLength + 2, CDPMAResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -178,22 +89,27 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDPMA? CDPMAResponse)
|
||||
{
|
||||
if(CDPMAResponse == null) return null;
|
||||
if(CDPMAResponse == null)
|
||||
return null;
|
||||
|
||||
CDPMA response = CDPMAResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
|
||||
foreach(CDPMADescriptors descriptor in response.PMADescriptors)
|
||||
{
|
||||
#if DEBUG
|
||||
if(descriptor.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(descriptor.Reserved != 0)
|
||||
sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine();
|
||||
#endif
|
||||
|
||||
switch(descriptor.ADR)
|
||||
{
|
||||
@@ -201,25 +117,32 @@ namespace DiscImageChef.Decoders.CD
|
||||
if(descriptor.POINT > 0)
|
||||
{
|
||||
sb.AppendFormat("Track {0}", descriptor.POINT);
|
||||
|
||||
switch((TocControl)(descriptor.CONTROL & 0x0D))
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.Append(" (Stereo audio track with no pre-emphasis)");
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.Append(" (Stereo audio track with 50/15 μs pre-emphasis)");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.Append(" (Quadraphonic audio track with no pre-emphasis)");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.Append(" (Quadraphonic audio track with 50/15 μs pre-emphasis)");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.Append(" (Data track, recorded uninterrupted)");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.Append(" (Data track, recorded incrementally)");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -229,6 +152,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
else
|
||||
sb.AppendFormat(" starts at {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC,
|
||||
descriptor.PFRAME);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat(" and ends at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec,
|
||||
descriptor.Frame, descriptor.HOUR);
|
||||
@@ -238,60 +162,100 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
else goto default;
|
||||
else
|
||||
goto default;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame);
|
||||
sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine();
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendFormat("Skip track assignment {0} says that tracks ", descriptor.POINT);
|
||||
if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min);
|
||||
if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec);
|
||||
if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame);
|
||||
if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN);
|
||||
if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC);
|
||||
if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME);
|
||||
|
||||
if(descriptor.Min > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Min);
|
||||
|
||||
if(descriptor.Sec > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Sec);
|
||||
|
||||
if(descriptor.Frame > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Frame);
|
||||
|
||||
if(descriptor.PMIN > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PMIN);
|
||||
|
||||
if(descriptor.PSEC > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PSEC);
|
||||
|
||||
if(descriptor.PFRAME > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PFRAME);
|
||||
|
||||
sb.AppendLine("should be skipped");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendFormat("Unskip track assignment {0} says that tracks ", descriptor.POINT);
|
||||
if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min);
|
||||
if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec);
|
||||
if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame);
|
||||
if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN);
|
||||
if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC);
|
||||
if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME);
|
||||
|
||||
if(descriptor.Min > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Min);
|
||||
|
||||
if(descriptor.Sec > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Sec);
|
||||
|
||||
if(descriptor.Frame > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.Frame);
|
||||
|
||||
if(descriptor.PMIN > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PMIN);
|
||||
|
||||
if(descriptor.PSEC > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PSEC);
|
||||
|
||||
if(descriptor.PFRAME > 0)
|
||||
sb.AppendFormat("{0} ", descriptor.PFRAME);
|
||||
|
||||
sb.AppendLine("should not be skipped");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendFormat("Skip time interval assignment {0} says that from ", descriptor.POINT);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
|
||||
descriptor.PFRAME, descriptor.PHOUR);
|
||||
else
|
||||
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
|
||||
descriptor.PFRAME);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec,
|
||||
descriptor.Frame, descriptor.HOUR);
|
||||
else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame);
|
||||
else
|
||||
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame);
|
||||
|
||||
sb.AppendLine("should be skipped");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendFormat("Unskip time interval assignment {0} says that from ", descriptor.POINT);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
|
||||
descriptor.PFRAME, descriptor.PHOUR);
|
||||
else
|
||||
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
|
||||
descriptor.PFRAME);
|
||||
|
||||
if(descriptor.PHOUR > 0)
|
||||
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec,
|
||||
descriptor.Frame, descriptor.HOUR);
|
||||
else sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame);
|
||||
else
|
||||
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame);
|
||||
|
||||
sb.AppendLine("should not be skipped");
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -307,6 +271,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
|
||||
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
|
||||
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -317,7 +282,50 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDPMAResponse)
|
||||
{
|
||||
CDPMA? decoded = Decode(CDPMAResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
public struct CDPMA
|
||||
{
|
||||
/// <summary>Total size of returned session information minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Track descriptors</summary>
|
||||
public CDPMADescriptors[] PMADescriptors;
|
||||
}
|
||||
|
||||
public struct CDPMADescriptors
|
||||
{
|
||||
/// <summary>Byte 0 Reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found</summary>
|
||||
public byte ADR;
|
||||
/// <summary>Byte 1, bits 3 to 0 Track attributes</summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>Byte 2</summary>
|
||||
public byte TNO;
|
||||
/// <summary>Byte 3</summary>
|
||||
public byte POINT;
|
||||
/// <summary>Byte 4</summary>
|
||||
public byte Min;
|
||||
/// <summary>Byte 5</summary>
|
||||
public byte Sec;
|
||||
/// <summary>Byte 6</summary>
|
||||
public byte Frame;
|
||||
/// <summary>Byte 7, bits 7 to 4</summary>
|
||||
public byte HOUR;
|
||||
/// <summary>Byte 7, bits 3 to 0</summary>
|
||||
public byte PHOUR;
|
||||
/// <summary>Byte 8</summary>
|
||||
public byte PMIN;
|
||||
/// <summary>Byte 9</summary>
|
||||
public byte PSEC;
|
||||
/// <summary>Byte 10</summary>
|
||||
public byte PFRAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
294
CD/Sector.cs
294
CD/Sector.cs
@@ -36,152 +36,143 @@ using System.Linq;
|
||||
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Sector
|
||||
{
|
||||
public static readonly byte[] ScrambleTable =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00,
|
||||
0x28, 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E,
|
||||
0x9E, 0x88, 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0,
|
||||
0x0E, 0xC8, 0x04, 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC,
|
||||
0x52, 0xD5, 0xFD, 0x9F, 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28,
|
||||
0x62, 0x9E, 0xA9, 0xA8, 0x7E, 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37,
|
||||
0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38, 0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56,
|
||||
0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B, 0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66,
|
||||
0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E, 0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4,
|
||||
0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0x7C, 0x69, 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7,
|
||||
0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84, 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6,
|
||||
0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42, 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27,
|
||||
0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4, 0x14, 0x47, 0x4F, 0x72, 0xB4,
|
||||
0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D, 0xC6, 0x91, 0x92, 0xEC,
|
||||
0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E, 0x81, 0xE0, 0x60,
|
||||
0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28, 0x60, 0x1E,
|
||||
0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0, 0x76,
|
||||
0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4,
|
||||
0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31,
|
||||
0xCD, 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81,
|
||||
0xCA, 0xE0, 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7,
|
||||
0x5F, 0x36, 0xB8, 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E,
|
||||
0xAE, 0xE4, 0x7C, 0x4B, 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98,
|
||||
0x37, 0x2A, 0x96, 0x9F, 0x2E, 0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC,
|
||||
0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7, 0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77,
|
||||
0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C, 0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33,
|
||||
0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC, 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89,
|
||||
0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48, 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF,
|
||||
0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD, 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01,
|
||||
0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85, 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56,
|
||||
0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7, 0x01, 0x9E, 0x80, 0x68, 0x60,
|
||||
0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8, 0x08, 0x4E, 0x86, 0xB4,
|
||||
0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32, 0xD6, 0x95, 0x9E,
|
||||
0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71, 0xC7, 0x64,
|
||||
0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9, 0xD6,
|
||||
0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F,
|
||||
0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2,
|
||||
0xE5, 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E,
|
||||
0xA8, 0x04, 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A,
|
||||
0xFD, 0xE3, 0x01, 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2,
|
||||
0x88, 0x49, 0xA6, 0xB6, 0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF,
|
||||
0x10, 0x4C, 0x0C, 0x35, 0xC5, 0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40,
|
||||
0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93, 0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2,
|
||||
0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE, 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57,
|
||||
0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD, 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88,
|
||||
0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84, 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C,
|
||||
0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E, 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD,
|
||||
0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2, 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2,
|
||||
0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95, 0x84, 0x6F, 0x23, 0x6C, 0x19,
|
||||
0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F, 0x75, 0xF4, 0x27, 0x07,
|
||||
0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20, 0x5D, 0xD8, 0x39,
|
||||
0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3, 0x08, 0x79,
|
||||
0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64, 0x70,
|
||||
0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B,
|
||||
0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44,
|
||||
0x3E, 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3,
|
||||
0x25, 0x89, 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52,
|
||||
0xFD, 0xFD, 0x81, 0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C,
|
||||
0x00, 0x21, 0xC0, 0x18, 0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1,
|
||||
0xD8, 0x48, 0x5A, 0xB6, 0xBB, 0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12,
|
||||
0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93, 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80,
|
||||
0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E, 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56,
|
||||
0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B, 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56,
|
||||
0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7, 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4,
|
||||
0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E, 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC,
|
||||
0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A, 0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2,
|
||||
0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE, 0x8D, 0x98, 0x65, 0xAA, 0xAB,
|
||||
0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF, 0x01, 0x94, 0x00, 0x6F,
|
||||
0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F, 0x2F, 0x6C, 0x1C,
|
||||
0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31, 0xE4, 0x14,
|
||||
0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04, 0x38,
|
||||
0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3,
|
||||
0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC,
|
||||
0x18, 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB,
|
||||
0x6E, 0xF3, 0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F,
|
||||
0x29, 0xA8, 0x1E, 0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6,
|
||||
0xE0, 0x76, 0xC8, 0x26, 0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE,
|
||||
0xEE, 0xF0, 0x4C, 0x44, 0x35, 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC,
|
||||
0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB, 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7,
|
||||
0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0, 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F,
|
||||
0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA, 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64,
|
||||
0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18, 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB,
|
||||
0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C, 0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F,
|
||||
0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1, 0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1,
|
||||
0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71, 0xA7, 0x64, 0x7A, 0xAB, 0x63,
|
||||
0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1, 0xC8, 0x5C, 0x56, 0xB9,
|
||||
0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF, 0x47, 0x0C, 0x32,
|
||||
0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7, 0x50, 0x76,
|
||||
0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A, 0xD7,
|
||||
0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81,
|
||||
0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E,
|
||||
0xC6, 0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2,
|
||||
0xAA, 0xC5, 0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A,
|
||||
0xAC, 0x23, 0x3D, 0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E,
|
||||
0xE4, 0x08, 0x4B, 0x46, 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43,
|
||||
0x0D, 0xF1, 0xC5, 0x84, 0x53, 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34,
|
||||
0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38, 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7,
|
||||
0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE, 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66,
|
||||
0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29, 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2,
|
||||
0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A, 0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3,
|
||||
0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07, 0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79,
|
||||
0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6, 0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91,
|
||||
0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F, 0x1B, 0x48, 0x0B, 0x76, 0x87,
|
||||
0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D, 0xF1, 0xE1, 0x84, 0x48,
|
||||
0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC, 0x2B, 0x15, 0xDF,
|
||||
0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90, 0x57, 0x2C,
|
||||
0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3, 0x4D,
|
||||
0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47,
|
||||
0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55,
|
||||
0xA2, 0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86,
|
||||
0x89, 0xA2, 0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44,
|
||||
0x1F, 0x73, 0x48, 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B,
|
||||
0x6D, 0xD3, 0x6D, 0x9D, 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE,
|
||||
0xF0, 0x70, 0x44, 0x24, 0x33, 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34,
|
||||
0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84, 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F,
|
||||
0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88, 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A,
|
||||
0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA, 0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA,
|
||||
0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A, 0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D,
|
||||
0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79, 0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1,
|
||||
0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40, 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB,
|
||||
0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77, 0x69, 0xE6, 0xAE, 0xCA, 0xFC,
|
||||
0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64, 0x36, 0xAB, 0x56, 0xFF,
|
||||
0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9, 0x81, 0xBE, 0xE0,
|
||||
0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90, 0x38, 0x6C,
|
||||
0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF, 0x60,
|
||||
0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C,
|
||||
0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56,
|
||||
0xF0, 0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA,
|
||||
0xD4, 0x43, 0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C,
|
||||
0x6E, 0xB9, 0xEC, 0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55,
|
||||
0x9E, 0xBF, 0x28, 0x70, 0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97,
|
||||
0x58, 0x6E, 0xBA, 0xAC, 0x73, 0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4,
|
||||
0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A, 0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91,
|
||||
0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D, 0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82,
|
||||
0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B, 0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98,
|
||||
0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C, 0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02,
|
||||
0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A, 0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF,
|
||||
0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB, 0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4,
|
||||
0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x28,
|
||||
0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E, 0x9E, 0x88,
|
||||
0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0, 0x0E, 0xC8, 0x04,
|
||||
0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC, 0x52, 0xD5, 0xFD, 0x9F,
|
||||
0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28, 0x62, 0x9E, 0xA9, 0xA8, 0x7E,
|
||||
0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38,
|
||||
0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B,
|
||||
0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66, 0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E,
|
||||
0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4, 0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0x7C, 0x69,
|
||||
0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84,
|
||||
0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42,
|
||||
0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, 0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4,
|
||||
0x14, 0x47, 0x4F, 0x72, 0xB4, 0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D,
|
||||
0xC6, 0x91, 0x92, 0xEC, 0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E,
|
||||
0x81, 0xE0, 0x60, 0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28,
|
||||
0x60, 0x1E, 0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0,
|
||||
0x76, 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4,
|
||||
0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31, 0xCD,
|
||||
0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81, 0xCA, 0xE0,
|
||||
0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7, 0x5F, 0x36, 0xB8,
|
||||
0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, 0xAE, 0xE4, 0x7C, 0x4B,
|
||||
0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, 0x37, 0x2A, 0x96, 0x9F, 0x2E,
|
||||
0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7,
|
||||
0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C,
|
||||
0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC,
|
||||
0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48,
|
||||
0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, 0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD,
|
||||
0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, 0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85,
|
||||
0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, 0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7,
|
||||
0x01, 0x9E, 0x80, 0x68, 0x60, 0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8,
|
||||
0x08, 0x4E, 0x86, 0xB4, 0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32,
|
||||
0xD6, 0x95, 0x9E, 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71,
|
||||
0xC7, 0x64, 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9,
|
||||
0xD6, 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F,
|
||||
0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2, 0xE5,
|
||||
0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, 0xA8, 0x04,
|
||||
0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, 0xFD, 0xE3, 0x01,
|
||||
0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, 0x88, 0x49, 0xA6, 0xB6,
|
||||
0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, 0x10, 0x4C, 0x0C, 0x35, 0xC5,
|
||||
0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93,
|
||||
0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE,
|
||||
0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, 0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD,
|
||||
0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, 0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84,
|
||||
0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, 0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E,
|
||||
0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, 0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2,
|
||||
0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, 0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95,
|
||||
0x84, 0x6F, 0x23, 0x6C, 0x19, 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F,
|
||||
0x75, 0xF4, 0x27, 0x07, 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20,
|
||||
0x5D, 0xD8, 0x39, 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3,
|
||||
0x08, 0x79, 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64,
|
||||
0x70, 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B,
|
||||
0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, 0x3E,
|
||||
0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, 0x25, 0x89,
|
||||
0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, 0xFD, 0xFD, 0x81,
|
||||
0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, 0x00, 0x21, 0xC0, 0x18,
|
||||
0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, 0xD8, 0x48, 0x5A, 0xB6, 0xBB,
|
||||
0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, 0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93,
|
||||
0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, 0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E,
|
||||
0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, 0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B,
|
||||
0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, 0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7,
|
||||
0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, 0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E,
|
||||
0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC, 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A,
|
||||
0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2, 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE,
|
||||
0x8D, 0x98, 0x65, 0xAA, 0xAB, 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF,
|
||||
0x01, 0x94, 0x00, 0x6F, 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F,
|
||||
0x2F, 0x6C, 0x1C, 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31,
|
||||
0xE4, 0x14, 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04,
|
||||
0x38, 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3,
|
||||
0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, 0x18,
|
||||
0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, 0x6E, 0xF3,
|
||||
0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, 0x29, 0xA8, 0x1E,
|
||||
0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, 0xE0, 0x76, 0xC8, 0x26,
|
||||
0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, 0xEE, 0xF0, 0x4C, 0x44, 0x35,
|
||||
0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, 0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB,
|
||||
0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, 0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0,
|
||||
0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, 0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA,
|
||||
0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64, 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18,
|
||||
0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB, 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C,
|
||||
0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F, 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1,
|
||||
0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1, 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71,
|
||||
0xA7, 0x64, 0x7A, 0xAB, 0x63, 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1,
|
||||
0xC8, 0x5C, 0x56, 0xB9, 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF,
|
||||
0x47, 0x0C, 0x32, 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7,
|
||||
0x50, 0x76, 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A,
|
||||
0xD7, 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81,
|
||||
0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, 0xC6,
|
||||
0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, 0xAA, 0xC5,
|
||||
0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, 0xAC, 0x23, 0x3D,
|
||||
0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, 0xE4, 0x08, 0x4B, 0x46,
|
||||
0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, 0x0D, 0xF1, 0xC5, 0x84, 0x53,
|
||||
0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, 0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38,
|
||||
0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7, 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE,
|
||||
0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66, 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29,
|
||||
0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2, 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A,
|
||||
0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3, 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07,
|
||||
0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79, 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6,
|
||||
0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F,
|
||||
0x1B, 0x48, 0x0B, 0x76, 0x87, 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D,
|
||||
0xF1, 0xE1, 0x84, 0x48, 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC,
|
||||
0x2B, 0x15, 0xDF, 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90,
|
||||
0x57, 0x2C, 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3,
|
||||
0x4D, 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47,
|
||||
0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, 0xA2,
|
||||
0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, 0x89, 0xA2,
|
||||
0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, 0x1F, 0x73, 0x48,
|
||||
0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, 0x6D, 0xD3, 0x6D, 0x9D,
|
||||
0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE, 0xF0, 0x70, 0x44, 0x24, 0x33,
|
||||
0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34, 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84,
|
||||
0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F, 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88,
|
||||
0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A, 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA,
|
||||
0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA, 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A,
|
||||
0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79,
|
||||
0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40,
|
||||
0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77,
|
||||
0x69, 0xE6, 0xAE, 0xCA, 0xFC, 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64,
|
||||
0x36, 0xAB, 0x56, 0xFF, 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9,
|
||||
0x81, 0xBE, 0xE0, 0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90,
|
||||
0x38, 0x6C, 0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF,
|
||||
0x60, 0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C,
|
||||
0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56, 0xF0,
|
||||
0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA, 0xD4, 0x43,
|
||||
0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C, 0x6E, 0xB9, 0xEC,
|
||||
0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55, 0x9E, 0xBF, 0x28, 0x70,
|
||||
0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97, 0x58, 0x6E, 0xBA, 0xAC, 0x73,
|
||||
0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4, 0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A,
|
||||
0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91, 0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D,
|
||||
0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82, 0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B,
|
||||
0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98, 0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C,
|
||||
0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02, 0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A,
|
||||
0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF, 0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB,
|
||||
0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4, 0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99
|
||||
};
|
||||
|
||||
public static readonly byte[] SyncMark =
|
||||
@@ -191,19 +182,26 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static byte[] Scramble(byte[] sector)
|
||||
{
|
||||
if(sector == null || sector.Length < 2352) return sector;
|
||||
if(sector == null ||
|
||||
sector.Length < 2352)
|
||||
return sector;
|
||||
|
||||
byte[] sync = new byte[12];
|
||||
Array.Copy(sector, 0, sync, 0, 12);
|
||||
|
||||
if(!SyncMark.SequenceEqual(sync)) return sector;
|
||||
if(!SyncMark.SequenceEqual(sync))
|
||||
return sector;
|
||||
|
||||
byte[] scrambled = new byte[sector.Length];
|
||||
for(int i = 0; i < 2352; i++) scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]);
|
||||
byte[] scrambled = new byte[sector.Length];
|
||||
|
||||
if(sector.Length <= 2352) return scrambled;
|
||||
for(int i = 0; i < 2352; i++)
|
||||
scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]);
|
||||
|
||||
for(int i = 2352; i < sector.Length; i++) scrambled[i] = sector[i];
|
||||
if(sector.Length <= 2352)
|
||||
return scrambled;
|
||||
|
||||
for(int i = 2352; i < sector.Length; i++)
|
||||
scrambled[i] = sector[i];
|
||||
|
||||
return scrambled;
|
||||
}
|
||||
|
||||
143
CD/Session.cs
143
CD/Session.cs
@@ -37,88 +37,23 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Session
|
||||
{
|
||||
public struct CDSessionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Total size of returned session information minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// First track number in hex
|
||||
/// </summary>
|
||||
public byte FirstCompleteSession;
|
||||
/// <summary>
|
||||
/// Last track number in hex
|
||||
/// </summary>
|
||||
public byte LastCompleteSession;
|
||||
/// <summary>
|
||||
/// Track descriptors
|
||||
/// </summary>
|
||||
public TrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct TrackDataDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 7 to 4
|
||||
/// Type of information in Q subchannel of block where this TOC entry was found
|
||||
/// </summary>
|
||||
public byte ADR;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 3 to 0
|
||||
/// Track attributes
|
||||
/// </summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// First track number in last complete session
|
||||
/// </summary>
|
||||
public byte TrackNumber;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 7
|
||||
/// First track number in last complete session start address in LBA or in MSF
|
||||
/// </summary>
|
||||
public uint TrackStartAddress;
|
||||
}
|
||||
|
||||
public static CDSessionInfo? Decode(byte[] CDSessionInfoResponse)
|
||||
{
|
||||
if(CDSessionInfoResponse == null) return null;
|
||||
if(CDSessionInfoResponse == null)
|
||||
return null;
|
||||
|
||||
CDSessionInfo decoded = new CDSessionInfo
|
||||
var decoded = new CDSessionInfo
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDSessionInfoResponse, 0),
|
||||
FirstCompleteSession = CDSessionInfoResponse[2],
|
||||
LastCompleteSession = CDSessionInfoResponse[3]
|
||||
FirstCompleteSession = CDSessionInfoResponse[2], LastCompleteSession = CDSessionInfoResponse[3]
|
||||
};
|
||||
|
||||
decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 8];
|
||||
@@ -128,6 +63,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
DicConsole.DebugWriteLine("CD Session Info decoder",
|
||||
"Expected CDSessionInfo size ({0} bytes) is not received size ({1} bytes), not decoding",
|
||||
decoded.DataLength + 2, CDSessionInfoResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -138,6 +74,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + i * 8 + 4] & 0x0F);
|
||||
decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + i * 8 + 4];
|
||||
decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + i * 8 + 4];
|
||||
|
||||
decoded.TrackDescriptors[i].TrackStartAddress =
|
||||
BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + i * 8 + 4);
|
||||
}
|
||||
@@ -147,18 +84,21 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDSessionInfo? CDSessionInfoResponse)
|
||||
{
|
||||
if(CDSessionInfoResponse == null) return null;
|
||||
if(CDSessionInfoResponse == null)
|
||||
return null;
|
||||
|
||||
CDSessionInfo response = CDSessionInfoResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine();
|
||||
sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine();
|
||||
|
||||
foreach(TrackDataDescriptor descriptor in response.TrackDescriptors)
|
||||
{
|
||||
sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress,
|
||||
(descriptor.TrackStartAddress & 0x0000FF00) >> 8,
|
||||
(descriptor.TrackStartAddress & 0x00FF0000) >> 16,
|
||||
@@ -168,15 +108,19 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case TocAdr.NoInformation:
|
||||
sb.AppendLine("Q subchannel mode not given");
|
||||
|
||||
break;
|
||||
case TocAdr.CurrentPosition:
|
||||
sb.AppendLine("Q subchannel stores current position");
|
||||
|
||||
break;
|
||||
case TocAdr.ISRC:
|
||||
sb.AppendLine("Q subchannel stores ISRC");
|
||||
|
||||
break;
|
||||
case TocAdr.MediaCatalogNumber:
|
||||
sb.AppendLine("Q subchannel stores media catalog number");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -188,35 +132,41 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.AppendLine("Stereo audio track with no pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.AppendLine("Quadraphonic audio track with no pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.AppendLine("Data track, recorded uninterrupted");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.AppendLine("Data track, recorded incrementally");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) ==
|
||||
(byte)TocControl.CopyPermissionMask
|
||||
? "Digital copy of track is permitted"
|
||||
(byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted"
|
||||
: "Digital copy of track is prohibited");
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
if(descriptor.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine();
|
||||
|
||||
if(descriptor.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
@@ -228,7 +178,36 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDSessionInfoResponse)
|
||||
{
|
||||
CDSessionInfo? decoded = Decode(CDSessionInfoResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
public struct CDSessionInfo
|
||||
{
|
||||
/// <summary>Total size of returned session information minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>First track number in hex</summary>
|
||||
public byte FirstCompleteSession;
|
||||
/// <summary>Last track number in hex</summary>
|
||||
public byte LastCompleteSession;
|
||||
/// <summary>Track descriptors</summary>
|
||||
public TrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct TrackDataDescriptor
|
||||
{
|
||||
/// <summary>Byte 0 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found</summary>
|
||||
public byte ADR;
|
||||
/// <summary>Byte 1, bits 3 to 0 Track attributes</summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>Byte 2 First track number in last complete session</summary>
|
||||
public byte TrackNumber;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 7 First track number in last complete session start address in LBA or in MSF</summary>
|
||||
public uint TrackStartAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
150
CD/TOC.cs
150
CD/TOC.cs
@@ -37,89 +37,23 @@ using DiscImageChef.Console;
|
||||
namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ISO/IEC 61104: Compact disc video system - 12 cm CD-V
|
||||
/// ISO/IEC 60908: Audio recording - Compact disc digital audio system
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ISO/IEC 61104: Compact
|
||||
/// disc video system - 12 cm CD-V ISO/IEC 60908: Audio recording - Compact disc digital audio system
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class TOC
|
||||
{
|
||||
public struct CDTOC
|
||||
{
|
||||
/// <summary>
|
||||
/// Total size of returned TOC minus this field
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// First track number in hex
|
||||
/// </summary>
|
||||
public byte FirstTrack;
|
||||
/// <summary>
|
||||
/// Last track number in hex
|
||||
/// </summary>
|
||||
public byte LastTrack;
|
||||
/// <summary>
|
||||
/// Track descriptors
|
||||
/// </summary>
|
||||
public CDTOCTrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct CDTOCTrackDataDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 7 to 4
|
||||
/// Type of information in Q subchannel of block where this TOC entry was found
|
||||
/// </summary>
|
||||
public byte ADR;
|
||||
/// <summary>
|
||||
/// Byte 1, bits 3 to 0
|
||||
/// Track attributes
|
||||
/// </summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Track number
|
||||
/// </summary>
|
||||
public byte TrackNumber;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 7
|
||||
/// The track start address in LBA or in MSF
|
||||
/// </summary>
|
||||
public uint TrackStartAddress;
|
||||
}
|
||||
|
||||
public static CDTOC? Decode(byte[] CDTOCResponse)
|
||||
{
|
||||
if(CDTOCResponse == null) return null;
|
||||
if(CDTOCResponse == null)
|
||||
return null;
|
||||
|
||||
CDTOC decoded = new CDTOC
|
||||
var decoded = new CDTOC
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0),
|
||||
FirstTrack = CDTOCResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0), FirstTrack = CDTOCResponse[2],
|
||||
LastTrack = CDTOCResponse[3]
|
||||
};
|
||||
|
||||
@@ -130,6 +64,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
DicConsole.DebugWriteLine("CD TOC decoder",
|
||||
"Expected CDTOC size ({0} bytes) is not received size ({1} bytes), not decoding",
|
||||
decoded.DataLength + 2, CDTOCResponse.Length);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -140,6 +75,7 @@ namespace DiscImageChef.Decoders.CD
|
||||
decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + i * 8 + 4] & 0x0F);
|
||||
decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + i * 8 + 4];
|
||||
decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + i * 8 + 4];
|
||||
|
||||
decoded.TrackDescriptors[i].TrackStartAddress =
|
||||
BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + i * 8 + 4);
|
||||
}
|
||||
@@ -149,18 +85,23 @@ namespace DiscImageChef.Decoders.CD
|
||||
|
||||
public static string Prettify(CDTOC? CDTOCResponse)
|
||||
{
|
||||
if(CDTOCResponse == null) return null;
|
||||
if(CDTOCResponse == null)
|
||||
return null;
|
||||
|
||||
CDTOC response = CDTOCResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("First track number in first complete session: {0}", response.FirstTrack).AppendLine();
|
||||
sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine();
|
||||
|
||||
foreach(CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors)
|
||||
{
|
||||
if(descriptor.TrackNumber == 0xAA) sb.AppendLine("Track number: Lead-Out");
|
||||
else sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine();
|
||||
if(descriptor.TrackNumber == 0xAA)
|
||||
sb.AppendLine("Track number: Lead-Out");
|
||||
else
|
||||
sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine();
|
||||
|
||||
sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress,
|
||||
(descriptor.TrackStartAddress & 0x0000FF00) >> 8,
|
||||
(descriptor.TrackStartAddress & 0x00FF0000) >> 16,
|
||||
@@ -170,21 +111,27 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case TocAdr.NoInformation:
|
||||
sb.AppendLine("Q subchannel mode not given");
|
||||
|
||||
break;
|
||||
case TocAdr.TrackPointer:
|
||||
sb.AppendLine("Q subchannel stores track pointer");
|
||||
|
||||
break;
|
||||
case TocAdr.VideoTrackPointer:
|
||||
sb.AppendLine("Q subchannel stores video track pointer");
|
||||
|
||||
break;
|
||||
case TocAdr.ISRC:
|
||||
sb.AppendLine("Q subchannel stores ISRC");
|
||||
|
||||
break;
|
||||
case TocAdr.MediaCatalogNumber:
|
||||
sb.AppendLine("Q subchannel stores media catalog number");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Q subchannel mode {0}", descriptor.ADR).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -196,35 +143,41 @@ namespace DiscImageChef.Decoders.CD
|
||||
{
|
||||
case TocControl.TwoChanNoPreEmph:
|
||||
sb.AppendLine("Stereo audio track with no pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.TwoChanPreEmph:
|
||||
sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanNoPreEmph:
|
||||
sb.AppendLine("Quadraphonic audio track with no pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.FourChanPreEmph:
|
||||
sb.AppendLine("Quadraphonic audio track with 50/15 μs pre-emphasis");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrack:
|
||||
sb.AppendLine("Data track, recorded uninterrupted");
|
||||
|
||||
break;
|
||||
case TocControl.DataTrackIncremental:
|
||||
sb.AppendLine("Data track, recorded incrementally");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) ==
|
||||
(byte)TocControl.CopyPermissionMask
|
||||
? "Digital copy of track is permitted"
|
||||
(byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted"
|
||||
: "Digital copy of track is prohibited");
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG
|
||||
if(descriptor.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine();
|
||||
|
||||
if(descriptor.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
@@ -236,7 +189,36 @@ namespace DiscImageChef.Decoders.CD
|
||||
public static string Prettify(byte[] CDTOCResponse)
|
||||
{
|
||||
CDTOC? decoded = Decode(CDTOCResponse);
|
||||
|
||||
return Prettify(decoded);
|
||||
}
|
||||
|
||||
public struct CDTOC
|
||||
{
|
||||
/// <summary>Total size of returned TOC minus this field</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>First track number in hex</summary>
|
||||
public byte FirstTrack;
|
||||
/// <summary>Last track number in hex</summary>
|
||||
public byte LastTrack;
|
||||
/// <summary>Track descriptors</summary>
|
||||
public CDTOCTrackDataDescriptor[] TrackDescriptors;
|
||||
}
|
||||
|
||||
public struct CDTOCTrackDataDescriptor
|
||||
{
|
||||
/// <summary>Byte 0 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found</summary>
|
||||
public byte ADR;
|
||||
/// <summary>Byte 1, bits 3 to 0 Track attributes</summary>
|
||||
public byte CONTROL;
|
||||
/// <summary>Byte 2 Track number</summary>
|
||||
public byte TrackNumber;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 7 The track start address in LBA or in MSF</summary>
|
||||
public uint TrackStartAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
DVD/AACS.cs
42
DVD/AACS.cs
@@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class AACS
|
||||
{
|
||||
public struct HDLeadInCopyright
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 2052
|
||||
/// HD DVD Lead-In Copyright Information
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to 2052 HD DVD Lead-In Copyright Information</summary>
|
||||
public byte[] CopyrightInformation;
|
||||
}
|
||||
}
|
||||
|
||||
42
DVD/ADIP.cs
42
DVD/ADIP.cs
@@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class ADIP
|
||||
{
|
||||
public struct ADIPInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 259
|
||||
/// ADIP, defined in DVD standards
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to 259 ADIP, defined in DVD standards</summary>
|
||||
public byte[] ADIP;
|
||||
}
|
||||
}
|
||||
|
||||
42
DVD/BCA.cs
42
DVD/BCA.cs
@@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class BCA
|
||||
{
|
||||
public struct BurstCuttingArea
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// Burst cutting area contents, 12 to 188 bytes
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to end Burst cutting area contents, 12 to 188 bytes</summary>
|
||||
public byte[] BCA;
|
||||
}
|
||||
}
|
||||
|
||||
62
DVD/CPRM.cs
62
DVD/CPRM.cs
@@ -35,71 +35,35 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class CPRM
|
||||
{
|
||||
public struct DiscMediaIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// Disc Media Identifier for CPRM
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to end Disc Media Identifier for CPRM</summary>
|
||||
public byte[] MediaIdentifier;
|
||||
}
|
||||
|
||||
public struct DiscMediaKeyBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// Disc Media Key Block for CPRM
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to end Disc Media Key Block for CPRM</summary>
|
||||
public byte[] MediaKeyBlock;
|
||||
}
|
||||
}
|
||||
|
||||
179
DVD/CSS&CPRM.cs
179
DVD/CSS&CPRM.cs
@@ -36,147 +36,94 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class CSS_CPRM
|
||||
{
|
||||
public struct LeadInCopyright
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Copy protection system type
|
||||
/// </summary>
|
||||
public CopyrightType CopyrightType;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Bitmask of regions where this disc is playable
|
||||
/// </summary>
|
||||
public byte RegionInformation;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
}
|
||||
|
||||
public struct DiscKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 2052
|
||||
/// Disc key for CSS, Album Identifier for CPPM
|
||||
/// </summary>
|
||||
public byte[] Key;
|
||||
}
|
||||
|
||||
public static LeadInCopyright? DecodeLeadInCopyright(byte[] response)
|
||||
{
|
||||
if(response?.Length != 8) return null;
|
||||
if(response?.Length != 8)
|
||||
return null;
|
||||
|
||||
return new LeadInCopyright
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]),
|
||||
Reserved1 = response[2],
|
||||
Reserved2 = response[3],
|
||||
CopyrightType = (CopyrightType)response[4],
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2],
|
||||
Reserved2 = response[3], CopyrightType = (CopyrightType)response[4],
|
||||
RegionInformation = response[5],
|
||||
Reserved3 = response[6],
|
||||
Reserved4 = response[7]
|
||||
Reserved3 = response[6], Reserved4 = response[7]
|
||||
};
|
||||
}
|
||||
|
||||
public static string PrettifyLeadInCopyright(LeadInCopyright? cmi)
|
||||
{
|
||||
if(cmi == null) return null;
|
||||
if(cmi == null)
|
||||
return null;
|
||||
|
||||
LeadInCopyright decoded = cmi.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
switch(decoded.CopyrightType)
|
||||
{
|
||||
case CopyrightType.NoProtection:
|
||||
sb.AppendLine("Disc has no encryption.");
|
||||
|
||||
break;
|
||||
case CopyrightType.CSS:
|
||||
sb.AppendLine("Disc is encrypted using CSS or CPPM.");
|
||||
|
||||
break;
|
||||
case CopyrightType.CPRM:
|
||||
sb.AppendLine("Disc is encrypted using CPRM.");
|
||||
|
||||
break;
|
||||
case CopyrightType.AACS:
|
||||
sb.AppendLine("Disc is encrypted using AACS.");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc is encrypted using unknown algorithm with ID {0}.", decoded.CopyrightType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(decoded.CopyrightType == 0) return sb.ToString();
|
||||
if(decoded.CopyrightType == 0)
|
||||
return sb.ToString();
|
||||
|
||||
if(decoded.RegionInformation == 0xFF) sb.AppendLine("Disc cannot be played in any region at all.");
|
||||
else if(decoded.RegionInformation == 0x00) sb.AppendLine("Disc can be played in any region.");
|
||||
if(decoded.RegionInformation == 0xFF)
|
||||
sb.AppendLine("Disc cannot be played in any region at all.");
|
||||
else if(decoded.RegionInformation == 0x00)
|
||||
sb.AppendLine("Disc can be played in any region.");
|
||||
else
|
||||
{
|
||||
sb.Append("Disc can be played in the following regions:");
|
||||
if((decoded.RegionInformation & 0x01) != 0x01) sb.Append(" 0");
|
||||
if((decoded.RegionInformation & 0x02) != 0x02) sb.Append(" 1");
|
||||
if((decoded.RegionInformation & 0x04) != 0x04) sb.Append(" 2");
|
||||
if((decoded.RegionInformation & 0x08) != 0x08) sb.Append(" 3");
|
||||
if((decoded.RegionInformation & 0x10) != 0x10) sb.Append(" 4");
|
||||
if((decoded.RegionInformation & 0x20) != 0x20) sb.Append(" 5");
|
||||
if((decoded.RegionInformation & 0x40) != 0x40) sb.Append(" 6");
|
||||
if((decoded.RegionInformation & 0x80) != 0x80) sb.Append(" 7");
|
||||
|
||||
if((decoded.RegionInformation & 0x01) != 0x01)
|
||||
sb.Append(" 0");
|
||||
|
||||
if((decoded.RegionInformation & 0x02) != 0x02)
|
||||
sb.Append(" 1");
|
||||
|
||||
if((decoded.RegionInformation & 0x04) != 0x04)
|
||||
sb.Append(" 2");
|
||||
|
||||
if((decoded.RegionInformation & 0x08) != 0x08)
|
||||
sb.Append(" 3");
|
||||
|
||||
if((decoded.RegionInformation & 0x10) != 0x10)
|
||||
sb.Append(" 4");
|
||||
|
||||
if((decoded.RegionInformation & 0x20) != 0x20)
|
||||
sb.Append(" 5");
|
||||
|
||||
if((decoded.RegionInformation & 0x40) != 0x40)
|
||||
sb.Append(" 6");
|
||||
|
||||
if((decoded.RegionInformation & 0x80) != 0x80)
|
||||
sb.Append(" 7");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
@@ -184,5 +131,35 @@ namespace DiscImageChef.Decoders.DVD
|
||||
|
||||
public static string PrettifyLeadInCopyright(byte[] response) =>
|
||||
PrettifyLeadInCopyright(DecodeLeadInCopyright(response));
|
||||
|
||||
public struct LeadInCopyright
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4 Copy protection system type</summary>
|
||||
public CopyrightType CopyrightType;
|
||||
/// <summary>Byte 5 Bitmask of regions where this disc is playable</summary>
|
||||
public byte RegionInformation;
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
}
|
||||
|
||||
public struct DiscKey
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 2052 Disc key for CSS, Album Identifier for CPPM</summary>
|
||||
public byte[] Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
174
DVD/Cartridge.cs
174
DVD/Cartridge.cs
@@ -36,159 +36,88 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class Cartridge
|
||||
{
|
||||
public struct MediumStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 7
|
||||
/// Medium is in a cartridge
|
||||
/// </summary>
|
||||
public bool Cartridge;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 6
|
||||
/// Medium has been taken out/inserted in a cartridge
|
||||
/// </summary>
|
||||
public bool OUT;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 5 to 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 3
|
||||
/// Media is write protected by reason stablished in RAMSWI
|
||||
/// </summary>
|
||||
public bool MSWI;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 2
|
||||
/// Media is write protected by cartridge
|
||||
/// </summary>
|
||||
public bool CWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 1
|
||||
/// Media is persistently write protected
|
||||
/// </summary>
|
||||
public bool PWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public bool Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Writable status depending on cartridge
|
||||
/// </summary>
|
||||
public byte DiscType;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest reserved.
|
||||
/// </summary>
|
||||
public byte RAMSWI;
|
||||
}
|
||||
|
||||
public static MediumStatus? Decode(byte[] response)
|
||||
{
|
||||
if(response?.Length != 8) return null;
|
||||
if(response?.Length != 8)
|
||||
return null;
|
||||
|
||||
return new MediumStatus
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]),
|
||||
Reserved1 = response[2],
|
||||
Reserved2 = response[3],
|
||||
Cartridge = (response[4] & 0x80) == 0x80,
|
||||
OUT = (response[4] & 0x40) == 0x40,
|
||||
Reserved3 = (byte)((response[4] & 0x30) >> 4),
|
||||
MSWI = (response[4] & 0x08) == 0x08,
|
||||
CWP = (response[4] & 0x04) == 0x04,
|
||||
PWP = (response[4] & 0x02) == 0x02,
|
||||
Reserved4 = (response[4] & 0x01) == 0x01,
|
||||
DiscType = response[5],
|
||||
Reserved5 = response[6],
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2],
|
||||
Reserved2 = response[3], Cartridge = (response[4] & 0x80) == 0x80,
|
||||
OUT = (response[4] & 0x40) == 0x40,
|
||||
Reserved3 = (byte)((response[4] & 0x30) >> 4), MSWI = (response[4] & 0x08) == 0x08,
|
||||
CWP = (response[4] & 0x04) == 0x04,
|
||||
PWP = (response[4] & 0x02) == 0x02,
|
||||
Reserved4 = (response[4] & 0x01) == 0x01,
|
||||
DiscType = response[5], Reserved5 = response[6],
|
||||
RAMSWI = response[7]
|
||||
};
|
||||
}
|
||||
|
||||
public static string Prettify(MediumStatus? status)
|
||||
{
|
||||
if(status == null) return null;
|
||||
if(status == null)
|
||||
return null;
|
||||
|
||||
MediumStatus decoded = status.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MediumStatus decoded = status.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(decoded.PWP) sb.AppendLine("Disc surface is set to write protected status");
|
||||
if(decoded.PWP)
|
||||
sb.AppendLine("Disc surface is set to write protected status");
|
||||
|
||||
if(decoded.Cartridge)
|
||||
{
|
||||
sb.AppendLine("Disc comes in a cartridge");
|
||||
if(decoded.OUT) sb.AppendLine("Disc has been extracted from the cartridge");
|
||||
if(decoded.CWP) sb.AppendLine("Cartridge is set to write protected");
|
||||
|
||||
if(decoded.OUT)
|
||||
sb.AppendLine("Disc has been extracted from the cartridge");
|
||||
|
||||
if(decoded.CWP)
|
||||
sb.AppendLine("Cartridge is set to write protected");
|
||||
}
|
||||
|
||||
switch(decoded.DiscType)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc shall not be written without a cartridge");
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine("Disc may be written without a cartridge");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown disc type id {0}", decoded.DiscType).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(!decoded.MSWI) return sb.ToString();
|
||||
if(!decoded.MSWI)
|
||||
return sb.ToString();
|
||||
|
||||
switch(decoded.RAMSWI)
|
||||
{
|
||||
case 0: break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc is write inhibited because it has been extracted from the cartridge");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("Disc is write inhibited for an unspecified reason");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Disc has unknown reason {0} for write inhibition", decoded.RAMSWI).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -196,5 +125,38 @@ namespace DiscImageChef.Decoders.DVD
|
||||
}
|
||||
|
||||
public static string Prettify(byte[] response) => Prettify(Decode(response));
|
||||
|
||||
public struct MediumStatus
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4, bit 7 Medium is in a cartridge</summary>
|
||||
public bool Cartridge;
|
||||
/// <summary>Byte 4, bit 6 Medium has been taken out/inserted in a cartridge</summary>
|
||||
public bool OUT;
|
||||
/// <summary>Byte 4, bits 5 to 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 4, bit 3 Media is write protected by reason stablished in RAMSWI</summary>
|
||||
public bool MSWI;
|
||||
/// <summary>Byte 4, bit 2 Media is write protected by cartridge</summary>
|
||||
public bool CWP;
|
||||
/// <summary>Byte 4, bit 1 Media is persistently write protected</summary>
|
||||
public bool PWP;
|
||||
/// <summary>Byte 4, bit 0 Reserved</summary>
|
||||
public bool Reserved4;
|
||||
/// <summary>Byte 5 Writable status depending on cartridge</summary>
|
||||
public byte DiscType;
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7 Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest
|
||||
/// reserved.
|
||||
/// </summary>
|
||||
public byte RAMSWI;
|
||||
}
|
||||
}
|
||||
}
|
||||
270
DVD/DDS.cs
270
DVD/DDS.cs
@@ -37,176 +37,28 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM)
|
||||
/// ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM)
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 272: 120 mm DVD
|
||||
/// Rewritable Disk (DVD-RAM) ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable
|
||||
/// Disk (DVD-RAM)
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class DDS
|
||||
{
|
||||
public struct DiscDefinitionStructure
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
|
||||
/// <summary>
|
||||
/// Bytes 4 to 5
|
||||
/// DDS Identifier = 0x0A0A
|
||||
/// </summary>
|
||||
public ushort Identifier;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 7
|
||||
/// If set, formatting is in process
|
||||
/// </summary>
|
||||
public bool InProcess;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 6
|
||||
/// If set, formatting is using partial certification
|
||||
/// Only in ECMA-272
|
||||
/// </summary>
|
||||
public bool PartialCertification;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 5
|
||||
/// If set, only a group is being formatted
|
||||
/// Only in ECMA-272
|
||||
/// </summary>
|
||||
public bool FormattingOnlyAGroup;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 4 to 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 1
|
||||
/// If set, disk has been certified by a user
|
||||
/// </summary>
|
||||
public bool UserCertification;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 0
|
||||
/// If set, disk has been certified by a manufacturer
|
||||
/// </summary>
|
||||
public bool ManufacturerCertification;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// How many times the DDS has been updated
|
||||
/// </summary>
|
||||
public uint UpdateCount;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 13
|
||||
/// How many groups the disk has
|
||||
/// 24 for ECMA-272
|
||||
/// 1 for ECMA-330
|
||||
/// </summary>
|
||||
public ushort Groups;
|
||||
/// <summary>
|
||||
/// Bytes 14 to 15
|
||||
/// How many zones the disk has
|
||||
/// Only in ECMA-330
|
||||
/// </summary>
|
||||
public ushort Zones;
|
||||
/// <summary>
|
||||
/// Bytes 14 to 19 in ECMA-272
|
||||
/// Bytes 16 to 83 in ECMA-330
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved;
|
||||
/// <summary>
|
||||
/// Bytes 20 to 43
|
||||
/// Group certification flags
|
||||
/// </summary>
|
||||
public GroupCertificationFlag[] GroupCertificationFlags;
|
||||
|
||||
/// <summary>
|
||||
/// Bytes 85 to 87
|
||||
/// Location of first sector in the Primary Spare Area
|
||||
/// </summary>
|
||||
public uint SpareAreaFirstPSN;
|
||||
/// <summary>
|
||||
/// Bytes 89 to 91
|
||||
/// Location of first sector in the Primary Spare Area
|
||||
/// </summary>
|
||||
public uint SpareAreaLastPSN;
|
||||
/// <summary>
|
||||
/// Bytes 93 to 95
|
||||
/// PSN for LSN 0
|
||||
/// </summary>
|
||||
public uint LSN0Location;
|
||||
/// <summary>
|
||||
/// The starting LSN of each zone
|
||||
/// </summary>
|
||||
public uint[] StartLSNForZone;
|
||||
}
|
||||
|
||||
public struct GroupCertificationFlag
|
||||
{
|
||||
/// <summary>
|
||||
/// Bit 7
|
||||
/// If set, formatting of this group is in process
|
||||
/// </summary>
|
||||
public bool InProcess;
|
||||
/// <summary>
|
||||
/// Bit 6
|
||||
/// If set, formatting is using partial certification
|
||||
/// </summary>
|
||||
public bool PartialCertification;
|
||||
/// <summary>
|
||||
/// Bits 5 to 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Bit 1
|
||||
/// If set, this group has been certified by user
|
||||
/// </summary>
|
||||
public bool UserCertification;
|
||||
/// <summary>
|
||||
/// Bit 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public bool Reserved2;
|
||||
}
|
||||
|
||||
public static DiscDefinitionStructure? Decode(byte[] response)
|
||||
{
|
||||
if(response?.Length != 2052) return null;
|
||||
if(response?.Length != 2052)
|
||||
return null;
|
||||
|
||||
DiscDefinitionStructure dds =
|
||||
new DiscDefinitionStructure {Identifier = (ushort)((response[4] << 8) + response[5])};
|
||||
var dds = new DiscDefinitionStructure
|
||||
{
|
||||
Identifier = (ushort)((response[4] << 8) + response[5])
|
||||
};
|
||||
|
||||
if(dds.Identifier != 0x0A0A) return null;
|
||||
if(dds.Identifier != 0x0A0A)
|
||||
return null;
|
||||
|
||||
// Common to both DVD-RAM versions
|
||||
dds.DataLength = (ushort)((response[0] << 8) + response[1]);
|
||||
@@ -216,8 +68,10 @@ namespace DiscImageChef.Decoders.DVD
|
||||
dds.InProcess |= (response[7] & 0x80) == 0x80;
|
||||
dds.UserCertification |= (response[7] & 0x02) == 0x02;
|
||||
dds.ManufacturerCertification |= (response[7] & 0x01) == 0x01;
|
||||
|
||||
dds.UpdateCount =
|
||||
(uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]);
|
||||
|
||||
dds.Groups =
|
||||
(ushort)((response[12] << 8) + response[13]);
|
||||
|
||||
@@ -230,6 +84,7 @@ namespace DiscImageChef.Decoders.DVD
|
||||
dds.Reserved = new byte[6];
|
||||
Array.Copy(response, 14, dds.Reserved, 0, 6);
|
||||
dds.GroupCertificationFlags = new GroupCertificationFlag[24];
|
||||
|
||||
for(int i = 0; i < 24; i++)
|
||||
{
|
||||
dds.GroupCertificationFlags[i].InProcess |= (response[20 + i] & 0x80) == 0x80;
|
||||
@@ -241,7 +96,8 @@ namespace DiscImageChef.Decoders.DVD
|
||||
}
|
||||
|
||||
// ECMA-330
|
||||
if(dds.Groups != 1) return dds;
|
||||
if(dds.Groups != 1)
|
||||
return dds;
|
||||
|
||||
{
|
||||
dds.Reserved4 = (byte)((response[7] & 0x7C) >> 2);
|
||||
@@ -263,23 +119,31 @@ namespace DiscImageChef.Decoders.DVD
|
||||
|
||||
public static string Prettify(DiscDefinitionStructure? dds)
|
||||
{
|
||||
if(dds == null) return null;
|
||||
if(dds == null)
|
||||
return null;
|
||||
|
||||
DiscDefinitionStructure decoded = dds.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(decoded.InProcess)
|
||||
{
|
||||
sb.AppendLine("Formatting in progress.");
|
||||
|
||||
if(decoded.Groups == 24)
|
||||
{
|
||||
if(decoded.PartialCertification) sb.AppendLine("Formatting is only using partial certification");
|
||||
if(decoded.FormattingOnlyAGroup) sb.AppendLine("Only a group is being formatted");
|
||||
if(decoded.PartialCertification)
|
||||
sb.AppendLine("Formatting is only using partial certification");
|
||||
|
||||
if(decoded.FormattingOnlyAGroup)
|
||||
sb.AppendLine("Only a group is being formatted");
|
||||
}
|
||||
}
|
||||
|
||||
if(decoded.UserCertification) sb.AppendLine("Disc has been certified by an user");
|
||||
if(decoded.ManufacturerCertification) sb.AppendLine("Disc has been certified by a manufacturer");
|
||||
if(decoded.UserCertification)
|
||||
sb.AppendLine("Disc has been certified by an user");
|
||||
|
||||
if(decoded.ManufacturerCertification)
|
||||
sb.AppendLine("Disc has been certified by a manufacturer");
|
||||
|
||||
sb.AppendFormat("DDS has been updated {0} times", decoded.UpdateCount).AppendLine();
|
||||
|
||||
@@ -289,6 +153,7 @@ namespace DiscImageChef.Decoders.DVD
|
||||
if(decoded.GroupCertificationFlags[i].InProcess)
|
||||
{
|
||||
sb.AppendFormat("Group {0} is being formatted", i).AppendLine();
|
||||
|
||||
if(decoded.GroupCertificationFlags[i].PartialCertification)
|
||||
sb.AppendFormat("Group {0} is being certified partially", i).AppendLine();
|
||||
}
|
||||
@@ -297,12 +162,15 @@ namespace DiscImageChef.Decoders.DVD
|
||||
sb.AppendFormat("Group {0} has been certified by an user", i).AppendLine();
|
||||
}
|
||||
|
||||
if(decoded.Groups != 1) return sb.ToString();
|
||||
if(decoded.Groups != 1)
|
||||
return sb.ToString();
|
||||
|
||||
{
|
||||
sb.AppendFormat("Disc has {0} zones", decoded.Zones).AppendLine();
|
||||
|
||||
sb.AppendFormat("Primary Spare Area stats at PSN {0:X}h and ends at PSN {1:X}h, inclusively",
|
||||
decoded.SpareAreaFirstPSN, decoded.SpareAreaLastPSN).AppendLine();
|
||||
|
||||
sb.AppendFormat("LSN 0 is at PSN {0:X}h", decoded.LSN0Location).AppendLine();
|
||||
|
||||
for(int i = 0; i < decoded.StartLSNForZone.Length; i++)
|
||||
@@ -313,5 +181,65 @@ namespace DiscImageChef.Decoders.DVD
|
||||
}
|
||||
|
||||
public static string Prettify(byte[] response) => Prettify(Decode(response));
|
||||
|
||||
public struct DiscDefinitionStructure
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
|
||||
/// <summary>Bytes 4 to 5 DDS Identifier = 0x0A0A</summary>
|
||||
public ushort Identifier;
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 7, bit 7 If set, formatting is in process</summary>
|
||||
public bool InProcess;
|
||||
/// <summary>Byte 7, bit 6 If set, formatting is using partial certification Only in ECMA-272</summary>
|
||||
public bool PartialCertification;
|
||||
/// <summary>Byte 7, bit 5 If set, only a group is being formatted Only in ECMA-272</summary>
|
||||
public bool FormattingOnlyAGroup;
|
||||
/// <summary>Byte 7, bits 4 to 2 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>Byte 7, bit 1 If set, disk has been certified by a user</summary>
|
||||
public bool UserCertification;
|
||||
/// <summary>Byte 7, bit 0 If set, disk has been certified by a manufacturer</summary>
|
||||
public bool ManufacturerCertification;
|
||||
/// <summary>Bytes 8 to 11 How many times the DDS has been updated</summary>
|
||||
public uint UpdateCount;
|
||||
/// <summary>Bytes 12 to 13 How many groups the disk has 24 for ECMA-272 1 for ECMA-330</summary>
|
||||
public ushort Groups;
|
||||
/// <summary>Bytes 14 to 15 How many zones the disk has Only in ECMA-330</summary>
|
||||
public ushort Zones;
|
||||
/// <summary>Bytes 14 to 19 in ECMA-272 Bytes 16 to 83 in ECMA-330 Reserved</summary>
|
||||
public byte[] Reserved;
|
||||
/// <summary>Bytes 20 to 43 Group certification flags</summary>
|
||||
public GroupCertificationFlag[] GroupCertificationFlags;
|
||||
|
||||
/// <summary>Bytes 85 to 87 Location of first sector in the Primary Spare Area</summary>
|
||||
public uint SpareAreaFirstPSN;
|
||||
/// <summary>Bytes 89 to 91 Location of first sector in the Primary Spare Area</summary>
|
||||
public uint SpareAreaLastPSN;
|
||||
/// <summary>Bytes 93 to 95 PSN for LSN 0</summary>
|
||||
public uint LSN0Location;
|
||||
/// <summary>The starting LSN of each zone</summary>
|
||||
public uint[] StartLSNForZone;
|
||||
}
|
||||
|
||||
public struct GroupCertificationFlag
|
||||
{
|
||||
/// <summary>Bit 7 If set, formatting of this group is in process</summary>
|
||||
public bool InProcess;
|
||||
/// <summary>Bit 6 If set, formatting is using partial certification</summary>
|
||||
public bool PartialCertification;
|
||||
/// <summary>Bits 5 to 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Bit 1 If set, this group has been certified by user</summary>
|
||||
public bool UserCertification;
|
||||
/// <summary>Bit 0 Reserved</summary>
|
||||
public bool Reserved2;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
DVD/DMI.cs
42
DVD/DMI.cs
@@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class DMI
|
||||
{
|
||||
public struct DiscManufacturingInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 2052
|
||||
/// Disc Manufacturing Information
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to 2052 Disc Manufacturing Information</summary>
|
||||
public byte[] DMI;
|
||||
}
|
||||
}
|
||||
|
||||
225
DVD/Enums.cs
225
DVD/Enums.cs
@@ -38,238 +38,111 @@ namespace DiscImageChef.Decoders.DVD
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DiskCategory : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// DVD-ROM. Version 1 is ECMA-267 and ECMA-268.
|
||||
/// </summary>
|
||||
DVDROM = 0,
|
||||
/// <summary>
|
||||
/// DVD-RAM. Version 1 is ECMA-272. Version 6 is ECMA-330.
|
||||
/// </summary>
|
||||
DVDRAM = 1,
|
||||
/// <summary>
|
||||
/// DVD-R. Version 1 is ECMA-279. Version 5 is ECMA-359. Version 6 is ECMA-382.
|
||||
/// </summary>
|
||||
DVDR = 2,
|
||||
/// <summary>
|
||||
/// DVD-RW. Version 2 is ECMA-338. Version 3 is ECMA-384.
|
||||
/// </summary>
|
||||
DVDRW = 3,
|
||||
/// <summary>
|
||||
/// HD DVD-ROM
|
||||
/// </summary>
|
||||
HDDVDROM = 4,
|
||||
/// <summary>
|
||||
/// HD DVD-RAM
|
||||
/// </summary>
|
||||
HDDVDRAM = 5,
|
||||
/// <summary>
|
||||
/// HD DVD-R
|
||||
/// </summary>
|
||||
HDDVDR = 6,
|
||||
/// <summary>
|
||||
/// HD DVD-RW
|
||||
/// </summary>
|
||||
HDDVDRW = 7,
|
||||
/// <summary>
|
||||
/// UMD. Version 0 is ECMA-365.
|
||||
/// </summary>
|
||||
UMD = 8,
|
||||
/// <summary>
|
||||
/// DVD+RW. Version 1 is ECMA-274. Version 2 is ECMA-337. Version 3 is ECMA-371.
|
||||
/// </summary>
|
||||
DVDPRW = 9,
|
||||
/// <summary>
|
||||
/// DVD+R. Version 1 is ECMA-349.
|
||||
/// </summary>
|
||||
DVDPR = 10,
|
||||
/// <summary>
|
||||
/// DVD+RW DL. Version 1 is ECMA-374.
|
||||
/// </summary>
|
||||
DVDPRWDL = 13,
|
||||
/// <summary>
|
||||
/// DVD+R DL. Version 1 is ECMA-364.
|
||||
/// </summary>
|
||||
DVDPRDL = 14,
|
||||
/// <summary>
|
||||
/// According to standards this value is reserved.
|
||||
/// It's used by Nintendo GODs and WODs.
|
||||
/// </summary>
|
||||
/// <summary>DVD-ROM. Version 1 is ECMA-267 and ECMA-268.</summary>
|
||||
DVDROM = 0, /// <summary>DVD-RAM. Version 1 is ECMA-272. Version 6 is ECMA-330.</summary>
|
||||
DVDRAM = 1, /// <summary>DVD-R. Version 1 is ECMA-279. Version 5 is ECMA-359. Version 6 is ECMA-382.</summary>
|
||||
DVDR = 2, /// <summary>DVD-RW. Version 2 is ECMA-338. Version 3 is ECMA-384.</summary>
|
||||
DVDRW = 3, /// <summary>HD DVD-ROM</summary>
|
||||
HDDVDROM = 4, /// <summary>HD DVD-RAM</summary>
|
||||
HDDVDRAM = 5, /// <summary>HD DVD-R</summary>
|
||||
HDDVDR = 6, /// <summary>HD DVD-RW</summary>
|
||||
HDDVDRW = 7, /// <summary>UMD. Version 0 is ECMA-365.</summary>
|
||||
UMD = 8, /// <summary>DVD+RW. Version 1 is ECMA-274. Version 2 is ECMA-337. Version 3 is ECMA-371.</summary>
|
||||
DVDPRW = 9, /// <summary>DVD+R. Version 1 is ECMA-349.</summary>
|
||||
DVDPR = 10, /// <summary>DVD+RW DL. Version 1 is ECMA-374.</summary>
|
||||
DVDPRWDL = 13, /// <summary>DVD+R DL. Version 1 is ECMA-364.</summary>
|
||||
DVDPRDL = 14, /// <summary>According to standards this value is reserved. It's used by Nintendo GODs and WODs.</summary>
|
||||
Nintendo = 15
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum MaximumRateField : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 2.52 Mbps
|
||||
/// </summary>
|
||||
TwoMbps = 0x00,
|
||||
/// <summary>
|
||||
/// 5.04 Mbps
|
||||
/// </summary>
|
||||
FiveMbps = 0x01,
|
||||
/// <summary>
|
||||
/// 10.08 Mbps
|
||||
/// </summary>
|
||||
TenMbps = 0x02,
|
||||
/// <summary>
|
||||
/// 20.16 Mbps
|
||||
/// </summary>
|
||||
TwentyMbps = 0x03,
|
||||
/// <summary>
|
||||
/// 30.24 Mbps
|
||||
/// </summary>
|
||||
ThirtyMbps = 0x04,
|
||||
Unspecified = 0x0F
|
||||
/// <summary>2.52 Mbps</summary>
|
||||
TwoMbps = 0x00, /// <summary>5.04 Mbps</summary>
|
||||
FiveMbps = 0x01, /// <summary>10.08 Mbps</summary>
|
||||
TenMbps = 0x02, /// <summary>20.16 Mbps</summary>
|
||||
TwentyMbps = 0x03, /// <summary>30.24 Mbps</summary>
|
||||
ThirtyMbps = 0x04, Unspecified = 0x0F
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum LayerTypeFieldMask : byte
|
||||
{
|
||||
Embossed = 0x01,
|
||||
Recordable = 0x02,
|
||||
Rewritable = 0x04,
|
||||
Reserved = 0x08
|
||||
Embossed = 0x01, Recordable = 0x02, Rewritable = 0x04,
|
||||
Reserved = 0x08
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum LinearDensityField : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 0.267 μm/bit
|
||||
/// </summary>
|
||||
TwoSix = 0x00,
|
||||
/// <summary>
|
||||
/// 0.293 μm/bit
|
||||
/// </summary>
|
||||
TwoNine = 0x01,
|
||||
/// <summary>
|
||||
/// 0.409 to 0.435 μm/bit
|
||||
/// </summary>
|
||||
FourZero = 0x02,
|
||||
/// <summary>
|
||||
/// 0.280 to 0.291 μm/bit
|
||||
/// </summary>
|
||||
TwoEight = 0x04,
|
||||
/// <summary>
|
||||
/// 0.153 μm/bit
|
||||
/// </summary>
|
||||
OneFive = 0x05,
|
||||
/// <summary>
|
||||
/// 0.130 to 0.140 μm/bit
|
||||
/// </summary>
|
||||
OneThree = 0x06,
|
||||
/// <summary>
|
||||
/// 0.353 μm/bit
|
||||
/// </summary>
|
||||
/// <summary>0.267 μm/bit</summary>
|
||||
TwoSix = 0x00, /// <summary>0.293 μm/bit</summary>
|
||||
TwoNine = 0x01, /// <summary>0.409 to 0.435 μm/bit</summary>
|
||||
FourZero = 0x02, /// <summary>0.280 to 0.291 μm/bit</summary>
|
||||
TwoEight = 0x04, /// <summary>0.153 μm/bit</summary>
|
||||
OneFive = 0x05, /// <summary>0.130 to 0.140 μm/bit</summary>
|
||||
OneThree = 0x06, /// <summary>0.353 μm/bit</summary>
|
||||
ThreeFive = 0x08
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum TrackDensityField : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 0.74 μm/track
|
||||
/// </summary>
|
||||
Seven = 0x00,
|
||||
/// <summary>
|
||||
/// 0.80 μm/track
|
||||
/// </summary>
|
||||
Eight = 0x01,
|
||||
/// <summary>
|
||||
/// 0.615 μm/track
|
||||
/// </summary>
|
||||
Six = 0x02,
|
||||
/// <summary>
|
||||
/// 0.40 μm/track
|
||||
/// </summary>
|
||||
Four = 0x03,
|
||||
/// <summary>
|
||||
/// 0.34 μm/track
|
||||
/// </summary>
|
||||
/// <summary>0.74 μm/track</summary>
|
||||
Seven = 0x00, /// <summary>0.80 μm/track</summary>
|
||||
Eight = 0x01, /// <summary>0.615 μm/track</summary>
|
||||
Six = 0x02, /// <summary>0.40 μm/track</summary>
|
||||
Four = 0x03, /// <summary>0.34 μm/track</summary>
|
||||
Three = 0x04
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum CopyrightType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// There is no copy protection
|
||||
/// </summary>
|
||||
NoProtection = 0x00,
|
||||
/// <summary>
|
||||
/// Copy protection is CSS/CPPM
|
||||
/// </summary>
|
||||
CSS = 0x01,
|
||||
/// <summary>
|
||||
/// Copy protection is CPRM
|
||||
/// </summary>
|
||||
CPRM = 0x02,
|
||||
/// <summary>
|
||||
/// Copy protection is AACS
|
||||
/// </summary>
|
||||
/// <summary>There is no copy protection</summary>
|
||||
NoProtection = 0x00, /// <summary>Copy protection is CSS/CPPM</summary>
|
||||
CSS = 0x01, /// <summary>Copy protection is CPRM</summary>
|
||||
CPRM = 0x02, /// <summary>Copy protection is AACS</summary>
|
||||
AACS = 0x10
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum WPDiscTypes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Should not write without a cartridge
|
||||
/// </summary>
|
||||
DoNotWrite = 0x00,
|
||||
/// <summary>
|
||||
/// Can write without a cartridge
|
||||
/// </summary>
|
||||
CanWrite = 0x01,
|
||||
Reserved1 = 0x02,
|
||||
Reserved2 = 0x03
|
||||
/// <summary>Should not write without a cartridge</summary>
|
||||
DoNotWrite = 0x00, /// <summary>Can write without a cartridge</summary>
|
||||
CanWrite = 0x01, Reserved1 = 0x02, Reserved2 = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DVDSize
|
||||
{
|
||||
/// <summary>
|
||||
/// 120 mm
|
||||
/// </summary>
|
||||
OneTwenty = 0,
|
||||
/// <summary>
|
||||
/// 80 mm
|
||||
/// </summary>
|
||||
/// <summary>120 mm</summary>
|
||||
OneTwenty = 0, /// <summary>80 mm</summary>
|
||||
Eighty = 1
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DVDRAMDiscType
|
||||
{
|
||||
/// <summary>
|
||||
/// Shall not be recorded without a case
|
||||
/// </summary>
|
||||
Cased = 0,
|
||||
/// <summary>
|
||||
/// May be recorded without a case or within one
|
||||
/// </summary>
|
||||
/// <summary>Shall not be recorded without a case</summary>
|
||||
Cased = 0, /// <summary>May be recorded without a case or within one</summary>
|
||||
Uncased = 1
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DVDLayerStructure
|
||||
{
|
||||
Unspecified = 0,
|
||||
InvertedStack = 1,
|
||||
TwoP = 2,
|
||||
Reserved = 3
|
||||
Unspecified = 0, InvertedStack = 1, TwoP = 2,
|
||||
Reserved = 3
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DVDRecordingSpeed
|
||||
{
|
||||
None = 0,
|
||||
Two = 0,
|
||||
Four = 0x10,
|
||||
Six = 0x20,
|
||||
Eight = 0x30,
|
||||
Ten = 0x40,
|
||||
None = 0, Two = 0, Four = 0x10,
|
||||
Six = 0x20, Eight = 0x30, Ten = 0x40,
|
||||
Twelve = 0x50
|
||||
}
|
||||
#endregion
|
||||
|
||||
192
DVD/Layers.cs
192
DVD/Layers.cs
@@ -35,209 +35,95 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Layers
|
||||
{
|
||||
public struct LayerCapacity
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 7
|
||||
/// If set, L0 capacity is immutable
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bit 7 If set, L0 capacity is immutable</summary>
|
||||
public bool InitStatus;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 6 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bits 6 to 0 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Byte 8 to 11
|
||||
/// L0 Data Area Capacity
|
||||
/// </summary>
|
||||
/// <summary>Byte 8 to 11 L0 Data Area Capacity</summary>
|
||||
public uint Capacity;
|
||||
}
|
||||
|
||||
public struct MiddleZoneStartAddress
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length = 10
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length = 10</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 7
|
||||
/// If set, L0 shifter middle area is immutable
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bit 7 If set, L0 shifter middle area is immutable</summary>
|
||||
public bool InitStatus;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 6 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bits 6 to 0 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Byte 8 to 11
|
||||
/// Start LBA of Shifted Middle Area on L0
|
||||
/// </summary>
|
||||
/// <summary>Byte 8 to 11 Start LBA of Shifted Middle Area on L0</summary>
|
||||
public uint ShiftedMiddleAreaStartAddress;
|
||||
}
|
||||
|
||||
public struct JumpIntervalSize
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length = 10
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length = 10</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Byte 8 to 11
|
||||
/// Jump Interval size for the Regular Interval Layer Jump
|
||||
/// </summary>
|
||||
/// <summary>Byte 8 to 11 Jump Interval size for the Regular Interval Layer Jump</summary>
|
||||
public uint Size;
|
||||
}
|
||||
|
||||
public struct ManualLayerJumpAddress
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length = 10
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length = 10</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
/// <summary>
|
||||
/// Byte 8 to 11
|
||||
/// LBA for the manual layer jump
|
||||
/// </summary>
|
||||
/// <summary>Byte 8 to 11 LBA for the manual layer jump</summary>
|
||||
public uint LBA;
|
||||
}
|
||||
}
|
||||
|
||||
1642
DVD/PFI.cs
1642
DVD/PFI.cs
File diff suppressed because it is too large
Load Diff
42
DVD/PRI.cs
42
DVD/PRI.cs
@@ -35,47 +35,23 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class PRI
|
||||
{
|
||||
public struct PreRecordedInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// Pre-recorded Information in Lead-in for writable media
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to end Pre-recorded Information in Lead-in for writable media</summary>
|
||||
public byte[] PRI;
|
||||
}
|
||||
}
|
||||
|
||||
77
DVD/RMD.cs
77
DVD/RMD.cs
@@ -35,86 +35,41 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class RMD
|
||||
{
|
||||
public struct LastBorderOutRMD
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// RMD in last recorded Border-out
|
||||
/// </summary>
|
||||
/// <summary>Bytes 4 to end RMD in last recorded Border-out</summary>
|
||||
public byte[] RMD;
|
||||
}
|
||||
|
||||
public struct HDMediumStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 7 to 1
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bits 7 to 1 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 0
|
||||
/// Test Zone has been extended
|
||||
/// </summary>
|
||||
/// <summary>Byte 4, bit 0 Test Zone has been extended</summary>
|
||||
public bool ExtendedTestZone;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Number of remaining RMDs in RDZ
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Number of remaining RMDs in RDZ</summary>
|
||||
public byte RemainingRMDs;
|
||||
/// <summary>
|
||||
/// Bytes 6 to 7
|
||||
/// Number of remaining RMDs in current RMZ
|
||||
/// </summary>
|
||||
/// <summary>Bytes 6 to 7 Number of remaining RMDs in current RMZ</summary>
|
||||
public ushort CurrentRemainingRMDs;
|
||||
}
|
||||
}
|
||||
|
||||
88
DVD/Spare.cs
88
DVD/Spare.cs
@@ -36,68 +36,22 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class Spare
|
||||
{
|
||||
public struct SpareAreaInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 7
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public uint UnusedPrimaryBlocks;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public uint UnusedSupplementaryBlocks;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 15
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public uint AllocatedSupplementaryBlocks;
|
||||
}
|
||||
|
||||
public static SpareAreaInformation? Decode(byte[] response)
|
||||
{
|
||||
if(response?.Length != 16) return null;
|
||||
if(response?.Length != 16)
|
||||
return null;
|
||||
|
||||
return new SpareAreaInformation
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]),
|
||||
Reserved1 = response[2],
|
||||
DataLength = (ushort)((response[0] << 8) + response[1]), Reserved1 = response[2],
|
||||
Reserved2 = response[3],
|
||||
UnusedPrimaryBlocks =
|
||||
(uint)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]),
|
||||
@@ -110,19 +64,37 @@ namespace DiscImageChef.Decoders.DVD
|
||||
|
||||
public static string Prettify(SpareAreaInformation? sai)
|
||||
{
|
||||
if(sai == null) return null;
|
||||
if(sai == null)
|
||||
return null;
|
||||
|
||||
SpareAreaInformation decoded = sai.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("{0} unused primary spare blocks", decoded.UnusedPrimaryBlocks).AppendLine();
|
||||
sb.AppendFormat("{0} unused supplementary spare blocks", decoded.UnusedSupplementaryBlocks).AppendLine();
|
||||
sb.AppendFormat("{0} allocated supplementary spare blocks", decoded.AllocatedSupplementaryBlocks)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} allocated supplementary spare blocks", decoded.AllocatedSupplementaryBlocks).
|
||||
AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string Prettify(byte[] response) => Prettify(Decode(response));
|
||||
|
||||
public struct SpareAreaInformation
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 7 Data length</summary>
|
||||
public uint UnusedPrimaryBlocks;
|
||||
/// <summary>Bytes 8 to 11 Data length</summary>
|
||||
public uint UnusedSupplementaryBlocks;
|
||||
/// <summary>Bytes 12 to 15 Data length</summary>
|
||||
public uint AllocatedSupplementaryBlocks;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
DVD/UDI.cs
82
DVD/UDI.cs
@@ -35,87 +35,39 @@ using System.Diagnostics.CodeAnalysis;
|
||||
namespace DiscImageChef.Decoders.DVD
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// ECMA 365
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g ECMA 365
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class UDI
|
||||
{
|
||||
public struct UniqueDiscIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Bytes 6 to 7
|
||||
/// Random number
|
||||
/// </summary>
|
||||
/// <summary>Bytes 6 to 7 Random number</summary>
|
||||
public ushort RandomNumber;
|
||||
/// <summary>
|
||||
/// Byte 8 to 11
|
||||
/// Year
|
||||
/// </summary>
|
||||
/// <summary>Byte 8 to 11 Year</summary>
|
||||
public uint Year;
|
||||
/// <summary>
|
||||
/// Byte 12 to 13
|
||||
/// Month
|
||||
/// </summary>
|
||||
/// <summary>Byte 12 to 13 Month</summary>
|
||||
public ushort Month;
|
||||
/// <summary>
|
||||
/// Byte 14 to 15
|
||||
/// Day
|
||||
/// </summary>
|
||||
/// <summary>Byte 14 to 15 Day</summary>
|
||||
public ushort Day;
|
||||
/// <summary>
|
||||
/// Byte 16 to 17
|
||||
/// Hour
|
||||
/// </summary>
|
||||
/// <summary>Byte 16 to 17 Hour</summary>
|
||||
public ushort Hour;
|
||||
/// <summary>
|
||||
/// Byte 18 to 19
|
||||
/// Minute
|
||||
/// </summary>
|
||||
/// <summary>Byte 18 to 19 Minute</summary>
|
||||
public ushort Minute;
|
||||
/// <summary>
|
||||
/// Byte 20 to 21
|
||||
/// Second
|
||||
/// </summary>
|
||||
/// <summary>Byte 20 to 21 Second</summary>
|
||||
public ushort Second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,54 +35,33 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace DiscImageChef.Decoders.Floppy
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods and structures for Commodore Amiga decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for Commodore Amiga decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Amiga
|
||||
{
|
||||
public struct Sector
|
||||
{
|
||||
/// <summary>
|
||||
/// Set to 0x00
|
||||
/// </summary>
|
||||
/// <summary>Set to 0x00</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// Set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>Set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] sync;
|
||||
/// <summary>
|
||||
/// Set to 0xFF
|
||||
/// </summary>
|
||||
/// <summary>Set to 0xFF</summary>
|
||||
public byte amiga;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// Remaining sectors til end of writing
|
||||
/// </summary>
|
||||
/// <summary>Remaining sectors til end of writing</summary>
|
||||
public byte remaining;
|
||||
/// <summary>
|
||||
/// OS dependent tag
|
||||
/// </summary>
|
||||
/// <summary>OS dependent tag</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] label;
|
||||
/// <summary>
|
||||
/// Checksum from <see cref="amiga" /> to <see cref="label" />
|
||||
/// </summary>
|
||||
/// <summary>Checksum from <see cref="amiga" /> to <see cref="label" /></summary>
|
||||
public uint headerChecksum;
|
||||
/// <summary>
|
||||
/// Checksum from <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>Checksum from <see cref="data" /></summary>
|
||||
public uint dataChecksum;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
|
||||
public byte[] data;
|
||||
|
||||
406
Floppy/Apple2.cs
406
Floppy/Apple2.cs
@@ -40,150 +40,58 @@ using DiscImageChef.Console;
|
||||
|
||||
namespace DiscImageChef.Decoders.Floppy
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods and structures for Apple ][ floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for Apple ][ floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Apple2
|
||||
{
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple ][ GCR floppy track
|
||||
/// </summary>
|
||||
public class RawTrack
|
||||
{
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, between 40 and 95 bytes
|
||||
/// </summary>
|
||||
public byte[] gap;
|
||||
public RawSector[] sectors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple ][ GCR floppy sector
|
||||
/// </summary>
|
||||
public class RawSector
|
||||
{
|
||||
/// <summary>
|
||||
/// Address field
|
||||
/// </summary>
|
||||
public RawAddressField addressField;
|
||||
/// <summary>
|
||||
/// Data field
|
||||
/// </summary>
|
||||
public RawDataField dataField;
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, between 14 and 24 bytes
|
||||
/// </summary>
|
||||
public byte[] gap;
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, between 5 and 10 bytes
|
||||
/// </summary>
|
||||
public byte[] innerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple ][ GCR floppy sector address field
|
||||
/// </summary>
|
||||
public class RawAddressField
|
||||
{
|
||||
/// <summary>
|
||||
/// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector
|
||||
/// checksum[0] = (decodedChecksum >> 1) | 0xAA
|
||||
/// checksum[1] = decodedChecksum | 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] checksum;
|
||||
/// <summary>
|
||||
/// Always 0xDE, 0xAA, 0xEB
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>
|
||||
/// Always 0xD5, 0xAA, 0x96
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>
|
||||
/// Sector number encoded as:
|
||||
/// sector[0] = (decodedSector >> 1) | 0xAA
|
||||
/// sector[1] = decodedSector | 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] sector;
|
||||
/// <summary>
|
||||
/// Track number encoded as:
|
||||
/// track[0] = (decodedTrack >> 1) | 0xAA
|
||||
/// track[1] = decodedTrack | 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] track;
|
||||
/// <summary>
|
||||
/// Volume number encoded as:
|
||||
/// volume[0] = (decodedVolume >> 1) | 0xAA
|
||||
/// volume[1] = decodedVolume | 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple ][ GCR floppy sector data field
|
||||
/// </summary>
|
||||
public class RawDataField
|
||||
{
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// Encoded data bytes.
|
||||
/// 410 bytes for 5to3 (aka DOS 3.2) format
|
||||
/// 342 bytes for 6to2 (aka DOS 3.3) format
|
||||
/// </summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// Always 0xDE, 0xAA, 0xEB
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>
|
||||
/// Always 0xD5, 0xAA, 0xAD
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
}
|
||||
|
||||
static readonly byte[] ReadTable5and3 =
|
||||
{
|
||||
// 00h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 10h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 20h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 30h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 40h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 50h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 60h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 70h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 80h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 90h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// A0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x01, 0x02, 0x03,
|
||||
|
||||
// B0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x05, 0x06, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0x09, 0x0A, 0x0B,
|
||||
|
||||
// C0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// D0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x0D, 0xFF, 0xFF, 0x0E, 0x0F, 0xFF, 0x10, 0x11, 0x12,
|
||||
|
||||
// E0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x14, 0xFF, 0x15, 0x16, 0x17,
|
||||
|
||||
// F0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0x19, 0x1A, 0xFF, 0xFF, 0x1B, 0x1C, 0xFF, 0x1D, 0x1E, 0x1F
|
||||
};
|
||||
@@ -192,48 +100,64 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
{
|
||||
// 00h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 10h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 20h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 30h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 40h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 50h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 60h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 70h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 80h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// 90h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x04, 0x05, 0x06,
|
||||
|
||||
// A0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
|
||||
|
||||
// B0h
|
||||
0xFF, 0xFF, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xFF, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
|
||||
|
||||
// C0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFF, 0x1C, 0x1D, 0x1E,
|
||||
|
||||
// D0h
|
||||
0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x20, 0x21, 0xFF, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
|
||||
// E0h
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x2A, 0x2B, 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
|
||||
|
||||
// F0h
|
||||
0xFF, 0xFF, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xFF, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the 5and3 encoded data
|
||||
/// </summary>
|
||||
/// <summary>Decodes the 5and3 encoded data</summary>
|
||||
/// <param name="data">5and3 encoded data.</param>
|
||||
public static byte[] Decode5and3(byte[] data)
|
||||
{
|
||||
if(data == null || data.Length != 410) return null;
|
||||
if(data == null ||
|
||||
data.Length != 410)
|
||||
return null;
|
||||
|
||||
byte[] buffer = new byte[data.Length];
|
||||
byte carry = 0;
|
||||
|
||||
for(int i = 0; i < data.Length; i++)
|
||||
{
|
||||
carry ^= ReadTable5and3[data[i]];
|
||||
@@ -241,6 +165,7 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
byte[] output = new byte[256];
|
||||
|
||||
for(int i = 0; i < 51; i++)
|
||||
{
|
||||
byte b1 = buffer[51 * 3 - i];
|
||||
@@ -260,16 +185,17 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the 6and2 encoded data
|
||||
/// </summary>
|
||||
/// <summary>Decodes the 6and2 encoded data</summary>
|
||||
/// <param name="data">6and2 encoded data.</param>
|
||||
public static byte[] Decode6and2(byte[] data)
|
||||
{
|
||||
if(data == null || data.Length != 342) return null;
|
||||
if(data == null ||
|
||||
data.Length != 342)
|
||||
return null;
|
||||
|
||||
byte[] buffer = new byte[data.Length];
|
||||
byte carry = 0;
|
||||
|
||||
for(int i = 0; i < data.Length; i++)
|
||||
{
|
||||
carry ^= ReadTable6and2[data[i]];
|
||||
@@ -277,6 +203,7 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
byte[] output = new byte[256];
|
||||
|
||||
for(uint i = 0; i < 256; i++)
|
||||
{
|
||||
output[i] = (byte)((buffer[86 + i] << 2) & 0xFF);
|
||||
@@ -303,13 +230,17 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
public static byte[] DecodeSector(RawSector sector)
|
||||
{
|
||||
if(sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA) return null;
|
||||
if(sector.addressField.prologue[0] != 0xD5 ||
|
||||
sector.addressField.prologue[1] != 0xAA)
|
||||
return null;
|
||||
|
||||
// Pre DOS 3.3
|
||||
if(sector.addressField.prologue[2] == 0xB5) return Decode5and3(sector.dataField.data);
|
||||
if(sector.addressField.prologue[2] == 0xB5)
|
||||
return Decode5and3(sector.dataField.data);
|
||||
|
||||
// DOS 3.3
|
||||
return sector.addressField.prologue[2] == 0x96 ? Decode6and2(sector.dataField.data) : null;
|
||||
|
||||
// Unknown
|
||||
|
||||
// Not Apple ][ GCR?
|
||||
@@ -322,7 +253,9 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
endOffset = offset;
|
||||
|
||||
// Not an Apple ][ GCR sector
|
||||
if(data == null || data.Length < 363) return null;
|
||||
if(data == null ||
|
||||
data.Length < 363)
|
||||
return null;
|
||||
|
||||
int position = offset;
|
||||
|
||||
@@ -331,49 +264,71 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
while(position < data.Length)
|
||||
{
|
||||
// Prologue found
|
||||
if(data[position] == 0xD5 && data[position + 1] == 0xAA)
|
||||
if(data[position] == 0xD5 &&
|
||||
data[position + 1] == 0xAA)
|
||||
{
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position);
|
||||
|
||||
// Epilogue not in correct position
|
||||
if(data[position + 11] != 0xDE || data[position + 12] != 0xAA) return null;
|
||||
if(data[position + 11] != 0xDE ||
|
||||
data[position + 12] != 0xAA)
|
||||
return null;
|
||||
|
||||
RawSector sector = new RawSector
|
||||
var sector = new RawSector
|
||||
{
|
||||
addressField = new RawAddressField
|
||||
{
|
||||
prologue = new[] {data[position], data[position + 1], data[position + 2]},
|
||||
volume = new[] {data[position + 3], data[position + 4]},
|
||||
track = new[] {data[position + 5], data[position + 6]},
|
||||
sector = new[] {data[position + 7], data[position + 8]},
|
||||
checksum = new[] {data[position + 9], data[position + 10]},
|
||||
prologue = new[]
|
||||
{
|
||||
data[position], data[position + 1], data[position + 2]
|
||||
},
|
||||
volume = new[]
|
||||
{
|
||||
data[position + 3], data[position + 4]
|
||||
},
|
||||
track = new[]
|
||||
{
|
||||
data[position + 5], data[position + 6]
|
||||
},
|
||||
sector = new[]
|
||||
{
|
||||
data[position + 7], data[position + 8]
|
||||
},
|
||||
checksum = new[]
|
||||
{
|
||||
data[position + 9], data[position + 10]
|
||||
},
|
||||
epilogue = new[]
|
||||
{
|
||||
data[position + 11], data[position + 12], data[position + 13]
|
||||
}
|
||||
{
|
||||
data[position + 11], data[position + 12], data[position + 13]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Volume {0}",
|
||||
(((sector.addressField.volume[0] & 0x55) << 1) |
|
||||
(sector.addressField.volume[1] & 0x55)) & 0xFF);
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Track {0}",
|
||||
(((sector.addressField.track[0] & 0x55) << 1) |
|
||||
(sector.addressField.track[1] & 0x55)) & 0xFF);
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Sector {0}",
|
||||
(((sector.addressField.sector[0] & 0x55) << 1) |
|
||||
(sector.addressField.sector[1] & 0x55)) & 0xFF);
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Checksum {0}",
|
||||
(((sector.addressField.checksum[0] & 0x55) << 1) |
|
||||
(sector.addressField.checksum[1] & 0x55)) & 0xFF);
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Epilogue {0:X2}{1:X2}{2:X2}",
|
||||
sector.addressField.epilogue[0], sector.addressField.epilogue[1],
|
||||
sector.addressField.epilogue[2]);
|
||||
|
||||
position += 14;
|
||||
int syncCount = 0;
|
||||
bool onSync = false;
|
||||
MemoryStream gaps = new MemoryStream();
|
||||
int syncCount = 0;
|
||||
bool onSync = false;
|
||||
var gaps = new MemoryStream();
|
||||
|
||||
while(data[position] == 0xFF)
|
||||
{
|
||||
@@ -384,16 +339,20 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
// Lost sync
|
||||
if(!onSync) return null;
|
||||
if(!onSync)
|
||||
return null;
|
||||
|
||||
// Prologue not found
|
||||
if(data[position] != 0xD5 || data[position + 1] != 0xAA) return null;
|
||||
if(data[position] != 0xD5 ||
|
||||
data[position + 1] != 0xAA)
|
||||
return null;
|
||||
|
||||
sector.innerGap = gaps.ToArray();
|
||||
sector.dataField = new RawDataField();
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Inner gap has {0} bytes",
|
||||
sector.innerGap.Length);
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position);
|
||||
sector.dataField.prologue = new byte[3];
|
||||
sector.dataField.prologue[0] = data[position];
|
||||
@@ -402,19 +361,24 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
position += 3;
|
||||
|
||||
gaps = new MemoryStream();
|
||||
|
||||
// Read data until epilogue is found
|
||||
while(data[position + 1] != 0xDE || data[position + 2] != 0xAA)
|
||||
while(data[position + 1] != 0xDE ||
|
||||
data[position + 2] != 0xAA)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
position++;
|
||||
|
||||
// No space left for epilogue
|
||||
if(position + 4 > data.Length) return null;
|
||||
if(position + 4 > data.Length)
|
||||
return null;
|
||||
}
|
||||
|
||||
sector.dataField.data = gaps.ToArray();
|
||||
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Data has {0} bytes",
|
||||
sector.dataField.data.Length);
|
||||
|
||||
sector.dataField.checksum = data[position];
|
||||
sector.dataField.epilogue = new byte[3];
|
||||
sector.dataField.epilogue[0] = data[position + 1];
|
||||
@@ -423,8 +387,10 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
position += 4;
|
||||
gaps = new MemoryStream();
|
||||
|
||||
// Read gap, if any
|
||||
while(position < data.Length && data[position] == 0xFF)
|
||||
while(position < data.Length &&
|
||||
data[position] == 0xFF)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
position++;
|
||||
@@ -438,32 +404,41 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
sector.gap = gaps.ToArray();
|
||||
|
||||
// Return current position to be able to read separate sectors
|
||||
endOffset = position;
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length);
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length);
|
||||
DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Finished sector at {0}", position);
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
if(data[position] == 0xFF) position++;
|
||||
if(data[position] == 0xFF)
|
||||
position++;
|
||||
|
||||
// Found data that is not sync or a prologue
|
||||
else return null;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch(IndexOutOfRangeException) { return null; }
|
||||
catch(IndexOutOfRangeException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] MarshalAddressField(RawAddressField addressField)
|
||||
{
|
||||
if(addressField == null) return null;
|
||||
if(addressField == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(addressField.prologue, 0, addressField.prologue.Length);
|
||||
raw.Write(addressField.volume, 0, addressField.volume.Length);
|
||||
raw.Write(addressField.track, 0, addressField.track.Length);
|
||||
raw.Write(addressField.sector, 0, addressField.sector.Length);
|
||||
raw.Write(addressField.volume, 0, addressField.volume.Length);
|
||||
raw.Write(addressField.track, 0, addressField.track.Length);
|
||||
raw.Write(addressField.sector, 0, addressField.sector.Length);
|
||||
raw.Write(addressField.checksum, 0, addressField.checksum.Length);
|
||||
raw.Write(addressField.epilogue, 0, addressField.epilogue.Length);
|
||||
|
||||
@@ -472,21 +447,22 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
public static byte[] MarshalSector(RawSector sector)
|
||||
{
|
||||
if(sector == null) return null;
|
||||
if(sector == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length);
|
||||
raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length);
|
||||
raw.Write(sector.addressField.track, 0, sector.addressField.track.Length);
|
||||
raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length);
|
||||
raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length);
|
||||
raw.Write(sector.addressField.track, 0, sector.addressField.track.Length);
|
||||
raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length);
|
||||
raw.Write(sector.addressField.checksum, 0, sector.addressField.checksum.Length);
|
||||
raw.Write(sector.addressField.epilogue, 0, sector.addressField.epilogue.Length);
|
||||
raw.Write(sector.innerGap, 0, sector.innerGap.Length);
|
||||
raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length);
|
||||
raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
|
||||
raw.Write(sector.innerGap, 0, sector.innerGap.Length);
|
||||
raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length);
|
||||
raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
|
||||
raw.WriteByte(sector.dataField.checksum);
|
||||
raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length);
|
||||
raw.Write(sector.gap, 0, sector.gap.Length);
|
||||
raw.Write(sector.gap, 0, sector.gap.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -498,13 +474,14 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
int position = offset;
|
||||
bool firstSector = true;
|
||||
bool onSync = false;
|
||||
MemoryStream gaps = new MemoryStream();
|
||||
var gaps = new MemoryStream();
|
||||
int count = 0;
|
||||
List<RawSector> sectors = new List<RawSector>();
|
||||
byte[] trackNumber = new byte[2];
|
||||
endOffset = offset;
|
||||
|
||||
while(position < data.Length && data[position] == 0xFF)
|
||||
while(position < data.Length &&
|
||||
data[position] == 0xFF)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
count++;
|
||||
@@ -512,15 +489,19 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
onSync = count >= 5;
|
||||
}
|
||||
|
||||
if(position >= data.Length) return null;
|
||||
if(position >= data.Length)
|
||||
return null;
|
||||
|
||||
if(!onSync) return null;
|
||||
if(!onSync)
|
||||
return null;
|
||||
|
||||
while(position < data.Length)
|
||||
{
|
||||
int oldPosition = position;
|
||||
RawSector sector = MarshalSector(data, out position, position);
|
||||
if(sector == null) break;
|
||||
|
||||
if(sector == null)
|
||||
break;
|
||||
|
||||
if(firstSector)
|
||||
{
|
||||
@@ -529,9 +510,11 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
firstSector = false;
|
||||
}
|
||||
|
||||
if(sector.addressField.track[0] != trackNumber[0] || sector.addressField.track[1] != trackNumber[1])
|
||||
if(sector.addressField.track[0] != trackNumber[0] ||
|
||||
sector.addressField.track[1] != trackNumber[1])
|
||||
{
|
||||
position = oldPosition;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -540,23 +523,33 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
(sector.addressField.sector[1] & 0x55)) & 0xFF,
|
||||
(((sector.addressField.track[0] & 0x55) << 1) |
|
||||
(sector.addressField.track[1] & 0x55)) & 0xFF);
|
||||
|
||||
sectors.Add(sector);
|
||||
}
|
||||
|
||||
if(sectors.Count == 0) return null;
|
||||
if(sectors.Count == 0)
|
||||
return null;
|
||||
|
||||
var track = new RawTrack
|
||||
{
|
||||
gap = gaps.ToArray(), sectors = sectors.ToArray()
|
||||
};
|
||||
|
||||
RawTrack track = new RawTrack {gap = gaps.ToArray(), sectors = sectors.ToArray()};
|
||||
endOffset = position;
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
public static byte[] MarshalTrack(RawTrack track)
|
||||
{
|
||||
if(track == null) return null;
|
||||
if(track == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(track.gap, 0, track.gap.Length);
|
||||
foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) raw.Write(rawSector, 0, rawSector.Length);
|
||||
|
||||
foreach(byte[] rawSector in track.sectors.Select(MarshalSector))
|
||||
raw.Write(rawSector, 0, rawSector.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -570,15 +563,18 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
int position = offset;
|
||||
|
||||
RawTrack track = MarshalTrack(data, out position, position);
|
||||
|
||||
while(track != null)
|
||||
{
|
||||
tracks.Add(track);
|
||||
track = MarshalTrack(data, out position, position);
|
||||
}
|
||||
|
||||
if(tracks.Count == 0) return null;
|
||||
if(tracks.Count == 0)
|
||||
return null;
|
||||
|
||||
endOffset = position;
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@@ -586,10 +582,13 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
public static byte[] MarshalDisk(RawTrack[] disk)
|
||||
{
|
||||
if(disk == null) return null;
|
||||
if(disk == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
foreach(byte[] rawTrack in disk.Select(MarshalTrack)) raw.Write(rawTrack, 0, rawTrack.Length);
|
||||
var raw = new MemoryStream();
|
||||
|
||||
foreach(byte[] rawTrack in disk.Select(MarshalTrack))
|
||||
raw.Write(rawTrack, 0, rawTrack.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -600,5 +599,66 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
return sector != null && position != 0;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple ][ GCR floppy track</summary>
|
||||
public class RawTrack
|
||||
{
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, between 40 and 95 bytes</summary>
|
||||
public byte[] gap;
|
||||
public RawSector[] sectors;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple ][ GCR floppy sector</summary>
|
||||
public class RawSector
|
||||
{
|
||||
/// <summary>Address field</summary>
|
||||
public RawAddressField addressField;
|
||||
/// <summary>Data field</summary>
|
||||
public RawDataField dataField;
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, between 14 and 24 bytes</summary>
|
||||
public byte[] gap;
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, between 5 and 10 bytes</summary>
|
||||
public byte[] innerGap;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple ][ GCR floppy sector address field</summary>
|
||||
public class RawAddressField
|
||||
{
|
||||
/// <summary>
|
||||
/// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector checksum[0] = (decodedChecksum >> 1) | 0xAA
|
||||
/// checksum[1] = decodedChecksum | 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] checksum;
|
||||
/// <summary>Always 0xDE, 0xAA, 0xEB</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>Always 0xD5, 0xAA, 0x96</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>Sector number encoded as: sector[0] = (decodedSector >> 1) | 0xAA sector[1] = decodedSector | 0xAA</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] sector;
|
||||
/// <summary>Track number encoded as: track[0] = (decodedTrack >> 1) | 0xAA track[1] = decodedTrack | 0xAA</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] track;
|
||||
/// <summary>Volume number encoded as: volume[0] = (decodedVolume >> 1) | 0xAA volume[1] = decodedVolume | 0xAA</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] volume;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple ][ GCR floppy sector data field</summary>
|
||||
public class RawDataField
|
||||
{
|
||||
public byte checksum;
|
||||
/// <summary>Encoded data bytes. 410 bytes for 5to3 (aka DOS 3.2) format 342 bytes for 6to2 (aka DOS 3.3) format</summary>
|
||||
public byte[] data;
|
||||
/// <summary>Always 0xDE, 0xAA, 0xEB</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>Always 0xD5, 0xAA, 0xAD</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,138 +42,35 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
// Information from:
|
||||
// Inside Macintosh, Volume II, ISBN 0-201-17732-3
|
||||
|
||||
/// <summary>
|
||||
/// Methods and structures for Apple Sony GCR floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
/// <summary>Methods and structures for Apple Sony GCR floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class AppleSony
|
||||
{
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple Sony GCR floppy track
|
||||
/// </summary>
|
||||
public class RawTrack
|
||||
{
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, 36 bytes
|
||||
/// </summary>
|
||||
public byte[] gap;
|
||||
public RawSector[] sectors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple Sony GCR floppy sector
|
||||
/// </summary>
|
||||
public class RawSector
|
||||
{
|
||||
/// <summary>
|
||||
/// Address field
|
||||
/// </summary>
|
||||
public RawAddressField addressField;
|
||||
/// <summary>
|
||||
/// Data field
|
||||
/// </summary>
|
||||
public RawDataField dataField;
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, unknown size
|
||||
/// </summary>
|
||||
public byte[] gap;
|
||||
/// <summary>
|
||||
/// Track preamble, set to self-sync 0xFF, 6 bytes
|
||||
/// </summary>
|
||||
public byte[] innerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple Sony GCR floppy sector address field
|
||||
/// </summary>
|
||||
public class RawAddressField
|
||||
{
|
||||
/// <summary>
|
||||
/// Checksum
|
||||
/// </summary>
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// Always 0xDE, 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>
|
||||
/// Disk format
|
||||
/// </summary>
|
||||
public AppleEncodedFormat format;
|
||||
/// <summary>
|
||||
/// Always 0xD5, 0xAA, 0x96
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>
|
||||
/// Encoded sector number
|
||||
/// </summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// Encoded side number
|
||||
/// </summary>
|
||||
public byte side;
|
||||
/// <summary>
|
||||
/// Encoded (decodedTrack & 0x3F)
|
||||
/// </summary>
|
||||
public byte track;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GCR-encoded Apple ][ GCR floppy sector data field
|
||||
/// </summary>
|
||||
public class RawDataField
|
||||
{
|
||||
/// <summary>
|
||||
/// Checksum
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] checksum;
|
||||
/// <summary>
|
||||
/// Encoded data bytes.
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)]
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// Always 0xDE, 0xAA
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>
|
||||
/// Always 0xD5, 0xAA, 0xAD
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>
|
||||
/// Spare, usually <see cref="RawAddressField.sector" />
|
||||
/// </summary>
|
||||
public byte spare;
|
||||
}
|
||||
|
||||
public static byte[] DecodeSector(RawSector sector)
|
||||
{
|
||||
if(sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA ||
|
||||
sector.addressField.prologue[2] != 0x96) return null;
|
||||
if(sector.addressField.prologue[0] != 0xD5 ||
|
||||
sector.addressField.prologue[1] != 0xAA ||
|
||||
sector.addressField.prologue[2] != 0x96)
|
||||
return null;
|
||||
|
||||
byte[] bf1 = new byte[175];
|
||||
byte[] bf2 = new byte[175];
|
||||
byte[] bf3 = new byte[175];
|
||||
byte[] nib_data = sector.dataField.data;
|
||||
MemoryStream ms = new MemoryStream();
|
||||
byte[] bf1 = new byte[175];
|
||||
byte[] bf2 = new byte[175];
|
||||
byte[] bf3 = new byte[175];
|
||||
byte[] nib_data = sector.dataField.data;
|
||||
var ms = new MemoryStream();
|
||||
|
||||
int j = 0;
|
||||
byte w3 = 0;
|
||||
|
||||
for(int i = 0; i <= 174; i++)
|
||||
{
|
||||
byte w4 = nib_data[j++];
|
||||
byte w1 = nib_data[j++];
|
||||
byte w2 = nib_data[j++];
|
||||
|
||||
if(i != 174) w3 = nib_data[j++];
|
||||
if(i != 174)
|
||||
w3 = nib_data[j++];
|
||||
|
||||
bf1[i] = (byte)(((w1 & 0x3F) | ((w4 << 2) & 0xC0)) & 0x0F);
|
||||
bf2[i] = (byte)(((w2 & 0x3F) | ((w4 << 4) & 0xC0)) & 0x0F);
|
||||
@@ -184,13 +81,17 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
uint ck1 = 0;
|
||||
uint ck2 = 0;
|
||||
uint ck3 = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
ck1 = (ck1 & 0xFF) << 1;
|
||||
if((ck1 & 0x0100) > 0) ck1++;
|
||||
|
||||
if((ck1 & 0x0100) > 0)
|
||||
ck1++;
|
||||
|
||||
byte carry = (byte)((bf1[j] ^ ck1) & 0xFF);
|
||||
ck3 += carry;
|
||||
|
||||
if((ck1 & 0x0100) > 0)
|
||||
{
|
||||
ck3++;
|
||||
@@ -201,6 +102,7 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
carry = (byte)((bf2[j] ^ ck3) & 0xFF);
|
||||
ck2 += carry;
|
||||
|
||||
if(ck3 > 0xFF)
|
||||
{
|
||||
ck2++;
|
||||
@@ -209,10 +111,12 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
ms.WriteByte(carry);
|
||||
|
||||
if(ms.Length == 524) break;
|
||||
if(ms.Length == 524)
|
||||
break;
|
||||
|
||||
carry = (byte)((bf3[j] ^ ck2) & 0xFF);
|
||||
ck1 += carry;
|
||||
|
||||
if(ck2 > 0xFF)
|
||||
{
|
||||
ck1++;
|
||||
@@ -235,7 +139,9 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
endOffset = offset;
|
||||
|
||||
// Not an Apple ][ GCR sector
|
||||
if(data == null || data.Length < 363) return null;
|
||||
if(data == null ||
|
||||
data.Length < 363)
|
||||
return null;
|
||||
|
||||
int position = offset;
|
||||
|
||||
@@ -244,29 +150,37 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
while(position < data.Length)
|
||||
{
|
||||
// Prologue found
|
||||
if(data[position] == 0xD5 && data[position + 1] == 0xAA && data[position + 2] == 0x96)
|
||||
if(data[position] == 0xD5 &&
|
||||
data[position + 1] == 0xAA &&
|
||||
data[position + 2] == 0x96)
|
||||
{
|
||||
// Epilogue not in correct position
|
||||
if(data[position + 8] != 0xDE || data[position + 9] != 0xAA) return null;
|
||||
if(data[position + 8] != 0xDE ||
|
||||
data[position + 9] != 0xAA)
|
||||
return null;
|
||||
|
||||
RawSector sector = new RawSector
|
||||
var sector = new RawSector
|
||||
{
|
||||
addressField = new RawAddressField
|
||||
{
|
||||
prologue = new[] {data[position], data[position + 1], data[position + 2]},
|
||||
track = data[position + 3],
|
||||
sector = data[position + 4],
|
||||
side = data[position + 5],
|
||||
format = (AppleEncodedFormat)data[position + 6],
|
||||
checksum = data[position + 7],
|
||||
epilogue = new[] {data[position + 8], data[position + 9]}
|
||||
prologue = new[]
|
||||
{
|
||||
data[position], data[position + 1], data[position + 2]
|
||||
},
|
||||
track = data[position + 3], sector = data[position + 4],
|
||||
side = data[position + 5],
|
||||
format = (AppleEncodedFormat)data[position + 6], checksum = data[position + 7],
|
||||
epilogue = new[]
|
||||
{
|
||||
data[position + 8], data[position + 9]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
position += 10;
|
||||
int syncCount = 0;
|
||||
bool onSync = false;
|
||||
MemoryStream gaps = new MemoryStream();
|
||||
int syncCount = 0;
|
||||
bool onSync = false;
|
||||
var gaps = new MemoryStream();
|
||||
|
||||
while(data[position] == 0xFF)
|
||||
{
|
||||
@@ -277,29 +191,40 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
// Lost sync
|
||||
if(!onSync) return null;
|
||||
if(!onSync)
|
||||
return null;
|
||||
|
||||
// Prologue not found
|
||||
if(data[position] != 0xDE || data[position + 1] != 0xAA || data[position + 2] != 0xAD)
|
||||
if(data[position] != 0xDE ||
|
||||
data[position + 1] != 0xAA ||
|
||||
data[position + 2] != 0xAD)
|
||||
return null;
|
||||
|
||||
sector.innerGap = gaps.ToArray();
|
||||
|
||||
sector.dataField = new RawDataField
|
||||
{
|
||||
prologue = new[] {data[position], data[position + 1], data[position + 2]},
|
||||
spare = data[position + 3]
|
||||
prologue = new[]
|
||||
{
|
||||
data[position], data[position + 1], data[position + 2]
|
||||
},
|
||||
spare = data[position + 3]
|
||||
};
|
||||
|
||||
position += 4;
|
||||
|
||||
gaps = new MemoryStream();
|
||||
|
||||
// Read data until epilogue is found
|
||||
while(data[position + 4] != 0xD5 || data[position + 5] != 0xAA)
|
||||
while(data[position + 4] != 0xD5 ||
|
||||
data[position + 5] != 0xAA)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
position++;
|
||||
|
||||
// No space left for epilogue
|
||||
if(position + 7 > data.Length) return null;
|
||||
if(position + 7 > data.Length)
|
||||
return null;
|
||||
}
|
||||
|
||||
sector.dataField.data = gaps.ToArray();
|
||||
@@ -314,8 +239,10 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
position += 7;
|
||||
gaps = new MemoryStream();
|
||||
|
||||
// Read gap, if any
|
||||
while(position < data.Length && data[position] == 0xFF)
|
||||
while(position < data.Length &&
|
||||
data[position] == 0xFF)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
position++;
|
||||
@@ -329,26 +256,35 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
}
|
||||
|
||||
sector.gap = gaps.ToArray();
|
||||
|
||||
// Return current position to be able to read separate sectors
|
||||
endOffset = position;
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
if(data[position] == 0xFF) position++;
|
||||
if(data[position] == 0xFF)
|
||||
position++;
|
||||
|
||||
// Found data that is not sync or a prologue
|
||||
else return null;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch(IndexOutOfRangeException) { return null; }
|
||||
catch(IndexOutOfRangeException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] MarshalAddressField(RawAddressField addressField)
|
||||
{
|
||||
if(addressField == null) return null;
|
||||
if(addressField == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(addressField.prologue, 0, addressField.prologue.Length);
|
||||
raw.WriteByte(addressField.track);
|
||||
raw.WriteByte(addressField.sector);
|
||||
@@ -361,22 +297,23 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
public static byte[] MarshalSector(RawSector sector)
|
||||
{
|
||||
if(sector == null) return null;
|
||||
if(sector == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length);
|
||||
raw.WriteByte(sector.addressField.track);
|
||||
raw.WriteByte(sector.addressField.sector);
|
||||
raw.WriteByte(sector.addressField.side);
|
||||
raw.WriteByte((byte)sector.addressField.format);
|
||||
raw.WriteByte(sector.addressField.checksum);
|
||||
raw.Write(sector.innerGap, 0, sector.innerGap.Length);
|
||||
raw.Write(sector.innerGap, 0, sector.innerGap.Length);
|
||||
raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length);
|
||||
raw.WriteByte(sector.dataField.spare);
|
||||
raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
|
||||
raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
|
||||
raw.Write(sector.dataField.checksum, 0, sector.dataField.checksum.Length);
|
||||
raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length);
|
||||
raw.Write(sector.gap, 0, sector.gap.Length);
|
||||
raw.Write(sector.gap, 0, sector.gap.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -388,14 +325,15 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
int position = offset;
|
||||
bool firstSector = true;
|
||||
bool onSync = false;
|
||||
MemoryStream gaps = new MemoryStream();
|
||||
var gaps = new MemoryStream();
|
||||
int count = 0;
|
||||
List<RawSector> sectors = new List<RawSector>();
|
||||
byte trackNumber = 0;
|
||||
byte sideNumber = 0;
|
||||
endOffset = offset;
|
||||
|
||||
while(position < data.Length && data[position] == 0xFF)
|
||||
while(position < data.Length &&
|
||||
data[position] == 0xFF)
|
||||
{
|
||||
gaps.WriteByte(data[position]);
|
||||
count++;
|
||||
@@ -403,15 +341,19 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
onSync = count >= 5;
|
||||
}
|
||||
|
||||
if(position >= data.Length) return null;
|
||||
if(position >= data.Length)
|
||||
return null;
|
||||
|
||||
if(!onSync) return null;
|
||||
if(!onSync)
|
||||
return null;
|
||||
|
||||
while(position < data.Length)
|
||||
{
|
||||
int oldPosition = position;
|
||||
RawSector sector = MarshalSector(data, out position, position);
|
||||
if(sector == null) break;
|
||||
|
||||
if(sector == null)
|
||||
break;
|
||||
|
||||
if(firstSector)
|
||||
{
|
||||
@@ -420,29 +362,40 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
firstSector = false;
|
||||
}
|
||||
|
||||
if(sector.addressField.track != trackNumber || sector.addressField.side != sideNumber)
|
||||
if(sector.addressField.track != trackNumber ||
|
||||
sector.addressField.side != sideNumber)
|
||||
{
|
||||
position = oldPosition;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sectors.Add(sector);
|
||||
}
|
||||
|
||||
if(sectors.Count == 0) return null;
|
||||
if(sectors.Count == 0)
|
||||
return null;
|
||||
|
||||
var track = new RawTrack
|
||||
{
|
||||
gap = gaps.ToArray(), sectors = sectors.ToArray()
|
||||
};
|
||||
|
||||
RawTrack track = new RawTrack {gap = gaps.ToArray(), sectors = sectors.ToArray()};
|
||||
endOffset = position;
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
public static byte[] MarshalTrack(RawTrack track)
|
||||
{
|
||||
if(track == null) return null;
|
||||
if(track == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
var raw = new MemoryStream();
|
||||
raw.Write(track.gap, 0, track.gap.Length);
|
||||
foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) raw.Write(rawSector, 0, rawSector.Length);
|
||||
|
||||
foreach(byte[] rawSector in track.sectors.Select(MarshalSector))
|
||||
raw.Write(rawSector, 0, rawSector.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -456,15 +409,18 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
int position = offset;
|
||||
|
||||
RawTrack track = MarshalTrack(data, out position, position);
|
||||
|
||||
while(track != null)
|
||||
{
|
||||
tracks.Add(track);
|
||||
track = MarshalTrack(data, out position, position);
|
||||
}
|
||||
|
||||
if(tracks.Count == 0) return null;
|
||||
if(tracks.Count == 0)
|
||||
return null;
|
||||
|
||||
endOffset = position;
|
||||
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@@ -472,10 +428,13 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
public static byte[] MarshalDisk(RawTrack[] disk)
|
||||
{
|
||||
if(disk == null) return null;
|
||||
if(disk == null)
|
||||
return null;
|
||||
|
||||
MemoryStream raw = new MemoryStream();
|
||||
foreach(byte[] rawTrack in disk.Select(MarshalTrack)) raw.Write(rawTrack, 0, rawTrack.Length);
|
||||
var raw = new MemoryStream();
|
||||
|
||||
foreach(byte[] rawTrack in disk.Select(MarshalTrack))
|
||||
raw.Write(rawTrack, 0, rawTrack.Length);
|
||||
|
||||
return raw.ToArray();
|
||||
}
|
||||
@@ -486,5 +445,66 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
|
||||
return sector != null && position != 0;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple Sony GCR floppy track</summary>
|
||||
public class RawTrack
|
||||
{
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, 36 bytes</summary>
|
||||
public byte[] gap;
|
||||
public RawSector[] sectors;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple Sony GCR floppy sector</summary>
|
||||
public class RawSector
|
||||
{
|
||||
/// <summary>Address field</summary>
|
||||
public RawAddressField addressField;
|
||||
/// <summary>Data field</summary>
|
||||
public RawDataField dataField;
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, unknown size</summary>
|
||||
public byte[] gap;
|
||||
/// <summary>Track preamble, set to self-sync 0xFF, 6 bytes</summary>
|
||||
public byte[] innerGap;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple Sony GCR floppy sector address field</summary>
|
||||
public class RawAddressField
|
||||
{
|
||||
/// <summary>Checksum</summary>
|
||||
public byte checksum;
|
||||
/// <summary>Always 0xDE, 0xAA</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>Disk format</summary>
|
||||
public AppleEncodedFormat format;
|
||||
/// <summary>Always 0xD5, 0xAA, 0x96</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>Encoded sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>Encoded side number</summary>
|
||||
public byte side;
|
||||
/// <summary>Encoded (decodedTrack & 0x3F)</summary>
|
||||
public byte track;
|
||||
}
|
||||
|
||||
/// <summary>GCR-encoded Apple ][ GCR floppy sector data field</summary>
|
||||
public class RawDataField
|
||||
{
|
||||
/// <summary>Checksum</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public byte[] checksum;
|
||||
/// <summary>Encoded data bytes.</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)]
|
||||
public byte[] data;
|
||||
/// <summary>Always 0xDE, 0xAA</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
|
||||
public byte[] epilogue;
|
||||
/// <summary>Always 0xD5, 0xAA, 0xAD</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] prologue;
|
||||
/// <summary>Spare, usually <see cref="RawAddressField.sector" /></summary>
|
||||
public byte spare;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,66 +35,39 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace DiscImageChef.Decoders.Floppy
|
||||
{
|
||||
/// <summary>
|
||||
/// Methods and structures for Commodore GCR floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for Commodore GCR floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Commodore
|
||||
{
|
||||
/// <summary>
|
||||
/// Decoded Commodore GCR sector header
|
||||
/// </summary>
|
||||
/// <summary>Decoded Commodore GCR sector header</summary>
|
||||
public struct SectorHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// Always 0x08
|
||||
/// </summary>
|
||||
/// <summary>Always 0x08</summary>
|
||||
public byte id;
|
||||
/// <summary>
|
||||
/// XOR of following fields
|
||||
/// </summary>
|
||||
/// <summary>XOR of following fields</summary>
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Format ID, unknown meaning
|
||||
/// </summary>
|
||||
/// <summary>Format ID, unknown meaning</summary>
|
||||
public ushort format;
|
||||
/// <summary>
|
||||
/// Filled with 0x0F
|
||||
/// </summary>
|
||||
/// <summary>Filled with 0x0F</summary>
|
||||
public ushort fill;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decoded Commodore GCR sector data
|
||||
/// </summary>
|
||||
/// <summary>Decoded Commodore GCR sector data</summary>
|
||||
public struct SectorData
|
||||
{
|
||||
/// <summary>
|
||||
/// Always 0x07
|
||||
/// </summary>
|
||||
/// <summary>Always 0x07</summary>
|
||||
public byte id;
|
||||
/// <summary>
|
||||
/// User data
|
||||
/// </summary>
|
||||
/// <summary>User data</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
|
||||
public byte data;
|
||||
/// <summary>
|
||||
/// XOR of <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>XOR of <see cref="data" /></summary>
|
||||
public byte checksum;
|
||||
/// <summary>
|
||||
/// Filled with 0x0F
|
||||
/// </summary>
|
||||
/// <summary>Filled with 0x0F</summary>
|
||||
public ushort fill;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,73 +34,35 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders.Floppy
|
||||
{
|
||||
/// <summary>
|
||||
/// In-sector code for sector size
|
||||
/// </summary>
|
||||
/// <summary>In-sector code for sector size</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum IBMSectorSizeCode : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 128 bytes/sector
|
||||
/// </summary>
|
||||
EighthKilo = 0,
|
||||
/// <summary>
|
||||
/// 256 bytes/sector
|
||||
/// </summary>
|
||||
QuarterKilo = 1,
|
||||
/// <summary>
|
||||
/// 512 bytes/sector
|
||||
/// </summary>
|
||||
HalfKilo = 2,
|
||||
/// <summary>
|
||||
/// 1024 bytes/sector
|
||||
/// </summary>
|
||||
Kilo = 3,
|
||||
/// <summary>
|
||||
/// 2048 bytes/sector
|
||||
/// </summary>
|
||||
TwiceKilo = 4,
|
||||
/// <summary>
|
||||
/// 4096 bytes/sector
|
||||
/// </summary>
|
||||
FriceKilo = 5,
|
||||
/// <summary>
|
||||
/// 8192 bytes/sector
|
||||
/// </summary>
|
||||
TwiceFriceKilo = 6,
|
||||
/// <summary>
|
||||
/// 16384 bytes/sector
|
||||
/// </summary>
|
||||
/// <summary>128 bytes/sector</summary>
|
||||
EighthKilo = 0, /// <summary>256 bytes/sector</summary>
|
||||
QuarterKilo = 1, /// <summary>512 bytes/sector</summary>
|
||||
HalfKilo = 2, /// <summary>1024 bytes/sector</summary>
|
||||
Kilo = 3, /// <summary>2048 bytes/sector</summary>
|
||||
TwiceKilo = 4, /// <summary>4096 bytes/sector</summary>
|
||||
FriceKilo = 5, /// <summary>8192 bytes/sector</summary>
|
||||
TwiceFriceKilo = 6, /// <summary>16384 bytes/sector</summary>
|
||||
FricelyFriceKilo = 7
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum IBMIdType : byte
|
||||
{
|
||||
IndexMark = 0xFC,
|
||||
AddressMark = 0xFE,
|
||||
DataMark = 0xFB,
|
||||
IndexMark = 0xFC, AddressMark = 0xFE, DataMark = 0xFB,
|
||||
DeletedDataMark = 0xF8
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum AppleEncodedFormat : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Disk is an Apple II 3.5" disk
|
||||
/// </summary>
|
||||
AppleII = 0x96,
|
||||
/// <summary>
|
||||
/// Disk is an Apple Lisa 3.5" disk
|
||||
/// </summary>
|
||||
Lisa = 0x97,
|
||||
/// <summary>
|
||||
/// Disk is an Apple Macintosh single-sided 3.5" disk
|
||||
/// </summary>
|
||||
MacSingleSide = 0x9A,
|
||||
/// <summary>
|
||||
/// Disk is an Apple Macintosh double-sided 3.5" disk
|
||||
/// </summary>
|
||||
/// <summary>Disk is an Apple II 3.5" disk</summary>
|
||||
AppleII = 0x96, /// <summary>Disk is an Apple Lisa 3.5" disk</summary>
|
||||
Lisa = 0x97, /// <summary>Disk is an Apple Macintosh single-sided 3.5" disk</summary>
|
||||
MacSingleSide = 0x9A, /// <summary>Disk is an Apple Macintosh double-sided 3.5" disk</summary>
|
||||
MacDoubleSide = 0xD9
|
||||
}
|
||||
}
|
||||
101
Floppy/ISO.cs
101
Floppy/ISO.cs
@@ -45,125 +45,76 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
// ECMA-147
|
||||
// ECMA-100
|
||||
|
||||
/// <summary>
|
||||
/// Methods and structures for ISO floppy decoding (also used by Atari ST and others)
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for ISO floppy decoding (also used by Atari ST and others)</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class ISO
|
||||
{
|
||||
/// <summary>
|
||||
/// ISO floppy track, also used by Atari ST and others
|
||||
/// </summary>
|
||||
/// <summary>ISO floppy track, also used by Atari ST and others</summary>
|
||||
public struct Track
|
||||
{
|
||||
/// <summary>
|
||||
/// Start of track, 32 bytes set to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>Start of track, 32 bytes set to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public byte[] innerGap;
|
||||
/// <summary>
|
||||
/// Track sectors
|
||||
/// </summary>
|
||||
/// <summary>Track sectors</summary>
|
||||
public Sector[] sectors;
|
||||
/// <summary>
|
||||
/// Undefined size
|
||||
/// </summary>
|
||||
/// <summary>Undefined size</summary>
|
||||
public byte[] gap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw demodulated format for IBM System 34 floppies
|
||||
/// </summary>
|
||||
/// <summary>Raw demodulated format for IBM System 34 floppies</summary>
|
||||
public struct Sector
|
||||
{
|
||||
/// <summary>
|
||||
/// Sector address mark
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark</summary>
|
||||
public AddressMark addressMark;
|
||||
/// <summary>
|
||||
/// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581
|
||||
/// </summary>
|
||||
/// <summary>22 bytes set to 0x4E, set to 0x22 on Commodore 1581</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)]
|
||||
public byte[] innerGap;
|
||||
/// <summary>
|
||||
/// Sector data block
|
||||
/// </summary>
|
||||
/// <summary>Sector data block</summary>
|
||||
public DataBlock dataBlock;
|
||||
/// <summary>
|
||||
/// Variable bytes set to 0x4E, ECMA defines 54
|
||||
/// </summary>
|
||||
/// <summary>Variable bytes set to 0x4E, ECMA defines 54</summary>
|
||||
public byte[] outerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector address mark for IBM System 34 floppies, contains sync word
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark for IBM System 34 floppies, contains sync word</summary>
|
||||
public struct AddressMark
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.AddressMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.AddressMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Side number
|
||||
/// </summary>
|
||||
/// <summary>Side number</summary>
|
||||
public byte side;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// <see cref="IBMSectorSizeCode" />
|
||||
/// </summary>
|
||||
public IBMSectorSizeCode sectorSize;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector data block for IBM System 34 floppies
|
||||
/// </summary>
|
||||
/// <summary>Sector data block for IBM System 34 floppies</summary>
|
||||
public struct DataBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// User data
|
||||
/// </summary>
|
||||
/// <summary>User data</summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="data" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,156 +45,94 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
// ECMA-147
|
||||
// ECMA-100
|
||||
|
||||
/// <summary>
|
||||
/// Methods and structures for perpendicular MFM floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for perpendicular MFM floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class Perpendicular
|
||||
{
|
||||
/// <summary>
|
||||
/// Perpendicular floppy track
|
||||
/// </summary>
|
||||
/// <summary>Perpendicular floppy track</summary>
|
||||
public struct Track
|
||||
{
|
||||
/// <summary>
|
||||
/// Start of track
|
||||
/// </summary>
|
||||
/// <summary>Start of track</summary>
|
||||
public TrackPreamble trackStart;
|
||||
/// <summary>
|
||||
/// Track sectors
|
||||
/// </summary>
|
||||
/// <summary>Track sectors</summary>
|
||||
public Sector[] sectors;
|
||||
/// <summary>
|
||||
/// Undefined size
|
||||
/// </summary>
|
||||
/// <summary>Undefined size</summary>
|
||||
public byte[] gap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw demodulated format for perpendicular floppies
|
||||
/// </summary>
|
||||
/// <summary>Raw demodulated format for perpendicular floppies</summary>
|
||||
public struct Sector
|
||||
{
|
||||
/// <summary>
|
||||
/// Sector address mark
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark</summary>
|
||||
public AddressMark addressMark;
|
||||
/// <summary>
|
||||
/// 41 bytes set to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>41 bytes set to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)]
|
||||
public byte[] innerGap;
|
||||
/// <summary>
|
||||
/// Sector data block
|
||||
/// </summary>
|
||||
/// <summary>Sector data block</summary>
|
||||
public DataBlock dataBlock;
|
||||
/// <summary>
|
||||
/// Variable-sized inter-sector gap, ECMA defines 83 bytes
|
||||
/// </summary>
|
||||
/// <summary>Variable-sized inter-sector gap, ECMA defines 83 bytes</summary>
|
||||
public byte[] outerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start of IBM PC MFM floppy track
|
||||
/// Used by IBM PC, Apple Macintosh (high-density only), and a lot others
|
||||
/// </summary>
|
||||
/// <summary>Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others</summary>
|
||||
public struct TrackPreamble
|
||||
{
|
||||
/// <summary>
|
||||
/// Gap from index pulse, 80 bytes set to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>Gap from index pulse, 80 bytes set to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
|
||||
public byte[] gap;
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0x00
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0x00</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xC2
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xC2</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] ctwo;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.IndexMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.IndexMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Gap until first sector, 50 bytes to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>Gap until first sector, 50 bytes to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
|
||||
public byte[] gap1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector address mark for IBM System 34 floppies, contains sync word
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark for IBM System 34 floppies, contains sync word</summary>
|
||||
public struct AddressMark
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.AddressMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.AddressMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Side number
|
||||
/// </summary>
|
||||
/// <summary>Side number</summary>
|
||||
public byte side;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// <see cref="IBMSectorSizeCode" />
|
||||
/// </summary>
|
||||
public IBMSectorSizeCode sectorSize;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector data block for IBM System 34 floppies
|
||||
/// </summary>
|
||||
/// <summary>Sector data block for IBM System 34 floppies</summary>
|
||||
public struct DataBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// User data
|
||||
/// </summary>
|
||||
/// <summary>User data</summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="data" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,157 +45,94 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
// ECMA-147
|
||||
// ECMA-100
|
||||
|
||||
/// <summary>
|
||||
/// Methods and structures for IBM System 34 floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for IBM System 34 floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class System34
|
||||
{
|
||||
/// <summary>
|
||||
/// Track format for IBM System 34 floppy
|
||||
/// Used by IBM PC, Apple Macintosh (high-density only), and a lot others
|
||||
/// </summary>
|
||||
/// <summary>Track format for IBM System 34 floppy Used by IBM PC, Apple Macintosh (high-density only), and a lot others</summary>
|
||||
public struct Track
|
||||
{
|
||||
/// <summary>
|
||||
/// Start of track
|
||||
/// </summary>
|
||||
/// <summary>Start of track</summary>
|
||||
public TrackPreamble trackStart;
|
||||
/// <summary>
|
||||
/// Track sectors
|
||||
/// </summary>
|
||||
/// <summary>Track sectors</summary>
|
||||
public Sector[] sectors;
|
||||
/// <summary>
|
||||
/// Undefined size
|
||||
/// </summary>
|
||||
/// <summary>Undefined size</summary>
|
||||
public byte[] gap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start of IBM PC MFM floppy track
|
||||
/// Used by IBM PC, Apple Macintosh (high-density only), and a lot others
|
||||
/// </summary>
|
||||
/// <summary>Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others</summary>
|
||||
public struct TrackPreamble
|
||||
{
|
||||
/// <summary>
|
||||
/// Gap from index pulse, 80 bytes set to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>Gap from index pulse, 80 bytes set to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
|
||||
public byte[] gap;
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0x00
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0x00</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xC2
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xC2</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] ctwo;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.IndexMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.IndexMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Gap until first sector, 50 bytes to 0x4E
|
||||
/// </summary>
|
||||
/// <summary>Gap until first sector, 50 bytes to 0x4E</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
|
||||
public byte[] gap1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw demodulated format for IBM System 34 floppies
|
||||
/// </summary>
|
||||
/// <summary>Raw demodulated format for IBM System 34 floppies</summary>
|
||||
public struct Sector
|
||||
{
|
||||
/// <summary>
|
||||
/// Sector address mark
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark</summary>
|
||||
public AddressMark addressMark;
|
||||
/// <summary>
|
||||
/// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581
|
||||
/// </summary>
|
||||
/// <summary>22 bytes set to 0x4E, set to 0x22 on Commodore 1581</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)]
|
||||
public byte[] innerGap;
|
||||
/// <summary>
|
||||
/// Sector data block
|
||||
/// </summary>
|
||||
/// <summary>Sector data block</summary>
|
||||
public DataBlock dataBlock;
|
||||
/// <summary>
|
||||
/// Variable bytes set to 0x4E, ECMA defines 54
|
||||
/// </summary>
|
||||
/// <summary>Variable bytes set to 0x4E, ECMA defines 54</summary>
|
||||
public byte[] outerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector address mark for IBM System 34 floppies, contains sync word
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark for IBM System 34 floppies, contains sync word</summary>
|
||||
public struct AddressMark
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.AddressMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.AddressMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Side number
|
||||
/// </summary>
|
||||
/// <summary>Side number</summary>
|
||||
public byte side;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// <see cref="IBMSectorSizeCode" />
|
||||
/// </summary>
|
||||
public IBMSectorSizeCode sectorSize;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="sectorSize" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector data block for IBM System 34 floppies
|
||||
/// </summary>
|
||||
/// <summary>Sector data block for IBM System 34 floppies</summary>
|
||||
public struct DataBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// 3 bytes set to 0xA1
|
||||
/// </summary>
|
||||
/// <summary>3 bytes set to 0xA1</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] aone;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// User data
|
||||
/// </summary>
|
||||
/// <summary>User data</summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="aone" /> to end of <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="aone" /> to end of <see cref="data" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,140 +45,85 @@ namespace DiscImageChef.Decoders.Floppy
|
||||
// ECMA-147
|
||||
// ECMA-100
|
||||
|
||||
/// <summary>
|
||||
/// Methods and structures for IBM System 3740 floppy decoding
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Methods and structures for IBM System 3740 floppy decoding</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class System3740
|
||||
{
|
||||
/// <summary>
|
||||
/// Track format for IBM System 3740 floppy
|
||||
/// </summary>
|
||||
/// <summary>Track format for IBM System 3740 floppy</summary>
|
||||
public struct Track
|
||||
{
|
||||
/// <summary>
|
||||
/// Start of track
|
||||
/// </summary>
|
||||
/// <summary>Start of track</summary>
|
||||
public TrackPreamble trackStart;
|
||||
/// <summary>
|
||||
/// Track sectors
|
||||
/// </summary>
|
||||
/// <summary>Track sectors</summary>
|
||||
public Sector[] sectors;
|
||||
/// <summary>
|
||||
/// Undefined size
|
||||
/// </summary>
|
||||
/// <summary>Undefined size</summary>
|
||||
public byte[] gap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start of IBM PC FM floppy track
|
||||
/// </summary>
|
||||
/// <summary>Start of IBM PC FM floppy track</summary>
|
||||
public struct TrackPreamble
|
||||
{
|
||||
/// <summary>
|
||||
/// Gap from index pulse, 80 bytes set to 0xFF
|
||||
/// </summary>
|
||||
/// <summary>Gap from index pulse, 80 bytes set to 0xFF</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
|
||||
public byte[] gap;
|
||||
/// <summary>
|
||||
/// 6 bytes set to 0x00
|
||||
/// </summary>
|
||||
/// <summary>6 bytes set to 0x00</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.IndexMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.IndexMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Gap until first sector, 26 bytes to 0xFF
|
||||
/// </summary>
|
||||
/// <summary>Gap until first sector, 26 bytes to 0xFF</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
|
||||
public byte[] gap1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw demodulated format for IBM System 3740 floppies
|
||||
/// </summary>
|
||||
/// <summary>Raw demodulated format for IBM System 3740 floppies</summary>
|
||||
public struct Sector
|
||||
{
|
||||
/// <summary>
|
||||
/// Sector address mark
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark</summary>
|
||||
public AddressMark addressMark;
|
||||
/// <summary>
|
||||
/// 11 bytes set to 0xFF
|
||||
/// </summary>
|
||||
/// <summary>11 bytes set to 0xFF</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
|
||||
public byte[] innerGap;
|
||||
/// <summary>
|
||||
/// Sector data block
|
||||
/// </summary>
|
||||
/// <summary>Sector data block</summary>
|
||||
public DataBlock dataBlock;
|
||||
/// <summary>
|
||||
/// Variable bytes set to 0xFF
|
||||
/// </summary>
|
||||
/// <summary>Variable bytes set to 0xFF</summary>
|
||||
public byte[] outerGap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector address mark for IBM System 3740 floppies, contains sync word
|
||||
/// </summary>
|
||||
/// <summary>Sector address mark for IBM System 3740 floppies, contains sync word</summary>
|
||||
public struct AddressMark
|
||||
{
|
||||
/// <summary>
|
||||
/// 6 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>6 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.AddressMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.AddressMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// Track number
|
||||
/// </summary>
|
||||
/// <summary>Track number</summary>
|
||||
public byte track;
|
||||
/// <summary>
|
||||
/// Side number
|
||||
/// </summary>
|
||||
/// <summary>Side number</summary>
|
||||
public byte side;
|
||||
/// <summary>
|
||||
/// Sector number
|
||||
/// </summary>
|
||||
/// <summary>Sector number</summary>
|
||||
public byte sector;
|
||||
/// <summary>
|
||||
/// <see cref="IBMSectorSizeCode" />
|
||||
/// </summary>
|
||||
public IBMSectorSizeCode sectorSize;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="type" /> to end of <see cref="sectorSize" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="type" /> to end of <see cref="sectorSize" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sector data block for IBM System 3740 floppies
|
||||
/// </summary>
|
||||
/// <summary>Sector data block for IBM System 3740 floppies</summary>
|
||||
public struct DataBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// 12 bytes set to 0
|
||||
/// </summary>
|
||||
/// <summary>12 bytes set to 0</summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] zero;
|
||||
/// <summary>
|
||||
/// Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" />
|
||||
/// </summary>
|
||||
/// <summary>Set to <see cref="IBMIdType.DataMark" /> or to <see cref="IBMIdType.DeletedDataMark" /></summary>
|
||||
public IBMIdType type;
|
||||
/// <summary>
|
||||
/// User data
|
||||
/// </summary>
|
||||
/// <summary>User data</summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// CRC16 from <see cref="type" /> to end of <see cref="data" />
|
||||
/// </summary>
|
||||
/// <summary>CRC16 from <see cref="type" /> to end of <see cref="data" /></summary>
|
||||
public ushort crc;
|
||||
}
|
||||
}
|
||||
|
||||
607
LisaTag.cs
607
LisaTag.cs
@@ -35,352 +35,20 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders
|
||||
{
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "NotAccessedField.Global"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class LisaTag
|
||||
{
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes)
|
||||
/// </summary>
|
||||
public struct ProfileTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>
|
||||
/// 0x06 bit 7, checksum valid?
|
||||
/// </summary>
|
||||
public bool ValidChk;
|
||||
/// <summary>
|
||||
/// 0x06 bits 6 to 0, used bytes in block
|
||||
/// </summary>
|
||||
public ushort UsedBytes;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, absolute page number
|
||||
/// </summary>
|
||||
public uint AbsPage;
|
||||
/// <summary>
|
||||
/// 0x0B, checksum of data
|
||||
/// </summary>
|
||||
public byte Checksum;
|
||||
/// <summary>
|
||||
/// 0x0C, relative page number
|
||||
/// </summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>
|
||||
/// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
|
||||
/// </summary>
|
||||
public uint NextBlock;
|
||||
/// <summary>
|
||||
/// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
|
||||
/// </summary>
|
||||
public uint PrevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Priam DataTower format
|
||||
/// </summary>
|
||||
public PriamTag ToPriam() =>
|
||||
new PriamTag
|
||||
{
|
||||
AbsPage = AbsPage,
|
||||
Checksum = Checksum,
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF,
|
||||
PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF,
|
||||
RelPage = RelPage,
|
||||
UsedBytes = UsedBytes,
|
||||
ValidChk = ValidChk,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Sony format
|
||||
/// </summary>
|
||||
public SonyTag ToSony() =>
|
||||
new SonyTag
|
||||
{
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = (ushort)NextBlock,
|
||||
PrevBlock = (ushort)PrevBlock,
|
||||
RelPage = RelPage,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a byte array representation of this tag
|
||||
/// </summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[20];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF));
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
if(ValidChk) tagBytes[6] += 0x80;
|
||||
tmp = BigEndianBitConverter.GetBytes(AbsPage);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 3);
|
||||
tagBytes[11] = Checksum;
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 12, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 14, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 17, 3);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Priam DataTower disks (24 bytes)
|
||||
/// </summary>
|
||||
public struct PriamTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>
|
||||
/// 0x06 bit 7, checksum valid?
|
||||
/// </summary>
|
||||
public bool ValidChk;
|
||||
/// <summary>
|
||||
/// 0x06 bits 6 to 0, used bytes in block
|
||||
/// </summary>
|
||||
public ushort UsedBytes;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, absolute page number
|
||||
/// </summary>
|
||||
public uint AbsPage;
|
||||
/// <summary>
|
||||
/// 0x0B, checksum of data
|
||||
/// </summary>
|
||||
public byte Checksum;
|
||||
/// <summary>
|
||||
/// 0x0C, relative page number
|
||||
/// </summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>
|
||||
/// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block
|
||||
/// </summary>
|
||||
public uint NextBlock;
|
||||
/// <summary>
|
||||
/// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block
|
||||
/// </summary>
|
||||
public uint PrevBlock;
|
||||
/// <summary>
|
||||
/// 0x14, disk size
|
||||
/// </summary>
|
||||
public uint DiskSize;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Apple Profile format
|
||||
/// </summary>
|
||||
public ProfileTag ToProfile() =>
|
||||
new ProfileTag
|
||||
{
|
||||
AbsPage = AbsPage,
|
||||
Checksum = Checksum,
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF,
|
||||
PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF,
|
||||
RelPage = RelPage,
|
||||
UsedBytes = UsedBytes,
|
||||
ValidChk = ValidChk,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Sony format
|
||||
/// </summary>
|
||||
public SonyTag ToSony() =>
|
||||
new SonyTag
|
||||
{
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = (ushort)(IsLast ? 0x7FF : NextBlock & 0x7FF),
|
||||
PrevBlock = (ushort)(IsFirst ? 0x7FF : PrevBlock & 0x7FF),
|
||||
RelPage = RelPage,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a byte array representation of this tag
|
||||
/// </summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[24];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF));
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
if(ValidChk) tagBytes[6] += 0x80;
|
||||
tmp = BigEndianBitConverter.GetBytes(AbsPage);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 3);
|
||||
tagBytes[11] = Checksum;
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 12, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 14, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 17, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(DiskSize);
|
||||
Array.Copy(tmp, 0, tagBytes, 20, 4);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LisaOS tag as stored on Apple Sony disks (12 bytes)
|
||||
/// </summary>
|
||||
public struct SonyTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>
|
||||
/// 0x06, relative page number
|
||||
/// </summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>
|
||||
/// 0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid
|
||||
/// </summary>
|
||||
public ushort NextBlock;
|
||||
/// <summary>
|
||||
/// 0x0A, 3 bytes, previous block, 0x7FF if it's first block
|
||||
/// </summary>
|
||||
public ushort PrevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Apple Profile format
|
||||
/// </summary>
|
||||
public ProfileTag ToProfile() =>
|
||||
new ProfileTag
|
||||
{
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF),
|
||||
PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF),
|
||||
RelPage = RelPage,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Converts this tag to Priam DataTower format
|
||||
/// </summary>
|
||||
public PriamTag ToPriam() =>
|
||||
new PriamTag
|
||||
{
|
||||
FileId = FileId,
|
||||
IsFirst = IsFirst,
|
||||
IsLast = IsLast,
|
||||
Kind = Kind,
|
||||
NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF),
|
||||
PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF),
|
||||
RelPage = RelPage,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a byte array representation of this tag
|
||||
/// </summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[12];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0x7FF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0x7FF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 10, 2);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
|
||||
public static SonyTag? DecodeSonyTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 12) return null;
|
||||
if(tag == null ||
|
||||
tag.Length != 12)
|
||||
return null;
|
||||
|
||||
SonyTag snTag = new SonyTag
|
||||
var snTag = new SonyTag
|
||||
{
|
||||
Version = BigEndianBitConverter.ToUInt16(tag, 0),
|
||||
Kind = (byte)((tag[2] & 0xC0) >> 6),
|
||||
Reserved = (byte)(tag[2] & 0x3F),
|
||||
Volume = tag[3],
|
||||
Version = BigEndianBitConverter.ToUInt16(tag, 0), Kind = (byte)((tag[2] & 0xC0) >> 6),
|
||||
Reserved = (byte)(tag[2] & 0x3F), Volume = tag[3],
|
||||
FileId = BigEndianBitConverter.ToInt16(tag, 4),
|
||||
RelPage = BigEndianBitConverter.ToUInt16(tag, 6),
|
||||
NextBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 8) & 0x7FF),
|
||||
@@ -395,9 +63,11 @@ namespace DiscImageChef.Decoders
|
||||
|
||||
public static ProfileTag? DecodeProfileTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 20) return null;
|
||||
if(tag == null ||
|
||||
tag.Length != 20)
|
||||
return null;
|
||||
|
||||
ProfileTag phTag = new ProfileTag();
|
||||
var phTag = new ProfileTag();
|
||||
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
@@ -438,9 +108,11 @@ namespace DiscImageChef.Decoders
|
||||
|
||||
public static PriamTag? DecodePriamTag(byte[] tag)
|
||||
{
|
||||
if(tag == null || tag.Length != 24) return null;
|
||||
if(tag == null ||
|
||||
tag.Length != 24)
|
||||
return null;
|
||||
|
||||
PriamTag pmTag = new PriamTag();
|
||||
var pmTag = new PriamTag();
|
||||
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
@@ -483,7 +155,8 @@ namespace DiscImageChef.Decoders
|
||||
|
||||
public static PriamTag? DecodeTag(byte[] tag)
|
||||
{
|
||||
if(tag == null) return null;
|
||||
if(tag == null)
|
||||
return null;
|
||||
|
||||
PriamTag pmTag;
|
||||
|
||||
@@ -492,7 +165,8 @@ namespace DiscImageChef.Decoders
|
||||
case 12:
|
||||
SonyTag? snTag = DecodeSonyTag(tag);
|
||||
|
||||
if(snTag == null) return null;
|
||||
if(snTag == null)
|
||||
return null;
|
||||
|
||||
pmTag = new PriamTag();
|
||||
pmTag.AbsPage = 0;
|
||||
@@ -515,7 +189,8 @@ namespace DiscImageChef.Decoders
|
||||
case 20:
|
||||
ProfileTag? phTag = DecodeProfileTag(tag);
|
||||
|
||||
if(phTag == null) return null;
|
||||
if(phTag == null)
|
||||
return null;
|
||||
|
||||
pmTag = new PriamTag();
|
||||
pmTag.AbsPage = phTag.Value.AbsPage;
|
||||
@@ -539,5 +214,243 @@ namespace DiscImageChef.Decoders
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes)</summary>
|
||||
public struct ProfileTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>0x06 bit 7, checksum valid?</summary>
|
||||
public bool ValidChk;
|
||||
/// <summary>0x06 bits 6 to 0, used bytes in block</summary>
|
||||
public ushort UsedBytes;
|
||||
/// <summary>0x08, 3 bytes, absolute page number</summary>
|
||||
public uint AbsPage;
|
||||
/// <summary>0x0B, checksum of data</summary>
|
||||
public byte Checksum;
|
||||
/// <summary>0x0C, relative page number</summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>0x0E, 3 bytes, next block, 0xFFFFFF if it's last block</summary>
|
||||
public uint NextBlock;
|
||||
/// <summary>0x11, 3 bytes, previous block, 0xFFFFFF if it's first block</summary>
|
||||
public uint PrevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>Converts this tag to Priam DataTower format</summary>
|
||||
public PriamTag ToPriam() => new PriamTag
|
||||
{
|
||||
AbsPage = AbsPage, Checksum = Checksum, FileId = FileId, IsFirst = IsFirst,
|
||||
IsLast = IsLast, Kind = Kind, NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF,
|
||||
PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF,
|
||||
RelPage = RelPage, UsedBytes = UsedBytes,
|
||||
ValidChk = ValidChk,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Converts this tag to Sony format</summary>
|
||||
public SonyTag ToSony() => new SonyTag
|
||||
{
|
||||
FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind,
|
||||
NextBlock = (ushort)NextBlock, PrevBlock = (ushort)PrevBlock, RelPage = RelPage, Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Gets a byte array representation of this tag</summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[20];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF));
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
|
||||
if(ValidChk)
|
||||
tagBytes[6] += 0x80;
|
||||
|
||||
tmp = BigEndianBitConverter.GetBytes(AbsPage);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 3);
|
||||
tagBytes[11] = Checksum;
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 12, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 14, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 17, 3);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>LisaOS tag as stored on Priam DataTower disks (24 bytes)</summary>
|
||||
public struct PriamTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>0x06 bit 7, checksum valid?</summary>
|
||||
public bool ValidChk;
|
||||
/// <summary>0x06 bits 6 to 0, used bytes in block</summary>
|
||||
public ushort UsedBytes;
|
||||
/// <summary>0x08, 3 bytes, absolute page number</summary>
|
||||
public uint AbsPage;
|
||||
/// <summary>0x0B, checksum of data</summary>
|
||||
public byte Checksum;
|
||||
/// <summary>0x0C, relative page number</summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>0x0E, 3 bytes, next block, 0xFFFFFF if it's last block</summary>
|
||||
public uint NextBlock;
|
||||
/// <summary>0x11, 3 bytes, previous block, 0xFFFFFF if it's first block</summary>
|
||||
public uint PrevBlock;
|
||||
/// <summary>0x14, disk size</summary>
|
||||
public uint DiskSize;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>Converts this tag to Apple Profile format</summary>
|
||||
public ProfileTag ToProfile() => new ProfileTag
|
||||
{
|
||||
AbsPage = AbsPage, Checksum = Checksum, FileId = FileId, IsFirst = IsFirst,
|
||||
IsLast = IsLast, Kind = Kind, NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF,
|
||||
PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF,
|
||||
RelPage = RelPage, UsedBytes = UsedBytes,
|
||||
ValidChk = ValidChk,
|
||||
Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Converts this tag to Sony format</summary>
|
||||
public SonyTag ToSony() => new SonyTag
|
||||
{
|
||||
FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind,
|
||||
NextBlock = (ushort)(IsLast ? 0x7FF : NextBlock & 0x7FF),
|
||||
PrevBlock = (ushort)(IsFirst ? 0x7FF : PrevBlock & 0x7FF), RelPage = RelPage, Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Gets a byte array representation of this tag</summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[24];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF));
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
|
||||
if(ValidChk)
|
||||
tagBytes[6] += 0x80;
|
||||
|
||||
tmp = BigEndianBitConverter.GetBytes(AbsPage);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 3);
|
||||
tagBytes[11] = Checksum;
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 12, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 14, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 17, 3);
|
||||
tmp = BigEndianBitConverter.GetBytes(DiskSize);
|
||||
Array.Copy(tmp, 0, tagBytes, 20, 4);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>LisaOS tag as stored on Apple Sony disks (12 bytes)</summary>
|
||||
public struct SonyTag
|
||||
{
|
||||
/// <summary>0x00, Lisa OS version number</summary>
|
||||
public ushort Version;
|
||||
/// <summary>0x02 bits 7 to 6, kind of info in this block</summary>
|
||||
public byte Kind;
|
||||
/// <summary>0x02 bits 5 to 0, reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>0x03, disk volume number</summary>
|
||||
public byte Volume;
|
||||
/// <summary>0x04, file ID</summary>
|
||||
public short FileId;
|
||||
/// <summary>0x06, relative page number</summary>
|
||||
public ushort RelPage;
|
||||
/// <summary>0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid</summary>
|
||||
public ushort NextBlock;
|
||||
/// <summary>0x0A, 3 bytes, previous block, 0x7FF if it's first block</summary>
|
||||
public ushort PrevBlock;
|
||||
|
||||
/// <summary>On-memory value for easy first block search.</summary>
|
||||
public bool IsFirst;
|
||||
/// <summary>On-memory value for easy last block search.</summary>
|
||||
public bool IsLast;
|
||||
|
||||
/// <summary>Converts this tag to Apple Profile format</summary>
|
||||
public ProfileTag ToProfile() => new ProfileTag
|
||||
{
|
||||
FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind,
|
||||
NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF),
|
||||
PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), RelPage = RelPage, Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Converts this tag to Priam DataTower format</summary>
|
||||
public PriamTag ToPriam() => new PriamTag
|
||||
{
|
||||
FileId = FileId, IsFirst = IsFirst, IsLast = IsLast, Kind = Kind,
|
||||
NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF),
|
||||
PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), RelPage = RelPage, Version = Version,
|
||||
Volume = Volume
|
||||
};
|
||||
|
||||
/// <summary>Gets a byte array representation of this tag</summary>
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] tagBytes = new byte[12];
|
||||
|
||||
byte[] tmp = BigEndianBitConverter.GetBytes(Version);
|
||||
Array.Copy(tmp, 0, tagBytes, 0, 2);
|
||||
tagBytes[2] = (byte)(Kind << 6);
|
||||
tagBytes[3] = Volume;
|
||||
tmp = BigEndianBitConverter.GetBytes(FileId);
|
||||
Array.Copy(tmp, 0, tagBytes, 4, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(RelPage);
|
||||
Array.Copy(tmp, 0, tagBytes, 6, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsLast ? 0x7FF : NextBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 8, 2);
|
||||
tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0x7FF : PrevBlock);
|
||||
Array.Copy(tmp, 1, tagBytes, 10, 2);
|
||||
|
||||
return tagBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
MMC/CID.cs
67
MMC/CID.cs
@@ -36,30 +36,28 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
public class CID
|
||||
{
|
||||
public byte Manufacturer;
|
||||
public byte DeviceType;
|
||||
public byte ApplicationID;
|
||||
public byte CRC;
|
||||
public byte DeviceType;
|
||||
public byte Manufacturer;
|
||||
public byte ManufacturingDate;
|
||||
public string ProductName;
|
||||
public byte ProductRevision;
|
||||
public uint ProductSerialNumber;
|
||||
public byte ManufacturingDate;
|
||||
public byte CRC;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Decoders
|
||||
{
|
||||
public static CID DecodeCID(uint[] response)
|
||||
{
|
||||
if(response?.Length != 4) return null;
|
||||
if(response?.Length != 4)
|
||||
return null;
|
||||
|
||||
byte[] data = new byte[16];
|
||||
|
||||
@@ -77,17 +75,17 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
public static CID DecodeCID(byte[] response)
|
||||
{
|
||||
if(response?.Length != 16) return null;
|
||||
if(response?.Length != 16)
|
||||
return null;
|
||||
|
||||
CID cid = new CID
|
||||
var cid = new CID
|
||||
{
|
||||
Manufacturer = response[0],
|
||||
DeviceType = (byte)(response[1] & 0x03),
|
||||
ProductRevision = response[9],
|
||||
ProductSerialNumber = BitConverter.ToUInt32(response, 10),
|
||||
ManufacturingDate = response[14],
|
||||
DeviceType = (byte)(response[1] & 0x03), ProductRevision = response[9],
|
||||
ProductSerialNumber = BitConverter.ToUInt32(response, 10), ManufacturingDate = response[14],
|
||||
CRC = (byte)((response[15] & 0xFE) >> 1)
|
||||
};
|
||||
|
||||
byte[] tmp = new byte[6];
|
||||
Array.Copy(response, 3, tmp, 0, 6);
|
||||
cid.ProductName = StringHandlers.CToString(tmp);
|
||||
@@ -97,85 +95,110 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
public static string PrettifyCID(CID cid)
|
||||
{
|
||||
if(cid == null) return null;
|
||||
if(cid == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("MultiMediaCard Device Identification Register:");
|
||||
sb.AppendFormat("\tManufacturer: {0}", VendorString.Prettify(cid.Manufacturer)).AppendLine();
|
||||
|
||||
switch(cid.DeviceType)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tRemovable device");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tBGA device");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tPOP device");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("\tApplication ID: {0}", cid.ApplicationID).AppendLine();
|
||||
sb.AppendFormat("\tProduct name: {0}", cid.ProductName).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tProduct revision: {0:X2}.{1:X2}", (cid.ProductRevision & 0xF0) >> 4,
|
||||
cid.ProductRevision & 0x0F).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tProduct serial number: {0}", cid.ProductSerialNumber).AppendLine();
|
||||
string year = "";
|
||||
|
||||
switch(cid.ManufacturingDate & 0x0F)
|
||||
{
|
||||
case 0:
|
||||
year = "1997 or 2013";
|
||||
|
||||
break;
|
||||
case 1:
|
||||
year = "1998 or 2014";
|
||||
|
||||
break;
|
||||
case 2:
|
||||
year = "1999 or 2015";
|
||||
|
||||
break;
|
||||
case 3:
|
||||
year = "2000 or 2016";
|
||||
|
||||
break;
|
||||
case 4:
|
||||
year = "2001 or 2017";
|
||||
|
||||
break;
|
||||
case 5:
|
||||
year = "2002 or 2018";
|
||||
|
||||
break;
|
||||
case 6:
|
||||
year = "2003 or 2019";
|
||||
|
||||
break;
|
||||
case 7:
|
||||
year = "2004 or 2020";
|
||||
|
||||
break;
|
||||
case 8:
|
||||
year = "2005 or 2021";
|
||||
|
||||
break;
|
||||
case 9:
|
||||
year = "2006 or 2022";
|
||||
|
||||
break;
|
||||
case 10:
|
||||
year = "2007 or 2023";
|
||||
|
||||
break;
|
||||
case 11:
|
||||
year = "2008 or 2024";
|
||||
|
||||
break;
|
||||
case 12:
|
||||
year = "2009 or 2025";
|
||||
|
||||
break;
|
||||
case 13:
|
||||
year = "2010";
|
||||
|
||||
break;
|
||||
case 14:
|
||||
year = "2011";
|
||||
|
||||
break;
|
||||
case 15:
|
||||
year = "2012";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF0) >> 4, year)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF0) >> 4, year).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("\tCID CRC: 0x{0:X2}", cid.CRC).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
254
MMC/CSD.cs
254
MMC/CSD.cs
@@ -36,55 +36,53 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public class CSD
|
||||
{
|
||||
public byte Structure;
|
||||
public byte Version;
|
||||
public byte TAAC;
|
||||
public byte NSAC;
|
||||
public byte Speed;
|
||||
public ushort Classes;
|
||||
public byte ReadBlockLength;
|
||||
public bool ReadsPartialBlocks;
|
||||
public bool WriteMisalignment;
|
||||
public bool ReadMisalignment;
|
||||
public bool ContentProtection;
|
||||
public bool Copy;
|
||||
public byte CRC;
|
||||
public byte DefaultECC;
|
||||
public bool DSRImplemented;
|
||||
public ushort Size;
|
||||
public byte ReadCurrentAtVddMin;
|
||||
public byte ReadCurrentAtVddMax;
|
||||
public byte WriteCurrentAtVddMin;
|
||||
public byte WriteCurrentAtVddMax;
|
||||
public byte SizeMultiplier;
|
||||
public byte ECC;
|
||||
public byte EraseGroupSize;
|
||||
public byte EraseGroupSizeMultiplier;
|
||||
public byte WriteProtectGroupSize;
|
||||
public bool WriteProtectGroupEnable;
|
||||
public byte DefaultECC;
|
||||
public byte WriteSpeedFactor;
|
||||
public byte WriteBlockLength;
|
||||
public bool WritesPartialBlocks;
|
||||
public bool ContentProtection;
|
||||
public bool FileFormatGroup;
|
||||
public bool Copy;
|
||||
public bool PermanentWriteProtect;
|
||||
public bool TemporaryWriteProtect;
|
||||
public byte FileFormat;
|
||||
public byte ECC;
|
||||
public byte CRC;
|
||||
public bool FileFormatGroup;
|
||||
public byte NSAC;
|
||||
public bool PermanentWriteProtect;
|
||||
public byte ReadBlockLength;
|
||||
public byte ReadCurrentAtVddMax;
|
||||
public byte ReadCurrentAtVddMin;
|
||||
public bool ReadMisalignment;
|
||||
public bool ReadsPartialBlocks;
|
||||
public ushort Size;
|
||||
public byte SizeMultiplier;
|
||||
public byte Speed;
|
||||
public byte Structure;
|
||||
public byte TAAC;
|
||||
public bool TemporaryWriteProtect;
|
||||
public byte Version;
|
||||
public byte WriteBlockLength;
|
||||
public byte WriteCurrentAtVddMax;
|
||||
public byte WriteCurrentAtVddMin;
|
||||
public bool WriteMisalignment;
|
||||
public bool WriteProtectGroupEnable;
|
||||
public byte WriteProtectGroupSize;
|
||||
public bool WritesPartialBlocks;
|
||||
public byte WriteSpeedFactor;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Decoders
|
||||
{
|
||||
public static CSD DecodeCSD(uint[] response)
|
||||
{
|
||||
if(response?.Length != 4) return null;
|
||||
if(response?.Length != 4)
|
||||
return null;
|
||||
|
||||
byte[] data = new byte[16];
|
||||
|
||||
@@ -102,21 +100,23 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
public static CSD DecodeCSD(byte[] response)
|
||||
{
|
||||
if(response?.Length != 16) return null;
|
||||
if(response?.Length != 16)
|
||||
return null;
|
||||
|
||||
return new CSD
|
||||
{
|
||||
Structure = (byte)((response[0] & 0xC0) >> 6),
|
||||
Version = (byte)((response[0] & 0x3C) >> 2),
|
||||
TAAC = response[1],
|
||||
NSAC = response[2],
|
||||
TAAC = response[1], NSAC = response[2],
|
||||
Speed = response[3],
|
||||
Classes = (ushort)((response[4] << 4) + ((response[5] & 0xF0) >> 4)),
|
||||
ReadBlockLength = (byte)(response[5] & 0x0F),
|
||||
ReadsPartialBlocks = (response[6] & 0x80) == 0x80,
|
||||
WriteMisalignment = (response[6] & 0x40) == 0x40,
|
||||
ReadMisalignment = (response[6] & 0x20) == 0x20,
|
||||
DSRImplemented = (response[6] & 0x10) == 0x10,
|
||||
WriteMisalignment =
|
||||
(response[6] & 0x40) == 0x40,
|
||||
ReadMisalignment = (response[6] & 0x20) == 0x20,
|
||||
DSRImplemented =
|
||||
(response[6] & 0x10) == 0x10,
|
||||
Size =
|
||||
(ushort)(((response[6] & 0x03) << 10) + (response[7] << 2) + ((response[8] & 0xC0) >> 6)),
|
||||
ReadCurrentAtVddMin = (byte)((response[8] & 0x38) >> 3),
|
||||
@@ -145,27 +145,33 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
public static string PrettifyCSD(CSD csd)
|
||||
{
|
||||
if(csd == null) return null;
|
||||
if(csd == null)
|
||||
return null;
|
||||
|
||||
double unitFactor = 0;
|
||||
double multiplier = 0;
|
||||
string unit = "";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("MultiMediaCard Device Specific Data Register:");
|
||||
|
||||
switch(csd.Structure)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tRegister version 1.0");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tRegister version 1.1");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tRegister version 1.2");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tRegister version is defined in Extended Device Specific Data Register");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -174,34 +180,42 @@ namespace DiscImageChef.Decoders.MMC
|
||||
case 0:
|
||||
unit = "ns";
|
||||
unitFactor = 1;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
unit = "ns";
|
||||
unitFactor = 10;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
unit = "ns";
|
||||
unitFactor = 100;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
unit = "μs";
|
||||
unitFactor = 1;
|
||||
|
||||
break;
|
||||
case 4:
|
||||
unit = "μs";
|
||||
unitFactor = 10;
|
||||
|
||||
break;
|
||||
case 5:
|
||||
unit = "μs";
|
||||
unitFactor = 100;
|
||||
|
||||
break;
|
||||
case 6:
|
||||
unit = "ms";
|
||||
unitFactor = 1;
|
||||
|
||||
break;
|
||||
case 7:
|
||||
unit = "ms";
|
||||
unitFactor = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -209,51 +223,67 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
multiplier = 0;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
multiplier = 1;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
multiplier = 1.2;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
multiplier = 1.3;
|
||||
|
||||
break;
|
||||
case 4:
|
||||
multiplier = 1.5;
|
||||
|
||||
break;
|
||||
case 5:
|
||||
multiplier = 2;
|
||||
|
||||
break;
|
||||
case 6:
|
||||
multiplier = 2.5;
|
||||
|
||||
break;
|
||||
case 7:
|
||||
multiplier = 3;
|
||||
|
||||
break;
|
||||
case 8:
|
||||
multiplier = 3.5;
|
||||
|
||||
break;
|
||||
case 9:
|
||||
multiplier = 4;
|
||||
|
||||
break;
|
||||
case 10:
|
||||
multiplier = 4.5;
|
||||
|
||||
break;
|
||||
case 11:
|
||||
multiplier = 5;
|
||||
|
||||
break;
|
||||
case 12:
|
||||
multiplier = 5.5;
|
||||
|
||||
break;
|
||||
case 13:
|
||||
multiplier = 6;
|
||||
|
||||
break;
|
||||
case 14:
|
||||
multiplier = 7;
|
||||
|
||||
break;
|
||||
case 15:
|
||||
multiplier = 8;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -263,23 +293,29 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tClock dependent part of data access is {0} clock cycles", csd.NSAC * 100).AppendLine();
|
||||
|
||||
unit = "MHz";
|
||||
|
||||
switch(csd.Speed & 0x07)
|
||||
{
|
||||
case 0:
|
||||
unitFactor = 0.1;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
unitFactor = 1;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
unitFactor = 10;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
unitFactor = 100;
|
||||
|
||||
break;
|
||||
default:
|
||||
unit = "unknown";
|
||||
unitFactor = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -287,51 +323,67 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
multiplier = 0;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
multiplier = 1;
|
||||
|
||||
break;
|
||||
case 2:
|
||||
multiplier = 1.2;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
multiplier = 1.3;
|
||||
|
||||
break;
|
||||
case 4:
|
||||
multiplier = 1.5;
|
||||
|
||||
break;
|
||||
case 5:
|
||||
multiplier = 2;
|
||||
|
||||
break;
|
||||
case 6:
|
||||
multiplier = 2.6;
|
||||
|
||||
break;
|
||||
case 7:
|
||||
multiplier = 3;
|
||||
|
||||
break;
|
||||
case 8:
|
||||
multiplier = 3.5;
|
||||
|
||||
break;
|
||||
case 9:
|
||||
multiplier = 4;
|
||||
|
||||
break;
|
||||
case 10:
|
||||
multiplier = 4.5;
|
||||
|
||||
break;
|
||||
case 11:
|
||||
multiplier = 5.2;
|
||||
|
||||
break;
|
||||
case 12:
|
||||
multiplier = 5.5;
|
||||
|
||||
break;
|
||||
case 13:
|
||||
multiplier = 6;
|
||||
|
||||
break;
|
||||
case 14:
|
||||
multiplier = 7;
|
||||
|
||||
break;
|
||||
case 15:
|
||||
multiplier = 8;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -339,20 +391,29 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice's clock frequency: {0}{1}", result, unit).AppendLine();
|
||||
|
||||
unit = "";
|
||||
|
||||
for(int cl = 0, mask = 1; cl <= 11; cl++, mask <<= 1)
|
||||
if((csd.Classes & mask) == mask)
|
||||
unit += $" {cl}";
|
||||
|
||||
sb.AppendFormat("\tDevice support command classes {0}", unit).AppendLine();
|
||||
if(csd.ReadBlockLength == 15) sb.AppendLine("\tRead block length size is defined in extended CSD");
|
||||
else sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine();
|
||||
|
||||
if(csd.ReadsPartialBlocks) sb.AppendLine("\tDevice allows reading partial blocks");
|
||||
if(csd.ReadBlockLength == 15)
|
||||
sb.AppendLine("\tRead block length size is defined in extended CSD");
|
||||
else
|
||||
sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine();
|
||||
|
||||
if(csd.WriteMisalignment) sb.AppendLine("\tWrite commands can cross physical block boundaries");
|
||||
if(csd.ReadMisalignment) sb.AppendLine("\tRead commands can cross physical block boundaries");
|
||||
if(csd.ReadsPartialBlocks)
|
||||
sb.AppendLine("\tDevice allows reading partial blocks");
|
||||
|
||||
if(csd.DSRImplemented) sb.AppendLine("\tDevice implements configurable driver stage");
|
||||
if(csd.WriteMisalignment)
|
||||
sb.AppendLine("\tWrite commands can cross physical block boundaries");
|
||||
|
||||
if(csd.ReadMisalignment)
|
||||
sb.AppendLine("\tRead commands can cross physical block boundaries");
|
||||
|
||||
if(csd.DSRImplemented)
|
||||
sb.AppendLine("\tDevice implements configurable driver stage");
|
||||
|
||||
if(csd.Size == 0xFFF)
|
||||
sb.AppendLine("\tDevice may be bigger than 2GiB and have its real size defined in the extended CSD");
|
||||
@@ -361,36 +422,49 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice has {0} blocks", (int)result).AppendLine();
|
||||
|
||||
result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) * Math.Pow(2, csd.ReadBlockLength);
|
||||
if(result > 1073741824) sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine();
|
||||
else if(result > 1048576) sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine();
|
||||
else if(result > 1024) sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine();
|
||||
else sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine();
|
||||
|
||||
if(result > 1073741824)
|
||||
sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine();
|
||||
else if(result > 1048576)
|
||||
sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine();
|
||||
else if(result > 1024)
|
||||
sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine();
|
||||
|
||||
switch(csd.ReadCurrentAtVddMin & 0x07)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice uses a maximum of 0.5mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice uses a maximum of 1mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice uses a maximum of 5mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice uses a maximum of 10mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice uses a maximum of 25mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice uses a maximum of 35mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice uses a maximum of 60mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice uses a maximum of 100mA for reading at minimum voltage");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -398,27 +472,35 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice uses a maximum of 1mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice uses a maximum of 5mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice uses a maximum of 10mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice uses a maximum of 25mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice uses a maximum of 35mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice uses a maximum of 45mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice uses a maximum of 80mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice uses a maximum of 200mA for reading at maximum voltage");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -426,27 +508,35 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice uses a maximum of 0.5mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice uses a maximum of 1mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice uses a maximum of 5mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice uses a maximum of 10mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice uses a maximum of 25mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice uses a maximum of 35mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice uses a maximum of 60mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice uses a maximum of 100mA for writing at minimum voltage");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -454,27 +544,35 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice uses a maximum of 1mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice uses a maximum of 5mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice uses a maximum of 10mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice uses a maximum of 25mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice uses a maximum of 35mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice uses a maximum of 45mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice uses a maximum of 80mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice uses a maximum of 200mA for writing at maximum voltage");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -487,72 +585,92 @@ namespace DiscImageChef.Decoders.MMC
|
||||
if(csd.WriteProtectGroupEnable)
|
||||
{
|
||||
sb.AppendLine("\tDevice can write protect regions");
|
||||
|
||||
// TODO: Check specification
|
||||
unitFactor = Convert.ToDouble(csd.WriteProtectGroupSize);
|
||||
sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1))
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)).
|
||||
AppendLine();
|
||||
}
|
||||
else sb.AppendLine("\tDevice can't write protect regions");
|
||||
else
|
||||
sb.AppendLine("\tDevice can't write protect regions");
|
||||
|
||||
switch(csd.DefaultECC)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice uses no ECC by default");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice uses BCH(542, 512) ECC by default");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendFormat("\tDevice uses unknown ECC code {0} by default", csd.DefaultECC).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)).
|
||||
AppendLine();
|
||||
|
||||
if(csd.WriteBlockLength == 15) sb.AppendLine("\tWrite block length size is defined in extended CSD");
|
||||
else sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine();
|
||||
if(csd.WriteBlockLength == 15)
|
||||
sb.AppendLine("\tWrite block length size is defined in extended CSD");
|
||||
else
|
||||
sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine();
|
||||
|
||||
if(csd.WritesPartialBlocks) sb.AppendLine("\tDevice allows writing partial blocks");
|
||||
if(csd.WritesPartialBlocks)
|
||||
sb.AppendLine("\tDevice allows writing partial blocks");
|
||||
|
||||
if(csd.ContentProtection) sb.AppendLine("\tDevice supports content protection");
|
||||
if(csd.ContentProtection)
|
||||
sb.AppendLine("\tDevice supports content protection");
|
||||
|
||||
if(!csd.Copy) sb.AppendLine("\tDevice contents are original");
|
||||
if(!csd.Copy)
|
||||
sb.AppendLine("\tDevice contents are original");
|
||||
|
||||
if(csd.PermanentWriteProtect) sb.AppendLine("\tDevice is permanently write protected");
|
||||
if(csd.PermanentWriteProtect)
|
||||
sb.AppendLine("\tDevice is permanently write protected");
|
||||
|
||||
if(csd.TemporaryWriteProtect) sb.AppendLine("\tDevice is temporarily write protected");
|
||||
if(csd.TemporaryWriteProtect)
|
||||
sb.AppendLine("\tDevice is temporarily write protected");
|
||||
|
||||
if(!csd.FileFormatGroup)
|
||||
switch(csd.FileFormat)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice is formatted like a hard disk");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice is formatted like a floppy disk using Microsoft FAT");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice uses Universal File Format");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDevice uses unknown file format code {0}", csd.FileFormat).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat).
|
||||
AppendLine();
|
||||
|
||||
switch(csd.ECC)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice currently uses no ECC");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice currently uses BCH(542, 512) ECC by default");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendFormat("\tDevice currently uses unknown ECC code {0}", csd.DefaultECC).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,193 +37,192 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"),
|
||||
StructLayout(LayoutKind.Sequential)]
|
||||
public class ExtendedCSD
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[] Reserved0;
|
||||
public byte ExtendedSecurityCommandsError;
|
||||
public byte SupportedCommandSets;
|
||||
public byte HPIFeatures;
|
||||
public byte AccessSize;
|
||||
public byte AddressedGroupToBeReleased;
|
||||
public byte BackgroundOperationsStatus;
|
||||
public byte BackgroundOperationsSupport;
|
||||
public byte MaxPackedReadCommands;
|
||||
public byte MaxPackedWriteCommands;
|
||||
public byte DataTagSupport;
|
||||
public byte TagUnitSize;
|
||||
public byte TagResourcesSize;
|
||||
public byte ContextManagementCaps;
|
||||
public byte LargeUnitSize;
|
||||
public byte ExtendedPartitionsSupport;
|
||||
public byte SupportedModes;
|
||||
public byte FFUFeatures;
|
||||
public byte OperationCodesTimeout;
|
||||
public uint FFUArgument;
|
||||
public byte BadBlockManagementMode;
|
||||
public byte BarrierControl;
|
||||
public byte BarrierSupport;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)]
|
||||
public byte[] Reserved1;
|
||||
public byte CMDQueuingSupport;
|
||||
public byte BootAreaWriteProtectionRegister;
|
||||
public byte BootBusConditions;
|
||||
public byte BootConfigProtection;
|
||||
public byte BootInformation;
|
||||
public byte BootPartitionSize;
|
||||
public byte BootWriteProtectionStatus;
|
||||
public byte BusWidth;
|
||||
public byte CacheControl;
|
||||
public byte CacheFlushing;
|
||||
public byte CacheFlushingPolicy;
|
||||
public uint CacheSize;
|
||||
public byte Class6CommandsControl;
|
||||
public byte CMDQueuingDepth;
|
||||
public uint NumberofFWSectorsCorrectlyProgrammed;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public byte[] VendorHealthReport;
|
||||
public byte DeviceLifeEstimationTypeB;
|
||||
public byte DeviceLifeEstimationTypeA;
|
||||
public byte PreEOLInformation;
|
||||
public byte OptimalReadSize;
|
||||
public byte OptimalWriteSize;
|
||||
public byte OptimalTrimUnitSize;
|
||||
public ushort DeviceVersion;
|
||||
public ulong FirmwareVersion;
|
||||
public byte PowerClassDDR200;
|
||||
public uint CacheSize;
|
||||
public byte GenericCMD6Timeout;
|
||||
public byte PowerOffNotificationTimeout;
|
||||
public byte BackgroundOperationsStatus;
|
||||
public byte CMDQueuingSupport;
|
||||
public byte CommandQueueModeEnable;
|
||||
public byte CommandSet;
|
||||
public byte CommandSetRevision;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
|
||||
public byte[] ContextConfiguration;
|
||||
public byte ContextManagementCaps;
|
||||
public uint CorrectlyProgrammedSectors;
|
||||
public byte InitializationTimeAfterPartition;
|
||||
public byte CacheFlushingPolicy;
|
||||
public byte PowerClassDDR52;
|
||||
public byte PowerClassDDR52_195;
|
||||
public byte PowerClassDDR200_195;
|
||||
public byte PowerClassDDR200_130;
|
||||
public byte MinimumWritePerformanceDDR52;
|
||||
public byte MinimumReadPerformanceDDR52;
|
||||
public byte Reserved2;
|
||||
public byte TRIMMultiplier;
|
||||
public byte SecureFeatureSupport;
|
||||
public byte SecureEraseMultiplier;
|
||||
public byte SecureTRIMMultiplier;
|
||||
public byte BootInformation;
|
||||
public byte Reserved3;
|
||||
public byte BootPartitionSize;
|
||||
public byte AccessSize;
|
||||
public byte HighCapacityEraseUnitSize;
|
||||
public byte HighCapacityEraseTimeout;
|
||||
public byte ReliableWriteSectorCount;
|
||||
public byte HighCapacityWriteProtectGroupSize;
|
||||
public byte SleepCurrentVcc;
|
||||
public byte SleepCurrentVccq;
|
||||
public byte ProductionStateAwarenessTimeout;
|
||||
public byte SleepAwakeTimeout;
|
||||
public byte SleepNotificationTimeout;
|
||||
public uint SectorCount;
|
||||
public byte SecureWriteProtectInformation;
|
||||
public byte MinimumWritePerformance52;
|
||||
public byte MinimumReadPerformance52;
|
||||
public byte MinimumWritePerformance26;
|
||||
public byte MinimumReadPerformance26;
|
||||
public byte MinimumWritePerformance26_4;
|
||||
public byte MinimumReadPerformance26_4;
|
||||
public byte Reserved4;
|
||||
public byte PowerClass26;
|
||||
public byte PowerClass52;
|
||||
public byte PowerClass26_195;
|
||||
public byte PowerClass52_195;
|
||||
public byte PartitionSwitchingTime;
|
||||
public byte OutOfInterruptBusyTiming;
|
||||
public byte DriverStrength;
|
||||
public byte DataTagSupport;
|
||||
public byte DeviceLifeEstimationTypeA;
|
||||
public byte DeviceLifeEstimationTypeB;
|
||||
public byte DeviceType;
|
||||
public byte Reserved5;
|
||||
public byte Structure;
|
||||
public byte Reserved6;
|
||||
public byte Revision;
|
||||
public byte CommandSet;
|
||||
public byte Reserved7;
|
||||
public byte CommandSetRevision;
|
||||
public byte Reserved8;
|
||||
public byte PowerClass;
|
||||
public byte Reserved9;
|
||||
public byte HighSpeedInterfaceTiming;
|
||||
public byte StrobeSupport;
|
||||
public byte BusWidth;
|
||||
public byte Reserved10;
|
||||
public byte ErasedMemoryContent;
|
||||
public byte Reserved11;
|
||||
public byte PartitionConfiguration;
|
||||
public byte BootConfigProtection;
|
||||
public byte BootBusConditions;
|
||||
public byte Reserved12;
|
||||
public byte HighDensityEraseGroupDefinition;
|
||||
public byte BootWriteProtectionStatus;
|
||||
public byte BootAreaWriteProtectionRegister;
|
||||
public byte Reserved13;
|
||||
public byte UserAreaWriteProtectionRegister;
|
||||
public byte Reserved14;
|
||||
public byte FirmwareConfiguration;
|
||||
public byte RPMBSize;
|
||||
public byte WriteReliabilitySettingRegister;
|
||||
public byte WriteReliabilityParameterRegister;
|
||||
public byte StartSanitizeOperation;
|
||||
public byte ManuallyStartBackgroundOperations;
|
||||
public ushort DeviceVersion;
|
||||
public byte DriverStrength;
|
||||
public byte EnableBackgroundOperationsHandshake;
|
||||
public byte HWResetFunction;
|
||||
public byte HPIManagement;
|
||||
public byte PartitioningSupport;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] MaxEnhancedAreaSize;
|
||||
public byte PartitionsAttribute;
|
||||
public byte PartitioningSetting;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] GeneralPurposePartitionSize;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] EnhancedUserDataAreaSize;
|
||||
public uint EnhancedUserDataStartAddress;
|
||||
public byte Reserved15;
|
||||
public byte BadBlockManagementMode;
|
||||
public byte ProductionStateAwareness;
|
||||
public byte PackageCaseTemperatureControl;
|
||||
public byte PeriodicWakeUp;
|
||||
public byte SupportsProgramCxDInDDR;
|
||||
public ushort Reserved16;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
||||
public byte[] VendorSpecific;
|
||||
public byte NativeSectorSize;
|
||||
public byte SectorSizeEmulation;
|
||||
public byte SectorSize;
|
||||
public byte InitializationTimeout;
|
||||
public byte Class6CommandsControl;
|
||||
public byte AddressedGroupToBeReleased;
|
||||
public byte ErasedMemoryContent;
|
||||
public ushort ExceptionEventsControl;
|
||||
public ushort ExceptionEventsStatus;
|
||||
public ushort ExtendedPartitionsAttribute;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
|
||||
public byte[] ContextConfiguration;
|
||||
public byte PackedCommandStatus;
|
||||
public byte PackedCommandFailureIndex;
|
||||
public byte PowerOffNotification;
|
||||
public byte CacheControl;
|
||||
public byte CacheFlushing;
|
||||
public byte BarrierControl;
|
||||
public byte ModeConfig;
|
||||
public byte ModeOperationCodes;
|
||||
public ushort Reserved17;
|
||||
public byte ExtendedPartitionsSupport;
|
||||
public byte ExtendedSecurityCommandsError;
|
||||
public uint FFUArgument;
|
||||
public byte FFUFeatures;
|
||||
public byte FFUStatus;
|
||||
public uint PreLoadingDataSize;
|
||||
public uint MaxPreLoadingDataSize;
|
||||
public byte ProductStateAwarenessEnablement;
|
||||
public byte SecureRemovalType;
|
||||
public byte CommandQueueModeEnable;
|
||||
public byte FirmwareConfiguration;
|
||||
public ulong FirmwareVersion;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] GeneralPurposePartitionSize;
|
||||
public byte GenericCMD6Timeout;
|
||||
public byte HighCapacityEraseTimeout;
|
||||
public byte HighCapacityEraseUnitSize;
|
||||
public byte HighCapacityWriteProtectGroupSize;
|
||||
public byte HighDensityEraseGroupDefinition;
|
||||
public byte HighSpeedInterfaceTiming;
|
||||
public byte HPIFeatures;
|
||||
public byte HPIManagement;
|
||||
public byte HWResetFunction;
|
||||
public byte InitializationTimeAfterPartition;
|
||||
public byte InitializationTimeout;
|
||||
public byte LargeUnitSize;
|
||||
public byte ManuallyStartBackgroundOperations;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public byte[] MaxEnhancedAreaSize;
|
||||
public byte MaxPackedReadCommands;
|
||||
public byte MaxPackedWriteCommands;
|
||||
public uint MaxPreLoadingDataSize;
|
||||
public byte MinimumReadPerformance26;
|
||||
public byte MinimumReadPerformance26_4;
|
||||
public byte MinimumReadPerformance52;
|
||||
public byte MinimumReadPerformanceDDR52;
|
||||
public byte MinimumWritePerformance26;
|
||||
public byte MinimumWritePerformance26_4;
|
||||
public byte MinimumWritePerformance52;
|
||||
public byte MinimumWritePerformanceDDR52;
|
||||
public byte ModeConfig;
|
||||
public byte ModeOperationCodes;
|
||||
public byte NativeSectorSize;
|
||||
public uint NumberofFWSectorsCorrectlyProgrammed;
|
||||
public byte OperationCodesTimeout;
|
||||
public byte OptimalReadSize;
|
||||
public byte OptimalTrimUnitSize;
|
||||
public byte OptimalWriteSize;
|
||||
public byte OutOfInterruptBusyTiming;
|
||||
public byte PackageCaseTemperatureControl;
|
||||
public byte PackedCommandFailureIndex;
|
||||
public byte PackedCommandStatus;
|
||||
public byte PartitionConfiguration;
|
||||
public byte PartitioningSetting;
|
||||
public byte PartitioningSupport;
|
||||
public byte PartitionsAttribute;
|
||||
public byte PartitionSwitchingTime;
|
||||
public byte PeriodicWakeUp;
|
||||
public byte PowerClass;
|
||||
public byte PowerClass26;
|
||||
public byte PowerClass26_195;
|
||||
public byte PowerClass52;
|
||||
public byte PowerClass52_195;
|
||||
public byte PowerClassDDR200;
|
||||
public byte PowerClassDDR200_130;
|
||||
public byte PowerClassDDR200_195;
|
||||
public byte PowerClassDDR52;
|
||||
public byte PowerClassDDR52_195;
|
||||
public byte PowerOffNotification;
|
||||
public byte PowerOffNotificationTimeout;
|
||||
public byte PreEOLInformation;
|
||||
public uint PreLoadingDataSize;
|
||||
public byte ProductionStateAwareness;
|
||||
public byte ProductionStateAwarenessTimeout;
|
||||
public byte ProductStateAwarenessEnablement;
|
||||
public byte ReliableWriteSectorCount;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
||||
public byte[] Reserved0;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)]
|
||||
public byte[] Reserved1;
|
||||
public byte Reserved10;
|
||||
public byte Reserved11;
|
||||
public byte Reserved12;
|
||||
public byte Reserved13;
|
||||
public byte Reserved14;
|
||||
public byte Reserved15;
|
||||
public ushort Reserved16;
|
||||
public ushort Reserved17;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
|
||||
public byte[] Reserved18;
|
||||
public byte Reserved2;
|
||||
public byte Reserved3;
|
||||
public byte Reserved4;
|
||||
public byte Reserved5;
|
||||
public byte Reserved6;
|
||||
public byte Reserved7;
|
||||
public byte Reserved8;
|
||||
public byte Reserved9;
|
||||
public byte Revision;
|
||||
public byte RPMBSize;
|
||||
public uint SectorCount;
|
||||
public byte SectorSize;
|
||||
public byte SectorSizeEmulation;
|
||||
public byte SecureEraseMultiplier;
|
||||
public byte SecureFeatureSupport;
|
||||
public byte SecureRemovalType;
|
||||
public byte SecureTRIMMultiplier;
|
||||
public byte SecureWriteProtectInformation;
|
||||
public byte SleepAwakeTimeout;
|
||||
public byte SleepCurrentVcc;
|
||||
public byte SleepCurrentVccq;
|
||||
public byte SleepNotificationTimeout;
|
||||
public byte StartSanitizeOperation;
|
||||
public byte StrobeSupport;
|
||||
public byte Structure;
|
||||
public byte SupportedCommandSets;
|
||||
public byte SupportedModes;
|
||||
public byte SupportsProgramCxDInDDR;
|
||||
public byte TagResourcesSize;
|
||||
public byte TagUnitSize;
|
||||
public byte TRIMMultiplier;
|
||||
public byte UserAreaWriteProtectionRegister;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public byte[] VendorHealthReport;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
|
||||
public byte[] VendorSpecific;
|
||||
public byte WriteReliabilityParameterRegister;
|
||||
public byte WriteReliabilitySettingRegister;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Decoders
|
||||
{
|
||||
public static ExtendedCSD DecodeExtendedCSD(byte[] response)
|
||||
{
|
||||
if(response == null) return null;
|
||||
if(response == null)
|
||||
return null;
|
||||
|
||||
if(response.Length != 512) return null;
|
||||
if(response.Length != 512)
|
||||
return null;
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(response, GCHandleType.Pinned);
|
||||
ExtendedCSD csd = (ExtendedCSD)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedCSD));
|
||||
GCHandle handle = GCHandle.Alloc(response, GCHandleType.Pinned);
|
||||
var csd = (ExtendedCSD)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedCSD));
|
||||
handle.Free();
|
||||
|
||||
return csd;
|
||||
@@ -231,16 +230,16 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
public static string PrettifyExtendedCSD(ExtendedCSD csd)
|
||||
{
|
||||
if(csd == null) return null;
|
||||
if(csd == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("MultiMediaCard Extended Device Specific Data Register:");
|
||||
|
||||
double unit;
|
||||
|
||||
if((csd.HPIFeatures & 0x01) == 0x01)
|
||||
sb.AppendLine((csd.HPIFeatures & 0x02) == 0x02
|
||||
? "\tDevice implements HPI using CMD12"
|
||||
sb.AppendLine((csd.HPIFeatures & 0x02) == 0x02 ? "\tDevice implements HPI using CMD12"
|
||||
: "\tDevice implements HPI using CMD13");
|
||||
|
||||
if((csd.BackgroundOperationsSupport & 0x01) == 0x01)
|
||||
@@ -257,53 +256,68 @@ namespace DiscImageChef.Decoders.MMC
|
||||
|
||||
if((csd.ExtendedPartitionsSupport & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice supports non-persistent extended partitions");
|
||||
|
||||
if((csd.ExtendedPartitionsSupport & 0x02) == 0x02)
|
||||
sb.AppendLine("\tDevice supports system code extended partitions");
|
||||
|
||||
if((csd.SupportedModes & 0x01) == 0x01) sb.AppendLine("\tDevice supports FFU");
|
||||
if((csd.SupportedModes & 0x02) == 0x02) sb.AppendLine("\tDevice supports Vendor Specific Mode");
|
||||
if((csd.SupportedModes & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice supports FFU");
|
||||
|
||||
if((csd.SupportedModes & 0x02) == 0x02)
|
||||
sb.AppendLine("\tDevice supports Vendor Specific Mode");
|
||||
|
||||
if((csd.CMDQueuingSupport & 0x01) == 0x01)
|
||||
sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberofFWSectorsCorrectlyProgrammed)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberofFWSectorsCorrectlyProgrammed).
|
||||
AppendLine();
|
||||
|
||||
switch(csd.DeviceLifeEstimationTypeB)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 8:
|
||||
sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 9:
|
||||
sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 10:
|
||||
sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 11:
|
||||
sb.AppendLine("\tDevice exceeded its maximum estimated life time");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -311,36 +325,47 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 8:
|
||||
sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 9:
|
||||
sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 10:
|
||||
sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time");
|
||||
|
||||
break;
|
||||
case 11:
|
||||
sb.AppendLine("\tDevice exceeded its maximum estimated life time");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -348,12 +373,15 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice informs it's in good health");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice informs it should be replaced soon");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice informs it should be replace immediately");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -364,31 +392,37 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice version: {0}", csd.DeviceVersion).AppendLine();
|
||||
sb.AppendFormat("\tFirmware version: {0}", csd.FirmwareVersion).AppendLine();
|
||||
|
||||
if(csd.CacheSize == 0) sb.AppendLine("\tDevice has no cache");
|
||||
else sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize).AppendLine();
|
||||
if(csd.CacheSize == 0)
|
||||
sb.AppendLine("\tDevice has no cache");
|
||||
else
|
||||
sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize).AppendLine();
|
||||
|
||||
if(csd.GenericCMD6Timeout > 0)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms by default for a SWITCH command",
|
||||
csd.GenericCMD6Timeout * 10).AppendLine();
|
||||
|
||||
if(csd.PowerOffNotificationTimeout > 0)
|
||||
sb
|
||||
.AppendFormat("\tDevice takes a maximum of {0} by default to power off from a SWITCH command notification",
|
||||
sb.
|
||||
AppendFormat("\tDevice takes a maximum of {0} by default to power off from a SWITCH command notification",
|
||||
csd.PowerOffNotificationTimeout * 10).AppendLine();
|
||||
|
||||
switch(csd.BackgroundOperationsStatus & 0x03)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice has no pending background operations");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice has non critical operations outstanding");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice has performance impacted operations outstanding");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice has critical operations outstanding");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -406,30 +440,41 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms for trimming a single erase group",
|
||||
csd.TRIMMultiplier * 300).AppendLine();
|
||||
|
||||
if((csd.SecureFeatureSupport & 0x40) == 0x40) sb.AppendLine("\tDevice supports the sanitize operation");
|
||||
if((csd.SecureFeatureSupport & 0x40) == 0x40)
|
||||
sb.AppendLine("\tDevice supports the sanitize operation");
|
||||
|
||||
if((csd.SecureFeatureSupport & 0x10) == 0x10)
|
||||
sb.AppendLine("\tDevice supports supports the secure and insecure trim operations");
|
||||
|
||||
if((csd.SecureFeatureSupport & 0x04) == 0x04)
|
||||
sb.AppendLine("\tDevice supports automatic erase on retired defective blocks");
|
||||
if((csd.SecureFeatureSupport & 0x01) == 0x01) sb.AppendLine("\tDevice supports secure purge operations");
|
||||
|
||||
if((csd.SecureFeatureSupport & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice supports secure purge operations");
|
||||
|
||||
if(csd.SecureEraseMultiplier > 0)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely erasing a single erase group",
|
||||
csd.SecureEraseMultiplier * 300).AppendLine();
|
||||
|
||||
if(csd.SecureTRIMMultiplier > 0)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely trimming a single erase group",
|
||||
csd.SecureTRIMMultiplier * 300).AppendLine();
|
||||
|
||||
if((csd.BootInformation & 0x04) == 0x04) sb.AppendLine("\tDevice supports high speed timing on boot");
|
||||
if((csd.BootInformation & 0x02) == 0x02) sb.AppendLine("\tDevice supports dual data rate on boot");
|
||||
if((csd.BootInformation & 0x01) == 0x01) sb.AppendLine("\tDevice supports alternative boot method");
|
||||
if((csd.BootInformation & 0x04) == 0x04)
|
||||
sb.AppendLine("\tDevice supports high speed timing on boot");
|
||||
|
||||
if((csd.BootInformation & 0x02) == 0x02)
|
||||
sb.AppendLine("\tDevice supports dual data rate on boot");
|
||||
|
||||
if((csd.BootInformation & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice supports alternative boot method");
|
||||
|
||||
if(csd.BootPartitionSize > 0)
|
||||
sb.AppendFormat("\tDevice has a {0} KiB boot partition", csd.BootPartitionSize * 128).AppendLine();
|
||||
|
||||
if((csd.AccessSize & 0x0F) > 0)
|
||||
sb.AppendFormat("\tDevice has a page size of {0} KiB", (csd.AccessSize & 0x0F) * 512.0 / 1024.0)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice has a page size of {0} KiB", (csd.AccessSize & 0x0F) * 512.0 / 1024.0).
|
||||
AppendLine();
|
||||
|
||||
if(csd.HighCapacityEraseUnitSize > 0)
|
||||
sb.AppendFormat("\tDevice erase groups are {0} KiB", csd.HighCapacityEraseUnitSize * 512).AppendLine();
|
||||
@@ -445,20 +490,27 @@ namespace DiscImageChef.Decoders.MMC
|
||||
if(csd.SleepCurrentVcc > 0)
|
||||
{
|
||||
unit = Math.Pow(2, csd.SleepCurrentVcc);
|
||||
if(unit > 1000) sb.AppendFormat("\tDevice uses {0} mA on Vcc when sleeping", unit / 1000).AppendLine();
|
||||
else sb.AppendFormat("\tDevice uses {0} μA on Vcc when sleeping", unit).AppendLine();
|
||||
|
||||
if(unit > 1000)
|
||||
sb.AppendFormat("\tDevice uses {0} mA on Vcc when sleeping", unit / 1000).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDevice uses {0} μA on Vcc when sleeping", unit).AppendLine();
|
||||
}
|
||||
|
||||
if(csd.SleepCurrentVccq > 0)
|
||||
{
|
||||
unit = Math.Pow(2, csd.SleepCurrentVccq);
|
||||
if(unit > 1000) sb.AppendFormat("\tDevice uses {0} mA on Vccq when sleeping", unit / 1000).AppendLine();
|
||||
else sb.AppendFormat("\tDevice uses {0} μA on Vccq when sleeping", unit).AppendLine();
|
||||
|
||||
if(unit > 1000)
|
||||
sb.AppendFormat("\tDevice uses {0} mA on Vccq when sleeping", unit / 1000).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDevice uses {0} μA on Vccq when sleeping", unit).AppendLine();
|
||||
}
|
||||
|
||||
if(csd.ProductionStateAwarenessTimeout > 0)
|
||||
{
|
||||
unit = Math.Pow(2, csd.ProductionStateAwareness) * 100;
|
||||
|
||||
if(unit > 1000000)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} s to switch production state awareness",
|
||||
unit / 1000000).AppendLine();
|
||||
@@ -466,13 +518,14 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms to switch production state awareness",
|
||||
unit / 1000).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} μs to switch production state awareness", unit)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} μs to switch production state awareness", unit).
|
||||
AppendLine();
|
||||
}
|
||||
|
||||
if(csd.SleepAwakeTimeout > 0)
|
||||
{
|
||||
unit = Math.Pow(2, csd.SleepAwakeTimeout) * 100;
|
||||
|
||||
if(unit > 1000000)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms to transition between sleep and standby states",
|
||||
unit / 1000000).AppendLine();
|
||||
@@ -487,13 +540,15 @@ namespace DiscImageChef.Decoders.MMC
|
||||
if(csd.SleepNotificationTimeout > 0)
|
||||
{
|
||||
unit = Math.Pow(2, csd.SleepNotificationTimeout) * 10;
|
||||
|
||||
if(unit > 1000000)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} s to move to sleep state", unit / 1000000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} s to move to sleep state", unit / 1000000).
|
||||
AppendLine();
|
||||
else if(unit > 1000)
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms to move to sleep state", unit / 1000)
|
||||
.AppendLine();
|
||||
else sb.AppendFormat("\tDevice takes a maximum of {0} μs to move to sleep state", unit).AppendLine();
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} ms to move to sleep state", unit / 1000).
|
||||
AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDevice takes a maximum of {0} μs to move to sleep state", unit).AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendFormat("\tDevice has {0} sectors", csd.SectorCount).AppendLine();
|
||||
@@ -501,18 +556,21 @@ namespace DiscImageChef.Decoders.MMC
|
||||
if((csd.SecureWriteProtectInformation & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("\tDevice supports secure write protection");
|
||||
|
||||
if((csd.SecureWriteProtectInformation & 0x02) == 0x02)
|
||||
sb.AppendLine("\tDevice has secure write protection enabled");
|
||||
}
|
||||
|
||||
unit = csd.MinimumReadPerformance26 * 150;
|
||||
|
||||
if(csd.MinimumReadPerformance26 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
unit = csd.MinimumReadPerformance26_4 * 150;
|
||||
|
||||
if(csd.MinimumReadPerformance26_4 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz 4-bit mode");
|
||||
else
|
||||
@@ -520,27 +578,31 @@ namespace DiscImageChef.Decoders.MMC
|
||||
unit / 1000).AppendLine();
|
||||
|
||||
unit = csd.MinimumReadPerformance52 * 150;
|
||||
|
||||
if(csd.MinimumReadPerformance52 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 52Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
unit = csd.MinimumReadPerformanceDDR52 * 300;
|
||||
|
||||
if(csd.MinimumReadPerformanceDDR52 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 4.8MB/s reading in DDR 52Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
unit = csd.MinimumWritePerformance26 * 150;
|
||||
|
||||
if(csd.MinimumWritePerformance26 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
unit = csd.MinimumWritePerformance26_4 * 150;
|
||||
|
||||
if(csd.MinimumWritePerformance26_4 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz 4-bit mode");
|
||||
else
|
||||
@@ -548,18 +610,20 @@ namespace DiscImageChef.Decoders.MMC
|
||||
unit / 1000).AppendLine();
|
||||
|
||||
unit = csd.MinimumWritePerformance52 * 150;
|
||||
|
||||
if(csd.MinimumWritePerformance52 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 52Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
unit = csd.MinimumWritePerformanceDDR52 * 300;
|
||||
|
||||
if(csd.MinimumWritePerformanceDDR52 == 0)
|
||||
sb.AppendLine("\tDevice cannot achieve 4.8MB/s writing in DDR 52Mhz mode");
|
||||
else
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in DDR 52Mhz mode", unit / 1000)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in DDR 52Mhz mode", unit / 1000).
|
||||
AppendLine();
|
||||
|
||||
if(csd.PartitionSwitchingTime > 0)
|
||||
sb.AppendFormat("\tDevice can take a maximum of {0} ms when switching partitions",
|
||||
@@ -569,20 +633,36 @@ namespace DiscImageChef.Decoders.MMC
|
||||
sb.AppendFormat("\tDevice can take a maximum of {0} ms when releasing from an interrupt",
|
||||
csd.OutOfInterruptBusyTiming * 10).AppendLine();
|
||||
|
||||
if((csd.DeviceType & 0x01) == 0x01) sb.AppendLine("\tDevice supports 26 Mhz mode");
|
||||
if((csd.DeviceType & 0x02) == 0x02) sb.AppendLine("\tDevice supports 52 Mhz mode");
|
||||
if((csd.DeviceType & 0x04) == 0x04) sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V");
|
||||
if((csd.DeviceType & 0x08) == 0x08) sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V");
|
||||
if((csd.DeviceType & 0x10) == 0x10) sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V");
|
||||
if((csd.DeviceType & 0x20) == 0x20) sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V");
|
||||
if((csd.DeviceType & 0x40) == 0x40) sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V");
|
||||
if((csd.DeviceType & 0x80) == 0x80) sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V");
|
||||
if((csd.DeviceType & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice supports 26 Mhz mode");
|
||||
|
||||
if((csd.DeviceType & 0x02) == 0x02)
|
||||
sb.AppendLine("\tDevice supports 52 Mhz mode");
|
||||
|
||||
if((csd.DeviceType & 0x04) == 0x04)
|
||||
sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V");
|
||||
|
||||
if((csd.DeviceType & 0x08) == 0x08)
|
||||
sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V");
|
||||
|
||||
if((csd.DeviceType & 0x10) == 0x10)
|
||||
sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V");
|
||||
|
||||
if((csd.DeviceType & 0x20) == 0x20)
|
||||
sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V");
|
||||
|
||||
if((csd.DeviceType & 0x40) == 0x40)
|
||||
sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V");
|
||||
|
||||
if((csd.DeviceType & 0x80) == 0x80)
|
||||
sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V");
|
||||
|
||||
sb.AppendFormat("\tCSD version 1.{0} revision 1.{1}", csd.Structure, csd.Revision).AppendLine();
|
||||
|
||||
if((csd.StrobeSupport & 0x01) == 0x01)
|
||||
{
|
||||
sb.AppendLine("\tDevice supports enhanced strobe mode");
|
||||
|
||||
sb.AppendLine((csd.BusWidth & 0x80) == 0x80
|
||||
? "\tDevice uses strobe during Data Out, CRC and CMD responses"
|
||||
: "\tDevice uses strobe during Data Out and CRC responses");
|
||||
@@ -592,43 +672,55 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice is using 1-bit data bus");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice is using 4-bit data bus");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice is using 8-bit data bus");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDevice is using 4-bit DDR data bus");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDevice is using 8-bit DDR data bus");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDevice is using unknown data bus code {0}", csd.BusWidth & 0x0F).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if((csd.PartitionConfiguration & 0x80) == 0x80) sb.AppendLine("\tDevice sends boot acknowledge");
|
||||
if((csd.PartitionConfiguration & 0x80) == 0x80)
|
||||
sb.AppendLine("\tDevice sends boot acknowledge");
|
||||
|
||||
switch((csd.PartitionConfiguration & 0x38) >> 3)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice is not boot enabled");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice boot partition 1 is enabled");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice boot partition 2 is enabled");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDevice user area is enable for boot");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown enabled boot partition code {0}",
|
||||
(csd.PartitionConfiguration & 0x38) >> 3).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -636,39 +728,48 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tThere is no access to boot partition");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tThere is read/write access to boot partition 1");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tThere is read/write access to boot partition 2");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tThere is read/write access to replay protected memory block");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tThere is access to general purpose partition {0}",
|
||||
(csd.PartitionConfiguration & 0x07) - 3).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if((csd.FirmwareConfiguration & 0x01) == 0x01) sb.AppendLine("\tFirmware updates are permanently disabled");
|
||||
if((csd.FirmwareConfiguration & 0x01) == 0x01)
|
||||
sb.AppendLine("\tFirmware updates are permanently disabled");
|
||||
|
||||
if(csd.RPMBSize > 0)
|
||||
sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128).
|
||||
AppendLine();
|
||||
|
||||
switch(csd.NativeSectorSize)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice natively uses 512 byte sectors");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice natively uses 4096 byte sectors");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDevice natively uses unknown sector size indicated by code {0}",
|
||||
csd.NativeSectorSize).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -676,13 +777,16 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice is emulating 512 byte sectors");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice is using natively sized sectors");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDevice emulates unknown sector size indicated by code {0}", csd.NativeSectorSize)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDevice emulates unknown sector size indicated by code {0}",
|
||||
csd.NativeSectorSize).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -690,19 +794,24 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice currently addresses 512 byte sectors");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice currently addresses 4096 byte sectors");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDevice currently addresses unknown sector size indicated by code {0}",
|
||||
csd.NativeSectorSize).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if((csd.CacheControl & 0x01) == 0x01) sb.AppendLine("\tDevice's cache is enabled");
|
||||
if((csd.CacheControl & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice's cache is enabled");
|
||||
|
||||
if((csd.CommandQueueModeEnable & 0x01) == 0x01) sb.AppendLine("\tDevice has enabled command queuing");
|
||||
if((csd.CommandQueueModeEnable & 0x01) == 0x01)
|
||||
sb.AppendLine("\tDevice has enabled command queuing");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
137
MMC/OCR.cs
137
MMC/OCR.cs
@@ -36,101 +36,126 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public class OCR
|
||||
{
|
||||
public bool PowerUp;
|
||||
public byte AccessMode;
|
||||
public bool OneSix;
|
||||
public bool PowerUp;
|
||||
public bool ThreeFive;
|
||||
public bool ThreeFour;
|
||||
public bool ThreeOne;
|
||||
public bool ThreeThree;
|
||||
public bool ThreeTwo;
|
||||
public bool ThreeOne;
|
||||
public bool ThreeZero;
|
||||
public bool TwoNine;
|
||||
public bool TwoEight;
|
||||
public bool TwoSeven;
|
||||
public bool TwoSix;
|
||||
public bool TwoFive;
|
||||
public bool TwoFour;
|
||||
public bool TwoNine;
|
||||
public bool TwoOne;
|
||||
public bool TwoSeven;
|
||||
public bool TwoSix;
|
||||
public bool TwoThree;
|
||||
public bool TwoTwo;
|
||||
public bool TwoOne;
|
||||
public bool TwoZero;
|
||||
public bool OneSix;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Decoders
|
||||
{
|
||||
public static OCR DecodeOCR(uint response) =>
|
||||
new OCR
|
||||
{
|
||||
PowerUp = (response & 0x80000000) == 0x80000000,
|
||||
AccessMode = (byte)((response & 0x60000000) >> 29),
|
||||
ThreeFive = (response & 0x00800000) == 0x00800000,
|
||||
ThreeFour = (response & 0x00400000) == 0x00400000,
|
||||
ThreeThree = (response & 0x00200000) == 0x00200000,
|
||||
ThreeTwo = (response & 0x00100000) == 0x00100000,
|
||||
ThreeOne = (response & 0x00080000) == 0x00080000,
|
||||
ThreeZero = (response & 0x00040000) == 0x00040000,
|
||||
TwoNine = (response & 0x00020000) == 0x00020000,
|
||||
TwoEight = (response & 0x00010000) == 0x00010000,
|
||||
TwoSeven = (response & 0x00008000) == 0x00008000,
|
||||
TwoSix = (response & 0x00004000) == 0x00004000,
|
||||
TwoFive = (response & 0x00002000) == 0x00002000,
|
||||
TwoFour = (response & 0x00001000) == 0x00001000,
|
||||
TwoThree = (response & 0x00000800) == 0x00000800,
|
||||
TwoTwo = (response & 0x00000400) == 0x00000400,
|
||||
TwoOne = (response & 0x00000200) == 0x00000200,
|
||||
TwoZero = (response & 0x00000100) == 0x00000100,
|
||||
OneSix = (response & 0x00000080) == 0x00000080
|
||||
};
|
||||
public static OCR DecodeOCR(uint response) => new OCR
|
||||
{
|
||||
PowerUp = (response & 0x80000000) == 0x80000000, AccessMode = (byte)((response & 0x60000000) >> 29),
|
||||
ThreeFive = (response & 0x00800000) == 0x00800000, ThreeFour = (response & 0x00400000) == 0x00400000,
|
||||
ThreeThree = (response & 0x00200000) == 0x00200000, ThreeTwo = (response & 0x00100000) == 0x00100000,
|
||||
ThreeOne = (response & 0x00080000) == 0x00080000, ThreeZero = (response & 0x00040000) == 0x00040000,
|
||||
TwoNine = (response & 0x00020000) == 0x00020000, TwoEight = (response & 0x00010000) == 0x00010000,
|
||||
TwoSeven = (response & 0x00008000) == 0x00008000, TwoSix = (response & 0x00004000) == 0x00004000,
|
||||
TwoFive = (response & 0x00002000) == 0x00002000, TwoFour = (response & 0x00001000) == 0x00001000,
|
||||
TwoThree = (response & 0x00000800) == 0x00000800, TwoTwo = (response & 0x00000400) == 0x00000400,
|
||||
TwoOne = (response & 0x00000200) == 0x00000200, TwoZero = (response & 0x00000100) == 0x00000100,
|
||||
OneSix = (response & 0x00000080) == 0x00000080
|
||||
};
|
||||
|
||||
public static OCR DecodeOCR(byte[] response) =>
|
||||
response?.Length != 4 ? null : DecodeOCR(BitConverter.ToUInt32(response, 0));
|
||||
|
||||
public static string PrettifyOCR(OCR ocr)
|
||||
{
|
||||
if(ocr == null) return null;
|
||||
if(ocr == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("MultiMediaCard Operation Conditions Register:");
|
||||
if(!ocr.PowerUp) sb.AppendLine("\tDevice is powering up");
|
||||
|
||||
if(!ocr.PowerUp)
|
||||
sb.AppendLine("\tDevice is powering up");
|
||||
|
||||
switch(ocr.AccessMode)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDevice is byte addressed");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice is sector addressed");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown device access mode {0}", ocr.AccessMode).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(ocr.ThreeFive) sb.AppendLine("\tDevice can work with supply 3.5~3.6V");
|
||||
if(ocr.ThreeFour) sb.AppendLine("\tDevice can work with supply 3.4~3.5V");
|
||||
if(ocr.ThreeThree) sb.AppendLine("\tDevice can work with supply 3.3~3.4V");
|
||||
if(ocr.ThreeTwo) sb.AppendLine("\tDevice can work with supply 3.2~3.3V");
|
||||
if(ocr.ThreeOne) sb.AppendLine("\tDevice can work with supply 3.1~3.2V");
|
||||
if(ocr.TwoNine) sb.AppendLine("\tDevice can work with supply 2.9~3.0V");
|
||||
if(ocr.TwoEight) sb.AppendLine("\tDevice can work with supply 2.8~2.9V");
|
||||
if(ocr.TwoSeven) sb.AppendLine("\tDevice can work with supply 2.7~2.8V");
|
||||
if(ocr.TwoSix) sb.AppendLine("\tDevice can work with supply 2.6~2.7V");
|
||||
if(ocr.TwoFive) sb.AppendLine("\tDevice can work with supply 2.5~2.6V");
|
||||
if(ocr.TwoFour) sb.AppendLine("\tDevice can work with supply 2.4~2.5V");
|
||||
if(ocr.TwoThree) sb.AppendLine("\tDevice can work with supply 2.3~2.4V");
|
||||
if(ocr.TwoTwo) sb.AppendLine("\tDevice can work with supply 2.2~2.3V");
|
||||
if(ocr.TwoOne) sb.AppendLine("\tDevice can work with supply 2.1~2.2V");
|
||||
if(ocr.TwoZero) sb.AppendLine("\tDevice can work with supply 2.0~2.1V");
|
||||
if(ocr.OneSix) sb.AppendLine("\tDevice can work with supply 1.65~1.95V");
|
||||
if(ocr.ThreeFive)
|
||||
sb.AppendLine("\tDevice can work with supply 3.5~3.6V");
|
||||
|
||||
if(ocr.ThreeFour)
|
||||
sb.AppendLine("\tDevice can work with supply 3.4~3.5V");
|
||||
|
||||
if(ocr.ThreeThree)
|
||||
sb.AppendLine("\tDevice can work with supply 3.3~3.4V");
|
||||
|
||||
if(ocr.ThreeTwo)
|
||||
sb.AppendLine("\tDevice can work with supply 3.2~3.3V");
|
||||
|
||||
if(ocr.ThreeOne)
|
||||
sb.AppendLine("\tDevice can work with supply 3.1~3.2V");
|
||||
|
||||
if(ocr.TwoNine)
|
||||
sb.AppendLine("\tDevice can work with supply 2.9~3.0V");
|
||||
|
||||
if(ocr.TwoEight)
|
||||
sb.AppendLine("\tDevice can work with supply 2.8~2.9V");
|
||||
|
||||
if(ocr.TwoSeven)
|
||||
sb.AppendLine("\tDevice can work with supply 2.7~2.8V");
|
||||
|
||||
if(ocr.TwoSix)
|
||||
sb.AppendLine("\tDevice can work with supply 2.6~2.7V");
|
||||
|
||||
if(ocr.TwoFive)
|
||||
sb.AppendLine("\tDevice can work with supply 2.5~2.6V");
|
||||
|
||||
if(ocr.TwoFour)
|
||||
sb.AppendLine("\tDevice can work with supply 2.4~2.5V");
|
||||
|
||||
if(ocr.TwoThree)
|
||||
sb.AppendLine("\tDevice can work with supply 2.3~2.4V");
|
||||
|
||||
if(ocr.TwoTwo)
|
||||
sb.AppendLine("\tDevice can work with supply 2.2~2.3V");
|
||||
|
||||
if(ocr.TwoOne)
|
||||
sb.AppendLine("\tDevice can work with supply 2.1~2.2V");
|
||||
|
||||
if(ocr.TwoZero)
|
||||
sb.AppendLine("\tDevice can work with supply 2.0~2.1V");
|
||||
|
||||
if(ocr.OneSix)
|
||||
sb.AppendLine("\tDevice can work with supply 1.65~1.95V");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ namespace DiscImageChef.Decoders.MMC
|
||||
{
|
||||
switch(mmcVendorId)
|
||||
{
|
||||
case 0x15: return "Samsung";
|
||||
case 0x2C: return "extreMEmory";
|
||||
default: return $"Unknown manufacturer ID 0x{mmcVendorId:X2}";
|
||||
case 0x15: return"Samsung";
|
||||
case 0x2C: return"extreMEmory";
|
||||
default: return$"Unknown manufacturer ID 0x{mmcVendorId:X2}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
125
PCMCIA/CIS.cs
125
PCMCIA/CIS.cs
@@ -38,9 +38,8 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.PCMCIA
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static class CIS
|
||||
{
|
||||
// TODO: Handle links? Or are they removed in lower layers of the operating system drivers?
|
||||
@@ -51,15 +50,21 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
|
||||
while(position < data.Length)
|
||||
{
|
||||
Tuple tuple = new Tuple {Code = (TupleCodes)data[position]};
|
||||
var tuple = new Tuple
|
||||
{
|
||||
Code = (TupleCodes)data[position]
|
||||
};
|
||||
|
||||
if(tuple.Code == TupleCodes.CISTPL_NULL) continue;
|
||||
if(tuple.Code == TupleCodes.CISTPL_NULL)
|
||||
continue;
|
||||
|
||||
if(tuple.Code == TupleCodes.CISTPL_END) break;
|
||||
if(tuple.Code == TupleCodes.CISTPL_END)
|
||||
break;
|
||||
|
||||
tuple.Link = data[position + 1];
|
||||
|
||||
if(position + 2 + tuple.Link > data.Length) break;
|
||||
if(position + 2 + tuple.Link > data.Length)
|
||||
break;
|
||||
|
||||
tuple.Data = new byte[tuple.Link + 2];
|
||||
Array.Copy(data, position, tuple.Data, 0, tuple.Link + 2);
|
||||
@@ -73,31 +78,35 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
|
||||
public static DeviceGeometryTuple DecodeDeviceGeometryTuple(Tuple tuple)
|
||||
{
|
||||
if(tuple == null) return null;
|
||||
if(tuple == null)
|
||||
return null;
|
||||
|
||||
if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) return null;
|
||||
if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO &&
|
||||
tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A)
|
||||
return null;
|
||||
|
||||
return tuple.Data == null ? null : DecodeDeviceGeometryTuple(tuple.Data);
|
||||
}
|
||||
|
||||
public static DeviceGeometryTuple DecodeDeviceGeometryTuple(byte[] data)
|
||||
{
|
||||
if((data?.Length - 2) % 6 != 0) return null;
|
||||
if((data?.Length - 2) % 6 != 0)
|
||||
return null;
|
||||
|
||||
DeviceGeometryTuple tuple = new DeviceGeometryTuple();
|
||||
var tuple = new DeviceGeometryTuple();
|
||||
List<DeviceGeometry> geometries = new List<DeviceGeometry>();
|
||||
|
||||
for(int position = 2; position < data.Length; position += 6)
|
||||
{
|
||||
DeviceGeometry geometry = new DeviceGeometry
|
||||
var geometry = new DeviceGeometry
|
||||
{
|
||||
CardInterface = data[position],
|
||||
EraseBlockSize = data[position + 1],
|
||||
ReadBlockSize = data[position + 2],
|
||||
WriteBlockSize = data[position + 3],
|
||||
Partitions = data[position + 4],
|
||||
Interleaving = data[position + 5]
|
||||
CardInterface = data[position], EraseBlockSize = data[position + 1],
|
||||
ReadBlockSize = data[position + 2],
|
||||
WriteBlockSize = data[position + 3],
|
||||
Partitions = data[position + 4],
|
||||
Interleaving = data[position + 5]
|
||||
};
|
||||
|
||||
geometries.Add(geometry);
|
||||
}
|
||||
|
||||
@@ -110,22 +119,30 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
|
||||
public static string PrettifyDeviceGeometryTuple(DeviceGeometryTuple tuple)
|
||||
{
|
||||
if(tuple == null) return null;
|
||||
if(tuple == null)
|
||||
return null;
|
||||
|
||||
if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) return null;
|
||||
if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO &&
|
||||
tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("PCMCIA Device Geometry Tuples:");
|
||||
|
||||
foreach(DeviceGeometry geometry in tuple.Geometries)
|
||||
{
|
||||
sb.AppendLine("\tGeometry:");
|
||||
sb.AppendFormat("\t\tDevice width: {0} bits", (1 << (geometry.CardInterface - 1)) * 8).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t\tErase block = {0} bytes",
|
||||
(1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t\tRead block = {0} bytes",
|
||||
(1 << (geometry.ReadBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t\tWrite block = {0} bytes",
|
||||
(1 << (geometry.WriteBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t\tPartition alignment = {0} bytes",
|
||||
(1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)) *
|
||||
(1 << (geometry.Partitions - 1))).AppendLine();
|
||||
@@ -142,31 +159,33 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
|
||||
public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(Tuple tuple)
|
||||
{
|
||||
if(tuple?.Code != TupleCodes.CISTPL_MANFID) return null;
|
||||
if(tuple?.Code != TupleCodes.CISTPL_MANFID)
|
||||
return null;
|
||||
|
||||
return tuple.Data == null ? null : DecodeManufacturerIdentificationTuple(tuple.Data);
|
||||
}
|
||||
|
||||
public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(byte[] data)
|
||||
{
|
||||
if(data == null) return null;
|
||||
if(data == null)
|
||||
return null;
|
||||
|
||||
if(data.Length < 6) return null;
|
||||
if(data.Length < 6)
|
||||
return null;
|
||||
|
||||
return new ManufacturerIdentificationTuple
|
||||
{
|
||||
Code = (TupleCodes)data[0],
|
||||
Link = data[1],
|
||||
ManufacturerID = BitConverter.ToUInt16(data, 2),
|
||||
CardID = BitConverter.ToUInt16(data, 4)
|
||||
Code = (TupleCodes)data[0], Link = data[1], ManufacturerID = BitConverter.ToUInt16(data, 2),
|
||||
CardID = BitConverter.ToUInt16(data, 4)
|
||||
};
|
||||
}
|
||||
|
||||
public static string PrettifyManufacturerIdentificationTuple(ManufacturerIdentificationTuple tuple)
|
||||
{
|
||||
if(tuple?.Code != TupleCodes.CISTPL_MANFID) return null;
|
||||
if(tuple?.Code != TupleCodes.CISTPL_MANFID)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("PCMCIA Manufacturer Identification Tuple:");
|
||||
sb.AppendFormat("\tManufacturer ID: {0}", VendorCode.Prettify(tuple.ManufacturerID)).AppendLine();
|
||||
sb.AppendFormat("\tCard ID:D 0x{0:X4}", tuple.CardID).AppendLine();
|
||||
@@ -182,40 +201,46 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
|
||||
public static Level1VersionTuple DecodeLevel1VersionTuple(Tuple tuple)
|
||||
{
|
||||
if(tuple?.Code != TupleCodes.CISTPL_VERS_1) return null;
|
||||
if(tuple?.Code != TupleCodes.CISTPL_VERS_1)
|
||||
return null;
|
||||
|
||||
return tuple.Data == null ? null : DecodeLevel1VersionTuple(tuple.Data);
|
||||
}
|
||||
|
||||
public static Level1VersionTuple DecodeLevel1VersionTuple(byte[] data)
|
||||
{
|
||||
if(data == null) return null;
|
||||
if(data == null)
|
||||
return null;
|
||||
|
||||
if(data.Length < 4) return null;
|
||||
if(data.Length < 4)
|
||||
return null;
|
||||
|
||||
List<byte> buffer = new List<byte>();
|
||||
List<string> strings = null;
|
||||
bool firstString = false;
|
||||
bool secondString = false;
|
||||
|
||||
Level1VersionTuple tuple = new Level1VersionTuple
|
||||
var tuple = new Level1VersionTuple
|
||||
{
|
||||
Code = (TupleCodes)data[0], Link = data[1], MajorVersion = data[2], MinorVersion = data[3]
|
||||
};
|
||||
|
||||
for(int position = 4; position < data.Length; position++)
|
||||
{
|
||||
if(data[position] == 0xFF) break;
|
||||
if(data[position] == 0xFF)
|
||||
break;
|
||||
|
||||
buffer.Add(data[position]);
|
||||
|
||||
if(data[position] != 0x00) continue;
|
||||
if(data[position] != 0x00)
|
||||
continue;
|
||||
|
||||
if(!firstString)
|
||||
{
|
||||
tuple.Manufacturer = StringHandlers.CToString(buffer.ToArray());
|
||||
buffer = new List<byte>();
|
||||
firstString = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -225,41 +250,51 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
tuple.Product = StringHandlers.CToString(buffer.ToArray());
|
||||
buffer = new List<byte>();
|
||||
firstString = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strings == null) strings = new List<string>();
|
||||
if(strings == null)
|
||||
strings = new List<string>();
|
||||
|
||||
strings.Add(StringHandlers.CToString(buffer.ToArray()));
|
||||
buffer = new List<byte>();
|
||||
}
|
||||
|
||||
if(strings != null) tuple.AdditionalInformation = strings.ToArray();
|
||||
if(strings != null)
|
||||
tuple.AdditionalInformation = strings.ToArray();
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
public static string PrettifyLevel1VersionTuple(Level1VersionTuple tuple)
|
||||
{
|
||||
if(tuple?.Code != TupleCodes.CISTPL_VERS_1) return null;
|
||||
if(tuple?.Code != TupleCodes.CISTPL_VERS_1)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("PCMCIA Level 1 Version / Product Information Tuple:");
|
||||
|
||||
sb.AppendFormat("\tCard indicates compliance with PC Card Standard Release {0}.{1}", tuple.MajorVersion,
|
||||
tuple.MinorVersion).AppendLine();
|
||||
|
||||
if(string.IsNullOrEmpty(tuple.Manufacturer)) sb.AppendLine("\tNo manufacturer information string.");
|
||||
else sb.AppendFormat("\tManufacturer: {0}", tuple.Manufacturer).AppendLine();
|
||||
if(string.IsNullOrEmpty(tuple.Manufacturer))
|
||||
sb.AppendLine("\tNo manufacturer information string.");
|
||||
else
|
||||
sb.AppendFormat("\tManufacturer: {0}", tuple.Manufacturer).AppendLine();
|
||||
|
||||
if(string.IsNullOrEmpty(tuple.Product)) sb.AppendLine("\tNo product name string.");
|
||||
else sb.AppendFormat("\tProduct name: {0}", tuple.Product).AppendLine();
|
||||
if(string.IsNullOrEmpty(tuple.Product))
|
||||
sb.AppendLine("\tNo product name string.");
|
||||
else
|
||||
sb.AppendFormat("\tProduct name: {0}", tuple.Product).AppendLine();
|
||||
|
||||
if(tuple.AdditionalInformation == null || tuple.AdditionalInformation.Length == 0)
|
||||
if(tuple.AdditionalInformation == null ||
|
||||
tuple.AdditionalInformation.Length == 0)
|
||||
sb.AppendLine("\tNo additional information.");
|
||||
else
|
||||
{
|
||||
sb.AppendLine("\tAdditional information:");
|
||||
|
||||
foreach(string info in tuple.AdditionalInformation.Where(info => !string.IsNullOrEmpty(info)))
|
||||
sb.AppendFormat("\t\t{0}", info).AppendLine();
|
||||
}
|
||||
|
||||
299
PCMCIA/Enums.cs
299
PCMCIA/Enums.cs
@@ -34,263 +34,88 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders.PCMCIA
|
||||
{
|
||||
/// <summary>
|
||||
/// Tuple codes.
|
||||
/// </summary>
|
||||
/// <summary>Tuple codes.</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum TupleCodes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Checksum control
|
||||
/// </summary>
|
||||
CISTPL_CHECKSUM = 0x10,
|
||||
/// <summary>
|
||||
/// End-of-chain
|
||||
/// </summary>
|
||||
CISTPL_END = 0xFF,
|
||||
/// <summary>
|
||||
/// Indirect access PC Card memory
|
||||
/// </summary>
|
||||
CISTPL_INDIRECT = 0x03,
|
||||
/// <summary>
|
||||
/// Link-target-control
|
||||
/// </summary>
|
||||
CISTPL_LINKTARGET = 0x13,
|
||||
/// <summary>
|
||||
/// Longlink to attribute memory
|
||||
/// </summary>
|
||||
CISTPL_LONGLINK_A = 0x11,
|
||||
/// <summary>
|
||||
/// Longlink to common memory
|
||||
/// </summary>
|
||||
CISTPL_LONGLINK_C = 0x12,
|
||||
/// <summary>
|
||||
/// Longlink to next chain on a Cardbus PC Card
|
||||
/// </summary>
|
||||
CISTPL_LONGLINK_CB = 0x02,
|
||||
/// <summary>
|
||||
/// Longlink to function specific chains
|
||||
/// </summary>
|
||||
CISTPL_LONGLINK_MFC = 0x06,
|
||||
/// <summary>
|
||||
/// No-link to common memory
|
||||
/// </summary>
|
||||
CISTPL_NO_LINK = 0x14,
|
||||
/// <summary>
|
||||
/// Null tuple
|
||||
/// </summary>
|
||||
CISTPL_NULL = 0x00,
|
||||
/// <summary>
|
||||
/// Alternate language string
|
||||
/// </summary>
|
||||
CISTPL_ALTSTR = 0x16,
|
||||
/// <summary>
|
||||
/// Common memory device information
|
||||
/// </summary>
|
||||
CISTPL_DEVICE = 0x01,
|
||||
/// <summary>
|
||||
/// Attribute memory device information
|
||||
/// </summary>
|
||||
CISTPL_DEVICE_A = 0x17,
|
||||
/// <summary>
|
||||
/// Other operating conditions information for attribute memory
|
||||
/// </summary>
|
||||
CISTPL_DEVICE_OA = 0x1D,
|
||||
/// <summary>
|
||||
/// Other operating conditions information for common memory
|
||||
/// </summary>
|
||||
CISTPL_DEVICE_OC = 0x1C,
|
||||
/// <summary>
|
||||
/// Device geometry information for common memory
|
||||
/// </summary>
|
||||
CISTPL_DEVICEGEO = 0x1E,
|
||||
/// <summary>
|
||||
/// Device geometry information for attribute memory
|
||||
/// </summary>
|
||||
CISTPL_DEVICEGEO_A = 0x1F,
|
||||
/// <summary>
|
||||
/// Extended common memory device information
|
||||
/// </summary>
|
||||
CISTPL_EXTDEVIC = 0x09,
|
||||
/// <summary>
|
||||
/// Function extensions
|
||||
/// </summary>
|
||||
CISTPL_FUNCE = 0x22,
|
||||
/// <summary>
|
||||
/// Function class identification
|
||||
/// </summary>
|
||||
CISTPL_FUNCID = 0x21,
|
||||
/// <summary>
|
||||
/// JEDEC programming information for attribute memory
|
||||
/// </summary>
|
||||
CISTPL_JEDEC_A = 0x19,
|
||||
/// <summary>
|
||||
/// JEDEC programming information for common memory
|
||||
/// </summary>
|
||||
CISTPL_JEDEC_C = 0x18,
|
||||
/// <summary>
|
||||
/// Manufacturer identification string
|
||||
/// </summary>
|
||||
CISTPL_MANFID = 0x20,
|
||||
/// <summary>
|
||||
/// Level 1 version/product information
|
||||
/// </summary>
|
||||
CISTPL_VERS_1 = 0x15,
|
||||
/// <summary>
|
||||
/// BAR for a CardBus PC Card
|
||||
/// </summary>
|
||||
CISTPL_BAR = 0x07,
|
||||
/// <summary>
|
||||
/// Configuration-table-entry
|
||||
/// </summary>
|
||||
CISTPL_CFTABLE_ENTRY = 0x1B,
|
||||
/// <summary>
|
||||
/// Configuration-table-entry for a CardBus PC Card
|
||||
/// </summary>
|
||||
CISTPL_CFTABLE_ENTRY_CB = 0x05,
|
||||
/// <summary>
|
||||
/// Configuration tuple for a 16-bit PC Card
|
||||
/// </summary>
|
||||
CISTPL_CONFIG = 0x1A,
|
||||
/// <summary>
|
||||
/// Configuration tuple for a CardBus PC Card
|
||||
/// </summary>
|
||||
CISTPL_CONFIG_CB = 0x04,
|
||||
/// <summary>
|
||||
/// Function state save/restore definition
|
||||
/// </summary>
|
||||
CISTPL_PWR_MGMNT = 0x08,
|
||||
/// <summary>
|
||||
/// Battery replacement date
|
||||
/// </summary>
|
||||
CISTPL_BATTERY = 0x45,
|
||||
/// <summary>
|
||||
/// Card initialization date
|
||||
/// </summary>
|
||||
CISTPL_DATE = 0x44,
|
||||
/// <summary>
|
||||
/// Level 2 version/product information
|
||||
/// </summary>
|
||||
CISTPL_VERS_2 = 0x40,
|
||||
/// <summary>
|
||||
/// Byte ordering for disk-like partitions
|
||||
/// </summary>
|
||||
CISTPL_BYTEORDER = 0x43,
|
||||
/// <summary>
|
||||
/// Data recording format for common memory
|
||||
/// </summary>
|
||||
CISTPL_FORMAT = 0x41,
|
||||
/// <summary>
|
||||
/// Data recording format for attribute memory
|
||||
/// </summary>
|
||||
CISTPL_FORMAT_A = 0x47,
|
||||
/// <summary>
|
||||
/// Partition geometry
|
||||
/// </summary>
|
||||
CISTPL_GEOMETRY = 0x42,
|
||||
/// <summary>
|
||||
/// Software interleaving
|
||||
/// </summary>
|
||||
CISTPL_SWIL = 0x23,
|
||||
/// <summary>
|
||||
/// Partition organization
|
||||
/// </summary>
|
||||
CISTPL_ORG = 0x46,
|
||||
/// <summary>
|
||||
/// Special purpose
|
||||
/// </summary>
|
||||
/// <summary>Checksum control</summary>
|
||||
CISTPL_CHECKSUM = 0x10, /// <summary>End-of-chain</summary>
|
||||
CISTPL_END = 0xFF, /// <summary>Indirect access PC Card memory</summary>
|
||||
CISTPL_INDIRECT = 0x03, /// <summary>Link-target-control</summary>
|
||||
CISTPL_LINKTARGET = 0x13, /// <summary>Longlink to attribute memory</summary>
|
||||
CISTPL_LONGLINK_A = 0x11, /// <summary>Longlink to common memory</summary>
|
||||
CISTPL_LONGLINK_C = 0x12, /// <summary>Longlink to next chain on a Cardbus PC Card</summary>
|
||||
CISTPL_LONGLINK_CB = 0x02, /// <summary>Longlink to function specific chains</summary>
|
||||
CISTPL_LONGLINK_MFC = 0x06, /// <summary>No-link to common memory</summary>
|
||||
CISTPL_NO_LINK = 0x14, /// <summary>Null tuple</summary>
|
||||
CISTPL_NULL = 0x00, /// <summary>Alternate language string</summary>
|
||||
CISTPL_ALTSTR = 0x16, /// <summary>Common memory device information</summary>
|
||||
CISTPL_DEVICE = 0x01, /// <summary>Attribute memory device information</summary>
|
||||
CISTPL_DEVICE_A = 0x17, /// <summary>Other operating conditions information for attribute memory</summary>
|
||||
CISTPL_DEVICE_OA = 0x1D, /// <summary>Other operating conditions information for common memory</summary>
|
||||
CISTPL_DEVICE_OC = 0x1C, /// <summary>Device geometry information for common memory</summary>
|
||||
CISTPL_DEVICEGEO = 0x1E, /// <summary>Device geometry information for attribute memory</summary>
|
||||
CISTPL_DEVICEGEO_A = 0x1F, /// <summary>Extended common memory device information</summary>
|
||||
CISTPL_EXTDEVIC = 0x09, /// <summary>Function extensions</summary>
|
||||
CISTPL_FUNCE = 0x22, /// <summary>Function class identification</summary>
|
||||
CISTPL_FUNCID = 0x21, /// <summary>JEDEC programming information for attribute memory</summary>
|
||||
CISTPL_JEDEC_A = 0x19, /// <summary>JEDEC programming information for common memory</summary>
|
||||
CISTPL_JEDEC_C = 0x18, /// <summary>Manufacturer identification string</summary>
|
||||
CISTPL_MANFID = 0x20, /// <summary>Level 1 version/product information</summary>
|
||||
CISTPL_VERS_1 = 0x15, /// <summary>BAR for a CardBus PC Card</summary>
|
||||
CISTPL_BAR = 0x07, /// <summary>Configuration-table-entry</summary>
|
||||
CISTPL_CFTABLE_ENTRY = 0x1B, /// <summary>Configuration-table-entry for a CardBus PC Card</summary>
|
||||
CISTPL_CFTABLE_ENTRY_CB = 0x05, /// <summary>Configuration tuple for a 16-bit PC Card</summary>
|
||||
CISTPL_CONFIG = 0x1A, /// <summary>Configuration tuple for a CardBus PC Card</summary>
|
||||
CISTPL_CONFIG_CB = 0x04, /// <summary>Function state save/restore definition</summary>
|
||||
CISTPL_PWR_MGMNT = 0x08, /// <summary>Battery replacement date</summary>
|
||||
CISTPL_BATTERY = 0x45, /// <summary>Card initialization date</summary>
|
||||
CISTPL_DATE = 0x44, /// <summary>Level 2 version/product information</summary>
|
||||
CISTPL_VERS_2 = 0x40, /// <summary>Byte ordering for disk-like partitions</summary>
|
||||
CISTPL_BYTEORDER = 0x43, /// <summary>Data recording format for common memory</summary>
|
||||
CISTPL_FORMAT = 0x41, /// <summary>Data recording format for attribute memory</summary>
|
||||
CISTPL_FORMAT_A = 0x47, /// <summary>Partition geometry</summary>
|
||||
CISTPL_GEOMETRY = 0x42, /// <summary>Software interleaving</summary>
|
||||
CISTPL_SWIL = 0x23, /// <summary>Partition organization</summary>
|
||||
CISTPL_ORG = 0x46, /// <summary>Special purpose</summary>
|
||||
CISTPL_SPCL = 0x90
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DeviceTypeCodes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No device, used to designate a hole
|
||||
/// </summary>
|
||||
DTYPE_NULL = 0,
|
||||
/// <summary>
|
||||
/// Masked ROM
|
||||
/// </summary>
|
||||
DTYPE_ROM = 1,
|
||||
/// <summary>
|
||||
/// One-type-programmable ROM
|
||||
/// </summary>
|
||||
DTYPE_OTPROM = 2,
|
||||
/// <summary>
|
||||
/// UV-Erasable Programmable ROM
|
||||
/// </summary>
|
||||
DTYPE_EPROM = 3,
|
||||
/// <summary>
|
||||
/// Electronically-Erasable Programmable ROM
|
||||
/// </summary>
|
||||
DTYPE_EEPROM = 4,
|
||||
/// <summary>
|
||||
/// Flash memory
|
||||
/// </summary>
|
||||
DTYPE_FLASH = 5,
|
||||
/// <summary>
|
||||
/// Static RAM
|
||||
/// </summary>
|
||||
DTYPE_SRAM = 6,
|
||||
/// <summary>
|
||||
/// Dynamic RAM
|
||||
/// </summary>
|
||||
DTYPE_DRAM = 7,
|
||||
/// <summary>
|
||||
/// Function-specific memory address range
|
||||
/// </summary>
|
||||
DTYPE_FUNCSPEC = 13,
|
||||
/// <summary>
|
||||
/// Extended type follows
|
||||
/// </summary>
|
||||
/// <summary>No device, used to designate a hole</summary>
|
||||
DTYPE_NULL = 0, /// <summary>Masked ROM</summary>
|
||||
DTYPE_ROM = 1, /// <summary>One-type-programmable ROM</summary>
|
||||
DTYPE_OTPROM = 2, /// <summary>UV-Erasable Programmable ROM</summary>
|
||||
DTYPE_EPROM = 3, /// <summary>Electronically-Erasable Programmable ROM</summary>
|
||||
DTYPE_EEPROM = 4, /// <summary>Flash memory</summary>
|
||||
DTYPE_FLASH = 5, /// <summary>Static RAM</summary>
|
||||
DTYPE_SRAM = 6, /// <summary>Dynamic RAM</summary>
|
||||
DTYPE_DRAM = 7, /// <summary>Function-specific memory address range</summary>
|
||||
DTYPE_FUNCSPEC = 13, /// <summary>Extended type follows</summary>
|
||||
DTYPE_EXTEND = 14
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum DeviceSpeedCodes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No device
|
||||
/// </summary>
|
||||
DSPEED_NULL = 0,
|
||||
/// <summary>
|
||||
/// 250 ns
|
||||
/// </summary>
|
||||
DSPEED_250NS = 1,
|
||||
/// <summary>
|
||||
/// 200 ns
|
||||
/// </summary>
|
||||
DSPEED_200NS = 2,
|
||||
/// <summary>
|
||||
/// 150 ns
|
||||
/// </summary>
|
||||
DSPEED_150NS = 3,
|
||||
/// <summary>
|
||||
/// 100 ns
|
||||
/// </summary>
|
||||
DSPEED_100NS = 4,
|
||||
/// <summary>
|
||||
/// Extended speed follows
|
||||
/// </summary>
|
||||
/// <summary>No device</summary>
|
||||
DSPEED_NULL = 0, /// <summary>250 ns</summary>
|
||||
DSPEED_250NS = 1, /// <summary>200 ns</summary>
|
||||
DSPEED_200NS = 2, /// <summary>150 ns</summary>
|
||||
DSPEED_150NS = 3, /// <summary>100 ns</summary>
|
||||
DSPEED_100NS = 4, /// <summary>Extended speed follows</summary>
|
||||
DSPEED_EXT = 7
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum FunctionCodes : byte
|
||||
{
|
||||
MultiFunction = 0x00,
|
||||
Memory = 0x01,
|
||||
Serial = 0x02,
|
||||
Parallel = 0x03,
|
||||
FixedDisk = 0x04,
|
||||
Video = 0x05,
|
||||
Network = 0x06,
|
||||
AIMS = 0x07,
|
||||
SCSI = 0x08,
|
||||
Security = 0x09,
|
||||
Instrument = 0x0A,
|
||||
HighSpeedSerial = 0x0B,
|
||||
VendorSpecific = 0xFE
|
||||
MultiFunction = 0x00, Memory = 0x01, Serial = 0x02,
|
||||
Parallel = 0x03, FixedDisk = 0x04, Video = 0x05,
|
||||
Network = 0x06, AIMS = 0x07, SCSI = 0x08,
|
||||
Security = 0x09, Instrument = 0x0A, HighSpeedSerial = 0x0B,
|
||||
VendorSpecific = 0xFE
|
||||
}
|
||||
}
|
||||
476
PCMCIA/Types.cs
476
PCMCIA/Types.cs
@@ -34,181 +34,128 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders.PCMCIA
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic classure of a PCMCIA tuple
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Basic classure of a PCMCIA tuple</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class Tuple
|
||||
{
|
||||
public TupleCodes Code;
|
||||
public byte Link;
|
||||
public byte[] Data;
|
||||
public byte Link;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checksum tuple
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Checksum tuple</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class ChecksumTuple
|
||||
{
|
||||
/// <summary>Modulo-256 sum of region</summary>
|
||||
public byte Checksum;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_CHECKSUM" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Offset to region to be checksummed
|
||||
/// </summary>
|
||||
public short Offset;
|
||||
/// <summary>
|
||||
/// Length of region to be checksummed
|
||||
/// </summary>
|
||||
/// <summary>Length of region to be checksummed</summary>
|
||||
public ushort Length;
|
||||
/// <summary>
|
||||
/// Modulo-256 sum of region
|
||||
/// </summary>
|
||||
public byte Checksum;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>Offset to region to be checksummed</summary>
|
||||
public short Offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indirect Access PC Card Memory
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Indirect Access PC Card Memory</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class IndirectTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_INDIRECT" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Link target tuple
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Link target tuple</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class LinkTargetTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_LINKTARGET" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// 'C''I''S' in ASCII
|
||||
/// </summary>
|
||||
/// <summary>'C''I''S' in ASCII</summary>
|
||||
public byte[] Tag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 16-bit PC Card Long Link Tuple
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>16-bit PC Card Long Link Tuple</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class LongLinkTuple
|
||||
{
|
||||
/// <summary>Target address</summary>
|
||||
public uint Address;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_LONGLINK_A" /> or <see cref="TupleCodes.CISTPL_LONGLINK_C" /> or
|
||||
/// <see cref="TupleCodes.CISTPL_LONGLINK_CB" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Target address
|
||||
/// </summary>
|
||||
public uint Address;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"),
|
||||
SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
public class ConfigurationAddress
|
||||
{
|
||||
/// <summary>
|
||||
/// Target address space, 0 = attribute, 1 = common
|
||||
/// </summary>
|
||||
public byte TargetAddressSpace;
|
||||
/// <summary>
|
||||
/// Target address
|
||||
/// </summary>
|
||||
/// <summary>Target address</summary>
|
||||
public uint Address;
|
||||
/// <summary>Target address space, 0 = attribute, 1 = common</summary>
|
||||
public byte TargetAddressSpace;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiple function link tuple
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
/// <summary>Multiple function link tuple</summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class MultipleFunctionLinkTuple
|
||||
{
|
||||
/// <summary>Link to more configuration registers</summary>
|
||||
public ConfigurationAddress[] Addresses;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_LONGLINK_MFC" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// How many functions follow
|
||||
/// </summary>
|
||||
/// <summary>How many functions follow</summary>
|
||||
public byte NumberFunctions;
|
||||
/// <summary>
|
||||
/// Link to more configuration registers
|
||||
/// </summary>
|
||||
public ConfigurationAddress[] Addresses;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class NoLinkTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_NO_LINK" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class AlternateStringTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_ALTSTR" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Array of strings. On memory they're preceded by an ISO Escape Code indicating codepage. Here they're stored as
|
||||
@@ -217,335 +164,218 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
public string[] Strings;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"),
|
||||
SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
public class ExtendedDeviceSpeed
|
||||
{
|
||||
/// <summary>
|
||||
/// Another extended follows
|
||||
/// </summary>
|
||||
public bool Extended;
|
||||
/// <summary>
|
||||
/// Speed mantisa
|
||||
/// </summary>
|
||||
public byte Mantissa;
|
||||
/// <summary>
|
||||
/// Speed exponent
|
||||
/// </summary>
|
||||
/// <summary>Speed exponent</summary>
|
||||
public byte Exponent;
|
||||
/// <summary>Another extended follows</summary>
|
||||
public bool Extended;
|
||||
/// <summary>Speed mantisa</summary>
|
||||
public byte Mantissa;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public struct DeviceInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Device type code
|
||||
/// </summary>
|
||||
/// <summary>Device type code</summary>
|
||||
public DeviceTypeCodes Type;
|
||||
/// <summary>
|
||||
/// Write protected
|
||||
/// </summary>
|
||||
/// <summary>Write protected</summary>
|
||||
public bool WPS;
|
||||
/// <summary>
|
||||
/// Speed code
|
||||
/// </summary>
|
||||
/// <summary>Speed code</summary>
|
||||
public DeviceSpeedCodes Speed;
|
||||
/// <summary>
|
||||
/// Extended speeds
|
||||
/// </summary>
|
||||
/// <summary>Extended speeds</summary>
|
||||
public ExtendedDeviceSpeed[] ExtendedSpeeds;
|
||||
/// <summary>
|
||||
/// Extended types
|
||||
/// </summary>
|
||||
/// <summary>Extended types</summary>
|
||||
public byte[] ExtendedTypes;
|
||||
/// <summary>
|
||||
/// Size in units - 1
|
||||
/// </summary>
|
||||
/// <summary>Size in units - 1</summary>
|
||||
public byte Units;
|
||||
/// <summary>
|
||||
/// Code to define units unit
|
||||
/// </summary>
|
||||
/// <summary>Code to define units unit</summary>
|
||||
public byte SizeCode;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class DeviceTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_DEVICE" /> or <see cref="TupleCodes.CISTPL_DEVICE_A" />
|
||||
/// </summary>
|
||||
/// <summary><see cref="TupleCodes.CISTPL_DEVICE" /> or <see cref="TupleCodes.CISTPL_DEVICE_A" /></summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Array of device information bytes
|
||||
/// </summary>
|
||||
/// <summary>Array of device information bytes</summary>
|
||||
public DeviceInfo[] Infos;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public struct OtherConditionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// True if another other condition info follows
|
||||
/// </summary>
|
||||
/// <summary>True if another other condition info follows</summary>
|
||||
public bool Extended;
|
||||
/// <summary>
|
||||
/// Vcc used
|
||||
/// </summary>
|
||||
/// <summary>Vcc used</summary>
|
||||
public byte VccUsed;
|
||||
/// <summary>
|
||||
/// Supports WAIT# signal
|
||||
/// </summary>
|
||||
/// <summary>Supports WAIT# signal</summary>
|
||||
public bool MWAIT;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class OtherConditionTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_DEVICE_OC" /> or <see cref="TupleCodes.CISTPL_DEVICE_OA" />
|
||||
/// </summary>
|
||||
/// <summary><see cref="TupleCodes.CISTPL_DEVICE_OC" /> or <see cref="TupleCodes.CISTPL_DEVICE_OA" /></summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Array of other condition information bytes
|
||||
/// </summary>
|
||||
public OtherConditionInfo[] OtherConditionInfos;
|
||||
/// <summary>
|
||||
/// Array of device information bytes
|
||||
/// </summary>
|
||||
/// <summary>Array of device information bytes</summary>
|
||||
public DeviceInfo[] Infos;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>Array of other condition information bytes</summary>
|
||||
public OtherConditionInfo[] OtherConditionInfos;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public struct DeviceGeometry
|
||||
{
|
||||
/// <summary>
|
||||
/// 1 << n-1 bytes, 2 = 16-bit PC Card, 3 = CardBus PC Card
|
||||
/// </summary>
|
||||
/// <summary>1 << n-1 bytes, 2 = 16-bit PC Card, 3 = CardBus PC Card</summary>
|
||||
public byte CardInterface;
|
||||
/// <summary>
|
||||
/// Erase block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses.
|
||||
/// If n == 4, and <see cref="CardInterface" /> == 16, erase block size = 32 * 4 = 128 bytes
|
||||
/// Erase block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses. If n == 4, and
|
||||
/// <see cref="CardInterface" /> == 16, erase block size = 32 * 4 = 128 bytes
|
||||
/// </summary>
|
||||
public byte EraseBlockSize;
|
||||
/// <summary>
|
||||
/// Read block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses.
|
||||
/// If n == 4, and <see cref="CardInterface" /> == 16, read block size = 32 * 4 = 128 bytes
|
||||
/// Read block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses. If n == 4, and
|
||||
/// <see cref="CardInterface" /> == 16, read block size = 32 * 4 = 128 bytes
|
||||
/// </summary>
|
||||
public byte ReadBlockSize;
|
||||
/// <summary>
|
||||
/// Write block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses.
|
||||
/// If n == 4, and <see cref="CardInterface" /> == 16, write block size = 32 * 4 = 128 bytes
|
||||
/// Write block size in 1 << n-1 increments of <see cref="CardInterface" /> wide accesses. If n == 4, and
|
||||
/// <see cref="CardInterface" /> == 16, write block size = 32 * 4 = 128 bytes
|
||||
/// </summary>
|
||||
public byte WriteBlockSize;
|
||||
/// <summary>
|
||||
/// Device partitioning in granularity of 1 << n-1 erase blocks
|
||||
/// If n == 4, and erase block is 128 bytes, partitions must be aligned to 32 erase block, or 4096 bytes
|
||||
/// Device partitioning in granularity of 1 << n-1 erase blocks If n == 4, and erase block is 128 bytes,
|
||||
/// partitions must be aligned to 32 erase block, or 4096 bytes
|
||||
/// </summary>
|
||||
public byte Partitions;
|
||||
/// <summary>
|
||||
/// Card employs a multiple of 1 << n-1 times interleaving the entire memory arrays
|
||||
/// </summary>
|
||||
/// <summary>Card employs a multiple of 1 << n-1 times interleaving the entire memory arrays</summary>
|
||||
public byte Interleaving;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public class DeviceGeometryTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_DEVICEGEO" /> or <see cref="TupleCodes.CISTPL_DEVICEGEO_A" />
|
||||
/// </summary>
|
||||
/// <summary><see cref="TupleCodes.CISTPL_DEVICEGEO" /> or <see cref="TupleCodes.CISTPL_DEVICEGEO_A" /></summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Array of device geometries
|
||||
/// </summary>
|
||||
/// <summary>Array of device geometries</summary>
|
||||
public DeviceGeometry[] Geometries;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class FunctionIdentificationTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_FUNCID" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Function code
|
||||
/// </summary>
|
||||
/// <summary>Function code</summary>
|
||||
public FunctionCodes Function;
|
||||
/// <summary>
|
||||
/// Device contains boot ROM
|
||||
/// </summary>
|
||||
public bool ROM;
|
||||
/// <summary>
|
||||
/// Device wants to be part of power-on-self-test
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>Device wants to be part of power-on-self-test</summary>
|
||||
public bool POST;
|
||||
/// <summary>Device contains boot ROM</summary>
|
||||
public bool ROM;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public class ManufacturerIdentificationTuple
|
||||
{
|
||||
/// <summary>Card ID</summary>
|
||||
public ushort CardID;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_MANFID" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Manufacturer ID
|
||||
/// </summary>
|
||||
/// <summary>Manufacturer ID</summary>
|
||||
public ushort ManufacturerID;
|
||||
/// <summary>
|
||||
/// Card ID
|
||||
/// </summary>
|
||||
public ushort CardID;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public class Level1VersionTuple
|
||||
{
|
||||
/// <summary>Additional information strings</summary>
|
||||
public string[] AdditionalInformation;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_VERS_1" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Major version of standard compliance
|
||||
/// </summary>
|
||||
/// <summary>Major version of standard compliance</summary>
|
||||
public byte MajorVersion;
|
||||
/// <summary>
|
||||
/// Minor version of standard compliance
|
||||
/// </summary>
|
||||
public byte MinorVersion;
|
||||
/// <summary>
|
||||
/// Manufacturer string
|
||||
/// </summary>
|
||||
/// <summary>Manufacturer string</summary>
|
||||
public string Manufacturer;
|
||||
/// <summary>
|
||||
/// Product string
|
||||
/// </summary>
|
||||
/// <summary>Minor version of standard compliance</summary>
|
||||
public byte MinorVersion;
|
||||
/// <summary>Product string</summary>
|
||||
public string Product;
|
||||
/// <summary>
|
||||
/// Additional information strings
|
||||
/// </summary>
|
||||
public string[] AdditionalInformation;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class Level2VersionTuple
|
||||
{
|
||||
/// <summary>Address of first data byte</summary>
|
||||
public ushort Address;
|
||||
/// <summary>Number of copies of CIS present</summary>
|
||||
public byte CISCopies;
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_VERS_2" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Version of this classure
|
||||
/// </summary>
|
||||
public byte StructureVersion;
|
||||
/// <summary>
|
||||
/// Level of compliance
|
||||
/// </summary>
|
||||
/// <summary>Level of compliance</summary>
|
||||
public byte Compliance;
|
||||
/// <summary>
|
||||
/// Address of first data byte
|
||||
/// </summary>
|
||||
public ushort Address;
|
||||
/// <summary>
|
||||
/// Vendor-specific byte
|
||||
/// </summary>
|
||||
public byte VendorSpecific1;
|
||||
/// <summary>
|
||||
/// Vendor-specific byte
|
||||
/// </summary>
|
||||
public byte VendorSpecific2;
|
||||
/// <summary>
|
||||
/// Number of copies of CIS present
|
||||
/// </summary>
|
||||
public byte CISCopies;
|
||||
/// <summary>
|
||||
/// Vendor of software that formatted the card
|
||||
/// </summary>
|
||||
public string OEM;
|
||||
/// <summary>
|
||||
/// Informational message about the card
|
||||
/// </summary>
|
||||
/// <summary>Informational message about the card</summary>
|
||||
public string Information;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>Vendor of software that formatted the card</summary>
|
||||
public string OEM;
|
||||
/// <summary>Version of this classure</summary>
|
||||
public byte StructureVersion;
|
||||
/// <summary>Vendor-specific byte</summary>
|
||||
public byte VendorSpecific1;
|
||||
/// <summary>Vendor-specific byte</summary>
|
||||
public byte VendorSpecific2;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public class GeometryTuple
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="TupleCodes.CISTPL_GEOMETRY" />
|
||||
/// </summary>
|
||||
public TupleCodes Code;
|
||||
/// <summary>
|
||||
/// Link to next tuple
|
||||
/// </summary>
|
||||
public byte Link;
|
||||
/// <summary>
|
||||
/// Sectors per track
|
||||
/// </summary>
|
||||
public byte SectorsPerTrack;
|
||||
/// <summary>
|
||||
/// Tracks per cylinder
|
||||
/// </summary>
|
||||
public byte TracksPerCylinder;
|
||||
/// <summary>
|
||||
/// Cylinders
|
||||
/// </summary>
|
||||
/// <summary>Cylinders</summary>
|
||||
public ushort Cylinders;
|
||||
/// <summary>Link to next tuple</summary>
|
||||
public byte Link;
|
||||
/// <summary>Sectors per track</summary>
|
||||
public byte SectorsPerTrack;
|
||||
/// <summary>Tracks per cylinder</summary>
|
||||
public byte TracksPerCylinder;
|
||||
}
|
||||
}
|
||||
@@ -42,321 +42,321 @@ namespace DiscImageChef.Decoders.PCMCIA
|
||||
switch(id)
|
||||
{
|
||||
#region JEDEC
|
||||
case 0x01: return "AMD";
|
||||
case 0x02: return "AMI";
|
||||
case 0x83: return "Fairchild";
|
||||
case 0x04: return "Fujitsu";
|
||||
case 0x85: return "GTE";
|
||||
case 0x86: return "Harris";
|
||||
case 0x07: return "Hitachi";
|
||||
case 0x08: return "Inmos";
|
||||
case 0x89: return "Intel";
|
||||
case 0x8A: return "I.T.T.";
|
||||
case 0x0B: return "Intersil";
|
||||
case 0x8C: return "Monolithic Memories";
|
||||
case 0x0D: return "Mostek";
|
||||
case 0x0E: return "Freescale";
|
||||
case 0x8F: return "National";
|
||||
case 0x10: return "NEC";
|
||||
case 0x91: return "RCA";
|
||||
case 0x92: return "Raytheon";
|
||||
case 0x13: return "Conexant";
|
||||
case 0x94: return "Seeq";
|
||||
case 0x15: return "NXP";
|
||||
case 0x16: return "Synertek";
|
||||
case 0x97: return "Texas Instruments";
|
||||
case 0x98: return "Toshiba";
|
||||
case 0x19: return "Xicor";
|
||||
case 0x1A: return "Zilog";
|
||||
case 0x9B: return "Eurotechnique";
|
||||
case 0x1C: return "Mitsubishi2";
|
||||
case 0x9D: return "Lucent";
|
||||
case 0x9E: return "Exel";
|
||||
case 0x1F: return "Atmel";
|
||||
case 0x20: return "SGS/Thomson";
|
||||
case 0xA1: return "Lattice Semiconductor";
|
||||
case 0xA2: return "NCR";
|
||||
case 0x23: return "Wafer Scale Integration";
|
||||
case 0xA4: return "International Business Machines";
|
||||
case 0x25: return "Tristar";
|
||||
case 0x26: return "Visic";
|
||||
case 0xA7: return "International CMOS Technology";
|
||||
case 0xA8: return "SSSI";
|
||||
case 0x29: return "Microchip Technology";
|
||||
case 0x2A: return "Ricoh";
|
||||
case 0xAB: return "VLSI";
|
||||
case 0x2C: return "Micron Technology";
|
||||
case 0xAD: return "Hynix Semiconductor";
|
||||
case 0xAE: return "OKI Semiconductor";
|
||||
case 0x2F: return "ACTEL";
|
||||
case 0xB0: return "Sharp";
|
||||
case 0x31: return "Catalyst";
|
||||
case 0x32: return "Panasonic";
|
||||
case 0xB3: return "IDT";
|
||||
case 0x34: return "Cypress";
|
||||
case 0xB5: return "Digital Equipment Corporation";
|
||||
case 0xB6: return "LSI Logic";
|
||||
case 0x37: return "Zarlink";
|
||||
case 0x38: return "UTMC";
|
||||
case 0xB9: return "Thinking Machine";
|
||||
case 0xBA: return "Thomson CSF";
|
||||
case 0x3B: return "Integrated CMOS";
|
||||
case 0xBC: return "Honeywell";
|
||||
case 0x3D: return "Tektronix";
|
||||
case 0x3E: return "Oracle Corporation";
|
||||
case 0xBF: return "Silicon Storage Technology";
|
||||
case 0x40: return "ProMos";
|
||||
case 0xC1: return "Infineon";
|
||||
case 0xC2: return "Macronix";
|
||||
case 0x43: return "Xerox";
|
||||
case 0xC4: return "Plus Logic";
|
||||
case 0x45: return "SanDisk Corporation";
|
||||
case 0x46: return "Elan Circuit Technology";
|
||||
case 0xC7: return "European Silicon";
|
||||
case 0xC8: return "Apple";
|
||||
case 0x49: return "Xilinx";
|
||||
case 0x4A: return "Compaq";
|
||||
case 0xCB: return "Protocol Engines";
|
||||
case 0x4C: return "SCI";
|
||||
case 0xCD: return "Seiko Instruments";
|
||||
case 0xCE: return "Samsung";
|
||||
case 0x4F: return "I3 Design System";
|
||||
case 0xD0: return "Klic";
|
||||
case 0x51: return "Crosspoint Solutions";
|
||||
case 0x52: return "Alliance Semiconductor";
|
||||
case 0xD3: return "Tandem";
|
||||
case 0x54: return "Hewlett-Packard";
|
||||
case 0xD5: return "Integrated Silicon Solutions";
|
||||
case 0xD6: return "Brooktree";
|
||||
case 0x57: return "New Media";
|
||||
case 0x58: return "MHS Electronic";
|
||||
case 0xD9: return "Performance Semiconductors";
|
||||
case 0xDA: return "Winbond Electronic";
|
||||
case 0x5B: return "Kawasaki Steel";
|
||||
case 0x5D: return "TECMAR";
|
||||
case 0x5E: return "Exar";
|
||||
case 0xDF: return "PCMCIA";
|
||||
case 0xE0: return "LG Semiconductor";
|
||||
case 0x61: return "Northern Telecom";
|
||||
case 0x62: return "Sanyo2";
|
||||
case 0xE3: return "Array Microsystems";
|
||||
case 0x64: return "Crystal Semiconductor";
|
||||
case 0xE5: return "Analog Devices";
|
||||
case 0xE6: return "PMC-Sierra";
|
||||
case 0x67: return "Asparix";
|
||||
case 0x68: return "Convex Computer";
|
||||
case 0xE9: return "Nimbus Technology";
|
||||
case 0x6B: return "Transwitch";
|
||||
case 0xEC: return "Micronas";
|
||||
case 0x6D: return "Canon";
|
||||
case 0x6E: return "Altera";
|
||||
case 0xEF: return "NEXCOM";
|
||||
case 0x70: return "Qualcomm";
|
||||
case 0xF1: return "Sony";
|
||||
case 0xF2: return "Cray Research";
|
||||
case 0x73: return "AMS";
|
||||
case 0xF4: return "Vitesse";
|
||||
case 0x75: return "Aster Electronics";
|
||||
case 0x76: return "Bay Networks";
|
||||
case 0xF7: return "Zentrum";
|
||||
case 0xF8: return "TRW";
|
||||
case 0x79: return "Thesys";
|
||||
case 0x7A: return "Solbourne Computer";
|
||||
case 0xFB: return "Allied-Signal";
|
||||
case 0x7C: return "Dialog Semiconductor";
|
||||
case 0xFD: return "Media Vision";
|
||||
case 0xFE: return "Numonyx Corporation";
|
||||
case 0x7F01: return "Cirrus Logic";
|
||||
case 0x7F02: return "National Instruments";
|
||||
case 0x7F04: return "Alcatel Mietec";
|
||||
case 0x7F07: return "JTAG Technologies";
|
||||
case 0x7F08: return "Loral";
|
||||
case 0x7F0B: return "Bestlink Systems";
|
||||
case 0x7F0D: return "GENNUM";
|
||||
case 0x7F0E: return "VideoLogic";
|
||||
case 0x7F10: return "Chip Express";
|
||||
case 0x7F13: return "TCSI";
|
||||
case 0x7F15: return "Hughes Aircraft";
|
||||
case 0x7F16: return "Lanstar Semiconductor";
|
||||
case 0x7F19: return "Music Semi";
|
||||
case 0x7F1A: return "Ericsson Components";
|
||||
case 0x7F1C: return "Eon Silicon Devices";
|
||||
case 0x7F1F: return "Integ.Memories Tech.";
|
||||
case 0x7F20: return "Corollary Inc.";
|
||||
case 0x7F23: return "EIV(Switzerland)";
|
||||
case 0x7F25: return "Zarlink(formerly Mitel)";
|
||||
case 0x7F26: return "Clearpoint";
|
||||
case 0x7F29: return "Vanguard";
|
||||
case 0x7F2A: return "Hagiwara Sys-Com";
|
||||
case 0x7F2C: return "Celestica";
|
||||
case 0x7F2F: return "Rohm Company Ltd.";
|
||||
case 0x7F31: return "Libit Signal Processing";
|
||||
case 0x7F32: return "Enhanced Memories Inc.";
|
||||
case 0x7F34: return "Adaptec Inc.";
|
||||
case 0x7F37: return "AMIC Technology";
|
||||
case 0x7F38: return "Adobe Systems";
|
||||
case 0x7F3B: return "Newport Digital";
|
||||
case 0x7F3D: return "T Square";
|
||||
case 0x7F3E: return "Seiko Epson";
|
||||
case 0x7F40: return "Viking Components";
|
||||
case 0x7F43: return "Suwa Electronics";
|
||||
case 0x7F45: return "Micron CMS";
|
||||
case 0x7F46: return "American Computer &Digital Components Inc";
|
||||
case 0x7F49: return "CPU Design";
|
||||
case 0x7F4A: return "Price Point";
|
||||
case 0x7F4C: return "Tellabs";
|
||||
case 0x7F4F: return "Transcend Information";
|
||||
case 0x7F51: return "CKD Corporation Ltd.";
|
||||
case 0x7F52: return "Capital Instruments, Inc.";
|
||||
case 0x7F54: return "Linvex Technology";
|
||||
case 0x7F57: return "Dynamem, Inc.";
|
||||
case 0x7F58: return "NERA ASA";
|
||||
case 0x7F5B: return "Acorn Computers";
|
||||
case 0x7F5D: return "Oak Technology, Inc.";
|
||||
case 0x7F5E: return "Itec Memory";
|
||||
case 0x7F61: return "Wintec Industries";
|
||||
case 0x7F62: return "Super PC Memory";
|
||||
case 0x7F64: return "Galvantech";
|
||||
case 0x7F67: return "GateField";
|
||||
case 0x7F68: return "Integrated Memory System";
|
||||
case 0x7F6B: return "Goldenram";
|
||||
case 0x7F6D: return "Cimaron Communications";
|
||||
case 0x7F6E: return "Nippon Steel Semi.Corp.";
|
||||
case 0x7F70: return "AMCC";
|
||||
case 0x7F73: return "Digital Microwave";
|
||||
case 0x7F75: return "MIMOS Semiconductor";
|
||||
case 0x7F76: return "Advanced Fibre";
|
||||
case 0x7F79: return "Acbel Polytech Inc.";
|
||||
case 0x7F7A: return "Apacer Technology";
|
||||
case 0x7F7C: return "FOXCONN";
|
||||
case 0x7F83: return "ILC Data Device";
|
||||
case 0x7F85: return "Micro Linear";
|
||||
case 0x7F86: return "Univ.Of NC";
|
||||
case 0x7F89: return "Nchip";
|
||||
case 0x7F8A: return "Galileo Tech";
|
||||
case 0x7F8C: return "Graychip";
|
||||
case 0x7F8F: return "Robert Bosch";
|
||||
case 0x7F91: return "DATARAM";
|
||||
case 0x7F92: return "United Microelec Corp.";
|
||||
case 0x7F94: return "Smart Modular";
|
||||
case 0x7F97: return "Qlogic";
|
||||
case 0x7F98: return "Kingston";
|
||||
case 0x7F9B: return "SpaSE";
|
||||
case 0x7F9D: return "Programmable Micro Corp";
|
||||
case 0x7F9E: return "DoD";
|
||||
case 0x7FA1: return "Dallas Semiconductor";
|
||||
case 0x7FA2: return "Omnivision";
|
||||
case 0x7FA4: return "Novatel Wireless";
|
||||
case 0x7FA7: return "Cabletron";
|
||||
case 0x7FA8: return "Silicon Technology";
|
||||
case 0x7FAB: return "Vantis";
|
||||
case 0x7FAD: return "Century";
|
||||
case 0x7FAE: return "Hal Computers";
|
||||
case 0x7FB0: return "Juniper Networks";
|
||||
case 0x7FB3: return "Tundra Semiconductor";
|
||||
case 0x7FB5: return "LightSpeed Semi.";
|
||||
case 0x7FB6: return "ZSP Corp.";
|
||||
case 0x7FB9: return "Dynachip";
|
||||
case 0x7FBA: return "PNY Electronics";
|
||||
case 0x7FBC: return "MMC Networks";
|
||||
case 0x7FBF: return "Broadcom";
|
||||
case 0x7FC1: return "V3 Semiconductor";
|
||||
case 0x7FC2: return "Flextronics(formerly Orbit)";
|
||||
case 0x7FC4: return "Transmeta";
|
||||
case 0x7FC7: return "Enhance 3000 Inc";
|
||||
case 0x7FC8: return "Tower Semiconductor";
|
||||
case 0x7FCB: return "Maxim Integrated Product";
|
||||
case 0x7FCD: return "Centaur Technology";
|
||||
case 0x7FCE: return "Unigen Corporation";
|
||||
case 0x7FD0: return "Memory Card Technology";
|
||||
case 0x7FD3: return "Aica Kogyo, Ltd.";
|
||||
case 0x7FD5: return "MSC Vertriebs GmbH";
|
||||
case 0x7FD6: return "AKM Company, Ltd.";
|
||||
case 0x7FD9: return "GSI Technology";
|
||||
case 0x7FDA: return "Dane-Elec (C Memory)";
|
||||
case 0x7FDC: return "Lara Technology";
|
||||
case 0x7FDF: return "Tanisys Technology";
|
||||
case 0x7FE0: return "Truevision";
|
||||
case 0x7FE3: return "MGV Memory";
|
||||
case 0x7FE5: return "Gadzoox Networks";
|
||||
case 0x7FE6: return "Multi Dimensional Cons.";
|
||||
case 0x7FE9: return "Triscend";
|
||||
case 0x7FEA: return "XaQti";
|
||||
case 0x7FEC: return "Clear Logic";
|
||||
case 0x7FEF: return "Advantage Memory";
|
||||
case 0x7FF1: return "LeCroy";
|
||||
case 0x7FF2: return "Yamaha Corporation";
|
||||
case 0x7FF4: return "NetLogic Microsystems";
|
||||
case 0x7FF7: return "BF Goodrich Data.";
|
||||
case 0x7FF8: return "Epigram";
|
||||
case 0x7FFB: return "Admor Memory";
|
||||
case 0x7FFD: return "Quadratics Superconductor";
|
||||
case 0x7FFE: return "3COM";
|
||||
case 0x01: return"AMD";
|
||||
case 0x02: return"AMI";
|
||||
case 0x83: return"Fairchild";
|
||||
case 0x04: return"Fujitsu";
|
||||
case 0x85: return"GTE";
|
||||
case 0x86: return"Harris";
|
||||
case 0x07: return"Hitachi";
|
||||
case 0x08: return"Inmos";
|
||||
case 0x89: return"Intel";
|
||||
case 0x8A: return"I.T.T.";
|
||||
case 0x0B: return"Intersil";
|
||||
case 0x8C: return"Monolithic Memories";
|
||||
case 0x0D: return"Mostek";
|
||||
case 0x0E: return"Freescale";
|
||||
case 0x8F: return"National";
|
||||
case 0x10: return"NEC";
|
||||
case 0x91: return"RCA";
|
||||
case 0x92: return"Raytheon";
|
||||
case 0x13: return"Conexant";
|
||||
case 0x94: return"Seeq";
|
||||
case 0x15: return"NXP";
|
||||
case 0x16: return"Synertek";
|
||||
case 0x97: return"Texas Instruments";
|
||||
case 0x98: return"Toshiba";
|
||||
case 0x19: return"Xicor";
|
||||
case 0x1A: return"Zilog";
|
||||
case 0x9B: return"Eurotechnique";
|
||||
case 0x1C: return"Mitsubishi2";
|
||||
case 0x9D: return"Lucent";
|
||||
case 0x9E: return"Exel";
|
||||
case 0x1F: return"Atmel";
|
||||
case 0x20: return"SGS/Thomson";
|
||||
case 0xA1: return"Lattice Semiconductor";
|
||||
case 0xA2: return"NCR";
|
||||
case 0x23: return"Wafer Scale Integration";
|
||||
case 0xA4: return"International Business Machines";
|
||||
case 0x25: return"Tristar";
|
||||
case 0x26: return"Visic";
|
||||
case 0xA7: return"International CMOS Technology";
|
||||
case 0xA8: return"SSSI";
|
||||
case 0x29: return"Microchip Technology";
|
||||
case 0x2A: return"Ricoh";
|
||||
case 0xAB: return"VLSI";
|
||||
case 0x2C: return"Micron Technology";
|
||||
case 0xAD: return"Hynix Semiconductor";
|
||||
case 0xAE: return"OKI Semiconductor";
|
||||
case 0x2F: return"ACTEL";
|
||||
case 0xB0: return"Sharp";
|
||||
case 0x31: return"Catalyst";
|
||||
case 0x32: return"Panasonic";
|
||||
case 0xB3: return"IDT";
|
||||
case 0x34: return"Cypress";
|
||||
case 0xB5: return"Digital Equipment Corporation";
|
||||
case 0xB6: return"LSI Logic";
|
||||
case 0x37: return"Zarlink";
|
||||
case 0x38: return"UTMC";
|
||||
case 0xB9: return"Thinking Machine";
|
||||
case 0xBA: return"Thomson CSF";
|
||||
case 0x3B: return"Integrated CMOS";
|
||||
case 0xBC: return"Honeywell";
|
||||
case 0x3D: return"Tektronix";
|
||||
case 0x3E: return"Oracle Corporation";
|
||||
case 0xBF: return"Silicon Storage Technology";
|
||||
case 0x40: return"ProMos";
|
||||
case 0xC1: return"Infineon";
|
||||
case 0xC2: return"Macronix";
|
||||
case 0x43: return"Xerox";
|
||||
case 0xC4: return"Plus Logic";
|
||||
case 0x45: return"SanDisk Corporation";
|
||||
case 0x46: return"Elan Circuit Technology";
|
||||
case 0xC7: return"European Silicon";
|
||||
case 0xC8: return"Apple";
|
||||
case 0x49: return"Xilinx";
|
||||
case 0x4A: return"Compaq";
|
||||
case 0xCB: return"Protocol Engines";
|
||||
case 0x4C: return"SCI";
|
||||
case 0xCD: return"Seiko Instruments";
|
||||
case 0xCE: return"Samsung";
|
||||
case 0x4F: return"I3 Design System";
|
||||
case 0xD0: return"Klic";
|
||||
case 0x51: return"Crosspoint Solutions";
|
||||
case 0x52: return"Alliance Semiconductor";
|
||||
case 0xD3: return"Tandem";
|
||||
case 0x54: return"Hewlett-Packard";
|
||||
case 0xD5: return"Integrated Silicon Solutions";
|
||||
case 0xD6: return"Brooktree";
|
||||
case 0x57: return"New Media";
|
||||
case 0x58: return"MHS Electronic";
|
||||
case 0xD9: return"Performance Semiconductors";
|
||||
case 0xDA: return"Winbond Electronic";
|
||||
case 0x5B: return"Kawasaki Steel";
|
||||
case 0x5D: return"TECMAR";
|
||||
case 0x5E: return"Exar";
|
||||
case 0xDF: return"PCMCIA";
|
||||
case 0xE0: return"LG Semiconductor";
|
||||
case 0x61: return"Northern Telecom";
|
||||
case 0x62: return"Sanyo2";
|
||||
case 0xE3: return"Array Microsystems";
|
||||
case 0x64: return"Crystal Semiconductor";
|
||||
case 0xE5: return"Analog Devices";
|
||||
case 0xE6: return"PMC-Sierra";
|
||||
case 0x67: return"Asparix";
|
||||
case 0x68: return"Convex Computer";
|
||||
case 0xE9: return"Nimbus Technology";
|
||||
case 0x6B: return"Transwitch";
|
||||
case 0xEC: return"Micronas";
|
||||
case 0x6D: return"Canon";
|
||||
case 0x6E: return"Altera";
|
||||
case 0xEF: return"NEXCOM";
|
||||
case 0x70: return"Qualcomm";
|
||||
case 0xF1: return"Sony";
|
||||
case 0xF2: return"Cray Research";
|
||||
case 0x73: return"AMS";
|
||||
case 0xF4: return"Vitesse";
|
||||
case 0x75: return"Aster Electronics";
|
||||
case 0x76: return"Bay Networks";
|
||||
case 0xF7: return"Zentrum";
|
||||
case 0xF8: return"TRW";
|
||||
case 0x79: return"Thesys";
|
||||
case 0x7A: return"Solbourne Computer";
|
||||
case 0xFB: return"Allied-Signal";
|
||||
case 0x7C: return"Dialog Semiconductor";
|
||||
case 0xFD: return"Media Vision";
|
||||
case 0xFE: return"Numonyx Corporation";
|
||||
case 0x7F01: return"Cirrus Logic";
|
||||
case 0x7F02: return"National Instruments";
|
||||
case 0x7F04: return"Alcatel Mietec";
|
||||
case 0x7F07: return"JTAG Technologies";
|
||||
case 0x7F08: return"Loral";
|
||||
case 0x7F0B: return"Bestlink Systems";
|
||||
case 0x7F0D: return"GENNUM";
|
||||
case 0x7F0E: return"VideoLogic";
|
||||
case 0x7F10: return"Chip Express";
|
||||
case 0x7F13: return"TCSI";
|
||||
case 0x7F15: return"Hughes Aircraft";
|
||||
case 0x7F16: return"Lanstar Semiconductor";
|
||||
case 0x7F19: return"Music Semi";
|
||||
case 0x7F1A: return"Ericsson Components";
|
||||
case 0x7F1C: return"Eon Silicon Devices";
|
||||
case 0x7F1F: return"Integ.Memories Tech.";
|
||||
case 0x7F20: return"Corollary Inc.";
|
||||
case 0x7F23: return"EIV(Switzerland)";
|
||||
case 0x7F25: return"Zarlink(formerly Mitel)";
|
||||
case 0x7F26: return"Clearpoint";
|
||||
case 0x7F29: return"Vanguard";
|
||||
case 0x7F2A: return"Hagiwara Sys-Com";
|
||||
case 0x7F2C: return"Celestica";
|
||||
case 0x7F2F: return"Rohm Company Ltd.";
|
||||
case 0x7F31: return"Libit Signal Processing";
|
||||
case 0x7F32: return"Enhanced Memories Inc.";
|
||||
case 0x7F34: return"Adaptec Inc.";
|
||||
case 0x7F37: return"AMIC Technology";
|
||||
case 0x7F38: return"Adobe Systems";
|
||||
case 0x7F3B: return"Newport Digital";
|
||||
case 0x7F3D: return"T Square";
|
||||
case 0x7F3E: return"Seiko Epson";
|
||||
case 0x7F40: return"Viking Components";
|
||||
case 0x7F43: return"Suwa Electronics";
|
||||
case 0x7F45: return"Micron CMS";
|
||||
case 0x7F46: return"American Computer &Digital Components Inc";
|
||||
case 0x7F49: return"CPU Design";
|
||||
case 0x7F4A: return"Price Point";
|
||||
case 0x7F4C: return"Tellabs";
|
||||
case 0x7F4F: return"Transcend Information";
|
||||
case 0x7F51: return"CKD Corporation Ltd.";
|
||||
case 0x7F52: return"Capital Instruments, Inc.";
|
||||
case 0x7F54: return"Linvex Technology";
|
||||
case 0x7F57: return"Dynamem, Inc.";
|
||||
case 0x7F58: return"NERA ASA";
|
||||
case 0x7F5B: return"Acorn Computers";
|
||||
case 0x7F5D: return"Oak Technology, Inc.";
|
||||
case 0x7F5E: return"Itec Memory";
|
||||
case 0x7F61: return"Wintec Industries";
|
||||
case 0x7F62: return"Super PC Memory";
|
||||
case 0x7F64: return"Galvantech";
|
||||
case 0x7F67: return"GateField";
|
||||
case 0x7F68: return"Integrated Memory System";
|
||||
case 0x7F6B: return"Goldenram";
|
||||
case 0x7F6D: return"Cimaron Communications";
|
||||
case 0x7F6E: return"Nippon Steel Semi.Corp.";
|
||||
case 0x7F70: return"AMCC";
|
||||
case 0x7F73: return"Digital Microwave";
|
||||
case 0x7F75: return"MIMOS Semiconductor";
|
||||
case 0x7F76: return"Advanced Fibre";
|
||||
case 0x7F79: return"Acbel Polytech Inc.";
|
||||
case 0x7F7A: return"Apacer Technology";
|
||||
case 0x7F7C: return"FOXCONN";
|
||||
case 0x7F83: return"ILC Data Device";
|
||||
case 0x7F85: return"Micro Linear";
|
||||
case 0x7F86: return"Univ.Of NC";
|
||||
case 0x7F89: return"Nchip";
|
||||
case 0x7F8A: return"Galileo Tech";
|
||||
case 0x7F8C: return"Graychip";
|
||||
case 0x7F8F: return"Robert Bosch";
|
||||
case 0x7F91: return"DATARAM";
|
||||
case 0x7F92: return"United Microelec Corp.";
|
||||
case 0x7F94: return"Smart Modular";
|
||||
case 0x7F97: return"Qlogic";
|
||||
case 0x7F98: return"Kingston";
|
||||
case 0x7F9B: return"SpaSE";
|
||||
case 0x7F9D: return"Programmable Micro Corp";
|
||||
case 0x7F9E: return"DoD";
|
||||
case 0x7FA1: return"Dallas Semiconductor";
|
||||
case 0x7FA2: return"Omnivision";
|
||||
case 0x7FA4: return"Novatel Wireless";
|
||||
case 0x7FA7: return"Cabletron";
|
||||
case 0x7FA8: return"Silicon Technology";
|
||||
case 0x7FAB: return"Vantis";
|
||||
case 0x7FAD: return"Century";
|
||||
case 0x7FAE: return"Hal Computers";
|
||||
case 0x7FB0: return"Juniper Networks";
|
||||
case 0x7FB3: return"Tundra Semiconductor";
|
||||
case 0x7FB5: return"LightSpeed Semi.";
|
||||
case 0x7FB6: return"ZSP Corp.";
|
||||
case 0x7FB9: return"Dynachip";
|
||||
case 0x7FBA: return"PNY Electronics";
|
||||
case 0x7FBC: return"MMC Networks";
|
||||
case 0x7FBF: return"Broadcom";
|
||||
case 0x7FC1: return"V3 Semiconductor";
|
||||
case 0x7FC2: return"Flextronics(formerly Orbit)";
|
||||
case 0x7FC4: return"Transmeta";
|
||||
case 0x7FC7: return"Enhance 3000 Inc";
|
||||
case 0x7FC8: return"Tower Semiconductor";
|
||||
case 0x7FCB: return"Maxim Integrated Product";
|
||||
case 0x7FCD: return"Centaur Technology";
|
||||
case 0x7FCE: return"Unigen Corporation";
|
||||
case 0x7FD0: return"Memory Card Technology";
|
||||
case 0x7FD3: return"Aica Kogyo, Ltd.";
|
||||
case 0x7FD5: return"MSC Vertriebs GmbH";
|
||||
case 0x7FD6: return"AKM Company, Ltd.";
|
||||
case 0x7FD9: return"GSI Technology";
|
||||
case 0x7FDA: return"Dane-Elec (C Memory)";
|
||||
case 0x7FDC: return"Lara Technology";
|
||||
case 0x7FDF: return"Tanisys Technology";
|
||||
case 0x7FE0: return"Truevision";
|
||||
case 0x7FE3: return"MGV Memory";
|
||||
case 0x7FE5: return"Gadzoox Networks";
|
||||
case 0x7FE6: return"Multi Dimensional Cons.";
|
||||
case 0x7FE9: return"Triscend";
|
||||
case 0x7FEA: return"XaQti";
|
||||
case 0x7FEC: return"Clear Logic";
|
||||
case 0x7FEF: return"Advantage Memory";
|
||||
case 0x7FF1: return"LeCroy";
|
||||
case 0x7FF2: return"Yamaha Corporation";
|
||||
case 0x7FF4: return"NetLogic Microsystems";
|
||||
case 0x7FF7: return"BF Goodrich Data.";
|
||||
case 0x7FF8: return"Epigram";
|
||||
case 0x7FFB: return"Admor Memory";
|
||||
case 0x7FFD: return"Quadratics Superconductor";
|
||||
case 0x7FFE: return"3COM";
|
||||
#endregion JEDEC
|
||||
|
||||
case 0x0100: return "Digital Equipment Corporation";
|
||||
case 0x0101: return "3Com Corporation";
|
||||
case 0x0102: return "Megahertz Corporation";
|
||||
case 0x0104: return "Socket Communications";
|
||||
case 0x0105: return "TDK Corporation";
|
||||
case 0x0108: return "Standard Microsystems Corporation";
|
||||
case 0x0109: return "Motorola Corporation";
|
||||
case 0x010b: return "National Instruments";
|
||||
case 0x0115: return "US Robotics Corporation";
|
||||
case 0x0121: return "Olicom";
|
||||
case 0x0126: return "Proxim";
|
||||
case 0x0128: return "Megahertz Corporation";
|
||||
case 0x012F: return "Adaptec Corporation";
|
||||
case 0x0137: return "Quatech";
|
||||
case 0x0138: return "Compaq";
|
||||
case 0x0140: return "Ositech";
|
||||
case 0x0143: return "D-Link";
|
||||
case 0x0149: return "Netgear";
|
||||
case 0x014D: return "Simple Technology";
|
||||
case 0x0156: return "Lucent Technologies";
|
||||
case 0x015F: return "Aironet Wireless Communications";
|
||||
case 0x016B: return "Ericsson";
|
||||
case 0x016C: return "Psion";
|
||||
case 0x0183: return "Compaq";
|
||||
case 0x0186: return "Kingston";
|
||||
case 0x0192: return "Sierra Wireless";
|
||||
case 0x0194: return "Dayna Corporation";
|
||||
case 0x01a6: return "Raytheon";
|
||||
case 0x01BF: return "Belkin";
|
||||
case 0x01EB: return "Bay Networks";
|
||||
case 0x0200: return "Farallon Communications";
|
||||
case 0x021B: return "Telecom Device";
|
||||
case 0x023D: return "Nokia Communications";
|
||||
case 0x0250: return "Samsung";
|
||||
case 0x0264: return "Anycom";
|
||||
case 0x0268: return "Alvarion Ltd.";
|
||||
case 0x026C: return "Symbol";
|
||||
case 0x026F: return "BUFFALO";
|
||||
case 0x0274: return "The Linksys Group";
|
||||
case 0x0288: return "NEC Infrontia";
|
||||
case 0x028A: return "I-O DATA";
|
||||
case 0x02AA: return "Asustek Computer";
|
||||
case 0x02AC: return "Siemens";
|
||||
case 0x02D2: return "Microsoft Corporation";
|
||||
case 0x02DF: return "AmbiCom Inc";
|
||||
case 0x0a02: return "BreezeCOM";
|
||||
case 0x10CD: return "NewMedia";
|
||||
case 0x1668: return "ACTIONTEC";
|
||||
case 0x3401: return "Lasat Communications A/S";
|
||||
case 0x4E01: return "Lexar Media";
|
||||
case 0x5241: return "Archos";
|
||||
case 0x890F: return "Dual";
|
||||
case 0x8A01: return "Compex Corporation";
|
||||
case 0xC001: return "Contec";
|
||||
case 0xC00B: return "MACNICA";
|
||||
case 0xC00C: return "Roland";
|
||||
case 0xC00F: return "Corega K.K.";
|
||||
case 0xC012: return "Hagiwara SYS-COM";
|
||||
case 0xC015: return "RATOC System Inc.";
|
||||
case 0xC020: return "NextCom K.K.";
|
||||
case 0xC250: return "EMTAC Technology Corporation";
|
||||
case 0xD601: return "Elsa";
|
||||
default: return $"Unknown vendor id 0x{id:X4}";
|
||||
case 0x0100: return"Digital Equipment Corporation";
|
||||
case 0x0101: return"3Com Corporation";
|
||||
case 0x0102: return"Megahertz Corporation";
|
||||
case 0x0104: return"Socket Communications";
|
||||
case 0x0105: return"TDK Corporation";
|
||||
case 0x0108: return"Standard Microsystems Corporation";
|
||||
case 0x0109: return"Motorola Corporation";
|
||||
case 0x010b: return"National Instruments";
|
||||
case 0x0115: return"US Robotics Corporation";
|
||||
case 0x0121: return"Olicom";
|
||||
case 0x0126: return"Proxim";
|
||||
case 0x0128: return"Megahertz Corporation";
|
||||
case 0x012F: return"Adaptec Corporation";
|
||||
case 0x0137: return"Quatech";
|
||||
case 0x0138: return"Compaq";
|
||||
case 0x0140: return"Ositech";
|
||||
case 0x0143: return"D-Link";
|
||||
case 0x0149: return"Netgear";
|
||||
case 0x014D: return"Simple Technology";
|
||||
case 0x0156: return"Lucent Technologies";
|
||||
case 0x015F: return"Aironet Wireless Communications";
|
||||
case 0x016B: return"Ericsson";
|
||||
case 0x016C: return"Psion";
|
||||
case 0x0183: return"Compaq";
|
||||
case 0x0186: return"Kingston";
|
||||
case 0x0192: return"Sierra Wireless";
|
||||
case 0x0194: return"Dayna Corporation";
|
||||
case 0x01a6: return"Raytheon";
|
||||
case 0x01BF: return"Belkin";
|
||||
case 0x01EB: return"Bay Networks";
|
||||
case 0x0200: return"Farallon Communications";
|
||||
case 0x021B: return"Telecom Device";
|
||||
case 0x023D: return"Nokia Communications";
|
||||
case 0x0250: return"Samsung";
|
||||
case 0x0264: return"Anycom";
|
||||
case 0x0268: return"Alvarion Ltd.";
|
||||
case 0x026C: return"Symbol";
|
||||
case 0x026F: return"BUFFALO";
|
||||
case 0x0274: return"The Linksys Group";
|
||||
case 0x0288: return"NEC Infrontia";
|
||||
case 0x028A: return"I-O DATA";
|
||||
case 0x02AA: return"Asustek Computer";
|
||||
case 0x02AC: return"Siemens";
|
||||
case 0x02D2: return"Microsoft Corporation";
|
||||
case 0x02DF: return"AmbiCom Inc";
|
||||
case 0x0a02: return"BreezeCOM";
|
||||
case 0x10CD: return"NewMedia";
|
||||
case 0x1668: return"ACTIONTEC";
|
||||
case 0x3401: return"Lasat Communications A/S";
|
||||
case 0x4E01: return"Lexar Media";
|
||||
case 0x5241: return"Archos";
|
||||
case 0x890F: return"Dual";
|
||||
case 0x8A01: return"Compex Corporation";
|
||||
case 0xC001: return"Contec";
|
||||
case 0xC00B: return"MACNICA";
|
||||
case 0xC00C: return"Roland";
|
||||
case 0xC00F: return"Corega K.K.";
|
||||
case 0xC012: return"Hagiwara SYS-COM";
|
||||
case 0xC015: return"RATOC System Inc.";
|
||||
case 0xC020: return"NextCom K.K.";
|
||||
case 0xC250: return"EMTAC Technology Corporation";
|
||||
case 0xD601: return"Elsa";
|
||||
default: return$"Unknown vendor id 0x{id:X4}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,33 +35,16 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class DiscStructureCapabilities
|
||||
{
|
||||
public struct Capability
|
||||
{
|
||||
/// <summary>
|
||||
/// READ/SEND DISC STRUCTURE format code
|
||||
/// </summary>
|
||||
public byte FormatCode;
|
||||
/// <summary>
|
||||
/// Supported in SEND DISC STRUCTURE
|
||||
/// </summary>
|
||||
public bool SDS;
|
||||
/// <summary>
|
||||
/// Supported in READ DISC STRUCTURE
|
||||
/// </summary>
|
||||
public bool RDS;
|
||||
}
|
||||
|
||||
public static Capability[] Decode(byte[] response)
|
||||
{
|
||||
ushort len = (ushort)((response[0] << 8) + response[1]);
|
||||
|
||||
if(len + 2 != response.Length) return null;
|
||||
if(len + 2 != response.Length)
|
||||
return null;
|
||||
|
||||
List<Capability> caps = new List<Capability>();
|
||||
|
||||
@@ -69,17 +52,27 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
while(offset < response.Length)
|
||||
{
|
||||
Capability cap = new Capability
|
||||
var cap = new Capability
|
||||
{
|
||||
FormatCode = response[offset],
|
||||
SDS = (response[offset + 1] & 0x80) == 0x80,
|
||||
RDS = (response[offset + 1] & 0x40) == 0x40
|
||||
FormatCode = response[offset], SDS = (response[offset + 1] & 0x80) == 0x80,
|
||||
RDS = (response[offset + 1] & 0x40) == 0x40
|
||||
};
|
||||
|
||||
caps.Add(cap);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
return caps.ToArray();
|
||||
}
|
||||
|
||||
public struct Capability
|
||||
{
|
||||
/// <summary>READ/SEND DISC STRUCTURE format code</summary>
|
||||
public byte FormatCode;
|
||||
/// <summary>Supported in SEND DISC STRUCTURE</summary>
|
||||
public bool SDS;
|
||||
/// <summary>Supported in READ DISC STRUCTURE</summary>
|
||||
public bool RDS;
|
||||
}
|
||||
}
|
||||
}
|
||||
1835
SCSI/EVPD.cs
1835
SCSI/EVPD.cs
File diff suppressed because it is too large
Load Diff
299
SCSI/Enums.cs
299
SCSI/Enums.cs
@@ -36,290 +36,115 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
public enum PeripheralQualifiers : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Peripheral qualifier: Device is connected and supported
|
||||
/// </summary>
|
||||
Supported = 0x00,
|
||||
/// <summary>
|
||||
/// Peripheral qualifier: Device is supported but not connected
|
||||
/// </summary>
|
||||
Unconnected = 0x01,
|
||||
/// <summary>
|
||||
/// Peripheral qualifier: Reserved value
|
||||
/// </summary>
|
||||
Reserved = 0x02,
|
||||
/// <summary>
|
||||
/// Peripheral qualifier: Device is connected but unsupported
|
||||
/// </summary>
|
||||
Unsupported = 0x03,
|
||||
/// <summary>
|
||||
/// Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07
|
||||
/// </summary>
|
||||
/// <summary>Peripheral qualifier: Device is connected and supported</summary>
|
||||
Supported = 0x00, /// <summary>Peripheral qualifier: Device is supported but not connected</summary>
|
||||
Unconnected = 0x01, /// <summary>Peripheral qualifier: Reserved value</summary>
|
||||
Reserved = 0x02, /// <summary>Peripheral qualifier: Device is connected but unsupported</summary>
|
||||
Unsupported = 0x03, /// <summary>Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07</summary>
|
||||
VendorMask = 0x04
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum PeripheralDeviceTypes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Direct-access device
|
||||
/// </summary>
|
||||
DirectAccess = 0x00,
|
||||
/// <summary>
|
||||
/// Sequential-access device
|
||||
/// </summary>
|
||||
SequentialAccess = 0x01,
|
||||
/// <summary>
|
||||
/// Printer device
|
||||
/// </summary>
|
||||
PrinterDevice = 0x02,
|
||||
/// <summary>
|
||||
/// Processor device
|
||||
/// </summary>
|
||||
ProcessorDevice = 0x03,
|
||||
/// <summary>
|
||||
/// Write-once device
|
||||
/// </summary>
|
||||
WriteOnceDevice = 0x04,
|
||||
/// <summary>
|
||||
/// CD-ROM/DVD/etc device
|
||||
/// </summary>
|
||||
MultiMediaDevice = 0x05,
|
||||
/// <summary>
|
||||
/// Scanner device
|
||||
/// </summary>
|
||||
ScannerDevice = 0x06,
|
||||
/// <summary>
|
||||
/// Optical memory device
|
||||
/// </summary>
|
||||
OpticalDevice = 0x07,
|
||||
/// <summary>
|
||||
/// Medium change device
|
||||
/// </summary>
|
||||
MediumChangerDevice = 0x08,
|
||||
/// <summary>
|
||||
/// Communications device
|
||||
/// </summary>
|
||||
CommsDevice = 0x09,
|
||||
/// <summary>
|
||||
/// Graphics arts pre-press device (defined in ASC IT8)
|
||||
/// </summary>
|
||||
PrePressDevice1 = 0x0A,
|
||||
/// <summary>
|
||||
/// Graphics arts pre-press device (defined in ASC IT8)
|
||||
/// </summary>
|
||||
PrePressDevice2 = 0x0B,
|
||||
/// <summary>
|
||||
/// Array controller device
|
||||
/// </summary>
|
||||
ArrayControllerDevice = 0x0C,
|
||||
/// <summary>
|
||||
/// Enclosure services device
|
||||
/// </summary>
|
||||
EnclosureServiceDevice = 0x0D,
|
||||
/// <summary>
|
||||
/// Simplified direct-access device
|
||||
/// </summary>
|
||||
SimplifiedDevice = 0x0E,
|
||||
/// <summary>
|
||||
/// Optical card reader/writer device
|
||||
/// </summary>
|
||||
OCRWDevice = 0x0F,
|
||||
/// <summary>
|
||||
/// Bridging Expanders
|
||||
/// </summary>
|
||||
BridgingExpander = 0x10,
|
||||
/// <summary>
|
||||
/// Object-based Storage Device
|
||||
/// </summary>
|
||||
ObjectDevice = 0x11,
|
||||
/// <summary>
|
||||
/// Automation/Drive Interface
|
||||
/// </summary>
|
||||
ADCDevice = 0x12,
|
||||
/// <summary>
|
||||
/// Security Manager Device
|
||||
/// </summary>
|
||||
SCSISecurityManagerDevice = 0x13,
|
||||
/// <summary>
|
||||
/// Host managed zoned block device
|
||||
/// </summary>
|
||||
SCSIZonedBlockDevice = 0x14,
|
||||
/// <summary>
|
||||
/// Well known logical unit
|
||||
/// </summary>
|
||||
WellKnownDevice = 0x1E,
|
||||
/// <summary>
|
||||
/// Unknown or no device type
|
||||
/// </summary>
|
||||
/// <summary>Direct-access device</summary>
|
||||
DirectAccess = 0x00, /// <summary>Sequential-access device</summary>
|
||||
SequentialAccess = 0x01, /// <summary>Printer device</summary>
|
||||
PrinterDevice = 0x02, /// <summary>Processor device</summary>
|
||||
ProcessorDevice = 0x03, /// <summary>Write-once device</summary>
|
||||
WriteOnceDevice = 0x04, /// <summary>CD-ROM/DVD/etc device</summary>
|
||||
MultiMediaDevice = 0x05, /// <summary>Scanner device</summary>
|
||||
ScannerDevice = 0x06, /// <summary>Optical memory device</summary>
|
||||
OpticalDevice = 0x07, /// <summary>Medium change device</summary>
|
||||
MediumChangerDevice = 0x08, /// <summary>Communications device</summary>
|
||||
CommsDevice = 0x09, /// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
|
||||
PrePressDevice1 = 0x0A, /// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
|
||||
PrePressDevice2 = 0x0B, /// <summary>Array controller device</summary>
|
||||
ArrayControllerDevice = 0x0C, /// <summary>Enclosure services device</summary>
|
||||
EnclosureServiceDevice = 0x0D, /// <summary>Simplified direct-access device</summary>
|
||||
SimplifiedDevice = 0x0E, /// <summary>Optical card reader/writer device</summary>
|
||||
OCRWDevice = 0x0F, /// <summary>Bridging Expanders</summary>
|
||||
BridgingExpander = 0x10, /// <summary>Object-based Storage Device</summary>
|
||||
ObjectDevice = 0x11, /// <summary>Automation/Drive Interface</summary>
|
||||
ADCDevice = 0x12, /// <summary>Security Manager Device</summary>
|
||||
SCSISecurityManagerDevice = 0x13, /// <summary>Host managed zoned block device</summary>
|
||||
SCSIZonedBlockDevice = 0x14, /// <summary>Well known logical unit</summary>
|
||||
WellKnownDevice = 0x1E, /// <summary>Unknown or no device type</summary>
|
||||
UnknownDevice = 0x1F
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum ANSIVersions : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Device does not claim conformance to any ANSI version
|
||||
/// </summary>
|
||||
ANSINoVersion = 0x00,
|
||||
/// <summary>
|
||||
/// Device complies with ANSI X3.131:1986
|
||||
/// </summary>
|
||||
ANSI1986Version = 0x01,
|
||||
/// <summary>
|
||||
/// Device complies with ANSI X3.131:1994
|
||||
/// </summary>
|
||||
ANSI1994Version = 0x02,
|
||||
/// <summary>
|
||||
/// Device complies with ANSI X3.301:1997
|
||||
/// </summary>
|
||||
ANSI1997Version = 0x03,
|
||||
/// <summary>
|
||||
/// Device complies with ANSI X3.351:2001
|
||||
/// </summary>
|
||||
ANSI2001Version = 0x04,
|
||||
/// <summary>
|
||||
/// Device complies with ANSI X3.408:2005.
|
||||
/// </summary>
|
||||
ANSI2005Version = 0x05,
|
||||
/// <summary>
|
||||
/// Device complies with SPC-4
|
||||
/// </summary>
|
||||
/// <summary>Device does not claim conformance to any ANSI version</summary>
|
||||
ANSINoVersion = 0x00, /// <summary>Device complies with ANSI X3.131:1986</summary>
|
||||
ANSI1986Version = 0x01, /// <summary>Device complies with ANSI X3.131:1994</summary>
|
||||
ANSI1994Version = 0x02, /// <summary>Device complies with ANSI X3.301:1997</summary>
|
||||
ANSI1997Version = 0x03, /// <summary>Device complies with ANSI X3.351:2001</summary>
|
||||
ANSI2001Version = 0x04, /// <summary>Device complies with ANSI X3.408:2005.</summary>
|
||||
ANSI2005Version = 0x05, /// <summary>Device complies with SPC-4</summary>
|
||||
ANSI2008Version = 0x06
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum ECMAVersions : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Device does not claim conformance to any ECMA version
|
||||
/// </summary>
|
||||
ECMANoVersion = 0x00,
|
||||
/// <summary>
|
||||
/// Device complies with a ECMA-111 standard
|
||||
/// </summary>
|
||||
/// <summary>Device does not claim conformance to any ECMA version</summary>
|
||||
ECMANoVersion = 0x00, /// <summary>Device complies with a ECMA-111 standard</summary>
|
||||
ECMA111 = 0x01
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum ISOVersions : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Device does not claim conformance to any ISO/IEC version
|
||||
/// </summary>
|
||||
ISONoVersion = 0x00,
|
||||
/// <summary>
|
||||
/// Device complies with ISO/IEC 9316:1995
|
||||
/// </summary>
|
||||
/// <summary>Device does not claim conformance to any ISO/IEC version</summary>
|
||||
ISONoVersion = 0x00, /// <summary>Device complies with ISO/IEC 9316:1995</summary>
|
||||
ISO1995Version = 0x02
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum SPIClocking : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Supports only ST
|
||||
/// </summary>
|
||||
ST = 0x00,
|
||||
/// <summary>
|
||||
/// Supports only DT
|
||||
/// </summary>
|
||||
DT = 0x01,
|
||||
/// <summary>
|
||||
/// Reserved value
|
||||
/// </summary>
|
||||
Reserved = 0x02,
|
||||
/// <summary>
|
||||
/// Supports ST and DT
|
||||
/// </summary>
|
||||
/// <summary>Supports only ST</summary>
|
||||
ST = 0x00, /// <summary>Supports only DT</summary>
|
||||
DT = 0x01, /// <summary>Reserved value</summary>
|
||||
Reserved = 0x02, /// <summary>Supports ST and DT</summary>
|
||||
STandDT = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum TGPSValues : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Assymetrical access not supported
|
||||
/// </summary>
|
||||
NotSupported = 0x00,
|
||||
/// <summary>
|
||||
/// Only implicit assymetrical access is supported
|
||||
/// </summary>
|
||||
OnlyImplicit = 0x01,
|
||||
/// <summary>
|
||||
/// Only explicit assymetrical access is supported
|
||||
/// </summary>
|
||||
OnlyExplicit = 0x02,
|
||||
/// <summary>
|
||||
/// Both implicit and explicit assymetrical access are supported
|
||||
/// </summary>
|
||||
/// <summary>Assymetrical access not supported</summary>
|
||||
NotSupported = 0x00, /// <summary>Only implicit assymetrical access is supported</summary>
|
||||
OnlyImplicit = 0x01, /// <summary>Only explicit assymetrical access is supported</summary>
|
||||
OnlyExplicit = 0x02, /// <summary>Both implicit and explicit assymetrical access are supported</summary>
|
||||
Both = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum ProtocolIdentifiers : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Fibre Channel
|
||||
/// </summary>
|
||||
FibreChannel = 0,
|
||||
/// <summary>
|
||||
/// Parallel SCSI
|
||||
/// </summary>
|
||||
SCSI = 1,
|
||||
/// <summary>
|
||||
/// SSA
|
||||
/// </summary>
|
||||
SSA = 2,
|
||||
/// <summary>
|
||||
/// IEEE-1394
|
||||
/// </summary>
|
||||
Firewire = 3,
|
||||
/// <summary>
|
||||
/// SCSI Remote Direct Memory Access Protocol
|
||||
/// </summary>
|
||||
RDMAP = 4,
|
||||
/// <summary>
|
||||
/// Internet SCSI
|
||||
/// </summary>
|
||||
iSCSI = 5,
|
||||
/// <summary>
|
||||
/// Serial SCSI
|
||||
/// </summary>
|
||||
SAS = 6,
|
||||
/// <summary>
|
||||
/// Automation/Drive Interface Transport Protocol
|
||||
/// </summary>
|
||||
ADT = 7,
|
||||
/// <summary>
|
||||
/// AT Attachment Interface (ATA/ATAPI)
|
||||
/// </summary>
|
||||
ATA = 8,
|
||||
/// <summary>
|
||||
/// USB Attached SCSI
|
||||
/// </summary>
|
||||
UAS = 9,
|
||||
/// <summary>
|
||||
/// SCSI over PCI Express
|
||||
/// </summary>
|
||||
SCSIe = 10,
|
||||
/// <summary>
|
||||
/// PCI Express
|
||||
/// </summary>
|
||||
PCIe = 11,
|
||||
/// <summary>
|
||||
/// No specific protocol
|
||||
/// </summary>
|
||||
/// <summary>Fibre Channel</summary>
|
||||
FibreChannel = 0, /// <summary>Parallel SCSI</summary>
|
||||
SCSI = 1, /// <summary>SSA</summary>
|
||||
SSA = 2, /// <summary>IEEE-1394</summary>
|
||||
Firewire = 3, /// <summary>SCSI Remote Direct Memory Access Protocol</summary>
|
||||
RDMAP = 4, /// <summary>Internet SCSI</summary>
|
||||
iSCSI = 5, /// <summary>Serial SCSI</summary>
|
||||
SAS = 6, /// <summary>Automation/Drive Interface Transport Protocol</summary>
|
||||
ADT = 7, /// <summary>AT Attachment Interface (ATA/ATAPI)</summary>
|
||||
ATA = 8, /// <summary>USB Attached SCSI</summary>
|
||||
UAS = 9, /// <summary>SCSI over PCI Express</summary>
|
||||
SCSIe = 10, /// <summary>PCI Express</summary>
|
||||
PCIe = 11, /// <summary>No specific protocol</summary>
|
||||
NoProtocol = 15
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public enum ScsiDefinitions : byte
|
||||
{
|
||||
Current = 0,
|
||||
SCSI1 = 1,
|
||||
CCS = 2,
|
||||
SCSI2 = 3,
|
||||
SCSI3 = 4
|
||||
Current = 0, SCSI1 = 1, CCS = 2,
|
||||
SCSI2 = 3, SCSI3 = 4
|
||||
}
|
||||
}
|
||||
1580
SCSI/Inquiry.cs
1580
SCSI/Inquiry.cs
File diff suppressed because it is too large
Load Diff
402
SCSI/MMC/AACS.cs
402
SCSI/MMC/AACS.cs
@@ -37,195 +37,20 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class AACS
|
||||
{
|
||||
public struct AACSVolumeIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// AACS volume identifier data
|
||||
/// </summary>
|
||||
public byte[] VolumeIdentifier;
|
||||
}
|
||||
|
||||
public struct AACSMediaSerialNumber
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// AACS media serial number
|
||||
/// </summary>
|
||||
public byte[] MediaSerialNumber;
|
||||
}
|
||||
|
||||
public struct AACSMediaIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// AACS media identifier data
|
||||
/// </summary>
|
||||
public byte[] MediaIdentifier;
|
||||
}
|
||||
|
||||
public struct AACSMediaKeyBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Number of MKB packs available to transfer
|
||||
/// </summary>
|
||||
public byte TotalPacks;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// AACS media key block packs
|
||||
/// </summary>
|
||||
public byte[] MediaKeyBlockPacks;
|
||||
}
|
||||
|
||||
public struct AACSDataKeys
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// AACS data keys
|
||||
/// </summary>
|
||||
public byte[] DataKeys;
|
||||
}
|
||||
|
||||
public struct AACSLBAExtentsResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data Length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Number of LBA extents the drive can store.
|
||||
/// if(MaxLBAExtents == 0 && DataLength > 2), 256 extents can be stored
|
||||
/// </summary>
|
||||
public byte MaxLBAExtents;
|
||||
/// <summary>
|
||||
/// Bytes 4 to end
|
||||
/// LBA Extents
|
||||
/// </summary>
|
||||
public AACSLBAExtent[] Extents;
|
||||
}
|
||||
|
||||
public struct AACSLBAExtent
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte[] Reserved;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// Start LBA of extent
|
||||
/// </summary>
|
||||
public uint StartLBA;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 15
|
||||
/// Extent length
|
||||
/// </summary>
|
||||
public uint LBACount;
|
||||
}
|
||||
|
||||
public static AACSVolumeIdentifier? DecodeAACSVolumeIdentifier(byte[] AACSVIResponse)
|
||||
{
|
||||
if(AACSVIResponse == null) return null;
|
||||
if(AACSVIResponse == null)
|
||||
return null;
|
||||
|
||||
AACSVolumeIdentifier decoded = new AACSVolumeIdentifier();
|
||||
var decoded = new AACSVolumeIdentifier();
|
||||
|
||||
decoded.VolumeIdentifier = new byte[AACSVIResponse.Length - 4];
|
||||
|
||||
@@ -239,16 +64,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSVolumeIdentifier(AACSVolumeIdentifier? AACSVIResponse)
|
||||
{
|
||||
if(AACSVIResponse == null) return null;
|
||||
if(AACSVIResponse == null)
|
||||
return null;
|
||||
|
||||
AACSVolumeIdentifier response = AACSVIResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("AACS Volume Identifier in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VolumeIdentifier, 80));
|
||||
|
||||
@@ -258,14 +87,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSVolumeIdentifier(byte[] AACSVIResponse)
|
||||
{
|
||||
AACSVolumeIdentifier? decoded = DecodeAACSVolumeIdentifier(AACSVIResponse);
|
||||
|
||||
return PrettifyAACSVolumeIdentifier(decoded);
|
||||
}
|
||||
|
||||
public static AACSMediaSerialNumber? DecodeAACSMediaSerialNumber(byte[] AACSMSNResponse)
|
||||
{
|
||||
if(AACSMSNResponse == null) return null;
|
||||
if(AACSMSNResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaSerialNumber decoded = new AACSMediaSerialNumber();
|
||||
var decoded = new AACSMediaSerialNumber();
|
||||
|
||||
decoded.MediaSerialNumber = new byte[AACSMSNResponse.Length - 4];
|
||||
|
||||
@@ -279,16 +110,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSMediaSerialNumber(AACSMediaSerialNumber? AACSMSNResponse)
|
||||
{
|
||||
if(AACSMSNResponse == null) return null;
|
||||
if(AACSMSNResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaSerialNumber response = AACSMSNResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("AACS Media Serial Number in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaSerialNumber, 80));
|
||||
|
||||
@@ -298,14 +133,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSMediaSerialNumber(byte[] AACSMSNResponse)
|
||||
{
|
||||
AACSMediaSerialNumber? decoded = DecodeAACSMediaSerialNumber(AACSMSNResponse);
|
||||
|
||||
return PrettifyAACSMediaSerialNumber(decoded);
|
||||
}
|
||||
|
||||
public static AACSMediaIdentifier? DecodeAACSMediaIdentifier(byte[] AACSMIResponse)
|
||||
{
|
||||
if(AACSMIResponse == null) return null;
|
||||
if(AACSMIResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaIdentifier decoded = new AACSMediaIdentifier();
|
||||
var decoded = new AACSMediaIdentifier();
|
||||
|
||||
decoded.MediaIdentifier = new byte[AACSMIResponse.Length - 4];
|
||||
|
||||
@@ -319,16 +156,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSMediaIdentifier(AACSMediaIdentifier? AACSMIResponse)
|
||||
{
|
||||
if(AACSMIResponse == null) return null;
|
||||
if(AACSMIResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaIdentifier response = AACSMIResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("AACS Media Identifier in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaIdentifier, 80));
|
||||
|
||||
@@ -338,14 +179,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSMediaIdentifier(byte[] AACSMIResponse)
|
||||
{
|
||||
AACSMediaIdentifier? decoded = DecodeAACSMediaIdentifier(AACSMIResponse);
|
||||
|
||||
return PrettifyAACSMediaIdentifier(decoded);
|
||||
}
|
||||
|
||||
public static AACSMediaKeyBlock? DecodeAACSMediaKeyBlock(byte[] AACSMKBResponse)
|
||||
{
|
||||
if(AACSMKBResponse == null) return null;
|
||||
if(AACSMKBResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaKeyBlock decoded = new AACSMediaKeyBlock();
|
||||
var decoded = new AACSMediaKeyBlock();
|
||||
|
||||
decoded.MediaKeyBlockPacks = new byte[AACSMKBResponse.Length - 4];
|
||||
|
||||
@@ -359,17 +202,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSMediaKeyBlock(AACSMediaKeyBlock? AACSMKBResponse)
|
||||
{
|
||||
if(AACSMKBResponse == null) return null;
|
||||
if(AACSMKBResponse == null)
|
||||
return null;
|
||||
|
||||
AACSMediaKeyBlock response = AACSMKBResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved != 0)
|
||||
sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks).
|
||||
AppendLine();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("AACS Media Key Blocks in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaKeyBlockPacks, 80));
|
||||
|
||||
@@ -379,14 +225,16 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSMediaKeyBlock(byte[] AACSMKBResponse)
|
||||
{
|
||||
AACSMediaKeyBlock? decoded = DecodeAACSMediaKeyBlock(AACSMKBResponse);
|
||||
|
||||
return PrettifyAACSMediaKeyBlock(decoded);
|
||||
}
|
||||
|
||||
public static AACSDataKeys? DecodeAACSDataKeys(byte[] AACSDKResponse)
|
||||
{
|
||||
if(AACSDKResponse == null) return null;
|
||||
if(AACSDKResponse == null)
|
||||
return null;
|
||||
|
||||
AACSDataKeys decoded = new AACSDataKeys();
|
||||
var decoded = new AACSDataKeys();
|
||||
|
||||
decoded.DataKeys = new byte[AACSDKResponse.Length - 4];
|
||||
|
||||
@@ -400,16 +248,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSDataKeys(AACSDataKeys? AACSDKResponse)
|
||||
{
|
||||
if(AACSDKResponse == null) return null;
|
||||
if(AACSDKResponse == null)
|
||||
return null;
|
||||
|
||||
AACSDataKeys response = AACSDKResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("AACS Data Keys in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DataKeys, 80));
|
||||
|
||||
@@ -419,21 +271,24 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSDataKeys(byte[] AACSDKResponse)
|
||||
{
|
||||
AACSDataKeys? decoded = DecodeAACSDataKeys(AACSDKResponse);
|
||||
|
||||
return PrettifyAACSDataKeys(decoded);
|
||||
}
|
||||
|
||||
public static AACSLBAExtentsResponse? DecodeAACSLBAExtents(byte[] AACSLBAExtsResponse)
|
||||
{
|
||||
if(AACSLBAExtsResponse == null) return null;
|
||||
if(AACSLBAExtsResponse == null)
|
||||
return null;
|
||||
|
||||
AACSLBAExtentsResponse decoded = new AACSLBAExtentsResponse
|
||||
var decoded = new AACSLBAExtentsResponse
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(AACSLBAExtsResponse, 0),
|
||||
Reserved = AACSLBAExtsResponse[2],
|
||||
MaxLBAExtents = AACSLBAExtsResponse[3]
|
||||
};
|
||||
|
||||
if((AACSLBAExtsResponse.Length - 4) % 16 != 0) return decoded;
|
||||
if((AACSLBAExtsResponse.Length - 4) % 16 != 0)
|
||||
return decoded;
|
||||
|
||||
decoded.Extents = new AACSLBAExtent[(AACSLBAExtsResponse.Length - 4) / 16];
|
||||
|
||||
@@ -450,17 +305,18 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyAACSLBAExtents(AACSLBAExtentsResponse? AACSLBAExtsResponse)
|
||||
{
|
||||
if(AACSLBAExtsResponse == null) return null;
|
||||
if(AACSLBAExtsResponse == null)
|
||||
return null;
|
||||
|
||||
AACSLBAExtentsResponse response = AACSLBAExtsResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(response.MaxLBAExtents == 0)
|
||||
sb.AppendLine(response.DataLength > 2
|
||||
? "Drive can store 256 LBA Extents"
|
||||
sb.AppendLine(response.DataLength > 2 ? "Drive can store 256 LBA Extents"
|
||||
: "Drive cannot store LBA Extents");
|
||||
else sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine();
|
||||
else
|
||||
sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine();
|
||||
|
||||
for(int i = 0; i < response.Extents.Length; i++)
|
||||
sb.AppendFormat("LBA Extent {0} starts at LBA {1} and goes for {2} sectors", i,
|
||||
@@ -472,7 +328,93 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyAACSLBAExtents(byte[] AACSLBAExtsResponse)
|
||||
{
|
||||
AACSLBAExtentsResponse? decoded = DecodeAACSLBAExtents(AACSLBAExtsResponse);
|
||||
|
||||
return PrettifyAACSLBAExtents(decoded);
|
||||
}
|
||||
|
||||
public struct AACSVolumeIdentifier
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to end AACS volume identifier data</summary>
|
||||
public byte[] VolumeIdentifier;
|
||||
}
|
||||
|
||||
public struct AACSMediaSerialNumber
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to end AACS media serial number</summary>
|
||||
public byte[] MediaSerialNumber;
|
||||
}
|
||||
|
||||
public struct AACSMediaIdentifier
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to end AACS media identifier data</summary>
|
||||
public byte[] MediaIdentifier;
|
||||
}
|
||||
|
||||
public struct AACSMediaKeyBlock
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>Byte 3 Number of MKB packs available to transfer</summary>
|
||||
public byte TotalPacks;
|
||||
/// <summary>Bytes 4 to end AACS media key block packs</summary>
|
||||
public byte[] MediaKeyBlockPacks;
|
||||
}
|
||||
|
||||
public struct AACSDataKeys
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to end AACS data keys</summary>
|
||||
public byte[] DataKeys;
|
||||
}
|
||||
|
||||
public struct AACSLBAExtentsResponse
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data Length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Byte 3 Number of LBA extents the drive can store. if(MaxLBAExtents == 0 && DataLength > 2), 256
|
||||
/// extents can be stored
|
||||
/// </summary>
|
||||
public byte MaxLBAExtents;
|
||||
/// <summary>Bytes 4 to end LBA Extents</summary>
|
||||
public AACSLBAExtent[] Extents;
|
||||
}
|
||||
|
||||
public struct AACSLBAExtent
|
||||
{
|
||||
/// <summary>Bytes 0 to 7 Reserved</summary>
|
||||
public byte[] Reserved;
|
||||
/// <summary>Bytes 8 to 11 Start LBA of extent</summary>
|
||||
public uint StartLBA;
|
||||
/// <summary>Bytes 12 to 15 Extent length</summary>
|
||||
public uint LBACount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,59 +37,23 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class CPRM
|
||||
{
|
||||
public struct CPRMMediaKeyBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data Length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Number of MKB packs available to transfer
|
||||
/// </summary>
|
||||
public byte TotalPacks;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// MKB Packs
|
||||
/// </summary>
|
||||
public byte[] MKBPackData;
|
||||
}
|
||||
|
||||
public static CPRMMediaKeyBlock? DecodeCPRMMediaKeyBlock(byte[] CPRMMKBResponse)
|
||||
{
|
||||
if(CPRMMKBResponse == null) return null;
|
||||
if(CPRMMKBResponse == null)
|
||||
return null;
|
||||
|
||||
CPRMMediaKeyBlock decoded = new CPRMMediaKeyBlock
|
||||
var decoded = new CPRMMediaKeyBlock
|
||||
{
|
||||
MKBPackData = new byte[CPRMMKBResponse.Length - 4],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0),
|
||||
Reserved = CPRMMKBResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0), Reserved = CPRMMKBResponse[2],
|
||||
TotalPacks = CPRMMKBResponse[3]
|
||||
};
|
||||
|
||||
@@ -100,17 +64,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyCPRMMediaKeyBlock(CPRMMediaKeyBlock? CPRMMKBResponse)
|
||||
{
|
||||
if(CPRMMKBResponse == null) return null;
|
||||
if(CPRMMKBResponse == null)
|
||||
return null;
|
||||
|
||||
CPRMMediaKeyBlock response = CPRMMKBResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved != 0)
|
||||
sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks).
|
||||
AppendLine();
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine();
|
||||
#endif
|
||||
sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("CPRM Media Key Blocks in hex follows:");
|
||||
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MKBPackData, 80));
|
||||
|
||||
@@ -120,7 +87,20 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyCPRMMediaKeyBlock(byte[] CPRMMKBResponse)
|
||||
{
|
||||
CPRMMediaKeyBlock? decoded = DecodeCPRMMediaKeyBlock(CPRMMKBResponse);
|
||||
|
||||
return PrettifyCPRMMediaKeyBlock(decoded);
|
||||
}
|
||||
|
||||
public struct CPRMMediaKeyBlock
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data Length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved;
|
||||
/// <summary>Byte 3 Number of MKB packs available to transfer</summary>
|
||||
public byte TotalPacks;
|
||||
/// <summary>Byte 4 MKB Packs</summary>
|
||||
public byte[] MKBPackData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,257 +37,29 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class DiscInformation
|
||||
{
|
||||
public struct StandardDiscInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// 32 + OPCTablesNumber*8
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 7 to 5
|
||||
/// 000b
|
||||
/// </summary>
|
||||
public byte DataType;
|
||||
/// <summary>
|
||||
/// Byte 2, bit 4
|
||||
/// If set, disc is erasable
|
||||
/// </summary>
|
||||
public bool Erasable;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 3 to 2
|
||||
/// Status of last session
|
||||
/// </summary>
|
||||
public byte LastSessionStatus;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 1 to 0
|
||||
/// Status of disc
|
||||
/// </summary>
|
||||
public byte DiscStatus;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Number of logical track that contains LBA 0
|
||||
/// </summary>
|
||||
public byte FirstTrackNumber;
|
||||
/// <summary>
|
||||
/// Byte 9 (MSB) and byte 4 (LSB)
|
||||
/// Number of sessions
|
||||
/// </summary>
|
||||
public ushort Sessions;
|
||||
/// <summary>
|
||||
/// Byte 10 (MSB) and byte 5 (LSB)
|
||||
/// Number of first track in last session
|
||||
/// </summary>
|
||||
public ushort FirstTrackLastSession;
|
||||
/// <summary>
|
||||
/// Byte 11 (MSB) and byte 6 (LSB)
|
||||
/// Number of last track in last session
|
||||
/// </summary>
|
||||
public ushort LastTrackLastSession;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 7
|
||||
/// If set, DiscIdentification is valid
|
||||
/// </summary>
|
||||
public bool DID_V;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 6
|
||||
/// If set, DiscBarcode is valid
|
||||
/// </summary>
|
||||
public bool DBC_V;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 5
|
||||
/// If set, disc is unrestricted
|
||||
/// </summary>
|
||||
public bool URU;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 4
|
||||
/// If set DiscApplicationCode is valid
|
||||
/// </summary>
|
||||
public bool DAC_V;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public bool Reserved;
|
||||
/// <summary>
|
||||
/// Byte 7, bit 2
|
||||
/// Copy of dirty bit from MRW status
|
||||
/// </summary>
|
||||
public bool Dbit;
|
||||
/// <summary>
|
||||
/// Byte 7, bits 1 to 0
|
||||
/// Background format status
|
||||
/// </summary>
|
||||
public byte BGFormatStatus;
|
||||
/// <summary>
|
||||
/// Byte 8
|
||||
/// Disc type code
|
||||
/// </summary>
|
||||
public byte DiscType;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 15
|
||||
/// Disc identification number from PMA
|
||||
/// </summary>
|
||||
public uint DiscIdentification;
|
||||
/// <summary>
|
||||
/// Bytes 16 to 19
|
||||
/// Last Session Lead-in Start Address (MSF for CD, LBA for others)
|
||||
/// </summary>
|
||||
public uint LastSessionLeadInStartLBA;
|
||||
/// <summary>
|
||||
/// Bytes 20 to 23
|
||||
/// Last Possible Lead-out Start Address (MSF for CD, LBA for others)
|
||||
/// </summary>
|
||||
public uint LastPossibleLeadOutStartLBA;
|
||||
/// <summary>
|
||||
/// Bytes 24 to 31
|
||||
/// Disc barcode
|
||||
/// </summary>
|
||||
public ulong DiscBarcode;
|
||||
/// <summary>
|
||||
/// Byte 32
|
||||
/// Disc application code
|
||||
/// </summary>
|
||||
public byte DiscApplicationCode;
|
||||
/// <summary>
|
||||
/// Byte 33
|
||||
/// How many OPC tables are
|
||||
/// </summary>
|
||||
public byte OPCTablesNumber;
|
||||
/// <summary>
|
||||
/// Bytes 34 to end
|
||||
/// OPC tables (8 bytes each)
|
||||
/// </summary>
|
||||
public OPCTable[] OPCTables;
|
||||
}
|
||||
|
||||
public struct OPCTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// kilobytes/sec this OPC table applies to
|
||||
/// </summary>
|
||||
public ushort Speed;
|
||||
/// <summary>
|
||||
/// Bytes 2 to 7
|
||||
/// OPC values
|
||||
/// </summary>
|
||||
public byte[] OPCValues;
|
||||
}
|
||||
|
||||
public struct TrackResourcesInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// 10
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 7 to 5
|
||||
/// 001b
|
||||
/// </summary>
|
||||
public byte DataType;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 4 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 5
|
||||
/// Maximum possible number of the tracks on the disc
|
||||
/// </summary>
|
||||
public ushort MaxTracks;
|
||||
/// <summary>
|
||||
/// Bytes 6 to 7
|
||||
/// Number of the assigned tracks on the disc
|
||||
/// </summary>
|
||||
public ushort AssignedTracks;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 9
|
||||
/// Maximum possible number of appendable tracks on the disc
|
||||
/// </summary>
|
||||
public ushort MaxAppendableTracks;
|
||||
/// <summary>
|
||||
/// Bytes 10 to 11
|
||||
/// Current number of appendable tracks on the disc
|
||||
/// </summary>
|
||||
public ushort AppendableTracks;
|
||||
}
|
||||
|
||||
public struct POWResourcesInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// 14
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 7 to 5
|
||||
/// 010b
|
||||
/// </summary>
|
||||
public byte DataType;
|
||||
/// <summary>
|
||||
/// Byte 2, bits 4 to 0
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Bytes 4 to 7
|
||||
/// Remaining POW replacements
|
||||
/// </summary>
|
||||
public uint RemainingPOWReplacements;
|
||||
/// <summary>
|
||||
/// Bytes 8 to 11
|
||||
/// Remaining POW reallocation map entries
|
||||
/// </summary>
|
||||
public uint RemainingPOWReallocation;
|
||||
/// <summary>
|
||||
/// Bytes 12 to 15
|
||||
/// Number of remaining POW updates
|
||||
/// </summary>
|
||||
public uint RemainingPOWUpdates;
|
||||
}
|
||||
|
||||
public static StandardDiscInformation? Decode000b(byte[] response)
|
||||
{
|
||||
if(response.Length < 34) return null;
|
||||
if(response.Length < 34)
|
||||
return null;
|
||||
|
||||
if((response[2] & 0xE0) != 0) return null;
|
||||
if((response[2] & 0xE0) != 0)
|
||||
return null;
|
||||
|
||||
StandardDiscInformation decoded =
|
||||
new StandardDiscInformation {DataLength = (ushort)((response[0] << 8) + response[1])};
|
||||
var decoded = new StandardDiscInformation
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1])
|
||||
};
|
||||
|
||||
if(decoded.DataLength + 2 != response.Length) return null;
|
||||
if(decoded.DataLength + 2 != response.Length)
|
||||
return null;
|
||||
|
||||
decoded.DataType = (byte)((response[2] & 0xE0) >> 5);
|
||||
decoded.Erasable |= (response[2] & 0x10) == 0x10;
|
||||
@@ -308,8 +80,10 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
decoded.DiscIdentification =
|
||||
(uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]);
|
||||
|
||||
decoded.LastSessionLeadInStartLBA =
|
||||
(uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]);
|
||||
|
||||
decoded.LastPossibleLeadOutStartLBA =
|
||||
(uint)((response[20] << 24) + (response[21] << 16) + (response[22] << 8) + response[23]);
|
||||
|
||||
@@ -321,9 +95,12 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
decoded.DiscApplicationCode = response[32];
|
||||
decoded.OPCTablesNumber = response[33];
|
||||
|
||||
if(decoded.OPCTablesNumber <= 0 || response.Length != decoded.OPCTablesNumber * 8 + 34) return decoded;
|
||||
if(decoded.OPCTablesNumber <= 0 ||
|
||||
response.Length != decoded.OPCTablesNumber * 8 + 34)
|
||||
return decoded;
|
||||
|
||||
decoded.OPCTables = new OPCTable[decoded.OPCTablesNumber];
|
||||
|
||||
for(int i = 0; i < decoded.OPCTablesNumber; i++)
|
||||
{
|
||||
decoded.OPCTables[i].Speed = (ushort)((response[34 + i * 8 + 0] << 16) + response[34 + i * 8 + 1]);
|
||||
@@ -336,30 +113,37 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string Prettify000b(StandardDiscInformation? information)
|
||||
{
|
||||
if(!information.HasValue) return null;
|
||||
if(!information.HasValue)
|
||||
return null;
|
||||
|
||||
StandardDiscInformation decoded = information.Value;
|
||||
|
||||
if(decoded.DataType != 0) return null;
|
||||
if(decoded.DataType != 0)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
switch(decoded.DiscType)
|
||||
{
|
||||
case 0x00:
|
||||
sb.AppendLine("Disc type declared as CD-DA or CD-ROM");
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine("Disc type declared as CD-i");
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine("Disc type declared as CD-ROM XA");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("Disc type is undefined");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("Unknown disc type {0:X2}h", decoded.DiscType).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -367,30 +151,38 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Disc is empty");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Disc is incomplete");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("Disc is finalized");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(decoded.Erasable) sb.AppendLine("Disc is erasable");
|
||||
if(decoded.Erasable)
|
||||
sb.AppendLine("Disc is erasable");
|
||||
|
||||
switch(decoded.LastSessionStatus)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("Last session is empty");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("Last session is incomplete");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("Last session is damaged");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("Last session is complete");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -398,26 +190,31 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("Media was being formatted in the background but it is stopped and incomplete");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("Media is currently being formatted in the background");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("Media background formatting has completed");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(decoded.Dbit) sb.AppendLine("MRW is dirty");
|
||||
if(decoded.Dbit)
|
||||
sb.AppendLine("MRW is dirty");
|
||||
|
||||
sb.AppendFormat("First track on disc is track {0}", decoded.FirstTrackNumber).AppendLine();
|
||||
sb.AppendFormat("Disc has {0} sessions", decoded.Sessions).AppendLine();
|
||||
sb.AppendFormat("First track in last session is track {0}", decoded.FirstTrackLastSession).AppendLine();
|
||||
sb.AppendFormat("Last track in last session is track {0}", decoded.LastTrackLastSession).AppendLine();
|
||||
|
||||
sb.AppendFormat("Last session Lead-In address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}",
|
||||
decoded.LastSessionLeadInStartLBA, (decoded.LastSessionLeadInStartLBA & 0xFF0000) >> 16,
|
||||
(decoded.LastSessionLeadInStartLBA & 0xFF00) >> 8,
|
||||
decoded.LastSessionLeadInStartLBA & 0xFF)
|
||||
.AppendLine();
|
||||
decoded.LastSessionLeadInStartLBA & 0xFF).AppendLine();
|
||||
|
||||
sb.AppendFormat("Last possible Lead-Out address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}",
|
||||
decoded.LastPossibleLeadOutStartLBA, (decoded.LastPossibleLeadOutStartLBA & 0xFF0000) >> 16,
|
||||
(decoded.LastPossibleLeadOutStartLBA & 0xFF00) >> 8,
|
||||
@@ -425,11 +222,17 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
sb.AppendLine(decoded.URU ? "Disc is defined for unrestricted use" : "Disc is defined for restricted use");
|
||||
|
||||
if(decoded.DID_V) sb.AppendFormat("Disc ID: {0:X6}", decoded.DiscIdentification & 0x00FFFFFF).AppendLine();
|
||||
if(decoded.DBC_V) sb.AppendFormat("Disc barcode: {0:X16}", decoded.DiscBarcode).AppendLine();
|
||||
if(decoded.DAC_V) sb.AppendFormat("Disc application code: {0}", decoded.DiscApplicationCode).AppendLine();
|
||||
if(decoded.DID_V)
|
||||
sb.AppendFormat("Disc ID: {0:X6}", decoded.DiscIdentification & 0x00FFFFFF).AppendLine();
|
||||
|
||||
if(decoded.OPCTables == null) return sb.ToString();
|
||||
if(decoded.DBC_V)
|
||||
sb.AppendFormat("Disc barcode: {0:X16}", decoded.DiscBarcode).AppendLine();
|
||||
|
||||
if(decoded.DAC_V)
|
||||
sb.AppendFormat("Disc application code: {0}", decoded.DiscApplicationCode).AppendLine();
|
||||
|
||||
if(decoded.OPCTables == null)
|
||||
return sb.ToString();
|
||||
|
||||
foreach(OPCTable table in decoded.OPCTables)
|
||||
sb.AppendFormat("OPC values for {0}Kbit/sec.: {1}, {2}, {3}, {4}, {5}, {6}", table.Speed,
|
||||
@@ -441,14 +244,19 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static TrackResourcesInformation? Decode001b(byte[] response)
|
||||
{
|
||||
if(response.Length != 12) return null;
|
||||
if(response.Length != 12)
|
||||
return null;
|
||||
|
||||
if((response[2] & 0xE0) != 0x20) return null;
|
||||
if((response[2] & 0xE0) != 0x20)
|
||||
return null;
|
||||
|
||||
TrackResourcesInformation decoded =
|
||||
new TrackResourcesInformation {DataLength = (ushort)((response[0] << 8) + response[1])};
|
||||
var decoded = new TrackResourcesInformation
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1])
|
||||
};
|
||||
|
||||
if(decoded.DataLength + 2 != response.Length) return null;
|
||||
if(decoded.DataLength + 2 != response.Length)
|
||||
return null;
|
||||
|
||||
decoded.DataType = (byte)((response[2] & 0xE0) >> 5);
|
||||
decoded.MaxTracks = (ushort)((response[4] << 8) + response[5]);
|
||||
@@ -461,18 +269,22 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string Prettify001b(TrackResourcesInformation? information)
|
||||
{
|
||||
if(!information.HasValue) return null;
|
||||
if(!information.HasValue)
|
||||
return null;
|
||||
|
||||
TrackResourcesInformation decoded = information.Value;
|
||||
|
||||
if(decoded.DataType != 1) return null;
|
||||
if(decoded.DataType != 1)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("{0} maximum possible tracks on the disc", decoded.MaxTracks).AppendLine();
|
||||
sb.AppendFormat("{0} assigned tracks on the disc", decoded.AssignedTracks).AppendLine();
|
||||
sb.AppendFormat("{0} maximum possible appendable tracks on the disc", decoded.AppendableTracks)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} maximum possible appendable tracks on the disc", decoded.AppendableTracks).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} current appendable tracks on the disc", decoded.MaxAppendableTracks).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
@@ -480,20 +292,28 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static POWResourcesInformation? Decode010b(byte[] response)
|
||||
{
|
||||
if(response.Length != 16) return null;
|
||||
if(response.Length != 16)
|
||||
return null;
|
||||
|
||||
if((response[2] & 0xE0) != 0x40) return null;
|
||||
if((response[2] & 0xE0) != 0x40)
|
||||
return null;
|
||||
|
||||
POWResourcesInformation decoded =
|
||||
new POWResourcesInformation {DataLength = (ushort)((response[0] << 8) + response[1])};
|
||||
var decoded = new POWResourcesInformation
|
||||
{
|
||||
DataLength = (ushort)((response[0] << 8) + response[1])
|
||||
};
|
||||
|
||||
if(decoded.DataLength + 2 != response.Length) return null;
|
||||
if(decoded.DataLength + 2 != response.Length)
|
||||
return null;
|
||||
|
||||
decoded.DataType = (byte)((response[2] & 0xE0) >> 5);
|
||||
|
||||
decoded.RemainingPOWReplacements =
|
||||
(ushort)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]);
|
||||
|
||||
decoded.RemainingPOWReallocation =
|
||||
(ushort)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]);
|
||||
|
||||
decoded.RemainingPOWUpdates =
|
||||
(ushort)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]);
|
||||
|
||||
@@ -502,17 +322,21 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string Prettify010b(POWResourcesInformation? information)
|
||||
{
|
||||
if(!information.HasValue) return null;
|
||||
if(!information.HasValue)
|
||||
return null;
|
||||
|
||||
POWResourcesInformation decoded = information.Value;
|
||||
|
||||
if(decoded.DataType != 1) return null;
|
||||
if(decoded.DataType != 1)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("{0} remaining POW replacements", decoded.RemainingPOWReplacements).AppendLine();
|
||||
sb.AppendFormat("{0} remaining POW reallocation map entries", decoded.RemainingPOWReallocation)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} remaining POW reallocation map entries", decoded.RemainingPOWReallocation).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("{0} remaining POW updates", decoded.RemainingPOWUpdates).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
@@ -520,9 +344,11 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string Prettify(byte[] response)
|
||||
{
|
||||
if(response == null) return null;
|
||||
if(response == null)
|
||||
return null;
|
||||
|
||||
if(response.Length < 12) return null;
|
||||
if(response.Length < 12)
|
||||
return null;
|
||||
|
||||
switch(response[2] & 0xE0)
|
||||
{
|
||||
@@ -533,5 +359,103 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public struct StandardDiscInformation
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 32 + OPCTablesNumber*8</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2, bits 7 to 5 000b</summary>
|
||||
public byte DataType;
|
||||
/// <summary>Byte 2, bit 4 If set, disc is erasable</summary>
|
||||
public bool Erasable;
|
||||
/// <summary>Byte 2, bits 3 to 2 Status of last session</summary>
|
||||
public byte LastSessionStatus;
|
||||
/// <summary>Byte 2, bits 1 to 0 Status of disc</summary>
|
||||
public byte DiscStatus;
|
||||
/// <summary>Byte 3 Number of logical track that contains LBA 0</summary>
|
||||
public byte FirstTrackNumber;
|
||||
/// <summary>Byte 9 (MSB) and byte 4 (LSB) Number of sessions</summary>
|
||||
public ushort Sessions;
|
||||
/// <summary>Byte 10 (MSB) and byte 5 (LSB) Number of first track in last session</summary>
|
||||
public ushort FirstTrackLastSession;
|
||||
/// <summary>Byte 11 (MSB) and byte 6 (LSB) Number of last track in last session</summary>
|
||||
public ushort LastTrackLastSession;
|
||||
/// <summary>Byte 7, bit 7 If set, DiscIdentification is valid</summary>
|
||||
public bool DID_V;
|
||||
/// <summary>Byte 7, bit 6 If set, DiscBarcode is valid</summary>
|
||||
public bool DBC_V;
|
||||
/// <summary>Byte 7, bit 5 If set, disc is unrestricted</summary>
|
||||
public bool URU;
|
||||
/// <summary>Byte 7, bit 4 If set DiscApplicationCode is valid</summary>
|
||||
public bool DAC_V;
|
||||
/// <summary>Byte 7, bit 3 Reserved</summary>
|
||||
public bool Reserved;
|
||||
/// <summary>Byte 7, bit 2 Copy of dirty bit from MRW status</summary>
|
||||
public bool Dbit;
|
||||
/// <summary>Byte 7, bits 1 to 0 Background format status</summary>
|
||||
public byte BGFormatStatus;
|
||||
/// <summary>Byte 8 Disc type code</summary>
|
||||
public byte DiscType;
|
||||
/// <summary>Bytes 12 to 15 Disc identification number from PMA</summary>
|
||||
public uint DiscIdentification;
|
||||
/// <summary>Bytes 16 to 19 Last Session Lead-in Start Address (MSF for CD, LBA for others)</summary>
|
||||
public uint LastSessionLeadInStartLBA;
|
||||
/// <summary>Bytes 20 to 23 Last Possible Lead-out Start Address (MSF for CD, LBA for others)</summary>
|
||||
public uint LastPossibleLeadOutStartLBA;
|
||||
/// <summary>Bytes 24 to 31 Disc barcode</summary>
|
||||
public ulong DiscBarcode;
|
||||
/// <summary>Byte 32 Disc application code</summary>
|
||||
public byte DiscApplicationCode;
|
||||
/// <summary>Byte 33 How many OPC tables are</summary>
|
||||
public byte OPCTablesNumber;
|
||||
/// <summary>Bytes 34 to end OPC tables (8 bytes each)</summary>
|
||||
public OPCTable[] OPCTables;
|
||||
}
|
||||
|
||||
public struct OPCTable
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 kilobytes/sec this OPC table applies to</summary>
|
||||
public ushort Speed;
|
||||
/// <summary>Bytes 2 to 7 OPC values</summary>
|
||||
public byte[] OPCValues;
|
||||
}
|
||||
|
||||
public struct TrackResourcesInformation
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 10</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2, bits 7 to 5 001b</summary>
|
||||
public byte DataType;
|
||||
/// <summary>Byte 2, bits 4 to 0 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 5 Maximum possible number of the tracks on the disc</summary>
|
||||
public ushort MaxTracks;
|
||||
/// <summary>Bytes 6 to 7 Number of the assigned tracks on the disc</summary>
|
||||
public ushort AssignedTracks;
|
||||
/// <summary>Bytes 8 to 9 Maximum possible number of appendable tracks on the disc</summary>
|
||||
public ushort MaxAppendableTracks;
|
||||
/// <summary>Bytes 10 to 11 Current number of appendable tracks on the disc</summary>
|
||||
public ushort AppendableTracks;
|
||||
}
|
||||
|
||||
public struct POWResourcesInformation
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 14</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2, bits 7 to 5 010b</summary>
|
||||
public byte DataType;
|
||||
/// <summary>Byte 2, bits 4 to 0 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Bytes 4 to 7 Remaining POW replacements</summary>
|
||||
public uint RemainingPOWReplacements;
|
||||
/// <summary>Bytes 8 to 11 Remaining POW reallocation map entries</summary>
|
||||
public uint RemainingPOWReallocation;
|
||||
/// <summary>Bytes 12 to 15 Number of remaining POW updates</summary>
|
||||
public uint RemainingPOWUpdates;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,56 +34,38 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum FormatLayerTypeCodes : ushort
|
||||
{
|
||||
CDLayer = 0x0008,
|
||||
DVDLayer = 0x0010,
|
||||
BDLayer = 0x0040,
|
||||
CDLayer = 0x0008, DVDLayer = 0x0010, BDLayer = 0x0040,
|
||||
HDDVDLayer = 0x0050
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum SessionStatusCodes : byte
|
||||
{
|
||||
Empty = 0x00,
|
||||
Incomplete = 0x01,
|
||||
ReservedOrDamaged = 0x02,
|
||||
Complete = 0x03
|
||||
Empty = 0x00, Incomplete = 0x01, ReservedOrDamaged = 0x02,
|
||||
Complete = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum DiscStatusCodes : byte
|
||||
{
|
||||
Empty = 0x00,
|
||||
Incomplete = 0x01,
|
||||
Finalized = 0x02,
|
||||
Others = 0x03
|
||||
Empty = 0x00, Incomplete = 0x01, Finalized = 0x02,
|
||||
Others = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum BGFormatStatusCodes : byte
|
||||
{
|
||||
NoFormattable = 0x00,
|
||||
IncompleteBackgroundFormat = 0x01,
|
||||
BackgroundFormatInProgress = 0x02,
|
||||
FormatComplete = 0x03
|
||||
NoFormattable = 0x00, IncompleteBackgroundFormat = 0x01, BackgroundFormatInProgress = 0x02,
|
||||
FormatComplete = 0x03
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
public enum DiscTypeCodes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Also valid for CD-DA, DVD and BD
|
||||
/// </summary>
|
||||
CDROM = 0x00,
|
||||
CDi = 0x10,
|
||||
CDROMXA = 0x20,
|
||||
Undefined = 0xFF
|
||||
/// <summary>Also valid for CD-DA, DVD and BD</summary>
|
||||
CDROM = 0x00, CDi = 0x10, CDROMXA = 0x20, Undefined = 0xFF
|
||||
}
|
||||
}
|
||||
4451
SCSI/MMC/Features.cs
4451
SCSI/MMC/Features.cs
File diff suppressed because it is too large
Load Diff
@@ -36,90 +36,29 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class Hybrid
|
||||
{
|
||||
public struct RecognizedFormatLayers
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data Length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4
|
||||
/// Number of format layers in hybrid disc identified by drive
|
||||
/// </summary>
|
||||
public byte NumberOfLayers;
|
||||
/// <summary>
|
||||
/// Byte 5, bits 7 to 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 5, bits 5 to 4
|
||||
/// Layer no. used when disc is inserted
|
||||
/// </summary>
|
||||
public byte DefaultFormatLayer;
|
||||
/// <summary>
|
||||
/// Byte 5, bits 3 to 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 5, bits 1 to 0
|
||||
/// Layer no. currently in use
|
||||
/// </summary>
|
||||
public byte OnlineFormatLayer;
|
||||
/// <summary>
|
||||
/// Bytes 6 to end
|
||||
/// Recognized format layers
|
||||
/// </summary>
|
||||
public ushort[] FormatLayers;
|
||||
}
|
||||
|
||||
public static RecognizedFormatLayers? DecodeFormatLayers(byte[] FormatLayersResponse)
|
||||
{
|
||||
if(FormatLayersResponse == null) return null;
|
||||
if(FormatLayersResponse == null)
|
||||
return null;
|
||||
|
||||
if(FormatLayersResponse.Length < 8) return null;
|
||||
if(FormatLayersResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
RecognizedFormatLayers decoded = new RecognizedFormatLayers
|
||||
var decoded = new RecognizedFormatLayers
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(FormatLayersResponse, 0),
|
||||
Reserved1 = FormatLayersResponse[2],
|
||||
Reserved2 = FormatLayersResponse[3],
|
||||
NumberOfLayers = FormatLayersResponse[4],
|
||||
Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6),
|
||||
DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4),
|
||||
Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2),
|
||||
Reserved1 = FormatLayersResponse[2], Reserved2 = FormatLayersResponse[3],
|
||||
NumberOfLayers = FormatLayersResponse[4], Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6),
|
||||
DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4),
|
||||
Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2),
|
||||
OnlineFormatLayer = (byte)(FormatLayersResponse[5] & 0x03),
|
||||
FormatLayers = new ushort[(FormatLayersResponse.Length - 6) / 2]
|
||||
};
|
||||
@@ -132,55 +71,81 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyFormatLayers(RecognizedFormatLayers? FormatLayersResponse)
|
||||
{
|
||||
if(FormatLayersResponse == null) return null;
|
||||
if(FormatLayersResponse == null)
|
||||
return null;
|
||||
|
||||
RecognizedFormatLayers response = FormatLayersResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("{0} format layers recognized", response.NumberOfLayers);
|
||||
|
||||
for(int i = 0; i < response.FormatLayers.Length; i++)
|
||||
switch(response.FormatLayers[i])
|
||||
{
|
||||
case (ushort)FormatLayerTypeCodes.BDLayer:
|
||||
case(ushort)FormatLayerTypeCodes.BDLayer:
|
||||
{
|
||||
sb.AppendFormat("Layer {0} is of type Blu-ray", i).AppendLine();
|
||||
if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer.");
|
||||
if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
if(response.DefaultFormatLayer == i)
|
||||
sb.AppendLine("This is the default layer.");
|
||||
|
||||
if(response.OnlineFormatLayer == i)
|
||||
sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (ushort)FormatLayerTypeCodes.CDLayer:
|
||||
case(ushort)FormatLayerTypeCodes.CDLayer:
|
||||
{
|
||||
sb.AppendFormat("Layer {0} is of type CD", i).AppendLine();
|
||||
if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer.");
|
||||
if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
if(response.DefaultFormatLayer == i)
|
||||
sb.AppendLine("This is the default layer.");
|
||||
|
||||
if(response.OnlineFormatLayer == i)
|
||||
sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (ushort)FormatLayerTypeCodes.DVDLayer:
|
||||
case(ushort)FormatLayerTypeCodes.DVDLayer:
|
||||
{
|
||||
sb.AppendFormat("Layer {0} is of type DVD", i).AppendLine();
|
||||
if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer.");
|
||||
if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
if(response.DefaultFormatLayer == i)
|
||||
sb.AppendLine("This is the default layer.");
|
||||
|
||||
if(response.OnlineFormatLayer == i)
|
||||
sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (ushort)FormatLayerTypeCodes.HDDVDLayer:
|
||||
case(ushort)FormatLayerTypeCodes.HDDVDLayer:
|
||||
{
|
||||
sb.AppendFormat("Layer {0} is of type HD DVD", i).AppendLine();
|
||||
if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer.");
|
||||
if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
if(response.DefaultFormatLayer == i)
|
||||
sb.AppendLine("This is the default layer.");
|
||||
|
||||
if(response.OnlineFormatLayer == i)
|
||||
sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i])
|
||||
.AppendLine();
|
||||
if(response.DefaultFormatLayer == i) sb.AppendLine("This is the default layer.");
|
||||
if(response.OnlineFormatLayer == i) sb.AppendLine("This is the layer actually in use.");
|
||||
sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i]).
|
||||
AppendLine();
|
||||
|
||||
if(response.DefaultFormatLayer == i)
|
||||
sb.AppendLine("This is the default layer.");
|
||||
|
||||
if(response.OnlineFormatLayer == i)
|
||||
sb.AppendLine("This is the layer actually in use.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -191,7 +156,30 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyFormatLayers(byte[] FormatLayersResponse)
|
||||
{
|
||||
RecognizedFormatLayers? decoded = DecodeFormatLayers(FormatLayersResponse);
|
||||
|
||||
return PrettifyFormatLayers(decoded);
|
||||
}
|
||||
|
||||
public struct RecognizedFormatLayers
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data Length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4 Number of format layers in hybrid disc identified by drive</summary>
|
||||
public byte NumberOfLayers;
|
||||
/// <summary>Byte 5, bits 7 to 6 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 5, bits 5 to 4 Layer no. used when disc is inserted</summary>
|
||||
public byte DefaultFormatLayer;
|
||||
/// <summary>Byte 5, bits 3 to 2 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>Byte 5, bits 1 to 0 Layer no. currently in use</summary>
|
||||
public byte OnlineFormatLayer;
|
||||
/// <summary>Bytes 6 to end Recognized format layers</summary>
|
||||
public ushort[] FormatLayers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,101 +37,29 @@ using System.Text;
|
||||
namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Information from the following standards:
|
||||
/// ANSI X3.304-1997
|
||||
/// T10/1048-D revision 9.0
|
||||
/// T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c
|
||||
/// T10/1228-D revision 11a
|
||||
/// T10/1363-D revision 10g
|
||||
/// T10/1545-D revision 1d
|
||||
/// T10/1545-D revision 5
|
||||
/// T10/1545-D revision 5a
|
||||
/// T10/1675-D revision 2c
|
||||
/// T10/1675-D revision 4
|
||||
/// T10/1836-D revision 2g
|
||||
/// Information from the following standards: ANSI X3.304-1997 T10/1048-D revision 9.0 T10/1048-D revision 10a
|
||||
/// T10/1228-D revision 7.0c T10/1228-D revision 11a T10/1363-D revision 10g T10/1545-D revision 1d T10/1545-D revision
|
||||
/// 5 T10/1545-D revision 5a T10/1675-D revision 2c T10/1675-D revision 4 T10/1836-D revision 2g
|
||||
/// </summary>
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static class WriteProtect
|
||||
{
|
||||
public struct WriteProtectionStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Bytes 0 to 1
|
||||
/// Data Length
|
||||
/// </summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>
|
||||
/// Byte 2
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Byte 3
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Byte 4, bits 7 to 4
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 3
|
||||
/// Writing inhibited by media specific reason
|
||||
/// </summary>
|
||||
public bool MSWI;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 2
|
||||
/// Cartridge sets write protection
|
||||
/// </summary>
|
||||
public bool CWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 1
|
||||
/// Media surface sets write protection
|
||||
/// </summary>
|
||||
public bool PWP;
|
||||
/// <summary>
|
||||
/// Byte 4, bit 0
|
||||
/// Software write protection until power down
|
||||
/// </summary>
|
||||
public bool SWPP;
|
||||
/// <summary>
|
||||
/// Byte 5
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>
|
||||
/// Byte 6
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>
|
||||
/// Byte 7
|
||||
/// Reserved
|
||||
/// </summary>
|
||||
public byte Reserved6;
|
||||
}
|
||||
|
||||
public static WriteProtectionStatus? DecodeWriteProtectionStatus(byte[] WPSResponse)
|
||||
{
|
||||
if(WPSResponse == null) return null;
|
||||
if(WPSResponse == null)
|
||||
return null;
|
||||
|
||||
WriteProtectionStatus decoded = new WriteProtectionStatus
|
||||
var decoded = new WriteProtectionStatus
|
||||
{
|
||||
DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0),
|
||||
Reserved1 = WPSResponse[2],
|
||||
DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0), Reserved1 = WPSResponse[2],
|
||||
Reserved2 = WPSResponse[3],
|
||||
Reserved3 = (byte)((WPSResponse[4] & 0xF0) >> 4),
|
||||
MSWI = Convert.ToBoolean(WPSResponse[4] & 0x08),
|
||||
CWP = Convert.ToBoolean(WPSResponse[4] & 0x04),
|
||||
PWP = Convert.ToBoolean(WPSResponse[4] & 0x02),
|
||||
SWPP = Convert.ToBoolean(WPSResponse[4] & 0x01),
|
||||
Reserved4 = WPSResponse[5],
|
||||
Reserved5 = WPSResponse[6],
|
||||
Reserved4 = WPSResponse[5], Reserved5 = WPSResponse[6],
|
||||
Reserved6 = WPSResponse[7]
|
||||
};
|
||||
|
||||
@@ -140,25 +68,44 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
|
||||
public static string PrettifyWriteProtectionStatus(WriteProtectionStatus? WPSResponse)
|
||||
{
|
||||
if(WPSResponse == null) return null;
|
||||
if(WPSResponse == null)
|
||||
return null;
|
||||
|
||||
WriteProtectionStatus response = WPSResponse.Value;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if(response.MSWI) sb.AppendLine("Writing inhibited by media specific reason");
|
||||
if(response.CWP) sb.AppendLine("Cartridge sets write protection");
|
||||
if(response.PWP) sb.AppendLine("Media surface sets write protection");
|
||||
if(response.SWPP) sb.AppendLine("Software write protection is set until power down");
|
||||
if(response.MSWI)
|
||||
sb.AppendLine("Writing inhibited by media specific reason");
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine();
|
||||
if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine();
|
||||
if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine();
|
||||
if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine();
|
||||
#endif
|
||||
if(response.CWP)
|
||||
sb.AppendLine("Cartridge sets write protection");
|
||||
|
||||
if(response.PWP)
|
||||
sb.AppendLine("Media surface sets write protection");
|
||||
|
||||
if(response.SWPP)
|
||||
sb.AppendLine("Software write protection is set until power down");
|
||||
|
||||
#if DEBUG
|
||||
if(response.Reserved1 != 0)
|
||||
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
|
||||
|
||||
if(response.Reserved2 != 0)
|
||||
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
|
||||
|
||||
if(response.Reserved3 != 0)
|
||||
sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine();
|
||||
|
||||
if(response.Reserved4 != 0)
|
||||
sb.AppendFormat("Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine();
|
||||
|
||||
if(response.Reserved5 != 0)
|
||||
sb.AppendFormat("Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine();
|
||||
|
||||
if(response.Reserved6 != 0)
|
||||
sb.AppendFormat("Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine();
|
||||
#endif
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -166,7 +113,34 @@ namespace DiscImageChef.Decoders.SCSI.MMC
|
||||
public static string PrettifyWriteProtectionStatus(byte[] WPSResponse)
|
||||
{
|
||||
WriteProtectionStatus? decoded = DecodeWriteProtectionStatus(WPSResponse);
|
||||
|
||||
return PrettifyWriteProtectionStatus(decoded);
|
||||
}
|
||||
|
||||
public struct WriteProtectionStatus
|
||||
{
|
||||
/// <summary>Bytes 0 to 1 Data Length</summary>
|
||||
public ushort DataLength;
|
||||
/// <summary>Byte 2 Reserved</summary>
|
||||
public byte Reserved1;
|
||||
/// <summary>Byte 3 Reserved</summary>
|
||||
public byte Reserved2;
|
||||
/// <summary>Byte 4, bits 7 to 4 Reserved</summary>
|
||||
public byte Reserved3;
|
||||
/// <summary>Byte 4, bit 3 Writing inhibited by media specific reason</summary>
|
||||
public bool MSWI;
|
||||
/// <summary>Byte 4, bit 2 Cartridge sets write protection</summary>
|
||||
public bool CWP;
|
||||
/// <summary>Byte 4, bit 1 Media surface sets write protection</summary>
|
||||
public bool PWP;
|
||||
/// <summary>Byte 4, bit 0 Software write protection until power down</summary>
|
||||
public bool SWPP;
|
||||
/// <summary>Byte 5 Reserved</summary>
|
||||
public byte Reserved4;
|
||||
/// <summary>Byte 6 Reserved</summary>
|
||||
public byte Reserved5;
|
||||
/// <summary>Byte 7 Reserved</summary>
|
||||
public byte Reserved6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,52 +35,41 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x00: Drive Operation Mode page
|
||||
/// <summary>
|
||||
/// Drive Operation Mode page
|
||||
/// Page code 0x00
|
||||
/// 4 bytes in INF-8070
|
||||
/// </summary>
|
||||
/// <summary>Drive Operation Mode page Page code 0x00 4 bytes in INF-8070</summary>
|
||||
public struct ModePage_00_SFF
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Select LUN Mode
|
||||
/// </summary>
|
||||
/// <summary>Select LUN Mode</summary>
|
||||
public bool SLM;
|
||||
/// <summary>
|
||||
/// Select LUN for rewritable
|
||||
/// </summary>
|
||||
/// <summary>Select LUN for rewritable</summary>
|
||||
public bool SLR;
|
||||
/// <summary>
|
||||
/// Disable verify for WRITE
|
||||
/// </summary>
|
||||
/// <summary>Disable verify for WRITE</summary>
|
||||
public bool DVW;
|
||||
/// <summary>
|
||||
/// Disable deferred error
|
||||
/// </summary>
|
||||
/// <summary>Disable deferred error</summary>
|
||||
public bool DDE;
|
||||
}
|
||||
|
||||
public static ModePage_00_SFF? DecodeModePage_00_SFF(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x00) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x00)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 4) return null;
|
||||
if(pageResponse.Length < 4)
|
||||
return null;
|
||||
|
||||
ModePage_00_SFF decoded = new ModePage_00_SFF();
|
||||
var decoded = new ModePage_00_SFF();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -98,19 +87,25 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_00_SFF(ModePage_00_SFF? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_00_SFF page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Drive Operation Mode page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.DVW) sb.AppendLine("\tVerifying after writing is disabled");
|
||||
if(page.DDE) sb.AppendLine("\tDrive will abort when a writing error is detected");
|
||||
if(page.DVW)
|
||||
sb.AppendLine("\tVerifying after writing is disabled");
|
||||
|
||||
if(!page.SLM) return sb.ToString();
|
||||
if(page.DDE)
|
||||
sb.AppendLine("\tDrive will abort when a writing error is detected");
|
||||
|
||||
if(!page.SLM)
|
||||
return sb.ToString();
|
||||
|
||||
sb.Append("\tDrive has two LUNs with rewritable being ");
|
||||
sb.AppendLine(page.SLR ? "LUN 1" : "LUN 0");
|
||||
|
||||
325
SCSI/Modes/01.cs
325
SCSI/Modes/01.cs
@@ -35,159 +35,10 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x01: Read-write error recovery page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x01
|
||||
/// 12 bytes in SCSI-2, SBC-1, SBC-2
|
||||
/// </summary>
|
||||
public struct ModePage_01
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Automatic Write Reallocation Enabled
|
||||
/// </summary>
|
||||
public bool AWRE;
|
||||
/// <summary>
|
||||
/// Automatic Read Reallocation Enabled
|
||||
/// </summary>
|
||||
public bool ARRE;
|
||||
/// <summary>
|
||||
/// Transfer block
|
||||
/// </summary>
|
||||
public bool TB;
|
||||
/// <summary>
|
||||
/// Read continuous
|
||||
/// </summary>
|
||||
public bool RC;
|
||||
/// <summary>
|
||||
/// Enable early recovery
|
||||
/// </summary>
|
||||
public bool EER;
|
||||
/// <summary>
|
||||
/// Post error reporting
|
||||
/// </summary>
|
||||
public bool PER;
|
||||
/// <summary>
|
||||
/// Disable transfer on error
|
||||
/// </summary>
|
||||
public bool DTE;
|
||||
/// <summary>
|
||||
/// Disable correction
|
||||
/// </summary>
|
||||
public bool DCR;
|
||||
/// <summary>
|
||||
/// How many times to retry a read operation
|
||||
/// </summary>
|
||||
public byte ReadRetryCount;
|
||||
/// <summary>
|
||||
/// How many bits of largest data burst error is maximum to apply error correction on it
|
||||
/// </summary>
|
||||
public byte CorrectionSpan;
|
||||
/// <summary>
|
||||
/// Offset to move the heads
|
||||
/// </summary>
|
||||
public sbyte HeadOffsetCount;
|
||||
/// <summary>
|
||||
/// Incremental position to which the recovered data strobe shall be adjusted
|
||||
/// </summary>
|
||||
public sbyte DataStrobeOffsetCount;
|
||||
/// <summary>
|
||||
/// How many times to retry a write operation
|
||||
/// </summary>
|
||||
public byte WriteRetryCount;
|
||||
/// <summary>
|
||||
/// Maximum time in ms to use in data error recovery procedures
|
||||
/// </summary>
|
||||
public ushort RecoveryTimeLimit;
|
||||
|
||||
/// <summary>
|
||||
/// Logical block provisioning error reporting is enabled
|
||||
/// </summary>
|
||||
public bool LBPERE;
|
||||
}
|
||||
|
||||
public static ModePage_01? DecodeModePage_01(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x01) return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
|
||||
ModePage_01 decoded = new ModePage_01();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80;
|
||||
decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40;
|
||||
decoded.TB |= (pageResponse[2] & 0x20) == 0x20;
|
||||
decoded.RC |= (pageResponse[2] & 0x10) == 0x10;
|
||||
decoded.EER |= (pageResponse[2] & 0x08) == 0x08;
|
||||
decoded.PER |= (pageResponse[2] & 0x04) == 0x04;
|
||||
decoded.DTE |= (pageResponse[2] & 0x02) == 0x02;
|
||||
decoded.DCR |= (pageResponse[2] & 0x01) == 0x01;
|
||||
|
||||
decoded.ReadRetryCount = pageResponse[3];
|
||||
decoded.CorrectionSpan = pageResponse[4];
|
||||
decoded.HeadOffsetCount = (sbyte)pageResponse[5];
|
||||
decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6];
|
||||
|
||||
if(pageResponse.Length < 12) return decoded;
|
||||
|
||||
decoded.WriteRetryCount = pageResponse[8];
|
||||
decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
|
||||
decoded.LBPERE |= (pageResponse[7] & 0x80) == 0x80;
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
public static string PrettifyModePage_01(byte[] pageResponse) =>
|
||||
PrettifyModePage_01(DecodeModePage_01(pageResponse));
|
||||
|
||||
public static string PrettifyModePage_01(ModePage_01? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
|
||||
ModePage_01 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Read-write error recovery page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.AWRE) sb.AppendLine("\tAutomatic write reallocation is enabled");
|
||||
if(page.ARRE) sb.AppendLine("\tAutomatic read reallocation is enabled");
|
||||
if(page.TB)
|
||||
sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION");
|
||||
if(page.RC)
|
||||
sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery");
|
||||
if(page.EER) sb.AppendLine("\tDrive will use the most expedient form of error recovery first");
|
||||
if(page.PER) sb.AppendLine("\tDrive shall report recovered errors");
|
||||
if(page.DTE) sb.AppendLine("\tTransfer will be terminated upon error detection");
|
||||
if(page.DCR) sb.AppendLine("\tError correction is disabled");
|
||||
if(page.ReadRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine();
|
||||
if(page.WriteRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine();
|
||||
if(page.RecoveryTimeLimit > 0)
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit)
|
||||
.AppendLine();
|
||||
if(page.LBPERE) sb.AppendLine("Logical block provisioning error reporting is enabled");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion Mode Page 0x01: Read-write error recovery page
|
||||
|
||||
public static byte[] EncodeModePage_01(ModePage_01 page)
|
||||
{
|
||||
byte[] pg = new byte[8];
|
||||
@@ -195,15 +46,32 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
pg[0] = 0x01;
|
||||
pg[1] = 6;
|
||||
|
||||
if(page.PS) pg[0] += 0x80;
|
||||
if(page.AWRE) pg[2] += 0x80;
|
||||
if(page.ARRE) pg[2] += 0x40;
|
||||
if(page.TB) pg[2] += 0x20;
|
||||
if(page.RC) pg[2] += 0x10;
|
||||
if(page.EER) pg[2] += 0x08;
|
||||
if(page.PER) pg[2] += 0x04;
|
||||
if(page.DTE) pg[2] += 0x02;
|
||||
if(page.DCR) pg[2] += 0x01;
|
||||
if(page.PS)
|
||||
pg[0] += 0x80;
|
||||
|
||||
if(page.AWRE)
|
||||
pg[2] += 0x80;
|
||||
|
||||
if(page.ARRE)
|
||||
pg[2] += 0x40;
|
||||
|
||||
if(page.TB)
|
||||
pg[2] += 0x20;
|
||||
|
||||
if(page.RC)
|
||||
pg[2] += 0x10;
|
||||
|
||||
if(page.EER)
|
||||
pg[2] += 0x08;
|
||||
|
||||
if(page.PER)
|
||||
pg[2] += 0x04;
|
||||
|
||||
if(page.DTE)
|
||||
pg[2] += 0x02;
|
||||
|
||||
if(page.DCR)
|
||||
pg[2] += 0x01;
|
||||
|
||||
pg[3] = page.ReadRetryCount;
|
||||
pg[4] = page.CorrectionSpan;
|
||||
@@ -220,5 +88,142 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
return pg;
|
||||
}
|
||||
|
||||
#region Mode Page 0x01: Read-write error recovery page
|
||||
/// <summary>Disconnect-reconnect page Page code 0x01 12 bytes in SCSI-2, SBC-1, SBC-2</summary>
|
||||
public struct ModePage_01
|
||||
{
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>Automatic Write Reallocation Enabled</summary>
|
||||
public bool AWRE;
|
||||
/// <summary>Automatic Read Reallocation Enabled</summary>
|
||||
public bool ARRE;
|
||||
/// <summary>Transfer block</summary>
|
||||
public bool TB;
|
||||
/// <summary>Read continuous</summary>
|
||||
public bool RC;
|
||||
/// <summary>Enable early recovery</summary>
|
||||
public bool EER;
|
||||
/// <summary>Post error reporting</summary>
|
||||
public bool PER;
|
||||
/// <summary>Disable transfer on error</summary>
|
||||
public bool DTE;
|
||||
/// <summary>Disable correction</summary>
|
||||
public bool DCR;
|
||||
/// <summary>How many times to retry a read operation</summary>
|
||||
public byte ReadRetryCount;
|
||||
/// <summary>How many bits of largest data burst error is maximum to apply error correction on it</summary>
|
||||
public byte CorrectionSpan;
|
||||
/// <summary>Offset to move the heads</summary>
|
||||
public sbyte HeadOffsetCount;
|
||||
/// <summary>Incremental position to which the recovered data strobe shall be adjusted</summary>
|
||||
public sbyte DataStrobeOffsetCount;
|
||||
/// <summary>How many times to retry a write operation</summary>
|
||||
public byte WriteRetryCount;
|
||||
/// <summary>Maximum time in ms to use in data error recovery procedures</summary>
|
||||
public ushort RecoveryTimeLimit;
|
||||
|
||||
/// <summary>Logical block provisioning error reporting is enabled</summary>
|
||||
public bool LBPERE;
|
||||
}
|
||||
|
||||
public static ModePage_01? DecodeModePage_01(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x01)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
var decoded = new ModePage_01();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80;
|
||||
decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40;
|
||||
decoded.TB |= (pageResponse[2] & 0x20) == 0x20;
|
||||
decoded.RC |= (pageResponse[2] & 0x10) == 0x10;
|
||||
decoded.EER |= (pageResponse[2] & 0x08) == 0x08;
|
||||
decoded.PER |= (pageResponse[2] & 0x04) == 0x04;
|
||||
decoded.DTE |= (pageResponse[2] & 0x02) == 0x02;
|
||||
decoded.DCR |= (pageResponse[2] & 0x01) == 0x01;
|
||||
|
||||
decoded.ReadRetryCount = pageResponse[3];
|
||||
decoded.CorrectionSpan = pageResponse[4];
|
||||
decoded.HeadOffsetCount = (sbyte)pageResponse[5];
|
||||
decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6];
|
||||
|
||||
if(pageResponse.Length < 12)
|
||||
return decoded;
|
||||
|
||||
decoded.WriteRetryCount = pageResponse[8];
|
||||
decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
|
||||
decoded.LBPERE |= (pageResponse[7] & 0x80) == 0x80;
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
public static string PrettifyModePage_01(byte[] pageResponse) =>
|
||||
PrettifyModePage_01(DecodeModePage_01(pageResponse));
|
||||
|
||||
public static string PrettifyModePage_01(ModePage_01? modePage)
|
||||
{
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_01 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Read-write error recovery page:");
|
||||
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.AWRE)
|
||||
sb.AppendLine("\tAutomatic write reallocation is enabled");
|
||||
|
||||
if(page.ARRE)
|
||||
sb.AppendLine("\tAutomatic read reallocation is enabled");
|
||||
|
||||
if(page.TB)
|
||||
sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION");
|
||||
|
||||
if(page.RC)
|
||||
sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery");
|
||||
|
||||
if(page.EER)
|
||||
sb.AppendLine("\tDrive will use the most expedient form of error recovery first");
|
||||
|
||||
if(page.PER)
|
||||
sb.AppendLine("\tDrive shall report recovered errors");
|
||||
|
||||
if(page.DTE)
|
||||
sb.AppendLine("\tTransfer will be terminated upon error detection");
|
||||
|
||||
if(page.DCR)
|
||||
sb.AppendLine("\tError correction is disabled");
|
||||
|
||||
if(page.ReadRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine();
|
||||
|
||||
if(page.WriteRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine();
|
||||
|
||||
if(page.RecoveryTimeLimit > 0)
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit).
|
||||
AppendLine();
|
||||
|
||||
if(page.LBPERE)
|
||||
sb.AppendLine("Logical block provisioning error reporting is enabled");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion Mode Page 0x01: Read-write error recovery page
|
||||
}
|
||||
}
|
||||
@@ -35,59 +35,73 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page)
|
||||
{
|
||||
byte[] pg = new byte[12];
|
||||
|
||||
pg[0] = 0x01;
|
||||
pg[1] = 10;
|
||||
|
||||
if(page.PS)
|
||||
pg[0] += 0x80;
|
||||
|
||||
pg[2] = page.Parameter;
|
||||
pg[3] = page.ReadRetryCount;
|
||||
|
||||
// This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page
|
||||
|
||||
pg[8] = page.WriteRetryCount;
|
||||
pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8);
|
||||
pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF);
|
||||
|
||||
return pg;
|
||||
}
|
||||
|
||||
#region Mode Page 0x01: Read error recovery page for MultiMedia Devices
|
||||
/// <summary>
|
||||
/// Read error recovery page for MultiMedia Devices
|
||||
/// Page code 0x01
|
||||
/// 8 bytes in SCSI-2, MMC-1
|
||||
/// 12 bytes in MMC-2, MMC-3
|
||||
/// Read error recovery page for MultiMedia Devices Page code 0x01 8 bytes in SCSI-2, MMC-1 12 bytes in MMC-2,
|
||||
/// MMC-3
|
||||
/// </summary>
|
||||
public struct ModePage_01_MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Error recovery parameter
|
||||
/// </summary>
|
||||
/// <summary>Error recovery parameter</summary>
|
||||
public byte Parameter;
|
||||
/// <summary>
|
||||
/// How many times to retry a read operation
|
||||
/// </summary>
|
||||
/// <summary>How many times to retry a read operation</summary>
|
||||
public byte ReadRetryCount;
|
||||
/// <summary>
|
||||
/// How many times to retry a write operation
|
||||
/// </summary>
|
||||
/// <summary>How many times to retry a write operation</summary>
|
||||
public byte WriteRetryCount;
|
||||
/// <summary>
|
||||
/// Maximum time in ms to use in data error recovery procedures
|
||||
/// </summary>
|
||||
/// <summary>Maximum time in ms to use in data error recovery procedures</summary>
|
||||
public ushort RecoveryTimeLimit;
|
||||
}
|
||||
|
||||
public static ModePage_01_MMC? DecodeModePage_01_MMC(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x01) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x01)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_01_MMC decoded = new ModePage_01_MMC();
|
||||
var decoded = new ModePage_01_MMC();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.Parameter = pageResponse[2];
|
||||
decoded.ReadRetryCount = pageResponse[3];
|
||||
|
||||
if(pageResponse.Length < 12) return decoded;
|
||||
if(pageResponse.Length < 12)
|
||||
return decoded;
|
||||
|
||||
decoded.WriteRetryCount = pageResponse[8];
|
||||
decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
|
||||
@@ -100,14 +114,17 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_01_MMC(ModePage_01_MMC? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_01_MMC page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Read error recovery page for MultiMedia Devices:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.ReadRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine();
|
||||
|
||||
@@ -121,8 +138,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION.";
|
||||
string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer.";
|
||||
string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer.";
|
||||
|
||||
string UnrecECCAbortData =
|
||||
"\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data.";
|
||||
|
||||
string UnrecCIRCAbortData =
|
||||
"\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data.";
|
||||
|
||||
@@ -130,51 +149,67 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0x00:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x01:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x04:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x05:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x06:
|
||||
sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x07:
|
||||
sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x11:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x14:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x15:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x24:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x25:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x26:
|
||||
sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x27:
|
||||
sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x30: goto case 0x10;
|
||||
case 0x31: goto case 0x11;
|
||||
@@ -182,37 +217,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case 0x35: goto case 0x15;
|
||||
default:
|
||||
sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.WriteRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine();
|
||||
|
||||
if(page.RecoveryTimeLimit > 0)
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit).
|
||||
AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion Mode Page 0x01: Read error recovery page for MultiMedia Devices
|
||||
|
||||
public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page)
|
||||
{
|
||||
byte[] pg = new byte[12];
|
||||
|
||||
pg[0] = 0x01;
|
||||
pg[1] = 10;
|
||||
|
||||
if(page.PS) pg[0] += 0x80;
|
||||
pg[2] = page.Parameter;
|
||||
pg[3] = page.ReadRetryCount;
|
||||
|
||||
// This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page
|
||||
|
||||
pg[8] = page.WriteRetryCount;
|
||||
pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8);
|
||||
pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF);
|
||||
|
||||
return pg;
|
||||
}
|
||||
}
|
||||
}
|
||||
109
SCSI/Modes/02.cs
109
SCSI/Modes/02.cs
@@ -35,82 +35,59 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x02: Disconnect-reconnect page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x02
|
||||
/// 16 bytes in SCSI-2, SPC-1, SPC-2, SPC-3, SPC-4, SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x02 16 bytes in SCSI-2, SPC-1, SPC-2, SPC-3, SPC-4, SPC-5</summary>
|
||||
public struct ModePage_02
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// How full should be the buffer prior to attempting a reselection
|
||||
/// </summary>
|
||||
/// <summary>How full should be the buffer prior to attempting a reselection</summary>
|
||||
public byte BufferFullRatio;
|
||||
/// <summary>
|
||||
/// How empty should be the buffer prior to attempting a reselection
|
||||
/// </summary>
|
||||
/// <summary>How empty should be the buffer prior to attempting a reselection</summary>
|
||||
public byte BufferEmptyRatio;
|
||||
/// <summary>
|
||||
/// Max. time in 100 µs increments that the target is permitted to assert BSY without a REQ/ACK
|
||||
/// </summary>
|
||||
/// <summary>Max. time in 100 µs increments that the target is permitted to assert BSY without a REQ/ACK</summary>
|
||||
public ushort BusInactivityLimit;
|
||||
/// <summary>
|
||||
/// Min. time in 100 µs increments to wait after releasing the bus before attempting reselection
|
||||
/// </summary>
|
||||
/// <summary>Min. time in 100 µs increments to wait after releasing the bus before attempting reselection</summary>
|
||||
public ushort DisconnectTimeLimit;
|
||||
/// <summary>
|
||||
/// Max. time in 100 µs increments allowed to use the bus before disconnecting, if granted the privilege and not
|
||||
/// restricted by <see cref="DTDC" />
|
||||
/// </summary>
|
||||
public ushort ConnectTimeLimit;
|
||||
/// <summary>
|
||||
/// Maximum amount of data before disconnecting in 512 bytes increments
|
||||
/// </summary>
|
||||
/// <summary>Maximum amount of data before disconnecting in 512 bytes increments</summary>
|
||||
public ushort MaxBurstSize;
|
||||
/// <summary>
|
||||
/// Data transfer disconnect control
|
||||
/// </summary>
|
||||
/// <summary>Data transfer disconnect control</summary>
|
||||
public byte DTDC;
|
||||
|
||||
/// <summary>
|
||||
/// Target shall not transfer data for a command during the same interconnect tenancy
|
||||
/// </summary>
|
||||
/// <summary>Target shall not transfer data for a command during the same interconnect tenancy</summary>
|
||||
public bool DIMM;
|
||||
/// <summary>
|
||||
/// Wether to use fair or unfair arbitration when requesting an interconnect tenancy
|
||||
/// </summary>
|
||||
/// <summary>Wether to use fair or unfair arbitration when requesting an interconnect tenancy</summary>
|
||||
public byte FairArbitration;
|
||||
/// <summary>
|
||||
/// Max. ammount of data in 512 bytes increments that may be transferred for a command along with the command
|
||||
/// </summary>
|
||||
/// <summary>Max. ammount of data in 512 bytes increments that may be transferred for a command along with the command</summary>
|
||||
public ushort FirstBurstSize;
|
||||
/// <summary>
|
||||
/// Target is allowed to re-order the data transfer
|
||||
/// </summary>
|
||||
/// <summary>Target is allowed to re-order the data transfer</summary>
|
||||
public bool EMDP;
|
||||
}
|
||||
|
||||
public static ModePage_02? DecodeModePage_02(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x02) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x02)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 12) return null;
|
||||
if(pageResponse.Length < 12)
|
||||
return null;
|
||||
|
||||
ModePage_02 decoded = new ModePage_02();
|
||||
var decoded = new ModePage_02();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.BufferFullRatio = pageResponse[2];
|
||||
@@ -128,7 +105,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
decoded.DTDC = (byte)(pageResponse[12] & 0x07);
|
||||
}
|
||||
|
||||
if(pageResponse.Length >= 16) decoded.FirstBurstSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
|
||||
if(pageResponse.Length >= 16)
|
||||
decoded.FirstBurstSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
|
||||
|
||||
return decoded;
|
||||
}
|
||||
@@ -138,55 +116,70 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_02(ModePage_02? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_02 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_02 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Disconnect-Reconnect mode page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.BufferFullRatio > 0)
|
||||
sb.AppendFormat("\t{0} ratio of buffer that shall be full prior to attempting a reselection",
|
||||
page.BufferFullRatio).AppendLine();
|
||||
|
||||
if(page.BufferEmptyRatio > 0)
|
||||
sb.AppendFormat("\t{0} ratio of buffer that shall be empty prior to attempting a reselection",
|
||||
page.BufferEmptyRatio).AppendLine();
|
||||
|
||||
if(page.BusInactivityLimit > 0)
|
||||
sb.AppendFormat("\t{0} µs maximum permitted to assert BSY without a REQ/ACK handshake",
|
||||
page.BusInactivityLimit * 100).AppendLine();
|
||||
|
||||
if(page.DisconnectTimeLimit > 0)
|
||||
sb.AppendFormat("\t{0} µs maximum permitted wait after releasing the bus before attempting reselection",
|
||||
page.DisconnectTimeLimit * 100).AppendLine();
|
||||
|
||||
if(page.ConnectTimeLimit > 0)
|
||||
sb
|
||||
.AppendFormat("\t{0} µs allowed to use the bus before disconnecting, if granted the privilege and not restricted",
|
||||
sb.
|
||||
AppendFormat("\t{0} µs allowed to use the bus before disconnecting, if granted the privilege and not restricted",
|
||||
page.ConnectTimeLimit * 100).AppendLine();
|
||||
|
||||
if(page.MaxBurstSize > 0)
|
||||
sb.AppendFormat("\t{0} bytes maximum can be transferred before disconnecting", page.MaxBurstSize * 512)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\t{0} bytes maximum can be transferred before disconnecting", page.MaxBurstSize * 512).
|
||||
AppendLine();
|
||||
|
||||
if(page.FirstBurstSize > 0)
|
||||
sb
|
||||
.AppendFormat("\t{0} bytes maximum can be transferred for a command along with the disconnect command",
|
||||
sb.
|
||||
AppendFormat("\t{0} bytes maximum can be transferred for a command along with the disconnect command",
|
||||
page.FirstBurstSize * 512).AppendLine();
|
||||
|
||||
if(page.DIMM)
|
||||
sb.AppendLine("\tTarget shall not transfer data for a command during the same interconnect tenancy");
|
||||
if(page.EMDP) sb.AppendLine("\tTarget is allowed to re-order the data transfer");
|
||||
|
||||
if(page.EMDP)
|
||||
sb.AppendLine("\tTarget is allowed to re-order the data transfer");
|
||||
|
||||
switch(page.DTDC)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tData transfer disconnect control is not used");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tAll data for a command shall be transferred within a single interconnect tenancy");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tAll data and the response for a command shall be transferred within a single interconnect tenancy");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tReserved data transfer disconnect control value {0}", page.DTDC).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
130
SCSI/Modes/03.cs
130
SCSI/Modes/03.cs
@@ -35,89 +35,62 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x03: Format device page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x03
|
||||
/// 24 bytes in SCSI-2, SBC-1
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x03 24 bytes in SCSI-2, SBC-1</summary>
|
||||
public struct ModePage_03
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors
|
||||
/// </summary>
|
||||
/// <summary>Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors</summary>
|
||||
public ushort TracksPerZone;
|
||||
/// <summary>
|
||||
/// Number of sectors per zone that shall be reserved for defect handling
|
||||
/// </summary>
|
||||
/// <summary>Number of sectors per zone that shall be reserved for defect handling</summary>
|
||||
public ushort AltSectorsPerZone;
|
||||
/// <summary>
|
||||
/// Number of tracks per zone that shall be reserved for defect handling
|
||||
/// </summary>
|
||||
/// <summary>Number of tracks per zone that shall be reserved for defect handling</summary>
|
||||
public ushort AltTracksPerZone;
|
||||
/// <summary>
|
||||
/// Number of tracks per LUN that shall be reserved for defect handling
|
||||
/// </summary>
|
||||
/// <summary>Number of tracks per LUN that shall be reserved for defect handling</summary>
|
||||
public ushort AltTracksPerLun;
|
||||
/// <summary>
|
||||
/// Number of physical sectors per track
|
||||
/// </summary>
|
||||
/// <summary>Number of physical sectors per track</summary>
|
||||
public ushort SectorsPerTrack;
|
||||
/// <summary>
|
||||
/// Bytes per physical sector
|
||||
/// </summary>
|
||||
/// <summary>Bytes per physical sector</summary>
|
||||
public ushort BytesPerSector;
|
||||
/// <summary>
|
||||
/// Interleave value, target dependent
|
||||
/// </summary>
|
||||
/// <summary>Interleave value, target dependent</summary>
|
||||
public ushort Interleave;
|
||||
/// <summary>
|
||||
/// Sectors between last block of one track and first block of the next
|
||||
/// </summary>
|
||||
/// <summary>Sectors between last block of one track and first block of the next</summary>
|
||||
public ushort TrackSkew;
|
||||
/// <summary>
|
||||
/// Sectors between last block of a cylinder and first block of the next one
|
||||
/// </summary>
|
||||
/// <summary>Sectors between last block of a cylinder and first block of the next one</summary>
|
||||
public ushort CylinderSkew;
|
||||
/// <summary>
|
||||
/// Soft-sectored
|
||||
/// </summary>
|
||||
/// <summary>Soft-sectored</summary>
|
||||
public bool SSEC;
|
||||
/// <summary>
|
||||
/// Hard-sectored
|
||||
/// </summary>
|
||||
/// <summary>Hard-sectored</summary>
|
||||
public bool HSEC;
|
||||
/// <summary>
|
||||
/// Removable
|
||||
/// </summary>
|
||||
/// <summary>Removable</summary>
|
||||
public bool RMB;
|
||||
/// <summary>
|
||||
/// If set, address are allocated progressively in a surface before going to the next.
|
||||
/// Otherwise, it goes by cylinders
|
||||
/// If set, address are allocated progressively in a surface before going to the next. Otherwise, it goes by
|
||||
/// cylinders
|
||||
/// </summary>
|
||||
public bool SURF;
|
||||
}
|
||||
|
||||
public static ModePage_03? DecodeModePage_03(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x03) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x03)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 24) return null;
|
||||
if(pageResponse.Length < 24)
|
||||
return null;
|
||||
|
||||
ModePage_03 decoded = new ModePage_03();
|
||||
var decoded = new ModePage_03();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.TracksPerZone = (ushort)((pageResponse[2] << 8) + pageResponse[3]);
|
||||
@@ -142,34 +115,49 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_03(ModePage_03? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_03 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_03 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Format device page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb
|
||||
.AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors",
|
||||
sb.
|
||||
AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors",
|
||||
page.TracksPerZone).AppendLine();
|
||||
sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling", page.AltSectorsPerZone)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling",
|
||||
page.AltSectorsPerZone).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} physical sectors per track", page.SectorsPerTrack).AppendLine();
|
||||
sb.AppendFormat("\t{0} Bytes per physical sector", page.BytesPerSector).AppendLine();
|
||||
sb.AppendFormat("\tTarget-dependent interleave value is {0}", page.Interleave).AppendLine();
|
||||
sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next", page.TrackSkew)
|
||||
.AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next",
|
||||
page.TrackSkew).AppendLine();
|
||||
|
||||
sb.AppendFormat("\t{0} sectors between last block of a cylinder and first block of the next one",
|
||||
page.CylinderSkew).AppendLine();
|
||||
if(page.SSEC) sb.AppendLine("\tDrive supports soft-sectoring format");
|
||||
if(page.HSEC) sb.AppendLine("\tDrive supports hard-sectoring format");
|
||||
if(page.RMB) sb.AppendLine("\tDrive media is removable");
|
||||
|
||||
if(page.SSEC)
|
||||
sb.AppendLine("\tDrive supports soft-sectoring format");
|
||||
|
||||
if(page.HSEC)
|
||||
sb.AppendLine("\tDrive supports hard-sectoring format");
|
||||
|
||||
if(page.RMB)
|
||||
sb.AppendLine("\tDrive media is removable");
|
||||
|
||||
sb.AppendLine(page.SURF
|
||||
? "\tSector addressing is progressively incremented in one surface before going to the next"
|
||||
: "\tSector addressing is progressively incremented in one cylinder before going to the next");
|
||||
|
||||
@@ -35,81 +35,63 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x04: Rigid disk drive geometry page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x04
|
||||
/// 24 bytes in SCSI-2, SBC-1
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x04 24 bytes in SCSI-2, SBC-1</summary>
|
||||
public struct ModePage_04
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Cylinders used for data storage
|
||||
/// </summary>
|
||||
/// <summary>Cylinders used for data storage</summary>
|
||||
public uint Cylinders;
|
||||
/// <summary>
|
||||
/// Heads for reading and/or writing
|
||||
/// </summary>
|
||||
/// <summary>Heads for reading and/or writing</summary>
|
||||
public byte Heads;
|
||||
/// <summary>
|
||||
/// Cylinder where write precompensation starts
|
||||
/// </summary>
|
||||
/// <summary>Cylinder where write precompensation starts</summary>
|
||||
public uint WritePrecompCylinder;
|
||||
/// <summary>
|
||||
/// Cylinder where write current reduction starts
|
||||
/// </summary>
|
||||
/// <summary>Cylinder where write current reduction starts</summary>
|
||||
public uint WriteReduceCylinder;
|
||||
/// <summary>
|
||||
/// Step rate in 100 ns units
|
||||
/// </summary>
|
||||
/// <summary>Step rate in 100 ns units</summary>
|
||||
public ushort DriveStepRate;
|
||||
/// <summary>
|
||||
/// Cylinder where the heads park
|
||||
/// </summary>
|
||||
/// <summary>Cylinder where the heads park</summary>
|
||||
public int LandingCylinder;
|
||||
/// <summary>
|
||||
/// Rotational position locking
|
||||
/// </summary>
|
||||
/// <summary>Rotational position locking</summary>
|
||||
public byte RPL;
|
||||
/// <summary>
|
||||
/// Rotational skew to apply when synchronized
|
||||
/// </summary>
|
||||
/// <summary>Rotational skew to apply when synchronized</summary>
|
||||
public byte RotationalOffset;
|
||||
/// <summary>
|
||||
/// Medium speed in rpm
|
||||
/// </summary>
|
||||
/// <summary>Medium speed in rpm</summary>
|
||||
public ushort MediumRotationRate;
|
||||
}
|
||||
|
||||
public static ModePage_04? DecodeModePage_04(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x04) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x04)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 20) return null;
|
||||
if(pageResponse.Length < 20)
|
||||
return null;
|
||||
|
||||
ModePage_04 decoded = new ModePage_04();
|
||||
var decoded = new ModePage_04();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.Cylinders = (uint)((pageResponse[2] << 16) + (pageResponse[3] << 8) + pageResponse[4]);
|
||||
decoded.Heads = pageResponse[5];
|
||||
decoded.WritePrecompCylinder = (uint)((pageResponse[6] << 16) + (pageResponse[7] << 8) + pageResponse[8]);
|
||||
|
||||
decoded.WriteReduceCylinder =
|
||||
(uint)((pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]);
|
||||
|
||||
decoded.DriveStepRate =
|
||||
(ushort)((pageResponse[12] << 8) + pageResponse[13]);
|
||||
|
||||
decoded.LandingCylinder = (pageResponse[14] << 16) + (pageResponse[15] << 8) + pageResponse[16];
|
||||
decoded.RPL = (byte)(pageResponse[17] & 0x03);
|
||||
decoded.RotationalOffset = pageResponse[18];
|
||||
@@ -125,23 +107,28 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_04(ModePage_04? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_04 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_04 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Rigid disk drive geometry page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\t{0} heads", page.Heads).AppendLine();
|
||||
sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine();
|
||||
|
||||
if(page.WritePrecompCylinder < page.Cylinders)
|
||||
sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder).
|
||||
AppendLine();
|
||||
|
||||
if(page.WriteReduceCylinder < page.Cylinders)
|
||||
sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder).
|
||||
AppendLine();
|
||||
|
||||
if(page.DriveStepRate > 0)
|
||||
sb.AppendFormat("\tDrive steps in {0} ns", (uint)page.DriveStepRate * 100).AppendLine();
|
||||
|
||||
@@ -154,15 +141,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tSpindle synchronization is disable or unsupported");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tTarget operates as a synchronized-spindle slave");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tTarget operates as a synchronized-spindle master");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tTarget operates as a synchronized-spindle master control");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
196
SCSI/Modes/05.cs
196
SCSI/Modes/05.cs
@@ -35,137 +35,87 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x05: Flexible disk page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x05
|
||||
/// 32 bytes in SCSI-2, SBC-1
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x05 32 bytes in SCSI-2, SBC-1</summary>
|
||||
public struct ModePage_05
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Data rate of peripheral device on kbit/s
|
||||
/// </summary>
|
||||
/// <summary>Data rate of peripheral device on kbit/s</summary>
|
||||
public ushort TransferRate;
|
||||
/// <summary>
|
||||
/// Heads for reading and/or writing
|
||||
/// </summary>
|
||||
/// <summary>Heads for reading and/or writing</summary>
|
||||
public byte Heads;
|
||||
/// <summary>
|
||||
/// Sectors per revolution per head
|
||||
/// </summary>
|
||||
/// <summary>Sectors per revolution per head</summary>
|
||||
public byte SectorsPerTrack;
|
||||
/// <summary>
|
||||
/// Bytes of data per sector
|
||||
/// </summary>
|
||||
/// <summary>Bytes of data per sector</summary>
|
||||
public ushort BytesPerSector;
|
||||
/// <summary>
|
||||
/// Cylinders used for data storage
|
||||
/// </summary>
|
||||
/// <summary>Cylinders used for data storage</summary>
|
||||
public ushort Cylinders;
|
||||
/// <summary>
|
||||
/// Cylinder where write precompensation starts
|
||||
/// </summary>
|
||||
/// <summary>Cylinder where write precompensation starts</summary>
|
||||
public ushort WritePrecompCylinder;
|
||||
/// <summary>
|
||||
/// Cylinder where write current reduction starts
|
||||
/// </summary>
|
||||
/// <summary>Cylinder where write current reduction starts</summary>
|
||||
public ushort WriteReduceCylinder;
|
||||
/// <summary>
|
||||
/// Step rate in 100 μs units
|
||||
/// </summary>
|
||||
/// <summary>Step rate in 100 μs units</summary>
|
||||
public ushort DriveStepRate;
|
||||
/// <summary>
|
||||
/// Width of step pulse in μs
|
||||
/// </summary>
|
||||
/// <summary>Width of step pulse in μs</summary>
|
||||
public byte DriveStepPulse;
|
||||
/// <summary>
|
||||
/// Head settle time in 100 μs units
|
||||
/// </summary>
|
||||
/// <summary>Head settle time in 100 μs units</summary>
|
||||
public ushort HeadSettleDelay;
|
||||
/// <summary>
|
||||
/// If <see cref="TRDY" /> is <c>true</c>, specified in 1/10s of a
|
||||
/// second the time waiting for read status before aborting medium
|
||||
/// access. Otherwise, indicates time to way before medimum access
|
||||
/// after motor on signal is asserted.
|
||||
/// If <see cref="TRDY" /> is <c>true</c>, specified in 1/10s of a second the time waiting for read status before
|
||||
/// aborting medium access. Otherwise, indicates time to way before medimum access after motor on signal is asserted.
|
||||
/// </summary>
|
||||
public byte MotorOnDelay;
|
||||
/// <summary>
|
||||
/// Time in 1/10s of a second to wait before releasing the motor on
|
||||
/// signal after an idle condition. 0xFF means to never release the
|
||||
/// signal
|
||||
/// Time in 1/10s of a second to wait before releasing the motor on signal after an idle condition. 0xFF means to
|
||||
/// never release the signal
|
||||
/// </summary>
|
||||
public byte MotorOffDelay;
|
||||
/// <summary>
|
||||
/// Specifies if a signal indicates that the medium is ready to be accessed
|
||||
/// </summary>
|
||||
/// <summary>Specifies if a signal indicates that the medium is ready to be accessed</summary>
|
||||
public bool TRDY;
|
||||
/// <summary>
|
||||
/// If <c>true</c> sectors start with one. Otherwise, they start with zero.
|
||||
/// </summary>
|
||||
/// <summary>If <c>true</c> sectors start with one. Otherwise, they start with zero.</summary>
|
||||
public bool SSN;
|
||||
/// <summary>
|
||||
/// If <c>true</c> specifies that motor on shall remain released.
|
||||
/// </summary>
|
||||
/// <summary>If <c>true</c> specifies that motor on shall remain released.</summary>
|
||||
public bool MO;
|
||||
/// <summary>
|
||||
/// Number of additional step pulses per cylinder.
|
||||
/// </summary>
|
||||
/// <summary>Number of additional step pulses per cylinder.</summary>
|
||||
public byte SPC;
|
||||
/// <summary>
|
||||
/// Write compensation value
|
||||
/// </summary>
|
||||
/// <summary>Write compensation value</summary>
|
||||
public byte WriteCompensation;
|
||||
/// <summary>
|
||||
/// Head loading time in ms.
|
||||
/// </summary>
|
||||
/// <summary>Head loading time in ms.</summary>
|
||||
public byte HeadLoadDelay;
|
||||
/// <summary>
|
||||
/// Head unloading time in ms.
|
||||
/// </summary>
|
||||
/// <summary>Head unloading time in ms.</summary>
|
||||
public byte HeadUnloadDelay;
|
||||
/// <summary>
|
||||
/// Description of shugart's bus pin 34 usage
|
||||
/// </summary>
|
||||
/// <summary>Description of shugart's bus pin 34 usage</summary>
|
||||
public byte Pin34;
|
||||
/// <summary>
|
||||
/// Description of shugart's bus pin 2 usage
|
||||
/// </summary>
|
||||
/// <summary>Description of shugart's bus pin 2 usage</summary>
|
||||
public byte Pin2;
|
||||
/// <summary>
|
||||
/// Description of shugart's bus pin 4 usage
|
||||
/// </summary>
|
||||
/// <summary>Description of shugart's bus pin 4 usage</summary>
|
||||
public byte Pin4;
|
||||
/// <summary>
|
||||
/// Description of shugart's bus pin 1 usage
|
||||
/// </summary>
|
||||
/// <summary>Description of shugart's bus pin 1 usage</summary>
|
||||
public byte Pin1;
|
||||
/// <summary>
|
||||
/// Medium speed in rpm
|
||||
/// </summary>
|
||||
/// <summary>Medium speed in rpm</summary>
|
||||
public ushort MediumRotationRate;
|
||||
}
|
||||
|
||||
public static ModePage_05? DecodeModePage_05(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x05) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x05)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 32) return null;
|
||||
if(pageResponse.Length < 32)
|
||||
return null;
|
||||
|
||||
ModePage_05 decoded = new ModePage_05();
|
||||
var decoded = new ModePage_05();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.TransferRate = (ushort)((pageResponse[2] << 8) + pageResponse[3]);
|
||||
@@ -201,57 +151,73 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_05(ModePage_05? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_05 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_05 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Flexible disk page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\tTransfer rate: {0} kbit/s", page.TransferRate).AppendLine();
|
||||
sb.AppendFormat("\t{0} heads", page.Heads).AppendLine();
|
||||
sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine();
|
||||
sb.AppendFormat("\t{0} sectors per track", page.SectorsPerTrack).AppendLine();
|
||||
sb.AppendFormat("\t{0} bytes per sector", page.BytesPerSector).AppendLine();
|
||||
|
||||
if(page.WritePrecompCylinder < page.Cylinders)
|
||||
sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder).
|
||||
AppendLine();
|
||||
|
||||
if(page.WriteReduceCylinder < page.Cylinders)
|
||||
sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder).
|
||||
AppendLine();
|
||||
|
||||
if(page.DriveStepRate > 0)
|
||||
sb.AppendFormat("\tDrive steps in {0} μs", (uint)page.DriveStepRate * 100).AppendLine();
|
||||
|
||||
if(page.DriveStepPulse > 0)
|
||||
sb.AppendFormat("\tEach step pulse is {0} ms", page.DriveStepPulse).AppendLine();
|
||||
|
||||
if(page.HeadSettleDelay > 0)
|
||||
sb.AppendFormat("\tHeads settles in {0} μs", (uint)page.HeadSettleDelay * 100).AppendLine();
|
||||
|
||||
if(!page.TRDY)
|
||||
sb
|
||||
.AppendFormat("\tTarget shall wait {0} seconds before attempting to access the medium after motor on is asserted",
|
||||
sb.
|
||||
AppendFormat("\tTarget shall wait {0} seconds before attempting to access the medium after motor on is asserted",
|
||||
(double)page.MotorOnDelay * 10).AppendLine();
|
||||
else
|
||||
sb
|
||||
.AppendFormat("\tTarget shall wait {0} seconds after drive is ready before aborting medium access attemps",
|
||||
sb.
|
||||
AppendFormat("\tTarget shall wait {0} seconds after drive is ready before aborting medium access attemps",
|
||||
(double)page.MotorOnDelay * 10).AppendLine();
|
||||
|
||||
if(page.MotorOffDelay != 0xFF)
|
||||
sb
|
||||
.AppendFormat("\tTarget shall wait {0} seconds before releasing the motor on signal after becoming idle",
|
||||
sb.
|
||||
AppendFormat("\tTarget shall wait {0} seconds before releasing the motor on signal after becoming idle",
|
||||
(double)page.MotorOffDelay * 10).AppendLine();
|
||||
else sb.AppendLine("\tTarget shall never release the motor on signal");
|
||||
else
|
||||
sb.AppendLine("\tTarget shall never release the motor on signal");
|
||||
|
||||
if(page.TRDY) sb.AppendLine("\tThere is a drive ready signal");
|
||||
if(page.SSN) sb.AppendLine("\tSectors start at 1");
|
||||
if(page.MO) sb.AppendLine("\tThe motor on signal shall remain released");
|
||||
if(page.TRDY)
|
||||
sb.AppendLine("\tThere is a drive ready signal");
|
||||
|
||||
if(page.SSN)
|
||||
sb.AppendLine("\tSectors start at 1");
|
||||
|
||||
if(page.MO)
|
||||
sb.AppendLine("\tThe motor on signal shall remain released");
|
||||
|
||||
sb.AppendFormat("\tDrive needs to do {0} step pulses per cylinder", page.SPC + 1).AppendLine();
|
||||
|
||||
if(page.WriteCompensation > 0)
|
||||
sb.AppendFormat("\tWrite pre-compensation is {0}", page.WriteCompensation).AppendLine();
|
||||
if(page.HeadLoadDelay > 0) sb.AppendFormat("\tHead takes {0} ms to load", page.HeadLoadDelay).AppendLine();
|
||||
|
||||
if(page.HeadLoadDelay > 0)
|
||||
sb.AppendFormat("\tHead takes {0} ms to load", page.HeadLoadDelay).AppendLine();
|
||||
|
||||
if(page.HeadUnloadDelay > 0)
|
||||
sb.AppendFormat("\tHead takes {0} ms to unload", page.HeadUnloadDelay).AppendLine();
|
||||
|
||||
@@ -262,18 +228,22 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPin 34 is unconnected");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.Append("\tPin 34 indicates drive is ready when active ");
|
||||
sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.Append("\tPin 34 indicates disk has changed when active ");
|
||||
sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tPin 34 indicates unknown function {0} when active ", page.Pin34 & 0x07);
|
||||
sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -281,22 +251,27 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPin 4 is unconnected");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.Append("\tPin 4 indicates drive is in use when active ");
|
||||
sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.Append("\tPin 4 indicates eject when active ");
|
||||
sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.Append("\tPin 4 indicates head load when active ");
|
||||
sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tPin 4 indicates unknown function {0} when active ", page.Pin4 & 0x07);
|
||||
sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -304,10 +279,12 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPin 2 is unconnected");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tPin 2 indicates unknown function {0} when active ", page.Pin2 & 0x07);
|
||||
sb.Append((page.Pin2 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -315,14 +292,17 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPin 1 is unconnected");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.Append("\tPin 1 indicates disk change reset when active ");
|
||||
sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tPin 1 indicates unknown function {0} when active ", page.Pin1 & 0x07);
|
||||
sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,40 +35,35 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x06: Optical memory page
|
||||
/// <summary>
|
||||
/// Optical memory page
|
||||
/// Page code 0x06
|
||||
/// 4 bytes in SCSI-2
|
||||
/// </summary>
|
||||
/// <summary>Optical memory page Page code 0x06 4 bytes in SCSI-2</summary>
|
||||
public struct ModePage_06
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Report updated block read
|
||||
/// </summary>
|
||||
/// <summary>Report updated block read</summary>
|
||||
public bool RUBR;
|
||||
}
|
||||
|
||||
public static ModePage_06? DecodeModePage_06(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x06) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x06)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 4) return null;
|
||||
if(pageResponse.Length < 4)
|
||||
return null;
|
||||
|
||||
ModePage_06 decoded = new ModePage_06();
|
||||
var decoded = new ModePage_06();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.RUBR |= (pageResponse[2] & 0x01) == 0x01;
|
||||
@@ -81,15 +76,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_06(ModePage_06? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_06 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_06 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI optical memory:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.RUBR) sb.AppendLine("\tOn reading an updated block drive will return RECOVERED ERROR");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.RUBR)
|
||||
sb.AppendLine("\tOn reading an updated block drive will return RECOVERED ERROR");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,65 +35,47 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x07: Verify error recovery page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x07
|
||||
/// 12 bytes in SCSI-2, SBC-1, SBC-2
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x07 12 bytes in SCSI-2, SBC-1, SBC-2</summary>
|
||||
public struct ModePage_07
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Enable early recovery
|
||||
/// </summary>
|
||||
/// <summary>Enable early recovery</summary>
|
||||
public bool EER;
|
||||
/// <summary>
|
||||
/// Post error reporting
|
||||
/// </summary>
|
||||
/// <summary>Post error reporting</summary>
|
||||
public bool PER;
|
||||
/// <summary>
|
||||
/// Disable transfer on error
|
||||
/// </summary>
|
||||
/// <summary>Disable transfer on error</summary>
|
||||
public bool DTE;
|
||||
/// <summary>
|
||||
/// Disable correction
|
||||
/// </summary>
|
||||
/// <summary>Disable correction</summary>
|
||||
public bool DCR;
|
||||
/// <summary>
|
||||
/// How many times to retry a verify operation
|
||||
/// </summary>
|
||||
/// <summary>How many times to retry a verify operation</summary>
|
||||
public byte VerifyRetryCount;
|
||||
/// <summary>
|
||||
/// How many bits of largest data burst error is maximum to apply error correction on it
|
||||
/// </summary>
|
||||
/// <summary>How many bits of largest data burst error is maximum to apply error correction on it</summary>
|
||||
public byte CorrectionSpan;
|
||||
/// <summary>
|
||||
/// Maximum time in ms to use in data error recovery procedures
|
||||
/// </summary>
|
||||
/// <summary>Maximum time in ms to use in data error recovery procedures</summary>
|
||||
public ushort RecoveryTimeLimit;
|
||||
}
|
||||
|
||||
public static ModePage_07? DecodeModePage_07(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x07) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x07)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 12) return null;
|
||||
if(pageResponse.Length < 12)
|
||||
return null;
|
||||
|
||||
ModePage_07 decoded = new ModePage_07();
|
||||
var decoded = new ModePage_07();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.EER |= (pageResponse[2] & 0x08) == 0x08;
|
||||
@@ -113,24 +95,35 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_07(ModePage_07? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_07 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_07 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Verify error recovery page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.EER)
|
||||
sb.AppendLine("\tDrive will use the most expedient form of error recovery first");
|
||||
|
||||
if(page.PER)
|
||||
sb.AppendLine("\tDrive shall report recovered errors");
|
||||
|
||||
if(page.DTE)
|
||||
sb.AppendLine("\tTransfer will be terminated upon error detection");
|
||||
|
||||
if(page.DCR)
|
||||
sb.AppendLine("\tError correction is disabled");
|
||||
|
||||
if(page.EER) sb.AppendLine("\tDrive will use the most expedient form of error recovery first");
|
||||
if(page.PER) sb.AppendLine("\tDrive shall report recovered errors");
|
||||
if(page.DTE) sb.AppendLine("\tTransfer will be terminated upon error detection");
|
||||
if(page.DCR) sb.AppendLine("\tError correction is disabled");
|
||||
if(page.VerifyRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine();
|
||||
|
||||
if(page.RecoveryTimeLimit > 0)
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit).
|
||||
AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,44 +35,37 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x07: Verify error recovery page for MultiMedia Devices
|
||||
/// <summary>
|
||||
/// Verify error recovery page for MultiMedia Devices
|
||||
/// Page code 0x07
|
||||
/// 8 bytes in SCSI-2, MMC-1
|
||||
/// </summary>
|
||||
/// <summary>Verify error recovery page for MultiMedia Devices Page code 0x07 8 bytes in SCSI-2, MMC-1</summary>
|
||||
public struct ModePage_07_MMC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Error recovery parameter
|
||||
/// </summary>
|
||||
/// <summary>Error recovery parameter</summary>
|
||||
public byte Parameter;
|
||||
/// <summary>
|
||||
/// How many times to retry a verify operation
|
||||
/// </summary>
|
||||
/// <summary>How many times to retry a verify operation</summary>
|
||||
public byte VerifyRetryCount;
|
||||
}
|
||||
|
||||
public static ModePage_07_MMC? DecodeModePage_07_MMC(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x07) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x07)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_07_MMC decoded = new ModePage_07_MMC();
|
||||
var decoded = new ModePage_07_MMC();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.Parameter = pageResponse[2];
|
||||
@@ -86,14 +79,17 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_07_MMC(ModePage_07_MMC? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_07_MMC page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Verify error recovery page for MultiMedia Devices:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.VerifyRetryCount > 0)
|
||||
sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine();
|
||||
|
||||
@@ -107,8 +103,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION.";
|
||||
string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer.";
|
||||
string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer.";
|
||||
|
||||
string UnrecECCAbortData =
|
||||
"\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data.";
|
||||
|
||||
string UnrecCIRCAbortData =
|
||||
"\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data.";
|
||||
|
||||
@@ -116,51 +114,67 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0x00:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x01:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x04:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x05:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x06:
|
||||
sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort);
|
||||
|
||||
break;
|
||||
case 0x07:
|
||||
sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort);
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x11:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x14:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x15:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort);
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x21:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x24:
|
||||
sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x25:
|
||||
sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x26:
|
||||
sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData);
|
||||
|
||||
break;
|
||||
case 0x27:
|
||||
sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData);
|
||||
|
||||
break;
|
||||
case 0x30: goto case 0x10;
|
||||
case 0x31: goto case 0x11;
|
||||
@@ -168,6 +182,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case 0x35: goto case 0x15;
|
||||
default:
|
||||
sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
197
SCSI/Modes/08.cs
197
SCSI/Modes/08.cs
@@ -35,104 +35,56 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x08: Caching page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x08
|
||||
/// 12 bytes in SCSI-2
|
||||
/// 20 bytes in SBC-1, SBC-2, SBC-3
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x08 12 bytes in SCSI-2 20 bytes in SBC-1, SBC-2, SBC-3</summary>
|
||||
public struct ModePage_08
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// <c>true</c> if write cache is enabled
|
||||
/// </summary>
|
||||
/// <summary><c>true</c> if write cache is enabled</summary>
|
||||
public bool WCE;
|
||||
/// <summary>
|
||||
/// Multiplication factor
|
||||
/// </summary>
|
||||
/// <summary>Multiplication factor</summary>
|
||||
public bool MF;
|
||||
/// <summary>
|
||||
/// <c>true</c> if read cache is enabled
|
||||
/// </summary>
|
||||
/// <summary><c>true</c> if read cache is enabled</summary>
|
||||
public bool RCD;
|
||||
/// <summary>
|
||||
/// Advices on reading-cache retention priority
|
||||
/// </summary>
|
||||
/// <summary>Advices on reading-cache retention priority</summary>
|
||||
public byte DemandReadRetentionPrio;
|
||||
/// <summary>
|
||||
/// Advices on writing-cache retention priority
|
||||
/// </summary>
|
||||
/// <summary>Advices on writing-cache retention priority</summary>
|
||||
public byte WriteRetentionPriority;
|
||||
/// <summary>
|
||||
/// If requested read blocks are more than this, no pre-fetch is done
|
||||
/// </summary>
|
||||
/// <summary>If requested read blocks are more than this, no pre-fetch is done</summary>
|
||||
public ushort DisablePreFetch;
|
||||
/// <summary>
|
||||
/// Minimum pre-fetch
|
||||
/// </summary>
|
||||
/// <summary>Minimum pre-fetch</summary>
|
||||
public ushort MinimumPreFetch;
|
||||
/// <summary>
|
||||
/// Maximum pre-fetch
|
||||
/// </summary>
|
||||
/// <summary>Maximum pre-fetch</summary>
|
||||
public ushort MaximumPreFetch;
|
||||
/// <summary>
|
||||
/// Upper limit on maximum pre-fetch value
|
||||
/// </summary>
|
||||
/// <summary>Upper limit on maximum pre-fetch value</summary>
|
||||
public ushort MaximumPreFetchCeiling;
|
||||
|
||||
/// <summary>
|
||||
/// Manual cache controlling
|
||||
/// </summary>
|
||||
/// <summary>Manual cache controlling</summary>
|
||||
public bool IC;
|
||||
/// <summary>
|
||||
/// Abort pre-fetch
|
||||
/// </summary>
|
||||
/// <summary>Abort pre-fetch</summary>
|
||||
public bool ABPF;
|
||||
/// <summary>
|
||||
/// Caching analysis permitted
|
||||
/// </summary>
|
||||
/// <summary>Caching analysis permitted</summary>
|
||||
public bool CAP;
|
||||
/// <summary>
|
||||
/// Pre-fetch over discontinuities
|
||||
/// </summary>
|
||||
/// <summary>Pre-fetch over discontinuities</summary>
|
||||
public bool Disc;
|
||||
/// <summary>
|
||||
/// <see cref="CacheSegmentSize" /> is to be used to control caching segmentation
|
||||
/// </summary>
|
||||
/// <summary><see cref="CacheSegmentSize" /> is to be used to control caching segmentation</summary>
|
||||
public bool Size;
|
||||
/// <summary>
|
||||
/// Force sequential write
|
||||
/// </summary>
|
||||
/// <summary>Force sequential write</summary>
|
||||
public bool FSW;
|
||||
/// <summary>
|
||||
/// Logical block cache segment size
|
||||
/// </summary>
|
||||
/// <summary>Logical block cache segment size</summary>
|
||||
public bool LBCSS;
|
||||
/// <summary>
|
||||
/// Disable read-ahead
|
||||
/// </summary>
|
||||
/// <summary>Disable read-ahead</summary>
|
||||
public bool DRA;
|
||||
/// <summary>
|
||||
/// How many segments should the cache be divided upon
|
||||
/// </summary>
|
||||
/// <summary>How many segments should the cache be divided upon</summary>
|
||||
public byte CacheSegments;
|
||||
/// <summary>
|
||||
/// How many bytes should the cache be divided upon
|
||||
/// </summary>
|
||||
/// <summary>How many bytes should the cache be divided upon</summary>
|
||||
public ushort CacheSegmentSize;
|
||||
/// <summary>
|
||||
/// How many bytes should be used as a buffer when all other cached data cannot be evicted
|
||||
/// </summary>
|
||||
/// <summary>How many bytes should be used as a buffer when all other cached data cannot be evicted</summary>
|
||||
public uint NonCacheSegmentSize;
|
||||
|
||||
public bool NV_DIS;
|
||||
@@ -140,15 +92,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static ModePage_08? DecodeModePage_08(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x08) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x08)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 12) return null;
|
||||
if(pageResponse.Length < 12)
|
||||
return null;
|
||||
|
||||
ModePage_08 decoded = new ModePage_08();
|
||||
var decoded = new ModePage_08();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.WCE |= (pageResponse[2] & 0x04) == 0x04;
|
||||
@@ -162,7 +118,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
decoded.MaximumPreFetch = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
|
||||
decoded.MaximumPreFetchCeiling = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
|
||||
|
||||
if(pageResponse.Length < 20) return decoded;
|
||||
if(pageResponse.Length < 20)
|
||||
return decoded;
|
||||
|
||||
decoded.IC |= (pageResponse[2] & 0x80) == 0x80;
|
||||
decoded.ABPF |= (pageResponse[2] & 0x40) == 0x40;
|
||||
@@ -188,31 +145,41 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_08(ModePage_08? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_08 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_08 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Caching mode page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.RCD) sb.AppendLine("\tRead-cache is enabled");
|
||||
if(page.WCE) sb.AppendLine("\tWrite-cache is enabled");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.RCD)
|
||||
sb.AppendLine("\tRead-cache is enabled");
|
||||
|
||||
if(page.WCE)
|
||||
sb.AppendLine("\tWrite-cache is enabled");
|
||||
|
||||
switch(page.DemandReadRetentionPrio)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive does not distinguish between cached read data");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tData put by READ commands should be evicted from cache sooner than data put in read cache by other means");
|
||||
|
||||
break;
|
||||
case 0xF:
|
||||
sb.AppendLine("\tData put by READ commands should not be evicted if there is data cached by other means that can be evicted");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown demand read retention priority value {0}", page.DemandReadRetentionPrio)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tUnknown demand read retention priority value {0}", page.DemandReadRetentionPrio).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -220,61 +187,76 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive does not distinguish between cached write data");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tData put by WRITE commands should be evicted from cache sooner than data put in write cache by other means");
|
||||
|
||||
break;
|
||||
case 0xF:
|
||||
sb.AppendLine("\tData put by WRITE commands should not be evicted if there is data cached by other means that can be evicted");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown demand write retention priority value {0}", page.DemandReadRetentionPrio)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tUnknown demand write retention priority value {0}",
|
||||
page.DemandReadRetentionPrio).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.DRA) sb.AppendLine("\tRead-ahead is disabled");
|
||||
if(page.DRA)
|
||||
sb.AppendLine("\tRead-ahead is disabled");
|
||||
else
|
||||
{
|
||||
if(page.MF) sb.AppendLine("\tPre-fetch values indicate a block multiplier");
|
||||
if(page.MF)
|
||||
sb.AppendLine("\tPre-fetch values indicate a block multiplier");
|
||||
|
||||
if(page.DisablePreFetch == 0) sb.AppendLine("\tNo pre-fetch will be done");
|
||||
if(page.DisablePreFetch == 0)
|
||||
sb.AppendLine("\tNo pre-fetch will be done");
|
||||
else
|
||||
{
|
||||
sb.AppendFormat("\tPre-fetch will be done for READ commands of {0} blocks or less",
|
||||
page.DisablePreFetch).AppendLine();
|
||||
|
||||
if(page.MinimumPreFetch > 0)
|
||||
sb.AppendFormat("At least {0} blocks will be always pre-fetched", page.MinimumPreFetch)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("At least {0} blocks will be always pre-fetched", page.MinimumPreFetch).
|
||||
AppendLine();
|
||||
|
||||
if(page.MaximumPreFetch > 0)
|
||||
sb.AppendFormat("\tA maximum of {0} blocks will be pre-fetched", page.MaximumPreFetch)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tA maximum of {0} blocks will be pre-fetched", page.MaximumPreFetch).
|
||||
AppendLine();
|
||||
|
||||
if(page.MaximumPreFetchCeiling > 0)
|
||||
sb
|
||||
.AppendFormat("\tA maximum of {0} blocks will be pre-fetched even if it is commanded to pre-fetch more",
|
||||
sb.
|
||||
AppendFormat("\tA maximum of {0} blocks will be pre-fetched even if it is commanded to pre-fetch more",
|
||||
page.MaximumPreFetchCeiling).AppendLine();
|
||||
|
||||
if(page.IC)
|
||||
sb.AppendLine("\tDevice should use number of cache segments or cache segment size for caching");
|
||||
if(page.ABPF) sb.AppendLine("\tPre-fetch should be aborted upong receiving a new command");
|
||||
if(page.CAP) sb.AppendLine("\tCaching analysis is permitted");
|
||||
|
||||
if(page.ABPF)
|
||||
sb.AppendLine("\tPre-fetch should be aborted upong receiving a new command");
|
||||
|
||||
if(page.CAP)
|
||||
sb.AppendLine("\tCaching analysis is permitted");
|
||||
|
||||
if(page.Disc)
|
||||
sb.AppendLine("\tPre-fetch can continue across discontinuities (such as cylinders or tracks)");
|
||||
}
|
||||
}
|
||||
|
||||
if(page.FSW) sb.AppendLine("\tDrive should not reorder the sequence of write commands to be faster");
|
||||
if(page.FSW)
|
||||
sb.AppendLine("\tDrive should not reorder the sequence of write commands to be faster");
|
||||
|
||||
if(page.Size)
|
||||
{
|
||||
if(page.CacheSegmentSize > 0)
|
||||
if(page.LBCSS)
|
||||
sb.AppendFormat("\tDrive cache segments should be {0} blocks long", page.CacheSegmentSize)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive cache segments should be {0} blocks long", page.CacheSegmentSize).
|
||||
AppendLine();
|
||||
else
|
||||
sb.AppendFormat("\tDrive cache segments should be {0} bytes long", page.CacheSegmentSize)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive cache segments should be {0} bytes long", page.CacheSegmentSize).
|
||||
AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -283,11 +265,12 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
}
|
||||
|
||||
if(page.NonCacheSegmentSize > 0)
|
||||
sb
|
||||
.AppendFormat("\tDrive shall allocate {0} bytes to buffer even when all cached data cannot be evicted",
|
||||
sb.
|
||||
AppendFormat("\tDrive shall allocate {0} bytes to buffer even when all cached data cannot be evicted",
|
||||
page.NonCacheSegmentSize).AppendLine();
|
||||
|
||||
if(page.NV_DIS) sb.AppendLine("\tNon-Volatile cache is disabled");
|
||||
if(page.NV_DIS)
|
||||
sb.AppendLine("\tNon-Volatile cache is disabled");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
288
SCSI/Modes/0A.cs
288
SCSI/Modes/0A.cs
@@ -35,147 +35,95 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x0A: Control mode page
|
||||
/// <summary>
|
||||
/// Control mode page
|
||||
/// Page code 0x0A
|
||||
/// 8 bytes in SCSI-2
|
||||
/// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Control mode page Page code 0x0A 8 bytes in SCSI-2 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5</summary>
|
||||
public struct ModePage_0A
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// If set, target shall report log exception conditions
|
||||
/// </summary>
|
||||
/// <summary>If set, target shall report log exception conditions</summary>
|
||||
public bool RLEC;
|
||||
/// <summary>
|
||||
/// Queue algorithm modifier
|
||||
/// </summary>
|
||||
/// <summary>Queue algorithm modifier</summary>
|
||||
public byte QueueAlgorithm;
|
||||
/// <summary>
|
||||
/// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or extended
|
||||
/// contingent allegiance condition
|
||||
/// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or
|
||||
/// extended contingent allegiance condition
|
||||
/// </summary>
|
||||
public byte QErr;
|
||||
/// <summary>
|
||||
/// Tagged queuing is disabled
|
||||
/// </summary>
|
||||
/// <summary>Tagged queuing is disabled</summary>
|
||||
public bool DQue;
|
||||
/// <summary>
|
||||
/// Extended Contingent Allegiance is enabled
|
||||
/// </summary>
|
||||
/// <summary>Extended Contingent Allegiance is enabled</summary>
|
||||
public bool EECA;
|
||||
/// <summary>
|
||||
/// Target may issue an asynchronous event notification upon completing its initialization
|
||||
/// </summary>
|
||||
/// <summary>Target may issue an asynchronous event notification upon completing its initialization</summary>
|
||||
public bool RAENP;
|
||||
/// <summary>
|
||||
/// Target may issue an asynchronous event notification instead of a unit attention condition
|
||||
/// </summary>
|
||||
/// <summary>Target may issue an asynchronous event notification instead of a unit attention condition</summary>
|
||||
public bool UAAENP;
|
||||
/// <summary>
|
||||
/// Target may issue an asynchronous event notification instead of a deferred error
|
||||
/// </summary>
|
||||
/// <summary>Target may issue an asynchronous event notification instead of a deferred error</summary>
|
||||
public bool EAENP;
|
||||
/// <summary>
|
||||
/// Minimum time in ms after initialization before attempting asynchronous event notifications
|
||||
/// </summary>
|
||||
/// <summary>Minimum time in ms after initialization before attempting asynchronous event notifications</summary>
|
||||
public ushort ReadyAENHoldOffPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// Global logging target save disabled
|
||||
/// </summary>
|
||||
/// <summary>Global logging target save disabled</summary>
|
||||
public bool GLTSD;
|
||||
/// <summary>
|
||||
/// CHECK CONDITION should be reported rather than a long busy condition
|
||||
/// </summary>
|
||||
/// <summary>CHECK CONDITION should be reported rather than a long busy condition</summary>
|
||||
public bool RAC;
|
||||
/// <summary>
|
||||
/// Software write protect is active
|
||||
/// </summary>
|
||||
/// <summary>Software write protect is active</summary>
|
||||
public bool SWP;
|
||||
/// <summary>
|
||||
/// Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited.
|
||||
/// </summary>
|
||||
/// <summary>Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited.</summary>
|
||||
public ushort BusyTimeoutPeriod;
|
||||
|
||||
/// <summary>
|
||||
/// Task set type
|
||||
/// </summary>
|
||||
/// <summary>Task set type</summary>
|
||||
public byte TST;
|
||||
/// <summary>
|
||||
/// Tasks aborted by other initiator's actions should be terminated with TASK ABORTED
|
||||
/// </summary>
|
||||
/// <summary>Tasks aborted by other initiator's actions should be terminated with TASK ABORTED</summary>
|
||||
public bool TAS;
|
||||
/// <summary>
|
||||
/// Action to be taken when a medium is inserted
|
||||
/// </summary>
|
||||
/// <summary>Action to be taken when a medium is inserted</summary>
|
||||
public byte AutoloadMode;
|
||||
/// <summary>
|
||||
/// Time in seconds to complete an extended self-test
|
||||
/// </summary>
|
||||
/// <summary>Time in seconds to complete an extended self-test</summary>
|
||||
public byte ExtendedSelfTestCompletionTime;
|
||||
|
||||
/// <summary>
|
||||
/// All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate
|
||||
/// </summary>
|
||||
/// <summary>All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate</summary>
|
||||
public bool TMF_ONLY;
|
||||
/// <summary>
|
||||
/// Device shall return descriptor format sense data when returning sense data in the same transactions as a CHECK
|
||||
/// CONDITION
|
||||
/// </summary>
|
||||
public bool D_SENSE;
|
||||
/// <summary>
|
||||
/// Unit attention interlocks control
|
||||
/// </summary>
|
||||
/// <summary>Unit attention interlocks control</summary>
|
||||
public byte UA_INTLCK_CTRL;
|
||||
/// <summary>
|
||||
/// LOGICAL BLOCK APPLICATION TAG should not be modified
|
||||
/// </summary>
|
||||
/// <summary>LOGICAL BLOCK APPLICATION TAG should not be modified</summary>
|
||||
public bool ATO;
|
||||
|
||||
/// <summary>
|
||||
/// Protector information checking is disabled
|
||||
/// </summary>
|
||||
/// <summary>Protector information checking is disabled</summary>
|
||||
public bool DPICZ;
|
||||
/// <summary>
|
||||
/// No unit attention on release
|
||||
/// </summary>
|
||||
/// <summary>No unit attention on release</summary>
|
||||
public bool NUAR;
|
||||
/// <summary>
|
||||
/// Application Tag mode page is enabled
|
||||
/// </summary>
|
||||
/// <summary>Application Tag mode page is enabled</summary>
|
||||
public bool ATMPE;
|
||||
/// <summary>
|
||||
/// Abort any write command without protection information
|
||||
/// </summary>
|
||||
/// <summary>Abort any write command without protection information</summary>
|
||||
public bool RWWP;
|
||||
/// <summary>
|
||||
/// Supportes block lengths and protection information
|
||||
/// </summary>
|
||||
/// <summary>Supportes block lengths and protection information</summary>
|
||||
public bool SBLP;
|
||||
}
|
||||
|
||||
public static ModePage_0A? DecodeModePage_0A(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x0A) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x0A)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_0A decoded = new ModePage_0A();
|
||||
var decoded = new ModePage_0A();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.RLEC |= (pageResponse[2] & 0x01) == 0x01;
|
||||
@@ -191,7 +139,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.ReadyAENHoldOffPeriod = (ushort)((pageResponse[6] << 8) + pageResponse[7]);
|
||||
|
||||
if(pageResponse.Length < 10) return decoded;
|
||||
if(pageResponse.Length < 10)
|
||||
return decoded;
|
||||
|
||||
// SPC-1
|
||||
decoded.GLTSD |= (pageResponse[2] & 0x02) == 0x02;
|
||||
@@ -228,49 +177,84 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0A(ModePage_0A? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0A page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_0A page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Control mode page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.RLEC) sb.AppendLine("\tIf set, target shall report log exception conditions");
|
||||
if(page.DQue) sb.AppendLine("\tTagged queuing is disabled");
|
||||
if(page.EECA) sb.AppendLine("\tExtended Contingent Allegiance is enabled");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.RLEC)
|
||||
sb.AppendLine("\tIf set, target shall report log exception conditions");
|
||||
|
||||
if(page.DQue)
|
||||
sb.AppendLine("\tTagged queuing is disabled");
|
||||
|
||||
if(page.EECA)
|
||||
sb.AppendLine("\tExtended Contingent Allegiance is enabled");
|
||||
|
||||
if(page.RAENP)
|
||||
sb.AppendLine("\tTarget may issue an asynchronous event notification upon completing its initialization");
|
||||
|
||||
if(page.UAAENP)
|
||||
sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a unit attention condition");
|
||||
|
||||
if(page.EAENP)
|
||||
sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a deferred error");
|
||||
if(page.GLTSD) sb.AppendLine("\tGlobal logging target save disabled");
|
||||
if(page.RAC) sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition");
|
||||
if(page.SWP) sb.AppendLine("\tSoftware write protect is active");
|
||||
|
||||
if(page.GLTSD)
|
||||
sb.AppendLine("\tGlobal logging target save disabled");
|
||||
|
||||
if(page.RAC)
|
||||
sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition");
|
||||
|
||||
if(page.SWP)
|
||||
sb.AppendLine("\tSoftware write protect is active");
|
||||
|
||||
if(page.TAS)
|
||||
sb.AppendLine("\tTasks aborted by other initiator's actions should be terminated with TASK ABORTED");
|
||||
|
||||
if(page.TMF_ONLY)
|
||||
sb.AppendLine("\tAll tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate");
|
||||
|
||||
if(page.D_SENSE)
|
||||
sb.AppendLine("\tDevice shall return descriptor format sense data when returning sense data in the same transactions as a CHECK CONDITION");
|
||||
if(page.ATO) sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified");
|
||||
if(page.DPICZ) sb.AppendLine("\tProtector information checking is disabled");
|
||||
if(page.NUAR) sb.AppendLine("\tNo unit attention on release");
|
||||
if(page.ATMPE) sb.AppendLine("\tApplication Tag mode page is enabled");
|
||||
if(page.RWWP) sb.AppendLine("\tAbort any write command without protection information");
|
||||
if(page.SBLP) sb.AppendLine("\tSupportes block lengths and protection information");
|
||||
|
||||
if(page.ATO)
|
||||
sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified");
|
||||
|
||||
if(page.DPICZ)
|
||||
sb.AppendLine("\tProtector information checking is disabled");
|
||||
|
||||
if(page.NUAR)
|
||||
sb.AppendLine("\tNo unit attention on release");
|
||||
|
||||
if(page.ATMPE)
|
||||
sb.AppendLine("\tApplication Tag mode page is enabled");
|
||||
|
||||
if(page.RWWP)
|
||||
sb.AppendLine("\tAbort any write command without protection information");
|
||||
|
||||
if(page.SBLP)
|
||||
sb.AppendLine("\tSupportes block lengths and protection information");
|
||||
|
||||
switch(page.TST)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tThe logical unit maintains one task set for all nexuses");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tThe logical unit maintains separate task sets for each nexus");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown Task set type {0}", page.TST).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -278,12 +262,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tCommands should be sent strictly ordered");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tCommands can be reordered in any manner");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown Queue Algorithm Modifier {0}", page.QueueAlgorithm).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -291,15 +278,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tIf ACA is established, the task set commands shall resume after it is cleared, otherwise they shall terminate with CHECK CONDITION");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tAll the affected commands in the task set shall be aborted when CHECK CONDITION is returned");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tAffected commands in the task set belonging with the CHECK CONDITION nexus shall be aborted");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendLine("\tReserved QErr value 2 is set");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -307,15 +298,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tLUN shall clear unit attention condition reported in the same nexus");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus and shall establish a unit attention condition for the initiator");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendLine("\tReserved UA_INTLCK_CTRL value 1 is set");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -323,15 +318,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tOn medium insertion, it shall be loaded for full access");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tOn medium insertion, it shall be loaded for auxiliary memory access only");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tOn medium insertion, it shall not be loaded");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tReserved autoload mode {0} set", page.AutoloadMode).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -343,8 +342,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(page.BusyTimeoutPeriod == 0xFFFF)
|
||||
sb.AppendLine("\tThere is no limit on the maximum time that is allowed to remain busy");
|
||||
else
|
||||
sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100).
|
||||
AppendLine();
|
||||
|
||||
if(page.ExtendedSelfTestCompletionTime > 0)
|
||||
sb.AppendFormat("\t{0} seconds to complete extended self-test", page.ExtendedSelfTestCompletionTime);
|
||||
@@ -354,58 +353,44 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
#endregion Mode Page 0x0A: Control mode page
|
||||
|
||||
#region Mode Page 0x0A subpage 0x01: Control Extension mode page
|
||||
/// <summary>
|
||||
/// Control Extension mode page
|
||||
/// Page code 0x0A
|
||||
/// Subpage code 0x01
|
||||
/// 32 bytes in SPC-3, SPC-4, SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Control Extension mode page Page code 0x0A Subpage code 0x01 32 bytes in SPC-3, SPC-4, SPC-5</summary>
|
||||
public struct ModePage_0A_S01
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Timestamp outside this standard
|
||||
/// </summary>
|
||||
/// <summary>Timestamp outside this standard</summary>
|
||||
public bool TCMOS;
|
||||
/// <summary>
|
||||
/// SCSI precedence
|
||||
/// </summary>
|
||||
/// <summary>SCSI precedence</summary>
|
||||
public bool SCSIP;
|
||||
/// <summary>
|
||||
/// Implicit Asymmetric Logical Unit Access Enabled
|
||||
/// </summary>
|
||||
/// <summary>Implicit Asymmetric Logical Unit Access Enabled</summary>
|
||||
public bool IALUAE;
|
||||
/// <summary>
|
||||
/// Initial task priority
|
||||
/// </summary>
|
||||
/// <summary>Initial task priority</summary>
|
||||
public byte InitialPriority;
|
||||
|
||||
/// <summary>
|
||||
/// Device life control disabled
|
||||
/// </summary>
|
||||
/// <summary>Device life control disabled</summary>
|
||||
public bool DLC;
|
||||
/// <summary>
|
||||
/// Maximum size of SENSE data in bytes
|
||||
/// </summary>
|
||||
/// <summary>Maximum size of SENSE data in bytes</summary>
|
||||
public byte MaximumSenseLength;
|
||||
}
|
||||
|
||||
public static ModePage_0A_S01? DecodeModePage_0A_S01(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) != 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) != 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse[0] & 0x3F) != 0x0A) return null;
|
||||
if((pageResponse[0] & 0x3F) != 0x0A)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] != 0x01) return null;
|
||||
if(pageResponse[1] != 0x01)
|
||||
return null;
|
||||
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null;
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 32) return null;
|
||||
if(pageResponse.Length < 32)
|
||||
return null;
|
||||
|
||||
ModePage_0A_S01 decoded = new ModePage_0A_S01();
|
||||
var decoded = new ModePage_0A_S01();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -423,29 +408,34 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0A_S01(ModePage_0A_S01? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0A_S01 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Control extension page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.TCMOS)
|
||||
{
|
||||
sb.Append("\tTimestamp can be initialized by methods outside of the SCSI standards");
|
||||
|
||||
if(page.SCSIP) sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them");
|
||||
if(page.SCSIP)
|
||||
sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them");
|
||||
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
if(page.IALUAE) sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled");
|
||||
if(page.IALUAE)
|
||||
sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled");
|
||||
|
||||
sb.AppendFormat("\tInitial priority is {0}", page.InitialPriority).AppendLine();
|
||||
|
||||
if(page.DLC) sb.AppendLine("\tDevice will not degrade performance to extend its life");
|
||||
if(page.DLC)
|
||||
sb.AppendLine("\tDevice will not degrade performance to extend its life");
|
||||
|
||||
if(page.MaximumSenseLength > 0)
|
||||
sb.AppendFormat("\tMaximum sense data would be {0} bytes", page.MaximumSenseLength).AppendLine();
|
||||
|
||||
@@ -35,22 +35,15 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x0B: Medium types supported page
|
||||
/// <summary>
|
||||
/// Disconnect-reconnect page
|
||||
/// Page code 0x0B
|
||||
/// 8 bytes in SCSI-2
|
||||
/// </summary>
|
||||
/// <summary>Disconnect-reconnect page Page code 0x0B 8 bytes in SCSI-2</summary>
|
||||
public struct ModePage_0B
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public MediumTypes MediumType1;
|
||||
public MediumTypes MediumType2;
|
||||
@@ -60,15 +53,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static ModePage_0B? DecodeModePage_0B(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x0B) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x0B)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_0B decoded = new ModePage_0B();
|
||||
var decoded = new ModePage_0B();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.MediumType1 = (MediumTypes)pageResponse[4];
|
||||
@@ -84,27 +81,32 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0B(ModePage_0B? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0B page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_0B page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Medium types supported page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.MediumType1 != MediumTypes.Default)
|
||||
sb.AppendFormat("Supported medium type one: {0}", GetMediumTypeDescription(page.MediumType1))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Supported medium type one: {0}", GetMediumTypeDescription(page.MediumType1)).
|
||||
AppendLine();
|
||||
|
||||
if(page.MediumType2 != MediumTypes.Default)
|
||||
sb.AppendFormat("Supported medium type two: {0}", GetMediumTypeDescription(page.MediumType2))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Supported medium type two: {0}", GetMediumTypeDescription(page.MediumType2)).
|
||||
AppendLine();
|
||||
|
||||
if(page.MediumType3 != MediumTypes.Default)
|
||||
sb.AppendFormat("Supported medium type three: {0}", GetMediumTypeDescription(page.MediumType3))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Supported medium type three: {0}", GetMediumTypeDescription(page.MediumType3)).
|
||||
AppendLine();
|
||||
|
||||
if(page.MediumType4 != MediumTypes.Default)
|
||||
sb.AppendFormat("Supported medium type four: {0}", GetMediumTypeDescription(page.MediumType4))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("Supported medium type four: {0}", GetMediumTypeDescription(page.MediumType4)).
|
||||
AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,48 +35,39 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x0D: CD-ROM parameteres page
|
||||
/// <summary>
|
||||
/// CD-ROM parameteres page
|
||||
/// Page code 0x0D
|
||||
/// 8 bytes in SCSI-2, MMC-1, MMC-2, MMC-3
|
||||
/// </summary>
|
||||
/// <summary>CD-ROM parameteres page Page code 0x0D 8 bytes in SCSI-2, MMC-1, MMC-2, MMC-3</summary>
|
||||
public struct ModePage_0D
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Time the drive shall remain in hold track state after seek or read
|
||||
/// </summary>
|
||||
/// <summary>Time the drive shall remain in hold track state after seek or read</summary>
|
||||
public byte InactivityTimerMultiplier;
|
||||
/// <summary>
|
||||
/// Seconds per Minute
|
||||
/// </summary>
|
||||
/// <summary>Seconds per Minute</summary>
|
||||
public ushort SecondsPerMinute;
|
||||
/// <summary>
|
||||
/// Frames per Second
|
||||
/// </summary>
|
||||
/// <summary>Frames per Second</summary>
|
||||
public ushort FramesPerSecond;
|
||||
}
|
||||
|
||||
public static ModePage_0D? DecodeModePage_0D(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x0D) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x0D)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_0D decoded = new ModePage_0D();
|
||||
var decoded = new ModePage_0D();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.InactivityTimerMultiplier = (byte)(pageResponse[3] & 0xF);
|
||||
@@ -91,68 +82,88 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0D(ModePage_0D? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0D page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_0D page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI CD-ROM parameters page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.InactivityTimerMultiplier)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive will remain in track hold state a vendor-specified time after a seek or read");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 125 ms after a seek or read");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 250 ms after a seek or read");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 500 ms after a seek or read");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 1 second after a seek or read");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 2 seconds after a seek or read");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 4 seconds after a seek or read");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 8 seconds after a seek or read");
|
||||
|
||||
break;
|
||||
case 8:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 16 seconds after a seek or read");
|
||||
|
||||
break;
|
||||
case 9:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 32 seconds after a seek or read");
|
||||
|
||||
break;
|
||||
case 10:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 1 minute after a seek or read");
|
||||
|
||||
break;
|
||||
case 11:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 2 minutes after a seek or read");
|
||||
|
||||
break;
|
||||
case 12:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 4 minutes after a seek or read");
|
||||
|
||||
break;
|
||||
case 13:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 8 minutes after a seek or read");
|
||||
|
||||
break;
|
||||
case 14:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 16 minutes after a seek or read");
|
||||
|
||||
break;
|
||||
case 15:
|
||||
sb.AppendLine("\tDrive will remain in track hold state 32 minutes after a seek or read");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.SecondsPerMinute > 0)
|
||||
sb.AppendFormat("\tEach minute has {0} seconds", page.SecondsPerMinute).AppendLine();
|
||||
|
||||
if(page.FramesPerSecond > 0)
|
||||
sb.AppendFormat("\tEach second has {0} frames", page.FramesPerSecond).AppendLine();
|
||||
|
||||
|
||||
185
SCSI/Modes/0E.cs
185
SCSI/Modes/0E.cs
@@ -35,88 +35,59 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x0E: CD-ROM audio control parameters page
|
||||
/// <summary>
|
||||
/// CD-ROM audio control parameters
|
||||
/// Page code 0x0E
|
||||
/// 16 bytes in SCSI-2, MMC-1, MMC-2, MMC-3
|
||||
/// </summary>
|
||||
/// <summary>CD-ROM audio control parameters Page code 0x0E 16 bytes in SCSI-2, MMC-1, MMC-2, MMC-3</summary>
|
||||
public struct ModePage_0E
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Return status as soon as playback operation starts
|
||||
/// </summary>
|
||||
/// <summary>Return status as soon as playback operation starts</summary>
|
||||
public bool Immed;
|
||||
/// <summary>
|
||||
/// Stop on track crossing
|
||||
/// </summary>
|
||||
/// <summary>Stop on track crossing</summary>
|
||||
public bool SOTC;
|
||||
/// <summary>
|
||||
/// Indicates <see cref="BlocksPerSecondOfAudio" /> is valid
|
||||
/// </summary>
|
||||
/// <summary>Indicates <see cref="BlocksPerSecondOfAudio" /> is valid</summary>
|
||||
public bool APRVal;
|
||||
/// <summary>
|
||||
/// Multiplier for <see cref="BlocksPerSecondOfAudio" />
|
||||
/// </summary>
|
||||
/// <summary>Multiplier for <see cref="BlocksPerSecondOfAudio" /></summary>
|
||||
public byte LBAFormat;
|
||||
/// <summary>
|
||||
/// LBAs per second of audio
|
||||
/// </summary>
|
||||
/// <summary>LBAs per second of audio</summary>
|
||||
public ushort BlocksPerSecondOfAudio;
|
||||
/// <summary>
|
||||
/// Channels output on this port
|
||||
/// </summary>
|
||||
/// <summary>Channels output on this port</summary>
|
||||
public byte OutputPort0ChannelSelection;
|
||||
/// <summary>
|
||||
/// Volume level for this port
|
||||
/// </summary>
|
||||
/// <summary>Volume level for this port</summary>
|
||||
public byte OutputPort0Volume;
|
||||
/// <summary>
|
||||
/// Channels output on this port
|
||||
/// </summary>
|
||||
/// <summary>Channels output on this port</summary>
|
||||
public byte OutputPort1ChannelSelection;
|
||||
/// <summary>
|
||||
/// Volume level for this port
|
||||
/// </summary>
|
||||
/// <summary>Volume level for this port</summary>
|
||||
public byte OutputPort1Volume;
|
||||
/// <summary>
|
||||
/// Channels output on this port
|
||||
/// </summary>
|
||||
/// <summary>Channels output on this port</summary>
|
||||
public byte OutputPort2ChannelSelection;
|
||||
/// <summary>
|
||||
/// Volume level for this port
|
||||
/// </summary>
|
||||
/// <summary>Volume level for this port</summary>
|
||||
public byte OutputPort2Volume;
|
||||
/// <summary>
|
||||
/// Channels output on this port
|
||||
/// </summary>
|
||||
/// <summary>Channels output on this port</summary>
|
||||
public byte OutputPort3ChannelSelection;
|
||||
/// <summary>
|
||||
/// Volume level for this port
|
||||
/// </summary>
|
||||
/// <summary>Volume level for this port</summary>
|
||||
public byte OutputPort3Volume;
|
||||
}
|
||||
|
||||
public static ModePage_0E? DecodeModePage_0E(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x0E) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x0E)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_0E decoded = new ModePage_0E();
|
||||
var decoded = new ModePage_0E();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.Immed |= (pageResponse[2] & 0x04) == 0x04;
|
||||
@@ -141,24 +112,31 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0E(ModePage_0E? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0E page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_0E page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI CD-ROM audio control parameters page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
sb.AppendLine(page.Immed
|
||||
? "\tDrive will return from playback command immediately"
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendLine(page.Immed ? "\tDrive will return from playback command immediately"
|
||||
: "\tDrive will return from playback command when playback ends");
|
||||
if(page.SOTC) sb.AppendLine("\tDrive will stop playback on track end");
|
||||
|
||||
if(page.SOTC)
|
||||
sb.AppendLine("\tDrive will stop playback on track end");
|
||||
|
||||
if(page.APRVal)
|
||||
{
|
||||
double blocks;
|
||||
if(page.LBAFormat == 8) blocks = page.BlocksPerSecondOfAudio * (1 / 256);
|
||||
else blocks = page.BlocksPerSecondOfAudio;
|
||||
|
||||
if(page.LBAFormat == 8)
|
||||
blocks = page.BlocksPerSecondOfAudio * (1 / 256);
|
||||
else
|
||||
blocks = page.BlocksPerSecondOfAudio;
|
||||
|
||||
sb.AppendFormat("\tThere are {0} blocks per each second of audio", blocks).AppendLine();
|
||||
}
|
||||
@@ -166,21 +144,32 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(page.OutputPort0ChannelSelection > 0)
|
||||
{
|
||||
sb.Append("\tOutput port 0 has channels ");
|
||||
if((page.OutputPort0ChannelSelection & 0x01) == 0x01) sb.Append("0 ");
|
||||
if((page.OutputPort0ChannelSelection & 0x02) == 0x02) sb.Append("1 ");
|
||||
if((page.OutputPort0ChannelSelection & 0x04) == 0x04) sb.Append("2 ");
|
||||
if((page.OutputPort0ChannelSelection & 0x08) == 0x08) sb.Append("3 ");
|
||||
|
||||
if((page.OutputPort0ChannelSelection & 0x01) == 0x01)
|
||||
sb.Append("0 ");
|
||||
|
||||
if((page.OutputPort0ChannelSelection & 0x02) == 0x02)
|
||||
sb.Append("1 ");
|
||||
|
||||
if((page.OutputPort0ChannelSelection & 0x04) == 0x04)
|
||||
sb.Append("2 ");
|
||||
|
||||
if((page.OutputPort0ChannelSelection & 0x08) == 0x08)
|
||||
sb.Append("3 ");
|
||||
|
||||
switch(page.OutputPort0Volume)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("muted");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("at maximum volume");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("at volume {0}", page.OutputPort0Volume).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -188,21 +177,32 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(page.OutputPort1ChannelSelection > 0)
|
||||
{
|
||||
sb.Append("\tOutput port 1 has channels ");
|
||||
if((page.OutputPort1ChannelSelection & 0x01) == 0x01) sb.Append("0 ");
|
||||
if((page.OutputPort1ChannelSelection & 0x02) == 0x02) sb.Append("1 ");
|
||||
if((page.OutputPort1ChannelSelection & 0x04) == 0x04) sb.Append("2 ");
|
||||
if((page.OutputPort1ChannelSelection & 0x08) == 0x08) sb.Append("3 ");
|
||||
|
||||
if((page.OutputPort1ChannelSelection & 0x01) == 0x01)
|
||||
sb.Append("0 ");
|
||||
|
||||
if((page.OutputPort1ChannelSelection & 0x02) == 0x02)
|
||||
sb.Append("1 ");
|
||||
|
||||
if((page.OutputPort1ChannelSelection & 0x04) == 0x04)
|
||||
sb.Append("2 ");
|
||||
|
||||
if((page.OutputPort1ChannelSelection & 0x08) == 0x08)
|
||||
sb.Append("3 ");
|
||||
|
||||
switch(page.OutputPort1Volume)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("muted");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("at maximum volume");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("at volume {0}", page.OutputPort1Volume).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -210,43 +210,66 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(page.OutputPort2ChannelSelection > 0)
|
||||
{
|
||||
sb.Append("\tOutput port 2 has channels ");
|
||||
if((page.OutputPort2ChannelSelection & 0x01) == 0x01) sb.Append("0 ");
|
||||
if((page.OutputPort2ChannelSelection & 0x02) == 0x02) sb.Append("1 ");
|
||||
if((page.OutputPort2ChannelSelection & 0x04) == 0x04) sb.Append("2 ");
|
||||
if((page.OutputPort2ChannelSelection & 0x08) == 0x08) sb.Append("3 ");
|
||||
|
||||
if((page.OutputPort2ChannelSelection & 0x01) == 0x01)
|
||||
sb.Append("0 ");
|
||||
|
||||
if((page.OutputPort2ChannelSelection & 0x02) == 0x02)
|
||||
sb.Append("1 ");
|
||||
|
||||
if((page.OutputPort2ChannelSelection & 0x04) == 0x04)
|
||||
sb.Append("2 ");
|
||||
|
||||
if((page.OutputPort2ChannelSelection & 0x08) == 0x08)
|
||||
sb.Append("3 ");
|
||||
|
||||
switch(page.OutputPort2Volume)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("muted");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("at maximum volume");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("at volume {0}", page.OutputPort2Volume).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(page.OutputPort3ChannelSelection <= 0) return sb.ToString();
|
||||
if(page.OutputPort3ChannelSelection <= 0)
|
||||
return sb.ToString();
|
||||
|
||||
sb.Append("\tOutput port 3 has channels ");
|
||||
if((page.OutputPort3ChannelSelection & 0x01) == 0x01) sb.Append("0 ");
|
||||
if((page.OutputPort3ChannelSelection & 0x02) == 0x02) sb.Append("1 ");
|
||||
if((page.OutputPort3ChannelSelection & 0x04) == 0x04) sb.Append("2 ");
|
||||
if((page.OutputPort3ChannelSelection & 0x08) == 0x08) sb.Append("3 ");
|
||||
|
||||
if((page.OutputPort3ChannelSelection & 0x01) == 0x01)
|
||||
sb.Append("0 ");
|
||||
|
||||
if((page.OutputPort3ChannelSelection & 0x02) == 0x02)
|
||||
sb.Append("1 ");
|
||||
|
||||
if((page.OutputPort3ChannelSelection & 0x04) == 0x04)
|
||||
sb.Append("2 ");
|
||||
|
||||
if((page.OutputPort3ChannelSelection & 0x08) == 0x08)
|
||||
sb.Append("3 ");
|
||||
|
||||
switch(page.OutputPort3Volume)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("muted");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("at maximum volume");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("at volume {0}", page.OutputPort3Volume).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,60 +35,45 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x0F: Data compression page
|
||||
/// <summary>
|
||||
/// Data compression page
|
||||
/// Page code 0x0F
|
||||
/// 16 bytes in SSC-1, SSC-2, SSC-3
|
||||
/// </summary>
|
||||
/// <summary>Data compression page Page code 0x0F 16 bytes in SSC-1, SSC-2, SSC-3</summary>
|
||||
public struct ModePage_0F
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Data compression enabled
|
||||
/// </summary>
|
||||
/// <summary>Data compression enabled</summary>
|
||||
public bool DCE;
|
||||
/// <summary>
|
||||
/// Data compression capable
|
||||
/// </summary>
|
||||
/// <summary>Data compression capable</summary>
|
||||
public bool DCC;
|
||||
/// <summary>
|
||||
/// Data decompression enabled
|
||||
/// </summary>
|
||||
/// <summary>Data decompression enabled</summary>
|
||||
public bool DDE;
|
||||
/// <summary>
|
||||
/// Report exception on decompression
|
||||
/// </summary>
|
||||
/// <summary>Report exception on decompression</summary>
|
||||
public byte RED;
|
||||
/// <summary>
|
||||
/// Compression algorithm
|
||||
/// </summary>
|
||||
/// <summary>Compression algorithm</summary>
|
||||
public uint CompressionAlgo;
|
||||
/// <summary>
|
||||
/// Decompression algorithm
|
||||
/// </summary>
|
||||
/// <summary>Decompression algorithm</summary>
|
||||
public uint DecompressionAlgo;
|
||||
}
|
||||
|
||||
public static ModePage_0F? DecodeModePage_0F(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x0F) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x0F)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_0F decoded = new ModePage_0F();
|
||||
var decoded = new ModePage_0F();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -99,6 +84,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.CompressionAlgo = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) +
|
||||
(pageResponse[6] << 8) + pageResponse[7]);
|
||||
|
||||
decoded.DecompressionAlgo = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) +
|
||||
(pageResponse[10] << 8) + pageResponse[11]);
|
||||
|
||||
@@ -110,43 +96,54 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_0F(ModePage_0F? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_0F page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_0F page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Data compression page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.DCC)
|
||||
{
|
||||
sb.AppendLine("\tDrive supports data compression");
|
||||
|
||||
if(page.DCE)
|
||||
{
|
||||
sb.Append("\tData compression is enabled with ");
|
||||
|
||||
switch(page.CompressionAlgo)
|
||||
{
|
||||
case 3:
|
||||
sb.AppendLine("IBM ALDC with 512 byte buffer");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("IBM ALDC with 1024 byte buffer");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("IBM ALDC with 2048 byte buffer");
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine("IBM IDRC");
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine("DCLZ");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("an unregistered compression algorithm");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -154,32 +151,42 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(page.DDE)
|
||||
{
|
||||
sb.AppendLine("\tData decompression is enabled");
|
||||
if(page.DecompressionAlgo == 0) sb.AppendLine("\tLast data read was uncompressed");
|
||||
|
||||
if(page.DecompressionAlgo == 0)
|
||||
sb.AppendLine("\tLast data read was uncompressed");
|
||||
else
|
||||
{
|
||||
sb.Append("\tLast data read was compressed with ");
|
||||
|
||||
switch(page.CompressionAlgo)
|
||||
{
|
||||
case 3:
|
||||
sb.AppendLine("IBM ALDC with 512 byte buffer");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("IBM ALDC with 1024 byte buffer");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("IBM ALDC with 2048 byte buffer");
|
||||
|
||||
break;
|
||||
case 0x10:
|
||||
sb.AppendLine("IBM IDRC");
|
||||
|
||||
break;
|
||||
case 0x20:
|
||||
sb.AppendLine("DCLZ");
|
||||
|
||||
break;
|
||||
case 0xFF:
|
||||
sb.AppendLine("an unregistered compression algorithm");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -187,7 +194,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
sb.AppendFormat("\tReport exception on compression is set to {0}", page.RED).AppendLine();
|
||||
}
|
||||
else sb.AppendLine("\tDrive does not support data compression");
|
||||
else
|
||||
sb.AppendLine("\tDrive does not support data compression");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,66 +35,57 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x10: XOR control mode page
|
||||
/// <summary>
|
||||
/// XOR control mode page
|
||||
/// Page code 0x10
|
||||
/// 24 bytes in SBC-1, SBC-2
|
||||
/// </summary>
|
||||
/// <summary>XOR control mode page Page code 0x10 24 bytes in SBC-1, SBC-2</summary>
|
||||
public struct ModePage_10
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Disables XOR operations
|
||||
/// </summary>
|
||||
/// <summary>Disables XOR operations</summary>
|
||||
public bool XORDIS;
|
||||
/// <summary>
|
||||
/// Maximum transfer length in blocks for a XOR command
|
||||
/// </summary>
|
||||
/// <summary>Maximum transfer length in blocks for a XOR command</summary>
|
||||
public uint MaxXorWrite;
|
||||
/// <summary>
|
||||
/// Maximum regenerate length in blocks
|
||||
/// </summary>
|
||||
/// <summary>Maximum regenerate length in blocks</summary>
|
||||
public uint MaxRegenSize;
|
||||
/// <summary>
|
||||
/// Maximum transfer length in blocks for READ during a rebuild
|
||||
/// </summary>
|
||||
/// <summary>Maximum transfer length in blocks for READ during a rebuild</summary>
|
||||
public uint MaxRebuildRead;
|
||||
/// <summary>
|
||||
/// Minimum time in ms between READs during a rebuild
|
||||
/// </summary>
|
||||
/// <summary>Minimum time in ms between READs during a rebuild</summary>
|
||||
public ushort RebuildDelay;
|
||||
}
|
||||
|
||||
public static ModePage_10? DecodeModePage_10(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x10) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x10)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 24) return null;
|
||||
if(pageResponse.Length < 24)
|
||||
return null;
|
||||
|
||||
ModePage_10 decoded = new ModePage_10();
|
||||
var decoded = new ModePage_10();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
decoded.XORDIS |= (pageResponse[2] & 0x02) == 0x02;
|
||||
|
||||
decoded.MaxXorWrite = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) +
|
||||
pageResponse[7]);
|
||||
|
||||
decoded.MaxRegenSize = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) +
|
||||
(pageResponse[14] << 8) + pageResponse[15]);
|
||||
|
||||
decoded.MaxRebuildRead = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) +
|
||||
(pageResponse[18] << 8) + pageResponse[19]);
|
||||
|
||||
decoded.RebuildDelay = (ushort)((pageResponse[22] << 8) + pageResponse[23]);
|
||||
|
||||
return decoded;
|
||||
@@ -105,27 +96,33 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_10(ModePage_10? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_10 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_10 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI XOR control mode page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.XORDIS) sb.AppendLine("\tXOR operations are disabled");
|
||||
if(page.XORDIS)
|
||||
sb.AppendLine("\tXOR operations are disabled");
|
||||
else
|
||||
{
|
||||
if(page.MaxXorWrite > 0)
|
||||
sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a single XOR WRITE command",
|
||||
page.MaxXorWrite).AppendLine();
|
||||
|
||||
if(page.MaxRegenSize > 0)
|
||||
sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a REGENERATE command",
|
||||
page.MaxRegenSize).AppendLine();
|
||||
|
||||
if(page.MaxRebuildRead > 0)
|
||||
sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a READ command during rebuild",
|
||||
page.MaxRebuildRead).AppendLine();
|
||||
|
||||
if(page.RebuildDelay > 0)
|
||||
sb.AppendFormat("\tDrive needs a minimum of {0} ms between READ commands during rebuild",
|
||||
page.RebuildDelay).AppendLine();
|
||||
|
||||
@@ -35,146 +35,91 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x10: Device configuration page
|
||||
/// <summary>
|
||||
/// Device configuration page
|
||||
/// Page code 0x10
|
||||
/// 16 bytes in SCSI-2, SSC-1, SSC-2, SSC-3
|
||||
/// </summary>
|
||||
/// <summary>Device configuration page Page code 0x10 16 bytes in SCSI-2, SSC-1, SSC-2, SSC-3</summary>
|
||||
public struct ModePage_10_SSC
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Used in mode select to change partition to one specified in <see cref="ActivePartition" />
|
||||
/// </summary>
|
||||
/// <summary>Used in mode select to change partition to one specified in <see cref="ActivePartition" /></summary>
|
||||
public bool CAP;
|
||||
/// <summary>
|
||||
/// Used in mode select to change format to one specified in <see cref="ActiveFormat" />
|
||||
/// </summary>
|
||||
/// <summary>Used in mode select to change format to one specified in <see cref="ActiveFormat" /></summary>
|
||||
public bool CAF;
|
||||
/// <summary>
|
||||
/// Active format, vendor-specific
|
||||
/// </summary>
|
||||
/// <summary>Active format, vendor-specific</summary>
|
||||
public byte ActiveFormat;
|
||||
/// <summary>
|
||||
/// Current logical partition
|
||||
/// </summary>
|
||||
/// <summary>Current logical partition</summary>
|
||||
public byte ActivePartition;
|
||||
/// <summary>
|
||||
/// How full the buffer shall be before writing to medium
|
||||
/// </summary>
|
||||
/// <summary>How full the buffer shall be before writing to medium</summary>
|
||||
public byte WriteBufferFullRatio;
|
||||
/// <summary>
|
||||
/// How empty the buffer shall be before reading more data from the medium
|
||||
/// </summary>
|
||||
/// <summary>How empty the buffer shall be before reading more data from the medium</summary>
|
||||
public byte ReadBufferEmptyRatio;
|
||||
/// <summary>
|
||||
/// Delay in 100 ms before buffered data is forcefully written to the medium even before buffer is full
|
||||
/// </summary>
|
||||
/// <summary>Delay in 100 ms before buffered data is forcefully written to the medium even before buffer is full</summary>
|
||||
public ushort WriteDelayTime;
|
||||
/// <summary>
|
||||
/// Drive supports recovering data from buffer
|
||||
/// </summary>
|
||||
/// <summary>Drive supports recovering data from buffer</summary>
|
||||
public bool DBR;
|
||||
/// <summary>
|
||||
/// Medium has block IDs
|
||||
/// </summary>
|
||||
/// <summary>Medium has block IDs</summary>
|
||||
public bool BIS;
|
||||
/// <summary>
|
||||
/// Drive recognizes and reports setmarks
|
||||
/// </summary>
|
||||
/// <summary>Drive recognizes and reports setmarks</summary>
|
||||
public bool RSmk;
|
||||
/// <summary>
|
||||
/// Drive selects best speed
|
||||
/// </summary>
|
||||
/// <summary>Drive selects best speed</summary>
|
||||
public bool AVC;
|
||||
/// <summary>
|
||||
/// If drive should stop pre-reading on filemarks
|
||||
/// </summary>
|
||||
/// <summary>If drive should stop pre-reading on filemarks</summary>
|
||||
public byte SOCF;
|
||||
/// <summary>
|
||||
/// If set, recovered buffer data is LIFO, otherwise, FIFO
|
||||
/// </summary>
|
||||
/// <summary>If set, recovered buffer data is LIFO, otherwise, FIFO</summary>
|
||||
public bool RBO;
|
||||
/// <summary>
|
||||
/// Report early warnings
|
||||
/// </summary>
|
||||
/// <summary>Report early warnings</summary>
|
||||
public bool REW;
|
||||
/// <summary>
|
||||
/// Inter-block gap
|
||||
/// </summary>
|
||||
/// <summary>Inter-block gap</summary>
|
||||
public byte GapSize;
|
||||
/// <summary>
|
||||
/// End-of-Data format
|
||||
/// </summary>
|
||||
/// <summary>End-of-Data format</summary>
|
||||
public byte EODDefined;
|
||||
/// <summary>
|
||||
/// EOD generation enabled
|
||||
/// </summary>
|
||||
/// <summary>EOD generation enabled</summary>
|
||||
public bool EEG;
|
||||
/// <summary>
|
||||
/// Synchronize data to medium on early warning
|
||||
/// </summary>
|
||||
/// <summary>Synchronize data to medium on early warning</summary>
|
||||
public bool SEW;
|
||||
/// <summary>
|
||||
/// Bytes to reduce buffer size on early warning
|
||||
/// </summary>
|
||||
/// <summary>Bytes to reduce buffer size on early warning</summary>
|
||||
public uint BufferSizeEarlyWarning;
|
||||
/// <summary>
|
||||
/// Selected data compression algorithm
|
||||
/// </summary>
|
||||
/// <summary>Selected data compression algorithm</summary>
|
||||
public byte SelectedCompression;
|
||||
|
||||
/// <summary>
|
||||
/// Soft write protect
|
||||
/// </summary>
|
||||
/// <summary>Soft write protect</summary>
|
||||
public bool SWP;
|
||||
/// <summary>
|
||||
/// Associated write protect
|
||||
/// </summary>
|
||||
/// <summary>Associated write protect</summary>
|
||||
public bool ASOCWP;
|
||||
/// <summary>
|
||||
/// Persistent write protect
|
||||
/// </summary>
|
||||
/// <summary>Persistent write protect</summary>
|
||||
public bool PERSWP;
|
||||
/// <summary>
|
||||
/// Permanent write protect
|
||||
/// </summary>
|
||||
/// <summary>Permanent write protect</summary>
|
||||
public bool PRMWP;
|
||||
|
||||
public bool BAML;
|
||||
public bool BAM;
|
||||
public byte RewindOnReset;
|
||||
|
||||
/// <summary>
|
||||
/// How drive shall respond to detection of compromised WORM medium integrity
|
||||
/// </summary>
|
||||
/// <summary>How drive shall respond to detection of compromised WORM medium integrity</summary>
|
||||
public byte WTRE;
|
||||
/// <summary>
|
||||
/// Respond to commands only if a reservation exists
|
||||
/// </summary>
|
||||
/// <summary>Respond to commands only if a reservation exists</summary>
|
||||
public bool OIR;
|
||||
}
|
||||
|
||||
public static ModePage_10_SSC? DecodeModePage_10_SSC(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x10) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x10)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_10_SSC decoded = new ModePage_10_SSC();
|
||||
var decoded = new ModePage_10_SSC();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.CAP |= (pageResponse[2] & 0x40) == 0x40;
|
||||
@@ -193,8 +138,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
decoded.EEG |= (pageResponse[10] & 0x10) == 0x10;
|
||||
decoded.SEW |= (pageResponse[10] & 0x08) == 0x08;
|
||||
decoded.SOCF = (byte)((pageResponse[8] & 0x0C) >> 2);
|
||||
|
||||
decoded.BufferSizeEarlyWarning =
|
||||
(uint)((pageResponse[11] << 16) + (pageResponse[12] << 8) + pageResponse[13]);
|
||||
|
||||
decoded.SelectedCompression = pageResponse[14];
|
||||
|
||||
decoded.SWP |= (pageResponse[10] & 0x04) == 0x04;
|
||||
@@ -218,54 +165,70 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_10_SSC(ModePage_10_SSC? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_10_SSC page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Device configuration page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\tActive format: {0}", page.ActiveFormat).AppendLine();
|
||||
sb.AppendFormat("\tActive partition: {0}", page.ActivePartition).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tWrite buffer shall have a full ratio of {0} before being flushed to medium",
|
||||
page.WriteBufferFullRatio).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tRead buffer shall have an empty ratio of {0} before more data is read from medium",
|
||||
page.ReadBufferEmptyRatio).AppendLine();
|
||||
sb
|
||||
.AppendFormat("\tDrive will delay {0} ms before buffered data is forcefully written to the medium even before buffer is full",
|
||||
|
||||
sb.
|
||||
AppendFormat("\tDrive will delay {0} ms before buffered data is forcefully written to the medium even before buffer is full",
|
||||
page.WriteDelayTime * 100).AppendLine();
|
||||
|
||||
if(page.DBR)
|
||||
{
|
||||
sb.AppendLine("\tDrive supports recovering data from buffer");
|
||||
sb.AppendLine(page.RBO
|
||||
? "\tRecovered buffer data comes in LIFO order"
|
||||
|
||||
sb.AppendLine(page.RBO ? "\tRecovered buffer data comes in LIFO order"
|
||||
: "\tRecovered buffer data comes in FIFO order");
|
||||
}
|
||||
|
||||
if(page.BIS) sb.AppendLine("\tMedium supports block IDs");
|
||||
if(page.RSmk) sb.AppendLine("\tDrive reports setmarks");
|
||||
if(page.BIS)
|
||||
sb.AppendLine("\tMedium supports block IDs");
|
||||
|
||||
if(page.RSmk)
|
||||
sb.AppendLine("\tDrive reports setmarks");
|
||||
|
||||
switch(page.SOCF)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive will pre-read until buffer is full");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will pre-read until one filemark is detected");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive will pre-read until two filemark is detected");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDrive will pre-read until three filemark is detected");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.REW)
|
||||
{
|
||||
sb.AppendLine("\tDrive reports early warnings");
|
||||
if(page.SEW) sb.AppendLine("\tDrive will synchronize buffer to medium on early warnings");
|
||||
|
||||
if(page.SEW)
|
||||
sb.AppendLine("\tDrive will synchronize buffer to medium on early warnings");
|
||||
}
|
||||
|
||||
switch(page.GapSize)
|
||||
@@ -273,6 +236,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case 0: break;
|
||||
case 1:
|
||||
sb.AppendLine("\tInter-block gap is long enough to support update in place");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
@@ -288,46 +252,60 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
sb.AppendFormat("\tInter-block gap is {0} times the device's defined gap size", page.GapSize)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tInter-block gap is {0} times the device's defined gap size", page.GapSize).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tInter-block gap is unknown value {0}", page.GapSize).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.EEG) sb.AppendLine("\tDrive generates end-of-data");
|
||||
if(page.EEG)
|
||||
sb.AppendLine("\tDrive generates end-of-data");
|
||||
|
||||
switch(page.SelectedCompression)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive does not use compression");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive uses default compression");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDrive uses unknown compression {0}", page.SelectedCompression).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.SWP) sb.AppendLine("\tSoftware write protect is enabled");
|
||||
if(page.ASOCWP) sb.AppendLine("\tAssociated write protect is enabled");
|
||||
if(page.PERSWP) sb.AppendLine("\tPersistent write protect is enabled");
|
||||
if(page.PRMWP) sb.AppendLine("\tPermanent write protect is enabled");
|
||||
if(page.SWP)
|
||||
sb.AppendLine("\tSoftware write protect is enabled");
|
||||
|
||||
if(page.ASOCWP)
|
||||
sb.AppendLine("\tAssociated write protect is enabled");
|
||||
|
||||
if(page.PERSWP)
|
||||
sb.AppendLine("\tPersistent write protect is enabled");
|
||||
|
||||
if(page.PRMWP)
|
||||
sb.AppendLine("\tPermanent write protect is enabled");
|
||||
|
||||
if(page.BAML)
|
||||
sb.AppendLine(page.BAM
|
||||
? "\tDrive operates using explicit address mode"
|
||||
sb.AppendLine(page.BAM ? "\tDrive operates using explicit address mode"
|
||||
: "\tDrive operates using implicit address mode");
|
||||
|
||||
switch(page.RewindOnReset)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive shall position to beginning of default data partition on reset");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive shall maintain its position on reset");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -335,13 +313,16 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will do nothing on WORM tampered medium");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive will return CHECK CONDITION on WORM tampered medium");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.OIR) sb.AppendLine("\tDrive will only respond to commands if it has received a reservation");
|
||||
if(page.OIR)
|
||||
sb.AppendLine("\tDrive will only respond to commands if it has received a reservation");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
149
SCSI/Modes/11.cs
149
SCSI/Modes/11.cs
@@ -36,111 +36,71 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x11: Medium partition page (1)
|
||||
public enum PartitionSizeUnitOfMeasures : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Partition size is measures in bytes
|
||||
/// </summary>
|
||||
Bytes = 0,
|
||||
/// <summary>
|
||||
/// Partition size is measures in Kilobytes
|
||||
/// </summary>
|
||||
Kilobytes = 1,
|
||||
/// <summary>
|
||||
/// Partition size is measures in Megabytes
|
||||
/// </summary>
|
||||
Megabytes = 2,
|
||||
/// <summary>
|
||||
/// Partition size is 10eUNITS bytes
|
||||
/// </summary>
|
||||
/// <summary>Partition size is measures in bytes</summary>
|
||||
Bytes = 0, /// <summary>Partition size is measures in Kilobytes</summary>
|
||||
Kilobytes = 1, /// <summary>Partition size is measures in Megabytes</summary>
|
||||
Megabytes = 2, /// <summary>Partition size is 10eUNITS bytes</summary>
|
||||
Exponential = 3
|
||||
}
|
||||
|
||||
public enum MediumFormatRecognitionValues : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical unit is incapable of format or partition recognition
|
||||
/// </summary>
|
||||
Incapable = 0,
|
||||
/// <summary>
|
||||
/// Logical unit is capable of format recognition only
|
||||
/// </summary>
|
||||
FormatCapable = 1,
|
||||
/// <summary>
|
||||
/// Logical unit is capable of partition recognition only
|
||||
/// </summary>
|
||||
PartitionCapable = 2,
|
||||
/// <summary>
|
||||
/// Logical unit is capable of both format and partition recognition
|
||||
/// </summary>
|
||||
/// <summary>Logical unit is incapable of format or partition recognition</summary>
|
||||
Incapable = 0, /// <summary>Logical unit is capable of format recognition only</summary>
|
||||
FormatCapable = 1, /// <summary>Logical unit is capable of partition recognition only</summary>
|
||||
PartitionCapable = 2, /// <summary>Logical unit is capable of both format and partition recognition</summary>
|
||||
Capable = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Medium partition page(1)
|
||||
/// Page code 0x11
|
||||
/// </summary>
|
||||
/// <summary>Medium partition page(1) Page code 0x11</summary>
|
||||
public struct ModePage_11
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Maximum number of additional partitions supported
|
||||
/// </summary>
|
||||
/// <summary>Maximum number of additional partitions supported</summary>
|
||||
public byte MaxAdditionalPartitions;
|
||||
/// <summary>
|
||||
/// Number of additional partitions to be defined for a volume
|
||||
/// </summary>
|
||||
/// <summary>Number of additional partitions to be defined for a volume</summary>
|
||||
public byte AdditionalPartitionsDefined;
|
||||
/// <summary>
|
||||
/// Device defines partitions based on its fixed definition
|
||||
/// </summary>
|
||||
/// <summary>Device defines partitions based on its fixed definition</summary>
|
||||
public bool FDP;
|
||||
/// <summary>
|
||||
/// Device should divide medium according to the additional partitions defined field using sizes defined by device
|
||||
/// </summary>
|
||||
/// <summary>Device should divide medium according to the additional partitions defined field using sizes defined by device</summary>
|
||||
public bool SDP;
|
||||
/// <summary>
|
||||
/// Initiator defines number and size of partitions
|
||||
/// </summary>
|
||||
/// <summary>Initiator defines number and size of partitions</summary>
|
||||
public bool IDP;
|
||||
/// <summary>
|
||||
/// Defines the unit on which the partition sizes are defined
|
||||
/// </summary>
|
||||
/// <summary>Defines the unit on which the partition sizes are defined</summary>
|
||||
public PartitionSizeUnitOfMeasures PSUM;
|
||||
public bool POFM;
|
||||
public bool CLEAR;
|
||||
public bool ADDP;
|
||||
/// <summary>
|
||||
/// Defines the capabilities for the unit to recognize media partitions and format
|
||||
/// </summary>
|
||||
/// <summary>Defines the capabilities for the unit to recognize media partitions and format</summary>
|
||||
public MediumFormatRecognitionValues MediumFormatRecognition;
|
||||
public byte PartitionUnits;
|
||||
/// <summary>
|
||||
/// Array of partition sizes in units defined above
|
||||
/// </summary>
|
||||
/// <summary>Array of partition sizes in units defined above</summary>
|
||||
public ushort[] PartitionSizes;
|
||||
}
|
||||
|
||||
public static ModePage_11? DecodeModePage_11(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x11) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x11)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_11 decoded = new ModePage_11();
|
||||
var decoded = new ModePage_11();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -171,30 +131,42 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_11(ModePage_11? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_11 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_11 page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI medium partition page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\t{0} maximum additional partitions", page.MaxAdditionalPartitions).AppendLine();
|
||||
sb.AppendFormat("\t{0} additional partitions defined", page.AdditionalPartitionsDefined).AppendLine();
|
||||
|
||||
if(page.FDP) sb.AppendLine("\tPartitions are fixed under device definitions");
|
||||
if(page.SDP) sb.AppendLine("\tNumber of partitions can be defined but their size is defined by the device");
|
||||
if(page.IDP) sb.AppendLine("\tNumber and size of partitions can be manually defined");
|
||||
if(page.FDP)
|
||||
sb.AppendLine("\tPartitions are fixed under device definitions");
|
||||
|
||||
if(page.SDP)
|
||||
sb.AppendLine("\tNumber of partitions can be defined but their size is defined by the device");
|
||||
|
||||
if(page.IDP)
|
||||
sb.AppendLine("\tNumber and size of partitions can be manually defined");
|
||||
|
||||
if(page.POFM)
|
||||
sb.AppendLine("\tPartition parameters will not be applied until a FORMAT MEDIUM command is received");
|
||||
if(!page.CLEAR && !page.ADDP)
|
||||
|
||||
if(!page.CLEAR &&
|
||||
!page.ADDP)
|
||||
sb.AppendLine("\tDevice may erase any or all partitions on MODE SELECT for partitioning");
|
||||
else if(page.CLEAR && !page.ADDP)
|
||||
else if(page.CLEAR &&
|
||||
!page.ADDP)
|
||||
sb.AppendLine("\tDevice shall erase all partitions on MODE SELECT for partitioning");
|
||||
else if(!page.CLEAR)
|
||||
sb.AppendLine("\tDevice shall not erase any partition on MODE SELECT for partitioning");
|
||||
else sb.AppendLine("\tDevice shall erase all partitions differing on size on MODE SELECT for partitioning");
|
||||
else
|
||||
sb.AppendLine("\tDevice shall erase all partitions differing on size on MODE SELECT for partitioning");
|
||||
|
||||
string measure;
|
||||
|
||||
@@ -203,23 +175,29 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case PartitionSizeUnitOfMeasures.Bytes:
|
||||
sb.AppendLine("\tPartitions are defined in bytes");
|
||||
measure = "bytes";
|
||||
|
||||
break;
|
||||
case PartitionSizeUnitOfMeasures.Kilobytes:
|
||||
sb.AppendLine("\tPartitions are defined in kilobytes");
|
||||
measure = "kilobytes";
|
||||
|
||||
break;
|
||||
case PartitionSizeUnitOfMeasures.Megabytes:
|
||||
sb.AppendLine("\tPartitions are defined in megabytes");
|
||||
measure = "megabytes";
|
||||
|
||||
break;
|
||||
case PartitionSizeUnitOfMeasures.Exponential:
|
||||
sb.AppendFormat("\tPartitions are defined in units of {0} bytes", Math.Pow(10, page.PartitionUnits))
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tPartitions are defined in units of {0} bytes",
|
||||
Math.Pow(10, page.PartitionUnits)).AppendLine();
|
||||
|
||||
measure = $"units of {Math.Pow(10, page.PartitionUnits)} bytes";
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown partition size unit code {0}", (byte)page.PSUM).AppendLine();
|
||||
measure = "units";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -227,19 +205,24 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case MediumFormatRecognitionValues.Capable:
|
||||
sb.AppendLine("\tDevice is capable of recognizing both medium partitions and format");
|
||||
|
||||
break;
|
||||
case MediumFormatRecognitionValues.FormatCapable:
|
||||
sb.AppendLine("\tDevice is capable of recognizing medium format");
|
||||
|
||||
break;
|
||||
case MediumFormatRecognitionValues.PartitionCapable:
|
||||
sb.AppendLine("\tDevice is capable of recognizing medium partitions");
|
||||
|
||||
break;
|
||||
case MediumFormatRecognitionValues.Incapable:
|
||||
sb.AppendLine("\tDevice is not capable of recognizing neither medium partitions nor format");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown medium recognition code {0}", (byte)page.MediumFormatRecognition)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tUnknown medium recognition code {0}", (byte)page.MediumFormatRecognition).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,42 +35,40 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Pages 0x12, 0x13, 0x14: Medium partition page (2-4)
|
||||
/// <summary>
|
||||
/// Medium partition page (2-4)
|
||||
/// Page codes 0x12, 0x13 and 0x14
|
||||
/// </summary>
|
||||
/// <summary>Medium partition page (2-4) Page codes 0x12, 0x13 and 0x14</summary>
|
||||
public struct ModePage_12_13_14
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Array of partition sizes in units defined in mode page 11
|
||||
/// </summary>
|
||||
/// <summary>Array of partition sizes in units defined in mode page 11</summary>
|
||||
public ushort[] PartitionSizes;
|
||||
}
|
||||
|
||||
public static ModePage_12_13_14? DecodeModePage_12_13_14(byte[] pageResponse)
|
||||
{
|
||||
if(pageResponse == null) return null;
|
||||
if(pageResponse == null)
|
||||
return null;
|
||||
|
||||
if((pageResponse[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse[0] & 0x3F) != 0x12 && (pageResponse[0] & 0x3F) != 0x13 &&
|
||||
(pageResponse[0] & 0x3F) != 0x14) return null;
|
||||
if((pageResponse[0] & 0x3F) != 0x12 &&
|
||||
(pageResponse[0] & 0x3F) != 0x13 &&
|
||||
(pageResponse[0] & 0x3F) != 0x14)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 2) return null;
|
||||
if(pageResponse.Length < 2)
|
||||
return null;
|
||||
|
||||
ModePage_12_13_14 decoded = new ModePage_12_13_14();
|
||||
var decoded = new ModePage_12_13_14();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -90,14 +88,16 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_12_13_14(ModePage_12_13_14? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_12_13_14 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI medium partition page (extra):");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\tMedium has defined {0} partitions", page.PartitionSizes.Length).AppendLine();
|
||||
|
||||
|
||||
170
SCSI/Modes/1A.cs
170
SCSI/Modes/1A.cs
@@ -35,68 +35,38 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x1A: Power condition page
|
||||
/// <summary>
|
||||
/// Power condition page
|
||||
/// Page code 0x1A
|
||||
/// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4
|
||||
/// 40 bytes in SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Power condition page Page code 0x1A 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 40 bytes in SPC-5</summary>
|
||||
public struct ModePage_1A
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Idle timer activated
|
||||
/// </summary>
|
||||
/// <summary>Idle timer activated</summary>
|
||||
public bool Idle;
|
||||
/// <summary>
|
||||
/// Standby timer activated
|
||||
/// </summary>
|
||||
/// <summary>Standby timer activated</summary>
|
||||
public bool Standby;
|
||||
/// <summary>
|
||||
/// Idle timer
|
||||
/// </summary>
|
||||
/// <summary>Idle timer</summary>
|
||||
public uint IdleTimer;
|
||||
/// <summary>
|
||||
/// Standby timer
|
||||
/// </summary>
|
||||
/// <summary>Standby timer</summary>
|
||||
public uint StandbyTimer;
|
||||
|
||||
/// <summary>
|
||||
/// Interactions between background functions and power management
|
||||
/// </summary>
|
||||
/// <summary>Interactions between background functions and power management</summary>
|
||||
public byte PM_BG_Precedence;
|
||||
/// <summary>
|
||||
/// Standby timer Y activated
|
||||
/// </summary>
|
||||
/// <summary>Standby timer Y activated</summary>
|
||||
public bool Standby_Y;
|
||||
/// <summary>
|
||||
/// Idle timer B activated
|
||||
/// </summary>
|
||||
/// <summary>Idle timer B activated</summary>
|
||||
public bool Idle_B;
|
||||
/// <summary>
|
||||
/// Idle timer C activated
|
||||
/// </summary>
|
||||
/// <summary>Idle timer C activated</summary>
|
||||
public bool Idle_C;
|
||||
/// <summary>
|
||||
/// Idle timer B
|
||||
/// </summary>
|
||||
/// <summary>Idle timer B</summary>
|
||||
public uint IdleTimer_B;
|
||||
/// <summary>
|
||||
/// Idle timer C
|
||||
/// </summary>
|
||||
/// <summary>Idle timer C</summary>
|
||||
public uint IdleTimer_C;
|
||||
/// <summary>
|
||||
/// Standby timer Y
|
||||
/// </summary>
|
||||
/// <summary>Standby timer Y</summary>
|
||||
public uint StandbyTimer_Y;
|
||||
public byte CCF_Idle;
|
||||
public byte CCF_Standby;
|
||||
@@ -105,15 +75,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static ModePage_1A? DecodeModePage_1A(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x1A) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x1A)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 12) return null;
|
||||
if(pageResponse.Length < 12)
|
||||
return null;
|
||||
|
||||
ModePage_1A decoded = new ModePage_1A();
|
||||
var decoded = new ModePage_1A();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -122,10 +96,12 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.IdleTimer = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) +
|
||||
pageResponse[7]);
|
||||
|
||||
decoded.StandbyTimer = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) +
|
||||
pageResponse[11]);
|
||||
|
||||
if(pageResponse.Length < 40) return decoded;
|
||||
if(pageResponse.Length < 40)
|
||||
return decoded;
|
||||
|
||||
decoded.PM_BG_Precedence = (byte)((pageResponse[2] & 0xC0) >> 6);
|
||||
decoded.Standby_Y |= (pageResponse[2] & 0x01) == 0x01;
|
||||
@@ -134,8 +110,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.IdleTimer_B = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) + (pageResponse[14] << 8) +
|
||||
pageResponse[15]);
|
||||
|
||||
decoded.IdleTimer_C = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) +
|
||||
pageResponse[19]);
|
||||
|
||||
decoded.StandbyTimer_Y = (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) +
|
||||
(pageResponse[22] << 8) + pageResponse[23]);
|
||||
|
||||
@@ -151,44 +129,60 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1A(ModePage_1A? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1A page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_1A page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Power condition page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.Standby && page.StandbyTimer > 0 || page.Standby_Y && page.StandbyTimer_Y > 0)
|
||||
if(page.Standby && page.StandbyTimer > 0 ||
|
||||
page.Standby_Y && page.StandbyTimer_Y > 0)
|
||||
{
|
||||
if(page.Standby && page.StandbyTimer > 0)
|
||||
if(page.Standby &&
|
||||
page.StandbyTimer > 0)
|
||||
sb.AppendFormat("\tStandby timer Z is set to {0} ms", page.StandbyTimer * 100).AppendLine();
|
||||
if(page.Standby_Y && page.StandbyTimer_Y > 0)
|
||||
|
||||
if(page.Standby_Y &&
|
||||
page.StandbyTimer_Y > 0)
|
||||
sb.AppendFormat("\tStandby timer Y is set to {0} ms", page.StandbyTimer_Y * 100).AppendLine();
|
||||
}
|
||||
else sb.AppendLine("\tDrive will not enter standy mode");
|
||||
else
|
||||
sb.AppendLine("\tDrive will not enter standy mode");
|
||||
|
||||
if(page.Idle && page.IdleTimer > 0 || page.Idle_B && page.IdleTimer_B > 0 ||
|
||||
if(page.Idle && page.IdleTimer > 0 ||
|
||||
page.Idle_B && page.IdleTimer_B > 0 ||
|
||||
page.Idle_C && page.IdleTimer_C > 0)
|
||||
{
|
||||
if(page.Idle && page.IdleTimer > 0)
|
||||
if(page.Idle &&
|
||||
page.IdleTimer > 0)
|
||||
sb.AppendFormat("\tIdle timer A is set to {0} ms", page.IdleTimer * 100).AppendLine();
|
||||
if(page.Idle_B && page.IdleTimer_B > 0)
|
||||
|
||||
if(page.Idle_B &&
|
||||
page.IdleTimer_B > 0)
|
||||
sb.AppendFormat("\tIdle timer B is set to {0} ms", page.IdleTimer_B * 100).AppendLine();
|
||||
if(page.Idle_C && page.IdleTimer_C > 0)
|
||||
|
||||
if(page.Idle_C &&
|
||||
page.IdleTimer_C > 0)
|
||||
sb.AppendFormat("\tIdle timer C is set to {0} ms", page.IdleTimer_C * 100).AppendLine();
|
||||
}
|
||||
else sb.AppendLine("\tDrive will not enter idle mode");
|
||||
else
|
||||
sb.AppendLine("\tDrive will not enter idle mode");
|
||||
|
||||
switch(page.PM_BG_Precedence)
|
||||
{
|
||||
case 0: break;
|
||||
case 1:
|
||||
sb.AppendLine("\tPerforming background functions take precedence over maintaining low power conditions");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tMaintaining low power conditions take precedence over performing background functions");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -197,41 +191,35 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
#endregion Mode Page 0x1A: Power condition page
|
||||
|
||||
#region Mode Page 0x1A subpage 0x01: Power Consumption mode page
|
||||
/// <summary>
|
||||
/// Power Consumption mode page
|
||||
/// Page code 0x1A
|
||||
/// Subpage code 0x01
|
||||
/// 16 bytes in SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Power Consumption mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5</summary>
|
||||
public struct ModePage_1A_S01
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Active power level
|
||||
/// </summary>
|
||||
/// <summary>Active power level</summary>
|
||||
public byte ActiveLevel;
|
||||
/// <summary>
|
||||
/// Power Consumption VPD identifier in use
|
||||
/// </summary>
|
||||
/// <summary>Power Consumption VPD identifier in use</summary>
|
||||
public byte PowerConsumptionIdentifier;
|
||||
}
|
||||
|
||||
public static ModePage_1A_S01? DecodeModePage_1A_S01(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) != 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) != 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse[0] & 0x3F) != 0x1A) return null;
|
||||
if((pageResponse[0] & 0x3F) != 0x1A)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] != 0x01) return null;
|
||||
if(pageResponse[1] != 0x01)
|
||||
return null;
|
||||
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null;
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_1A_S01 decoded = new ModePage_1A_S01();
|
||||
var decoded = new ModePage_1A_S01();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.ActiveLevel = (byte)(pageResponse[6] & 0x03);
|
||||
@@ -245,29 +233,35 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1A_S01(ModePage_1A_S01? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1A_S01 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Power Consumption page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.ActiveLevel)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendFormat("\tDevice power consumption is dictated by identifier {0} of Power Consumption VPD",
|
||||
page.PowerConsumptionIdentifier).AppendLine();
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDevice is in highest relative power consumption level");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDevice is in intermediate relative power consumption level");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDevice is in lowest relative power consumption level");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,56 +35,43 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x1B: Removable Block Access Capabilities page
|
||||
/// <summary>
|
||||
/// Removable Block Access Capabilities page
|
||||
/// Page code 0x1B
|
||||
/// 12 bytes in INF-8070
|
||||
/// </summary>
|
||||
/// <summary>Removable Block Access Capabilities page Page code 0x1B 12 bytes in INF-8070</summary>
|
||||
public struct ModePage_1B
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Supports reporting progress of format
|
||||
/// </summary>
|
||||
/// <summary>Supports reporting progress of format</summary>
|
||||
public bool SRFP;
|
||||
/// <summary>
|
||||
/// Non-CD Optical Device
|
||||
/// </summary>
|
||||
/// <summary>Non-CD Optical Device</summary>
|
||||
public bool NCD;
|
||||
/// <summary>
|
||||
/// Phase change dual device supporting a CD and a Non-CD Optical devices
|
||||
/// </summary>
|
||||
/// <summary>Phase change dual device supporting a CD and a Non-CD Optical devices</summary>
|
||||
public bool SML;
|
||||
/// <summary>
|
||||
/// Total number of LUNs
|
||||
/// </summary>
|
||||
/// <summary>Total number of LUNs</summary>
|
||||
public byte TLUN;
|
||||
/// <summary>
|
||||
/// System Floppy Type device
|
||||
/// </summary>
|
||||
/// <summary>System Floppy Type device</summary>
|
||||
public bool SFLP;
|
||||
}
|
||||
|
||||
public static ModePage_1B? DecodeModePage_1B(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x1B) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x1B)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 12) return null;
|
||||
if(pageResponse.Length < 12)
|
||||
return null;
|
||||
|
||||
ModePage_1B decoded = new ModePage_1B();
|
||||
var decoded = new ModePage_1B();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.SFLP |= (pageResponse[2] & 0x80) == 0x80;
|
||||
@@ -102,20 +89,31 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1B(ModePage_1B? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1B page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_1B page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Removable Block Access Capabilities page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.SFLP) sb.AppendLine("\tDrive can be used as a system floppy device");
|
||||
if(page.SRFP) sb.AppendLine("\tDrive supports reporting progress of format");
|
||||
if(page.NCD) sb.AppendLine("\tDrive is a Non-CD Optical Device");
|
||||
if(page.SML) sb.AppendLine("\tDevice is a dual device supporting CD and Non-CD Optical");
|
||||
if(page.TLUN > 0) sb.AppendFormat("\tDrive supports {0} LUNs", page.TLUN).AppendLine();
|
||||
if(page.SFLP)
|
||||
sb.AppendLine("\tDrive can be used as a system floppy device");
|
||||
|
||||
if(page.SRFP)
|
||||
sb.AppendLine("\tDrive supports reporting progress of format");
|
||||
|
||||
if(page.NCD)
|
||||
sb.AppendLine("\tDrive is a Non-CD Optical Device");
|
||||
|
||||
if(page.SML)
|
||||
sb.AppendLine("\tDevice is a dual device supporting CD and Non-CD Optical");
|
||||
|
||||
if(page.TLUN > 0)
|
||||
sb.AppendFormat("\tDrive supports {0} LUNs", page.TLUN).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
199
SCSI/Modes/1C.cs
199
SCSI/Modes/1C.cs
@@ -35,78 +35,55 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x1C: Informational exceptions control page
|
||||
/// <summary>
|
||||
/// Informational exceptions control page
|
||||
/// Page code 0x1C
|
||||
/// 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4
|
||||
/// </summary>
|
||||
/// <summary>Informational exceptions control page Page code 0x1C 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4</summary>
|
||||
public struct ModePage_1C
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Informational exception operations should not affect performance
|
||||
/// </summary>
|
||||
/// <summary>Informational exception operations should not affect performance</summary>
|
||||
public bool Perf;
|
||||
/// <summary>
|
||||
/// Disable informational exception operations
|
||||
/// </summary>
|
||||
/// <summary>Disable informational exception operations</summary>
|
||||
public bool DExcpt;
|
||||
/// <summary>
|
||||
/// Create a test device failure at next interval time
|
||||
/// </summary>
|
||||
/// <summary>Create a test device failure at next interval time</summary>
|
||||
public bool Test;
|
||||
/// <summary>
|
||||
/// Log informational exception conditions
|
||||
/// </summary>
|
||||
/// <summary>Log informational exception conditions</summary>
|
||||
public bool LogErr;
|
||||
/// <summary>
|
||||
/// Method of reporting informational exceptions
|
||||
/// </summary>
|
||||
/// <summary>Method of reporting informational exceptions</summary>
|
||||
public byte MRIE;
|
||||
/// <summary>
|
||||
/// 100 ms period to report an informational exception condition
|
||||
/// </summary>
|
||||
/// <summary>100 ms period to report an informational exception condition</summary>
|
||||
public uint IntervalTimer;
|
||||
/// <summary>
|
||||
/// How many times to report informational exceptions
|
||||
/// </summary>
|
||||
/// <summary>How many times to report informational exceptions</summary>
|
||||
public uint ReportCount;
|
||||
|
||||
/// <summary>
|
||||
/// Enable background functions
|
||||
/// </summary>
|
||||
/// <summary>Enable background functions</summary>
|
||||
public bool EBF;
|
||||
/// <summary>
|
||||
/// Warning reporting enabled
|
||||
/// </summary>
|
||||
/// <summary>Warning reporting enabled</summary>
|
||||
public bool EWasc;
|
||||
|
||||
/// <summary>
|
||||
/// Enable reporting of background self-test errors
|
||||
/// </summary>
|
||||
/// <summary>Enable reporting of background self-test errors</summary>
|
||||
public bool EBACKERR;
|
||||
}
|
||||
|
||||
public static ModePage_1C? DecodeModePage_1C(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x1C) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x1C)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_1C decoded = new ModePage_1C();
|
||||
var decoded = new ModePage_1C();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -137,16 +114,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1C(ModePage_1C? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1C page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_1C page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Informational exceptions control page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.DExcpt) sb.AppendLine("\tInformational exceptions are disabled");
|
||||
if(page.DExcpt)
|
||||
sb.AppendLine("\tInformational exceptions are disabled");
|
||||
else
|
||||
{
|
||||
sb.AppendLine("\tInformational exceptions are enabled");
|
||||
@@ -155,33 +135,46 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tNo reporting of informational exception condition");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tAsynchronous event reporting of informational exceptions");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tGenerate unit attention on informational exceptions");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tConditionally generate recovered error on informational exceptions");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tUnconditionally generate recovered error on informational exceptions");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tGenerate no sense on informational exceptions");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tOnly report informational exception condition on request");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown method of reporting {0}", page.MRIE).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.Perf) sb.AppendLine("\tInformational exceptions reporting should not affect drive performance");
|
||||
if(page.Test) sb.AppendLine("\tA test informational exception will raise on next timer");
|
||||
if(page.LogErr) sb.AppendLine("\tDrive shall log informational exception conditions");
|
||||
if(page.Perf)
|
||||
sb.AppendLine("\tInformational exceptions reporting should not affect drive performance");
|
||||
|
||||
if(page.Test)
|
||||
sb.AppendLine("\tA test informational exception will raise on next timer");
|
||||
|
||||
if(page.LogErr)
|
||||
sb.AppendLine("\tDrive shall log informational exception conditions");
|
||||
|
||||
if(page.IntervalTimer > 0)
|
||||
if(page.IntervalTimer == 0xFFFFFFFF)
|
||||
@@ -194,74 +187,61 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
page.ReportCount);
|
||||
}
|
||||
|
||||
if(page.EWasc) sb.AppendLine("\tWarning reporting is enabled");
|
||||
if(page.EBF) sb.AppendLine("\tBackground functions are enabled");
|
||||
if(page.EBACKERR) sb.AppendLine("\tDrive will report background self-test errors");
|
||||
if(page.EWasc)
|
||||
sb.AppendLine("\tWarning reporting is enabled");
|
||||
|
||||
if(page.EBF)
|
||||
sb.AppendLine("\tBackground functions are enabled");
|
||||
|
||||
if(page.EBACKERR)
|
||||
sb.AppendLine("\tDrive will report background self-test errors");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion Mode Page 0x1C: Informational exceptions control page
|
||||
|
||||
#region Mode Page 0x1C subpage 0x01: Background Control mode page
|
||||
/// <summary>
|
||||
/// Background Control mode page
|
||||
/// Page code 0x1A
|
||||
/// Subpage code 0x01
|
||||
/// 16 bytes in SPC-5
|
||||
/// </summary>
|
||||
/// <summary>Background Control mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5</summary>
|
||||
public struct ModePage_1C_S01
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Suspend on log full
|
||||
/// </summary>
|
||||
/// <summary>Suspend on log full</summary>
|
||||
public bool S_L_Full;
|
||||
/// <summary>
|
||||
/// Log only when intervention required
|
||||
/// </summary>
|
||||
/// <summary>Log only when intervention required</summary>
|
||||
public bool LOWIR;
|
||||
/// <summary>
|
||||
/// Enable background medium scan
|
||||
/// </summary>
|
||||
/// <summary>Enable background medium scan</summary>
|
||||
public bool En_Bms;
|
||||
/// <summary>
|
||||
/// Enable background pre-scan
|
||||
/// </summary>
|
||||
/// <summary>Enable background pre-scan</summary>
|
||||
public bool En_Ps;
|
||||
/// <summary>
|
||||
/// Time in hours between background medium scans
|
||||
/// </summary>
|
||||
/// <summary>Time in hours between background medium scans</summary>
|
||||
public ushort BackgroundScanInterval;
|
||||
/// <summary>
|
||||
/// Maximum time in hours for a background pre-scan to complete
|
||||
/// </summary>
|
||||
/// <summary>Maximum time in hours for a background pre-scan to complete</summary>
|
||||
public ushort BackgroundPrescanTimeLimit;
|
||||
/// <summary>
|
||||
/// Minimum time in ms being idle before resuming a background scan
|
||||
/// </summary>
|
||||
/// <summary>Minimum time in ms being idle before resuming a background scan</summary>
|
||||
public ushort MinIdleBeforeBgScan;
|
||||
/// <summary>
|
||||
/// Maximum time in ms to start processing commands while performing a background scan
|
||||
/// </summary>
|
||||
/// <summary>Maximum time in ms to start processing commands while performing a background scan</summary>
|
||||
public ushort MaxTimeSuspendBgScan;
|
||||
}
|
||||
|
||||
public static ModePage_1C_S01? DecodeModePage_1C_S01(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) != 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) != 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse[0] & 0x3F) != 0x1C) return null;
|
||||
if((pageResponse[0] & 0x3F) != 0x1C)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] != 0x01) return null;
|
||||
if(pageResponse[1] != 0x01)
|
||||
return null;
|
||||
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) return null;
|
||||
if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_1C_S01 decoded = new ModePage_1C_S01();
|
||||
var decoded = new ModePage_1C_S01();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -283,19 +263,28 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1C_S01(ModePage_1C_S01? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1C_S01 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Background Control page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.S_L_Full) sb.AppendLine("\tBackground scans will be halted if log is full");
|
||||
if(page.LOWIR) sb.AppendLine("\tBackground scans will only be logged if they require intervention");
|
||||
if(page.En_Bms) sb.AppendLine("\tBackground medium scans are enabled");
|
||||
if(page.En_Ps) sb.AppendLine("\tBackground pre-scans are enabled");
|
||||
if(page.S_L_Full)
|
||||
sb.AppendLine("\tBackground scans will be halted if log is full");
|
||||
|
||||
if(page.LOWIR)
|
||||
sb.AppendLine("\tBackground scans will only be logged if they require intervention");
|
||||
|
||||
if(page.En_Bms)
|
||||
sb.AppendLine("\tBackground medium scans are enabled");
|
||||
|
||||
if(page.En_Ps)
|
||||
sb.AppendLine("\tBackground pre-scans are enabled");
|
||||
|
||||
if(page.BackgroundScanInterval > 0)
|
||||
sb.AppendFormat("\t{0} hours shall be between the start of a background scan operation and the next",
|
||||
@@ -310,8 +299,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
page.MinIdleBeforeBgScan).AppendLine();
|
||||
|
||||
if(page.MaxTimeSuspendBgScan > 0)
|
||||
sb
|
||||
.AppendFormat("\tAt most {0} ms must be before suspending a background scan operation and processing received commands",
|
||||
sb.
|
||||
AppendFormat("\tAt most {0} ms must be before suspending a background scan operation and processing received commands",
|
||||
page.MaxTimeSuspendBgScan).AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
@@ -35,48 +35,39 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x1C: Timer & Protect page
|
||||
/// <summary>
|
||||
/// Timer & Protect page
|
||||
/// Page code 0x1C
|
||||
/// 8 bytes in INF-8070
|
||||
/// </summary>
|
||||
/// <summary>Timer & Protect page Page code 0x1C 8 bytes in INF-8070</summary>
|
||||
public struct ModePage_1C_SFF
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// Time the device shall remain in the current state after seek, read or write operation
|
||||
/// </summary>
|
||||
/// <summary>Time the device shall remain in the current state after seek, read or write operation</summary>
|
||||
public byte InactivityTimeMultiplier;
|
||||
/// <summary>
|
||||
/// Disabled until power cycle
|
||||
/// </summary>
|
||||
/// <summary>Disabled until power cycle</summary>
|
||||
public bool DISP;
|
||||
/// <summary>
|
||||
/// Software Write Protect until Power-down
|
||||
/// </summary>
|
||||
/// <summary>Software Write Protect until Power-down</summary>
|
||||
public bool SWPP;
|
||||
}
|
||||
|
||||
public static ModePage_1C_SFF? DecodeModePage_1C_SFF(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x1C) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x1C)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ModePage_1C_SFF decoded = new ModePage_1C_SFF();
|
||||
var decoded = new ModePage_1C_SFF();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.DISP |= (pageResponse[2] & 0x02) == 0x02;
|
||||
@@ -92,67 +83,88 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1C_SFF(ModePage_1C_SFF? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1C_SFF page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Timer & Protect page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.DISP) sb.AppendLine("\tDrive is disabled until power is cycled");
|
||||
if(page.SWPP) sb.AppendLine("\tDrive is software write-protected until powered down");
|
||||
if(page.DISP)
|
||||
sb.AppendLine("\tDrive is disabled until power is cycled");
|
||||
|
||||
if(page.SWPP)
|
||||
sb.AppendLine("\tDrive is software write-protected until powered down");
|
||||
|
||||
switch(page.InactivityTimeMultiplier)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive will remain in same status a vendor-specified time after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will remain in same status 125 ms after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive will remain in same status 250 ms after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDrive will remain in same status 500 ms after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDrive will remain in same status 1 second after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDrive will remain in same status 2 seconds after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tDrive will remain in same status 4 seconds after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 7:
|
||||
sb.AppendLine("\tDrive will remain in same status 8 seconds after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 8:
|
||||
sb.AppendLine("\tDrive will remain in same status 16 seconds after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 9:
|
||||
sb.AppendLine("\tDrive will remain in same status 32 seconds after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 10:
|
||||
sb.AppendLine("\tDrive will remain in same status 1 minute after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 11:
|
||||
sb.AppendLine("\tDrive will remain in same status 2 minutes after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 12:
|
||||
sb.AppendLine("\tDrive will remain in same status 4 minutes after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 13:
|
||||
sb.AppendLine("\tDrive will remain in same status 8 minutes after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 14:
|
||||
sb.AppendLine("\tDrive will remain in same status 16 minutes after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
case 15:
|
||||
sb.AppendLine("\tDrive will remain in same status 32 minutes after a seek, read or write operation");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,17 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x1D: Medium Configuration Mode Page
|
||||
public struct ModePage_1D
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public bool WORMM;
|
||||
public byte WormModeLabelRestrictions;
|
||||
@@ -54,15 +51,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static ModePage_1D? DecodeModePage_1D(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x1D) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x1D)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 32) return null;
|
||||
if(pageResponse.Length < 32)
|
||||
return null;
|
||||
|
||||
ModePage_1D decoded = new ModePage_1D();
|
||||
var decoded = new ModePage_1D();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.WORMM |= (pageResponse[2] & 0x01) == 0x01;
|
||||
@@ -77,31 +78,38 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_1D(ModePage_1D? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
ModePage_1D page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_1D page = modePage.Value;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI Medium Configuration Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.WORMM) sb.AppendLine("\tDrive is operating in WORM mode");
|
||||
if(page.WORMM)
|
||||
sb.AppendLine("\tDrive is operating in WORM mode");
|
||||
|
||||
switch(page.WormModeLabelRestrictions)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive does not allow any logical blocks to be overwritten");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive allows a tape header to be overwritten");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive allows all format labels to be overwritten");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown WORM mode label restrictions code {0}", page.WormModeLabelRestrictions)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tUnknown WORM mode label restrictions code {0}", page.WormModeLabelRestrictions).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -109,13 +117,16 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten except filemark closes to BOP");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown WORM mode filemark restrictions code {0}",
|
||||
page.WormModeLabelRestrictions).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,17 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Certance Mode Page 0x21: Drive Capabilities Control Mode page
|
||||
public struct Certance_ModePage_21
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte OperatingSystemsSupport;
|
||||
public byte FirmwareTestControl2;
|
||||
@@ -59,15 +56,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static Certance_ModePage_21? DecodeCertanceModePage_21(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x21) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x21)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 9) return null;
|
||||
if(pageResponse.Length != 9)
|
||||
return null;
|
||||
|
||||
Certance_ModePage_21 decoded = new Certance_ModePage_21();
|
||||
var decoded = new Certance_ModePage_21();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.OperatingSystemsSupport = pageResponse[2];
|
||||
@@ -87,23 +88,27 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyCertanceModePage_21(Certance_ModePage_21? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
Certance_ModePage_21 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("Certance Drive Capabilities Control Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.OperatingSystemsSupport)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tOperating systems support is standard LTO");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tOperating systems support is unknown code {0}", page.OperatingSystemsSupport)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tOperating systems support is unknown code {0}", page.OperatingSystemsSupport).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -112,15 +117,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tFactory test code is disabled");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tFactory test code 1 is disabled");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tFactory test code 2 is disabled");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown factory test code {0}", page.FirmwareTestControl).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -128,12 +137,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPower-On Self-Test is enabled");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tPower-On Self-Test is disable");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown Power-On Self-Test code {0}", page.ExtendedPOSTMode).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -141,37 +153,48 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tCompression is controlled using mode pages 0Fh and 10h");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tCompression is enabled and not controllable");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tCompression is disabled and not controllable");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown compression control code {0}", page.DataCompressionControl).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.HostUnloadOverride) sb.AppendLine("\tSCSI UNLOAD command will not eject the cartridge");
|
||||
if(page.HostUnloadOverride)
|
||||
sb.AppendLine("\tSCSI UNLOAD command will not eject the cartridge");
|
||||
|
||||
sb.Append("\tHow should tapes be unloaded in a power cycle, tape incompatibility, firmware download or cleaning end: ");
|
||||
|
||||
switch(page.AutoUnloadMode)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tTape will stay threaded at beginning");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tTape will be unthreaded");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tTape will be unthreaded and unloaded");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tData tapes will be threaded at beginning, rest will be unloaded");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown auto unload code {0}", page.AutoUnloadMode).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,18 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Certance Mode Page 0x22: Interface Control Mode Page
|
||||
public struct Certance_ModePage_22
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte BaudRate;
|
||||
public byte CmdFwd;
|
||||
@@ -63,15 +59,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static Certance_ModePage_22? DecodeCertanceModePage_22(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x22) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x22)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 16) return null;
|
||||
if(pageResponse.Length != 16)
|
||||
return null;
|
||||
|
||||
Certance_ModePage_22 decoded = new Certance_ModePage_22();
|
||||
var decoded = new Certance_ModePage_22();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.BaudRate = pageResponse[2];
|
||||
@@ -94,14 +94,16 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyCertanceModePage_22(Certance_ModePage_22? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
Certance_ModePage_22 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("Certance Interface Control Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.BaudRate)
|
||||
{
|
||||
@@ -109,38 +111,46 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case 1:
|
||||
case 2:
|
||||
sb.AppendLine("\tLibrary interface will operate at 9600 baud on next reset");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tLibrary interface will operate at 19200 baud on next reset");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tLibrary interface will operate at 38400 baud on next reset");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tLibrary interface will operate at 57600 baud on next reset");
|
||||
|
||||
break;
|
||||
case 6:
|
||||
sb.AppendLine("\tLibrary interface will operate at 115200 baud on next reset");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown library interface baud rate code {0}", page.BaudRate).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendLine(page.StopBits
|
||||
? "Library interface transmits 2 stop bits per byte"
|
||||
sb.AppendLine(page.StopBits ? "Library interface transmits 2 stop bits per byte"
|
||||
: "Library interface transmits 1 stop bits per byte");
|
||||
|
||||
switch(page.CmdFwd)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tCommand forwarding is disabled");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tCommand forwarding is enabled");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown command forwarding code {0}", page.CmdFwd).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -148,26 +158,29 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tPort A link is down");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tPort A uses Parallel SCSI Ultra-160 interface");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown port A transport type code {0}", page.PortATransportType).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.PortATransportType > 0)
|
||||
sb.AppendFormat("\tDrive responds to SCSI ID {0}", page.PortAPresentSelectionID).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tDrive will respond to SCSI ID {0} on Port A enabling", page.NextSelectionID)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive will respond to SCSI ID {0} on Port A enabling", page.NextSelectionID).
|
||||
AppendLine();
|
||||
|
||||
sb.AppendFormat("\tDrive jumpers choose SCSI ID {0}", page.JumperedSelectionID).AppendLine();
|
||||
|
||||
sb.AppendLine(page.PortAEnabled ? "\tSCSI port is enabled" : "\tSCSI port is disabled");
|
||||
|
||||
sb.AppendLine(page.PortAEnabledOnPower
|
||||
? "\tSCSI port will be enabled on next power up"
|
||||
sb.AppendLine(page.PortAEnabledOnPower ? "\tSCSI port will be enabled on next power up"
|
||||
: "\tSCSI port will be disabled on next power up");
|
||||
|
||||
return sb.ToString();
|
||||
|
||||
@@ -35,17 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region IBM Mode Page 0x24: Drive Capabilities Control Mode page
|
||||
public struct IBM_ModePage_24
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte ModeControl;
|
||||
public byte VelocitySetting;
|
||||
@@ -55,15 +52,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static IBM_ModePage_24? DecodeIBMModePage_24(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x24) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x24)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 8) return null;
|
||||
if(pageResponse.Length != 8)
|
||||
return null;
|
||||
|
||||
IBM_ModePage_24 decoded = new IBM_ModePage_24();
|
||||
var decoded = new IBM_ModePage_24();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.ModeControl = pageResponse[2];
|
||||
@@ -79,22 +80,27 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyIBMModePage_24(IBM_ModePage_24? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
IBM_ModePage_24 page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("IBM Vendor-Specific Control Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\tVendor-specific mode control: {0}", page.ModeControl);
|
||||
sb.AppendFormat("\tVendor-specific mode control: {0}", page.ModeControl);
|
||||
sb.AppendFormat("\tVendor-specific velocity setting: {0}", page.VelocitySetting);
|
||||
|
||||
if(!page.EncryptionCapable) return sb.ToString();
|
||||
if(!page.EncryptionCapable)
|
||||
return sb.ToString();
|
||||
|
||||
sb.AppendLine("\tDrive supports encryption");
|
||||
if(page.EncryptionEnabled) sb.AppendLine("\tDrive has encryption enabled");
|
||||
|
||||
if(page.EncryptionEnabled)
|
||||
sb.AppendLine("\tDrive has encryption enabled");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
476
SCSI/Modes/2A.cs
476
SCSI/Modes/2A.cs
@@ -39,116 +39,63 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Mode Page 0x2A: CD-ROM capabilities page
|
||||
/// <summary>
|
||||
/// CD-ROM capabilities page
|
||||
/// Page code 0x2A
|
||||
/// 16 bytes in OB-U0077C
|
||||
/// 20 bytes in SFF-8020i
|
||||
/// 22 bytes in MMC-1
|
||||
/// 26 bytes in MMC-2
|
||||
/// Variable bytes in MMC-3
|
||||
/// CD-ROM capabilities page Page code 0x2A 16 bytes in OB-U0077C 20 bytes in SFF-8020i 22 bytes in MMC-1 26 bytes
|
||||
/// in MMC-2 Variable bytes in MMC-3
|
||||
/// </summary>
|
||||
public class ModePage_2A
|
||||
{
|
||||
public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors;
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS { get; set; }
|
||||
/// <summary>
|
||||
/// Drive supports multi-session and/or Photo-CD
|
||||
/// </summary>
|
||||
/// <summary>Drive supports multi-session and/or Photo-CD</summary>
|
||||
public bool MultiSession { get; set; }
|
||||
/// <summary>
|
||||
/// Drive is capable of reading sectors in Mode 2 Form 2 format
|
||||
/// </summary>
|
||||
/// <summary>Drive is capable of reading sectors in Mode 2 Form 2 format</summary>
|
||||
public bool Mode2Form2 { get; set; }
|
||||
/// <summary>
|
||||
/// Drive is capable of reading sectors in Mode 2 Form 1 format
|
||||
/// </summary>
|
||||
/// <summary>Drive is capable of reading sectors in Mode 2 Form 1 format</summary>
|
||||
public bool Mode2Form1 { get; set; }
|
||||
/// <summary>
|
||||
/// Drive is capable of playing audio
|
||||
/// </summary>
|
||||
/// <summary>Drive is capable of playing audio</summary>
|
||||
public bool AudioPlay { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can return the ISRC
|
||||
/// </summary>
|
||||
/// <summary>Drive can return the ISRC</summary>
|
||||
public bool ISRC { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can return the media catalogue number
|
||||
/// </summary>
|
||||
/// <summary>Drive can return the media catalogue number</summary>
|
||||
public bool UPC { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can return C2 pointers
|
||||
/// </summary>
|
||||
/// <summary>Drive can return C2 pointers</summary>
|
||||
public bool C2Pointer { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can read, deinterlave and correct R-W subchannels
|
||||
/// </summary>
|
||||
/// <summary>Drive can read, deinterlave and correct R-W subchannels</summary>
|
||||
public bool DeinterlaveSubchannel { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can read interleaved and uncorrected R-W subchannels
|
||||
/// </summary>
|
||||
/// <summary>Drive can read interleaved and uncorrected R-W subchannels</summary>
|
||||
public bool Subchannel { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can continue from a loss of streaming on audio reading
|
||||
/// </summary>
|
||||
/// <summary>Drive can continue from a loss of streaming on audio reading</summary>
|
||||
public bool AccurateCDDA { get; set; }
|
||||
/// <summary>
|
||||
/// Audio can be read as digital data
|
||||
/// </summary>
|
||||
/// <summary>Audio can be read as digital data</summary>
|
||||
public bool CDDACommand { get; set; }
|
||||
/// <summary>
|
||||
/// Loading Mechanism Type
|
||||
/// </summary>
|
||||
/// <summary>Loading Mechanism Type</summary>
|
||||
public byte LoadingMechanism { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can eject discs
|
||||
/// </summary>
|
||||
/// <summary>Drive can eject discs</summary>
|
||||
public bool Eject { get; set; }
|
||||
/// <summary>
|
||||
/// Drive's optional prevent jumper status
|
||||
/// </summary>
|
||||
/// <summary>Drive's optional prevent jumper status</summary>
|
||||
public bool PreventJumper { get; set; }
|
||||
/// <summary>
|
||||
/// Current lock status
|
||||
/// </summary>
|
||||
/// <summary>Current lock status</summary>
|
||||
public bool LockState { get; set; }
|
||||
/// <summary>
|
||||
/// Drive can lock media
|
||||
/// </summary>
|
||||
/// <summary>Drive can lock media</summary>
|
||||
public bool Lock { get; set; }
|
||||
/// <summary>
|
||||
/// Each channel can be muted independently
|
||||
/// </summary>
|
||||
/// <summary>Each channel can be muted independently</summary>
|
||||
public bool SeparateChannelMute { get; set; }
|
||||
/// <summary>
|
||||
/// Each channel's volume can be controlled independently
|
||||
/// </summary>
|
||||
/// <summary>Each channel's volume can be controlled independently</summary>
|
||||
public bool SeparateChannelVolume { get; set; }
|
||||
/// <summary>
|
||||
/// Maximum drive speed in Kbytes/second
|
||||
/// </summary>
|
||||
/// <summary>Maximum drive speed in Kbytes/second</summary>
|
||||
public ushort MaximumSpeed { get; set; }
|
||||
/// <summary>
|
||||
/// Supported volume levels
|
||||
/// </summary>
|
||||
/// <summary>Supported volume levels</summary>
|
||||
public ushort SupportedVolumeLevels { get; set; }
|
||||
/// <summary>
|
||||
/// Buffer size in Kbytes
|
||||
/// </summary>
|
||||
/// <summary>Buffer size in Kbytes</summary>
|
||||
public ushort BufferSize { get; set; }
|
||||
/// <summary>
|
||||
/// Current drive speed in Kbytes/second
|
||||
/// </summary>
|
||||
/// <summary>Current drive speed in Kbytes/second</summary>
|
||||
public ushort CurrentSpeed { get; set; }
|
||||
|
||||
public bool Method2 { get; set; }
|
||||
@@ -185,8 +132,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
public byte RotationControlSelected { get; set; }
|
||||
public ushort CurrentWriteSpeedSelected { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[Key]
|
||||
[JsonIgnore, Key]
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
@@ -198,15 +144,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static ModePage_2A DecodeModePage_2A(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x2A) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x2A)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 16) return null;
|
||||
if(pageResponse.Length < 16)
|
||||
return null;
|
||||
|
||||
ModePage_2A decoded = new ModePage_2A();
|
||||
var decoded = new ModePage_2A();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -237,7 +187,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
|
||||
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
|
||||
|
||||
if(pageResponse.Length < 20) return decoded;
|
||||
if(pageResponse.Length < 20)
|
||||
return decoded;
|
||||
|
||||
decoded.Method2 |= (pageResponse[2] & 0x04) == 0x04;
|
||||
decoded.ReadCDRW |= (pageResponse[2] & 0x02) == 0x02;
|
||||
@@ -258,7 +209,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
decoded.RCK |= (pageResponse[17] & 0x04) == 0x04;
|
||||
decoded.BCK |= (pageResponse[17] & 0x02) == 0x02;
|
||||
|
||||
if(pageResponse.Length < 22) return decoded;
|
||||
if(pageResponse.Length < 22)
|
||||
return decoded;
|
||||
|
||||
decoded.TestWrite |= (pageResponse[3] & 0x04) == 0x04;
|
||||
decoded.MaxWriteSpeed = (ushort)((pageResponse[18] << 8) + pageResponse[19]);
|
||||
@@ -266,7 +218,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.ReadBarcode |= (pageResponse[5] & 0x80) == 0x80;
|
||||
|
||||
if(pageResponse.Length < 26) return decoded;
|
||||
if(pageResponse.Length < 26)
|
||||
return decoded;
|
||||
|
||||
decoded.ReadDVDRAM |= (pageResponse[2] & 0x20) == 0x20;
|
||||
decoded.ReadDVDR |= (pageResponse[2] & 0x10) == 0x10;
|
||||
@@ -280,7 +233,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
decoded.CMRSupported = (ushort)((pageResponse[22] << 8) + pageResponse[23]);
|
||||
|
||||
if(pageResponse.Length < 32) return decoded;
|
||||
if(pageResponse.Length < 32)
|
||||
return decoded;
|
||||
|
||||
decoded.BUF |= (pageResponse[4] & 0x80) == 0x80;
|
||||
decoded.RotationControlSelected = (byte)(pageResponse[27] & 0x03);
|
||||
@@ -307,96 +261,191 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
pageResponse[0] = 0x2A;
|
||||
|
||||
if(decoded.PS) pageResponse[0] += 0x80;
|
||||
if(decoded.PS)
|
||||
pageResponse[0] += 0x80;
|
||||
|
||||
if(decoded.AudioPlay) pageResponse[4] += 0x01;
|
||||
if(decoded.Mode2Form1) pageResponse[4] += 0x10;
|
||||
if(decoded.Mode2Form2) pageResponse[4] += 0x20;
|
||||
if(decoded.MultiSession) pageResponse[4] += 0x40;
|
||||
if(decoded.AudioPlay)
|
||||
pageResponse[4] += 0x01;
|
||||
|
||||
if(decoded.CDDACommand) pageResponse[5] += 0x01;
|
||||
if(decoded.AccurateCDDA) pageResponse[5] += 0x02;
|
||||
if(decoded.Subchannel) pageResponse[5] += 0x04;
|
||||
if(decoded.DeinterlaveSubchannel) pageResponse[5] += 0x08;
|
||||
if(decoded.C2Pointer) pageResponse[5] += 0x10;
|
||||
if(decoded.UPC) pageResponse[5] += 0x20;
|
||||
if(decoded.ISRC) pageResponse[5] += 0x40;
|
||||
if(decoded.Mode2Form1)
|
||||
pageResponse[4] += 0x10;
|
||||
|
||||
if(decoded.Mode2Form2)
|
||||
pageResponse[4] += 0x20;
|
||||
|
||||
if(decoded.MultiSession)
|
||||
pageResponse[4] += 0x40;
|
||||
|
||||
if(decoded.CDDACommand)
|
||||
pageResponse[5] += 0x01;
|
||||
|
||||
if(decoded.AccurateCDDA)
|
||||
pageResponse[5] += 0x02;
|
||||
|
||||
if(decoded.Subchannel)
|
||||
pageResponse[5] += 0x04;
|
||||
|
||||
if(decoded.DeinterlaveSubchannel)
|
||||
pageResponse[5] += 0x08;
|
||||
|
||||
if(decoded.C2Pointer)
|
||||
pageResponse[5] += 0x10;
|
||||
|
||||
if(decoded.UPC)
|
||||
pageResponse[5] += 0x20;
|
||||
|
||||
if(decoded.ISRC)
|
||||
pageResponse[5] += 0x40;
|
||||
|
||||
decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5);
|
||||
if(decoded.Lock) pageResponse[6] += 0x01;
|
||||
if(decoded.LockState) pageResponse[6] += 0x02;
|
||||
if(decoded.PreventJumper) pageResponse[6] += 0x04;
|
||||
if(decoded.Eject) pageResponse[6] += 0x08;
|
||||
|
||||
if(decoded.SeparateChannelVolume) pageResponse[7] += 0x01;
|
||||
if(decoded.SeparateChannelMute) pageResponse[7] += 0x02;
|
||||
if(decoded.Lock)
|
||||
pageResponse[6] += 0x01;
|
||||
|
||||
if(decoded.LockState)
|
||||
pageResponse[6] += 0x02;
|
||||
|
||||
if(decoded.PreventJumper)
|
||||
pageResponse[6] += 0x04;
|
||||
|
||||
if(decoded.Eject)
|
||||
pageResponse[6] += 0x08;
|
||||
|
||||
if(decoded.SeparateChannelVolume)
|
||||
pageResponse[7] += 0x01;
|
||||
|
||||
if(decoded.SeparateChannelMute)
|
||||
pageResponse[7] += 0x02;
|
||||
|
||||
decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
|
||||
decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
|
||||
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
|
||||
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
|
||||
|
||||
if(decoded.Method2 || decoded.ReadCDRW || decoded.ReadCDR || decoded.WriteCDRW ||
|
||||
decoded.WriteCDR ||
|
||||
decoded.Composite || decoded.DigitalPort1 || decoded.DigitalPort2 || decoded.SDP ||
|
||||
decoded.SSS ||
|
||||
decoded.Length > 0 || decoded.LSBF || decoded.RCK || decoded.BCK)
|
||||
if(decoded.Method2 ||
|
||||
decoded.ReadCDRW ||
|
||||
decoded.ReadCDR ||
|
||||
decoded.WriteCDRW ||
|
||||
decoded.WriteCDR ||
|
||||
decoded.Composite ||
|
||||
decoded.DigitalPort1 ||
|
||||
decoded.DigitalPort2 ||
|
||||
decoded.SDP ||
|
||||
decoded.SSS ||
|
||||
decoded.Length > 0 ||
|
||||
decoded.LSBF ||
|
||||
decoded.RCK ||
|
||||
decoded.BCK)
|
||||
{
|
||||
length = 20;
|
||||
if(decoded.Method2) pageResponse[2] += 0x04;
|
||||
if(decoded.ReadCDRW) pageResponse[2] += 0x02;
|
||||
if(decoded.ReadCDR) pageResponse[2] += 0x01;
|
||||
|
||||
if(decoded.WriteCDRW) pageResponse[3] += 0x02;
|
||||
if(decoded.WriteCDR) pageResponse[3] += 0x01;
|
||||
if(decoded.Method2)
|
||||
pageResponse[2] += 0x04;
|
||||
|
||||
if(decoded.Composite) pageResponse[4] += 0x02;
|
||||
if(decoded.DigitalPort1) pageResponse[4] += 0x04;
|
||||
if(decoded.DigitalPort2) pageResponse[4] += 0x08;
|
||||
if(decoded.ReadCDRW)
|
||||
pageResponse[2] += 0x02;
|
||||
|
||||
if(decoded.SDP) pageResponse[7] += 0x04;
|
||||
if(decoded.SSS) pageResponse[7] += 0x08;
|
||||
if(decoded.ReadCDR)
|
||||
pageResponse[2] += 0x01;
|
||||
|
||||
if(decoded.WriteCDRW)
|
||||
pageResponse[3] += 0x02;
|
||||
|
||||
if(decoded.WriteCDR)
|
||||
pageResponse[3] += 0x01;
|
||||
|
||||
if(decoded.Composite)
|
||||
pageResponse[4] += 0x02;
|
||||
|
||||
if(decoded.DigitalPort1)
|
||||
pageResponse[4] += 0x04;
|
||||
|
||||
if(decoded.DigitalPort2)
|
||||
pageResponse[4] += 0x08;
|
||||
|
||||
if(decoded.SDP)
|
||||
pageResponse[7] += 0x04;
|
||||
|
||||
if(decoded.SSS)
|
||||
pageResponse[7] += 0x08;
|
||||
|
||||
pageResponse[17] = (byte)(decoded.Length << 4);
|
||||
if(decoded.LSBF) pageResponse[17] += 0x08;
|
||||
if(decoded.RCK) pageResponse[17] += 0x04;
|
||||
if(decoded.BCK) pageResponse[17] += 0x02;
|
||||
|
||||
if(decoded.LSBF)
|
||||
pageResponse[17] += 0x08;
|
||||
|
||||
if(decoded.RCK)
|
||||
pageResponse[17] += 0x04;
|
||||
|
||||
if(decoded.BCK)
|
||||
pageResponse[17] += 0x02;
|
||||
}
|
||||
|
||||
if(decoded.TestWrite || decoded.MaxWriteSpeed > 0 || decoded.CurrentWriteSpeed > 0 || decoded.ReadBarcode)
|
||||
if(decoded.TestWrite ||
|
||||
decoded.MaxWriteSpeed > 0 ||
|
||||
decoded.CurrentWriteSpeed > 0 ||
|
||||
decoded.ReadBarcode)
|
||||
{
|
||||
length = 22;
|
||||
if(decoded.TestWrite) pageResponse[3] += 0x04;
|
||||
|
||||
if(decoded.TestWrite)
|
||||
pageResponse[3] += 0x04;
|
||||
|
||||
pageResponse[18] = (byte)((decoded.MaxWriteSpeed & 0xFF00) >> 8);
|
||||
pageResponse[19] = (byte)(decoded.MaxWriteSpeed & 0xFF);
|
||||
pageResponse[20] = (byte)((decoded.CurrentWriteSpeed & 0xFF00) >> 8);
|
||||
pageResponse[21] = (byte)(decoded.CurrentWriteSpeed & 0xFF);
|
||||
if(decoded.ReadBarcode) pageResponse[5] += 0x80;
|
||||
|
||||
if(decoded.ReadBarcode)
|
||||
pageResponse[5] += 0x80;
|
||||
}
|
||||
|
||||
if(decoded.ReadDVDRAM || decoded.ReadDVDR || decoded.ReadDVDROM || decoded.WriteDVDRAM ||
|
||||
decoded.WriteDVDR || decoded.LeadInPW || decoded.SCC || decoded.CMRSupported > 0)
|
||||
if(decoded.ReadDVDRAM ||
|
||||
decoded.ReadDVDR ||
|
||||
decoded.ReadDVDROM ||
|
||||
decoded.WriteDVDRAM ||
|
||||
decoded.WriteDVDR ||
|
||||
decoded.LeadInPW ||
|
||||
decoded.SCC ||
|
||||
decoded.CMRSupported > 0)
|
||||
|
||||
{
|
||||
length = 26;
|
||||
if(decoded.ReadDVDRAM) pageResponse[2] += 0x20;
|
||||
if(decoded.ReadDVDR) pageResponse[2] += 0x10;
|
||||
if(decoded.ReadDVDROM) pageResponse[2] += 0x08;
|
||||
|
||||
if(decoded.WriteDVDRAM) pageResponse[3] += 0x20;
|
||||
if(decoded.WriteDVDR) pageResponse[3] += 0x10;
|
||||
if(decoded.ReadDVDRAM)
|
||||
pageResponse[2] += 0x20;
|
||||
|
||||
if(decoded.LeadInPW) pageResponse[3] += 0x20;
|
||||
if(decoded.SCC) pageResponse[3] += 0x10;
|
||||
if(decoded.ReadDVDR)
|
||||
pageResponse[2] += 0x10;
|
||||
|
||||
if(decoded.ReadDVDROM)
|
||||
pageResponse[2] += 0x08;
|
||||
|
||||
if(decoded.WriteDVDRAM)
|
||||
pageResponse[3] += 0x20;
|
||||
|
||||
if(decoded.WriteDVDR)
|
||||
pageResponse[3] += 0x10;
|
||||
|
||||
if(decoded.LeadInPW)
|
||||
pageResponse[3] += 0x20;
|
||||
|
||||
if(decoded.SCC)
|
||||
pageResponse[3] += 0x10;
|
||||
|
||||
pageResponse[22] = (byte)((decoded.CMRSupported & 0xFF00) >> 8);
|
||||
pageResponse[23] = (byte)(decoded.CMRSupported & 0xFF);
|
||||
}
|
||||
|
||||
if(decoded.BUF || decoded.RotationControlSelected > 0 || decoded.CurrentWriteSpeedSelected > 0)
|
||||
if(decoded.BUF ||
|
||||
decoded.RotationControlSelected > 0 ||
|
||||
decoded.CurrentWriteSpeedSelected > 0)
|
||||
{
|
||||
length = 32;
|
||||
if(decoded.BUF) pageResponse[4] += 0x80;
|
||||
|
||||
if(decoded.BUF)
|
||||
pageResponse[4] += 0x80;
|
||||
|
||||
pageResponse[27] += decoded.RotationControlSelected;
|
||||
pageResponse[28] = (byte)((decoded.CurrentWriteSpeedSelected & 0xFF00) >> 8);
|
||||
pageResponse[29] = (byte)(decoded.CurrentWriteSpeedSelected & 0xFF);
|
||||
@@ -405,12 +454,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(decoded.WriteSpeedPerformanceDescriptors != null)
|
||||
{
|
||||
length = 32;
|
||||
|
||||
for(int i = 0; i < decoded.WriteSpeedPerformanceDescriptors.Length; i++)
|
||||
{
|
||||
length += 4;
|
||||
pageResponse[1 + 32 + i * 4] = decoded.WriteSpeedPerformanceDescriptors[i].RotationControl;
|
||||
|
||||
pageResponse[2 + 32 + i * 4] =
|
||||
(byte)((decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF00) >> 8);
|
||||
|
||||
pageResponse[3 + 32 + i * 4] =
|
||||
(byte)(decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF);
|
||||
}
|
||||
@@ -419,6 +471,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
pageResponse[1] = (byte)(length - 2);
|
||||
byte[] buf = new byte[length];
|
||||
Array.Copy(pageResponse, 0, buf, 0, length);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -427,57 +480,87 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyModePage_2A(ModePage_2A modePage)
|
||||
{
|
||||
if(modePage is null) return null;
|
||||
if(modePage is null)
|
||||
return null;
|
||||
|
||||
ModePage_2A page = modePage;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ModePage_2A page = modePage;
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("SCSI CD-ROM capabilities page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.AudioPlay) sb.AppendLine("\tDrive can play audio");
|
||||
if(page.Mode2Form1) sb.AppendLine("\tDrive can read sectors in Mode 2 Form 1 format");
|
||||
if(page.Mode2Form2) sb.AppendLine("\tDrive can read sectors in Mode 2 Form 2 format");
|
||||
if(page.MultiSession) sb.AppendLine("\tDrive supports multi-session discs and/or Photo-CD");
|
||||
if(page.AudioPlay)
|
||||
sb.AppendLine("\tDrive can play audio");
|
||||
|
||||
if(page.CDDACommand) sb.AppendLine("\tDrive can read digital audio");
|
||||
if(page.AccurateCDDA) sb.AppendLine("\tDrive can continue from streaming loss");
|
||||
if(page.Subchannel) sb.AppendLine("\tDrive can read uncorrected and interleaved R-W subchannels");
|
||||
if(page.DeinterlaveSubchannel) sb.AppendLine("\tDrive can read, deinterleave and correct R-W subchannels");
|
||||
if(page.C2Pointer) sb.AppendLine("\tDrive supports C2 pointers");
|
||||
if(page.UPC) sb.AppendLine("\tDrive can read Media Catalogue Number");
|
||||
if(page.ISRC) sb.AppendLine("\tDrive can read ISRC");
|
||||
if(page.Mode2Form1)
|
||||
sb.AppendLine("\tDrive can read sectors in Mode 2 Form 1 format");
|
||||
|
||||
if(page.Mode2Form2)
|
||||
sb.AppendLine("\tDrive can read sectors in Mode 2 Form 2 format");
|
||||
|
||||
if(page.MultiSession)
|
||||
sb.AppendLine("\tDrive supports multi-session discs and/or Photo-CD");
|
||||
|
||||
if(page.CDDACommand)
|
||||
sb.AppendLine("\tDrive can read digital audio");
|
||||
|
||||
if(page.AccurateCDDA)
|
||||
sb.AppendLine("\tDrive can continue from streaming loss");
|
||||
|
||||
if(page.Subchannel)
|
||||
sb.AppendLine("\tDrive can read uncorrected and interleaved R-W subchannels");
|
||||
|
||||
if(page.DeinterlaveSubchannel)
|
||||
sb.AppendLine("\tDrive can read, deinterleave and correct R-W subchannels");
|
||||
|
||||
if(page.C2Pointer)
|
||||
sb.AppendLine("\tDrive supports C2 pointers");
|
||||
|
||||
if(page.UPC)
|
||||
sb.AppendLine("\tDrive can read Media Catalogue Number");
|
||||
|
||||
if(page.ISRC)
|
||||
sb.AppendLine("\tDrive can read ISRC");
|
||||
|
||||
switch(page.LoadingMechanism)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tDrive uses media caddy");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive uses a tray");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive is pop-up");
|
||||
|
||||
break;
|
||||
case 4:
|
||||
sb.AppendLine("\tDrive is a changer with individually changeable discs");
|
||||
|
||||
break;
|
||||
case 5:
|
||||
sb.AppendLine("\tDrive is a changer using cartridges");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", page.LoadingMechanism)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", page.LoadingMechanism).
|
||||
AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.Lock) sb.AppendLine("\tDrive can lock media");
|
||||
if(page.Lock)
|
||||
sb.AppendLine("\tDrive can lock media");
|
||||
|
||||
if(page.PreventJumper)
|
||||
{
|
||||
sb.AppendLine("\tDrive power ups locked");
|
||||
sb.AppendLine(page.LockState
|
||||
? "\tDrive is locked, media cannot be ejected or inserted"
|
||||
|
||||
sb.AppendLine(page.LockState ? "\tDrive is locked, media cannot be ejected or inserted"
|
||||
: "\tDrive is not locked, media can be ejected and inserted");
|
||||
}
|
||||
else
|
||||
@@ -485,16 +568,24 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
? "\tDrive is locked, media cannot be ejected, but if empty, can be inserted"
|
||||
: "\tDrive is not locked, media can be ejected and inserted");
|
||||
|
||||
if(page.Eject) sb.AppendLine("\tDrive can eject media");
|
||||
if(page.Eject)
|
||||
sb.AppendLine("\tDrive can eject media");
|
||||
|
||||
if(page.SeparateChannelMute) sb.AppendLine("\tEach channel can be muted independently");
|
||||
if(page.SeparateChannelVolume) sb.AppendLine("\tEach channel's volume can be controlled independently");
|
||||
if(page.SeparateChannelMute)
|
||||
sb.AppendLine("\tEach channel can be muted independently");
|
||||
|
||||
if(page.SeparateChannelVolume)
|
||||
sb.AppendLine("\tEach channel's volume can be controlled independently");
|
||||
|
||||
if(page.SupportedVolumeLevels > 0)
|
||||
sb.AppendFormat("\tDrive supports {0} volume levels", page.SupportedVolumeLevels).AppendLine();
|
||||
if(page.BufferSize > 0) sb.AppendFormat("\tDrive has {0} Kbyte of buffer", page.BufferSize).AppendLine();
|
||||
|
||||
if(page.BufferSize > 0)
|
||||
sb.AppendFormat("\tDrive has {0} Kbyte of buffer", page.BufferSize).AppendLine();
|
||||
|
||||
if(page.MaximumSpeed > 0)
|
||||
sb.AppendFormat("\tDrive's maximum reading speed is {0} Kbyte/sec.", page.MaximumSpeed).AppendLine();
|
||||
|
||||
if(page.CurrentSpeed > 0)
|
||||
sb.AppendFormat("\tDrive's current reading speed is {0} Kbyte/sec.", page.CurrentSpeed).AppendLine();
|
||||
|
||||
@@ -502,23 +593,34 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
sb.AppendLine(page.WriteCDR ? "\tDrive can read and write CD-R" : "\tDrive can read CD-R");
|
||||
|
||||
if(page.Method2) sb.AppendLine("\tDrive supports reading CD-R packet media");
|
||||
if(page.Method2)
|
||||
sb.AppendLine("\tDrive supports reading CD-R packet media");
|
||||
}
|
||||
|
||||
if(page.ReadCDRW)
|
||||
sb.AppendLine(page.WriteCDRW ? "\tDrive can read and write CD-RW" : "\tDrive can read CD-RW");
|
||||
|
||||
if(page.ReadDVDROM) sb.AppendLine("\tDrive can read DVD-ROM");
|
||||
if(page.ReadDVDROM)
|
||||
sb.AppendLine("\tDrive can read DVD-ROM");
|
||||
|
||||
if(page.ReadDVDR)
|
||||
sb.AppendLine(page.WriteDVDR ? "\tDrive can read and write DVD-R" : "\tDrive can read DVD-R");
|
||||
|
||||
if(page.ReadDVDRAM)
|
||||
sb.AppendLine(page.WriteDVDRAM ? "\tDrive can read and write DVD-RAM" : "\tDrive can read DVD-RAM");
|
||||
|
||||
if(page.Composite) sb.AppendLine("\tDrive can deliver a composite audio and video data stream");
|
||||
if(page.DigitalPort1) sb.AppendLine("\tDrive supports IEC-958 digital output on port 1");
|
||||
if(page.DigitalPort2) sb.AppendLine("\tDrive supports IEC-958 digital output on port 2");
|
||||
if(page.Composite)
|
||||
sb.AppendLine("\tDrive can deliver a composite audio and video data stream");
|
||||
|
||||
if(page.DigitalPort1)
|
||||
sb.AppendLine("\tDrive supports IEC-958 digital output on port 1");
|
||||
|
||||
if(page.DigitalPort2)
|
||||
sb.AppendLine("\tDrive supports IEC-958 digital output on port 2");
|
||||
|
||||
if(page.SDP)
|
||||
sb.AppendLine("\tDrive contains a changer that can report the exact contents of the slots");
|
||||
|
||||
if(page.SDP) sb.AppendLine("\tDrive contains a changer that can report the exact contents of the slots");
|
||||
if(page.CurrentWriteSpeedSelected > 0)
|
||||
{
|
||||
if(page.RotationControlSelected == 0)
|
||||
@@ -531,33 +633,41 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
else
|
||||
{
|
||||
if(page.MaxWriteSpeed > 0)
|
||||
sb.AppendFormat("\tDrive's maximum writing speed is {0} Kbyte/sec.", page.MaxWriteSpeed)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive's maximum writing speed is {0} Kbyte/sec.", page.MaxWriteSpeed).
|
||||
AppendLine();
|
||||
|
||||
if(page.CurrentWriteSpeed > 0)
|
||||
sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec.", page.CurrentWriteSpeed)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec.", page.CurrentWriteSpeed).
|
||||
AppendLine();
|
||||
}
|
||||
|
||||
if(page.WriteSpeedPerformanceDescriptors != null)
|
||||
foreach(ModePage_2A_WriteDescriptor descriptor in
|
||||
page.WriteSpeedPerformanceDescriptors.Where(descriptor => descriptor.WriteSpeed > 0))
|
||||
if(descriptor.RotationControl == 0)
|
||||
sb.AppendFormat("\tDrive supports writing at {0} Kbyte/sec. in CLV mode", descriptor.WriteSpeed)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tDrive supports writing at {0} Kbyte/sec. in CLV mode",
|
||||
descriptor.WriteSpeed).AppendLine();
|
||||
else if(descriptor.RotationControl == 1)
|
||||
sb.AppendFormat("\tDrive supports writing at is {0} Kbyte/sec. in pure CAV mode",
|
||||
descriptor.WriteSpeed).AppendLine();
|
||||
|
||||
if(page.TestWrite) sb.AppendLine("\tDrive supports test writing");
|
||||
if(page.TestWrite)
|
||||
sb.AppendLine("\tDrive supports test writing");
|
||||
|
||||
if(page.ReadBarcode) sb.AppendLine("\tDrive can read barcode");
|
||||
if(page.ReadBarcode)
|
||||
sb.AppendLine("\tDrive can read barcode");
|
||||
|
||||
if(page.SCC) sb.AppendLine("\tDrive can read both sides of a disc");
|
||||
if(page.LeadInPW) sb.AppendLine("\tDrive an read raw R-W subchannel from the Lead-In");
|
||||
if(page.SCC)
|
||||
sb.AppendLine("\tDrive can read both sides of a disc");
|
||||
|
||||
if(page.CMRSupported == 1) sb.AppendLine("\tDrive supports DVD CSS and/or DVD CPPM");
|
||||
if(page.LeadInPW)
|
||||
sb.AppendLine("\tDrive an read raw R-W subchannel from the Lead-In");
|
||||
|
||||
if(page.BUF) sb.AppendLine("\tDrive supports buffer under-run free recording");
|
||||
if(page.CMRSupported == 1)
|
||||
sb.AppendLine("\tDrive supports DVD CSS and/or DVD CPPM");
|
||||
|
||||
if(page.BUF)
|
||||
sb.AppendLine("\tDrive supports buffer under-run free recording");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,18 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region IBM Mode Page 0x2F: Behaviour Configuration Mode page
|
||||
public struct IBM_ModePage_2F
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte FenceBehaviour;
|
||||
public byte CleanBehaviour;
|
||||
@@ -63,27 +59,28 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static IBM_ModePage_2F? DecodeIBMModePage_2F(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x2F) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x2F)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length < 8) return null;
|
||||
if(pageResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
return new IBM_ModePage_2F
|
||||
{
|
||||
PS = (pageResponse[0] & 0x80) == 0x80,
|
||||
FenceBehaviour = pageResponse[2],
|
||||
CleanBehaviour = pageResponse[3],
|
||||
WORMEmulation = pageResponse[4],
|
||||
SenseDataBehaviour = pageResponse[5],
|
||||
CCDM = (pageResponse[6] & 0x04) == 0x04,
|
||||
DDEOR = (pageResponse[6] & 0x02) == 0x02,
|
||||
CLNCHK = (pageResponse[6] & 0x01) == 0x01,
|
||||
FirmwareUpdateBehaviour = pageResponse[7],
|
||||
UOE_C = (byte)((pageResponse[8] & 0x30) >> 4),
|
||||
UOE_F = (byte)((pageResponse[8] & 0x0C) >> 2)
|
||||
PS = (pageResponse[0] & 0x80) == 0x80, FenceBehaviour = pageResponse[2],
|
||||
CleanBehaviour = pageResponse[3], WORMEmulation = pageResponse[4],
|
||||
SenseDataBehaviour = pageResponse[5],
|
||||
CCDM = (pageResponse[6] & 0x04) == 0x04,
|
||||
DDEOR = (pageResponse[6] & 0x02) == 0x02,
|
||||
CLNCHK = (pageResponse[6] & 0x01) == 0x01, FirmwareUpdateBehaviour = pageResponse[7],
|
||||
UOE_C = (byte)((pageResponse[8] & 0x30) >> 4),
|
||||
UOE_F = (byte)((pageResponse[8] & 0x0C) >> 2)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -92,25 +89,30 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyIBMModePage_2F(IBM_ModePage_2F? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
IBM_ModePage_2F page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("IBM Behaviour Configuration Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.FenceBehaviour)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tFence behaviour is normal");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tPanic fence behaviour is enabled");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown fence behaviour code {0}", page.FenceBehaviour).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -118,12 +120,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tCleaning behaviour is normal");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will periodically request cleaning");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown cleaning behaviour code {0}", page.CleanBehaviour).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,12 +136,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tWORM emulation is disabled");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tWORM emulation is enabled");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown WORM emulation code {0}", page.WORMEmulation).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -144,24 +152,38 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tUses 35-bytes sense data");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tUses 96-bytes sense data");
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat("\tUnknown sense data behaviour code {0}", page.WORMEmulation).AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(page.CLNCHK) sb.AppendLine("\tDrive will set Check Condition when cleaning is needed");
|
||||
if(page.DDEOR) sb.AppendLine("\tNo deferred error will be reported to a rewind command");
|
||||
if(page.CCDM) sb.AppendLine("\tDrive will set Check Condition when the criteria for Dead Media is met");
|
||||
if(page.CLNCHK)
|
||||
sb.AppendLine("\tDrive will set Check Condition when cleaning is needed");
|
||||
|
||||
if(page.DDEOR)
|
||||
sb.AppendLine("\tNo deferred error will be reported to a rewind command");
|
||||
|
||||
if(page.CCDM)
|
||||
sb.AppendLine("\tDrive will set Check Condition when the criteria for Dead Media is met");
|
||||
|
||||
if(page.FirmwareUpdateBehaviour > 0)
|
||||
sb.AppendLine("\tDrive will not accept downlevel firmware via an FMR tape");
|
||||
|
||||
if(page.UOE_C == 1) sb.AppendLine("\tDrive will eject cleaning cartridges on error");
|
||||
if(page.UOE_F == 1) sb.AppendLine("\tDrive will eject firmware cartridges on error");
|
||||
if(page.UOE_D == 1) sb.AppendLine("\tDrive will eject data cartridges on error");
|
||||
if(page.UOE_C == 1)
|
||||
sb.AppendLine("\tDrive will eject cleaning cartridges on error");
|
||||
|
||||
if(page.UOE_F == 1)
|
||||
sb.AppendLine("\tDrive will eject firmware cartridges on error");
|
||||
|
||||
if(page.UOE_D == 1)
|
||||
sb.AppendLine("\tDrive will eject data cartridges on error");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -36,27 +36,30 @@ using System.Linq;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Apple Mode Page 0x30: Apple OEM String
|
||||
static readonly byte[] AppleOEMString =
|
||||
{
|
||||
0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49,
|
||||
0x4E, 0x43, 0x2E
|
||||
0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x4E,
|
||||
0x43, 0x2E
|
||||
};
|
||||
|
||||
public static bool IsAppleModePage_30(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return false;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return false;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x30) return false;
|
||||
if((pageResponse?[0] & 0x3F) != 0x30)
|
||||
return false;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return false;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return false;
|
||||
|
||||
if(pageResponse.Length != 30) return false;
|
||||
if(pageResponse.Length != 30)
|
||||
return false;
|
||||
|
||||
byte[] str = new byte[20];
|
||||
Array.Copy(pageResponse, 10, str, 0, 20);
|
||||
|
||||
@@ -36,17 +36,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region HP Mode Page 0x3B: Serial Number Override Mode page
|
||||
public struct HP_ModePage_3B
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte MSN;
|
||||
public byte[] SerialNumber;
|
||||
@@ -54,15 +51,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static HP_ModePage_3B? DecodeHPModePage_3B(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3B) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3B)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 16) return null;
|
||||
if(pageResponse.Length != 16)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3B decoded = new HP_ModePage_3B();
|
||||
var decoded = new HP_ModePage_3B();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.MSN = (byte)(pageResponse[2] & 0x03);
|
||||
@@ -77,22 +78,26 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyHPModePage_3B(HP_ModePage_3B? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3B page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("HP Serial Number Override Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.MSN)
|
||||
{
|
||||
case 1:
|
||||
sb.AppendLine("\tSerial number is the manufacturer's default value");
|
||||
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendLine("\tSerial number is not the manufacturer's default value");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,17 +36,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region HP Mode Page 0x3C: Device Time Mode page
|
||||
public struct HP_ModePage_3C
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public bool LT;
|
||||
public bool WT;
|
||||
@@ -64,30 +61,39 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static HP_ModePage_3C? DecodeHPModePage_3C(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3C) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3C)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 36) return null;
|
||||
if(pageResponse.Length != 36)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3C decoded = new HP_ModePage_3C();
|
||||
var decoded = new HP_ModePage_3C();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.LT |= (pageResponse[2] & 0x04) == 0x04;
|
||||
decoded.WT |= (pageResponse[2] & 0x02) == 0x02;
|
||||
decoded.PT |= (pageResponse[2] & 0x01) == 0x01;
|
||||
decoded.CurrentPowerOn = (ushort)((pageResponse[6] << 8) + pageResponse[7]);
|
||||
|
||||
decoded.PowerOnTime = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) +
|
||||
pageResponse[11]);
|
||||
|
||||
decoded.UTC |= (pageResponse[14] & 0x02) == 0x02;
|
||||
decoded.NTP |= (pageResponse[14] & 0x01) == 0x01;
|
||||
|
||||
decoded.WorldTime = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) +
|
||||
pageResponse[19]);
|
||||
|
||||
decoded.LibraryHours = pageResponse[23];
|
||||
decoded.LibraryMinutes = pageResponse[24];
|
||||
decoded.LibrarySeconds = pageResponse[25];
|
||||
|
||||
decoded.CumulativePowerOn = (uint)((pageResponse[32] << 24) + (pageResponse[33] << 16) +
|
||||
(pageResponse[34] << 8) + pageResponse[35]);
|
||||
|
||||
@@ -99,30 +105,38 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyHPModePage_3C(HP_ModePage_3C? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3C page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("HP Device Time Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.PT)
|
||||
{
|
||||
sb.AppendFormat("\tDrive has been powered up {0} times", page.CurrentPowerOn);
|
||||
|
||||
sb.AppendFormat("\tDrive has been powered up since {0} this time",
|
||||
TimeSpan.FromSeconds(page.PowerOnTime)).AppendLine();
|
||||
|
||||
sb.AppendFormat("\tDrive has been powered up a total of {0}",
|
||||
TimeSpan.FromSeconds(page.CumulativePowerOn)).AppendLine();
|
||||
}
|
||||
|
||||
if(page.WT)
|
||||
{
|
||||
sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime))
|
||||
.AppendLine();
|
||||
if(page.UTC) sb.AppendLine("\tDrive's time is UTC");
|
||||
if(page.NTP) sb.AppendLine("\tDrive's time is synchronized with a NTP source");
|
||||
sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime)).
|
||||
AppendLine();
|
||||
|
||||
if(page.UTC)
|
||||
sb.AppendLine("\tDrive's time is UTC");
|
||||
|
||||
if(page.NTP)
|
||||
sb.AppendLine("\tDrive's time is synchronized with a NTP source");
|
||||
}
|
||||
|
||||
if(page.LT)
|
||||
|
||||
@@ -35,32 +35,33 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region HP Mode Page 0x3D: Extended Reset Mode page
|
||||
public struct HP_ModePage_3D
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public byte ResetBehaviour;
|
||||
}
|
||||
|
||||
public static HP_ModePage_3D? DecodeHPModePage_3D(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3D) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3D)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 4) return null;
|
||||
if(pageResponse.Length != 4)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3D decoded = new HP_ModePage_3D();
|
||||
var decoded = new HP_ModePage_3D();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.ResetBehaviour = (byte)(pageResponse[2] & 0x03);
|
||||
@@ -73,25 +74,30 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyHPModePage_3D(HP_ModePage_3D? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3D page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("HP Extended Reset Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
switch(page.ResetBehaviour)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendLine("\tNormal reset behaviour");
|
||||
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendLine("\tDrive will flush and position itself on a LUN or target reset");
|
||||
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendLine("\tDrive will maintain position on a LUN or target reset");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,32 +35,33 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region IBM Mode Page 0x3D: Behaviour Configuration Mode page
|
||||
public struct IBM_ModePage_3D
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public ushort NumberOfWraps;
|
||||
}
|
||||
|
||||
public static IBM_ModePage_3D? DecodeIBMModePage_3D(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3D) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3D)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 5) return null;
|
||||
if(pageResponse.Length != 5)
|
||||
return null;
|
||||
|
||||
IBM_ModePage_3D decoded = new IBM_ModePage_3D();
|
||||
var decoded = new IBM_ModePage_3D();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.NumberOfWraps = (ushort)((pageResponse[3] << 8) + pageResponse[4]);
|
||||
@@ -73,14 +74,16 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyIBMModePage_3D(IBM_ModePage_3D? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
IBM_ModePage_3D page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("IBM LEOT Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendFormat("\t{0} wraps", page.NumberOfWraps).AppendLine();
|
||||
|
||||
|
||||
@@ -36,68 +36,51 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region Fujitsu Mode Page 0x3E: Verify Control page
|
||||
public enum Fujitsu_VerifyModes : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Always verify after writing
|
||||
/// </summary>
|
||||
Always = 0,
|
||||
/// <summary>
|
||||
/// Never verify after writing
|
||||
/// </summary>
|
||||
Never = 1,
|
||||
/// <summary>
|
||||
/// Verify after writing depending on condition
|
||||
/// </summary>
|
||||
Depends = 2,
|
||||
Reserved = 4
|
||||
/// <summary>Always verify after writing</summary>
|
||||
Always = 0, /// <summary>Never verify after writing</summary>
|
||||
Never = 1, /// <summary>Verify after writing depending on condition</summary>
|
||||
Depends = 2, Reserved = 4
|
||||
}
|
||||
|
||||
public struct Fujitsu_ModePage_3E
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
/// <summary>
|
||||
/// If set, AV data support mode is applied
|
||||
/// </summary>
|
||||
/// <summary>If set, AV data support mode is applied</summary>
|
||||
public bool audioVisualMode;
|
||||
/// <summary>
|
||||
/// If set the test write operation is restricted
|
||||
/// </summary>
|
||||
/// <summary>If set the test write operation is restricted</summary>
|
||||
public bool streamingMode;
|
||||
public byte Reserved1;
|
||||
/// <summary>
|
||||
/// Verify mode for WRITE commands
|
||||
/// </summary>
|
||||
/// <summary>Verify mode for WRITE commands</summary>
|
||||
public Fujitsu_VerifyModes verifyMode;
|
||||
public byte Reserved2;
|
||||
/// <summary>
|
||||
/// Device type provided in response to INQUIRY
|
||||
/// </summary>
|
||||
/// <summary>Device type provided in response to INQUIRY</summary>
|
||||
public PeripheralDeviceTypes devType;
|
||||
public byte[] Reserved3;
|
||||
}
|
||||
|
||||
public static Fujitsu_ModePage_3E? DecodeFujitsuModePage_3E(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3E) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3E)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 8) return null;
|
||||
if(pageResponse.Length != 8)
|
||||
return null;
|
||||
|
||||
Fujitsu_ModePage_3E decoded = new Fujitsu_ModePage_3E();
|
||||
var decoded = new Fujitsu_ModePage_3E();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
|
||||
@@ -120,16 +103,20 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyFujitsuModePage_3E(Fujitsu_ModePage_3E? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
Fujitsu_ModePage_3E page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("Fujitsu Verify Control Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
if(page.audioVisualMode)
|
||||
sb.AppendLine("\tAudio/Visual data support mode is applied");
|
||||
|
||||
if(page.audioVisualMode) sb.AppendLine("\tAudio/Visual data support mode is applied");
|
||||
if(page.streamingMode)
|
||||
sb.AppendLine("\tTest write operation is restricted during read or write operations.");
|
||||
|
||||
@@ -137,17 +124,20 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case Fujitsu_VerifyModes.Always:
|
||||
sb.AppendLine("\tAlways apply the verify operation");
|
||||
|
||||
break;
|
||||
case Fujitsu_VerifyModes.Never:
|
||||
sb.AppendLine("\tNever apply the verify operation");
|
||||
|
||||
break;
|
||||
case Fujitsu_VerifyModes.Depends:
|
||||
sb.AppendLine("\tApply the verify operation depending on the condition");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb.AppendFormat("\tThe device type that would be provided in the INQUIRY response is {0}", page.devType)
|
||||
.AppendLine();
|
||||
sb.AppendFormat("\tThe device type that would be provided in the INQUIRY response is {0}", page.devType).
|
||||
AppendLine();
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -35,17 +35,14 @@ using System.Text;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
#region HP Mode Page 0x3E: CD-ROM Emulation/Disaster Recovery Mode page
|
||||
public struct HP_ModePage_3E
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters can be saved
|
||||
/// </summary>
|
||||
/// <summary>Parameters can be saved</summary>
|
||||
public bool PS;
|
||||
public bool NonAuto;
|
||||
public bool CDmode;
|
||||
@@ -53,15 +50,19 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static HP_ModePage_3E? DecodeHPModePage_3E(byte[] pageResponse)
|
||||
{
|
||||
if((pageResponse?[0] & 0x40) == 0x40) return null;
|
||||
if((pageResponse?[0] & 0x40) == 0x40)
|
||||
return null;
|
||||
|
||||
if((pageResponse?[0] & 0x3F) != 0x3E) return null;
|
||||
if((pageResponse?[0] & 0x3F) != 0x3E)
|
||||
return null;
|
||||
|
||||
if(pageResponse[1] + 2 != pageResponse.Length) return null;
|
||||
if(pageResponse[1] + 2 != pageResponse.Length)
|
||||
return null;
|
||||
|
||||
if(pageResponse.Length != 4) return null;
|
||||
if(pageResponse.Length != 4)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3E decoded = new HP_ModePage_3E();
|
||||
var decoded = new HP_ModePage_3E();
|
||||
|
||||
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
|
||||
decoded.NonAuto |= (pageResponse[2] & 0x02) == 0x02;
|
||||
@@ -75,19 +76,22 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static string PrettifyHPModePage_3E(HP_ModePage_3E? modePage)
|
||||
{
|
||||
if(!modePage.HasValue) return null;
|
||||
if(!modePage.HasValue)
|
||||
return null;
|
||||
|
||||
HP_ModePage_3E page = modePage.Value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("HP CD-ROM Emulation/Disaster Recovery Mode Page:");
|
||||
|
||||
if(page.PS) sb.AppendLine("\tParameters can be saved");
|
||||
if(page.PS)
|
||||
sb.AppendLine("\tParameters can be saved");
|
||||
|
||||
sb.AppendLine(page.CDmode
|
||||
? "\tDrive is emulating a CD-ROM drive"
|
||||
sb.AppendLine(page.CDmode ? "\tDrive is emulating a CD-ROM drive"
|
||||
: "\tDrive is not emulating a CD-ROM drive");
|
||||
if(page.NonAuto) sb.AppendLine("\tDrive will not exit emulation automatically");
|
||||
|
||||
if(page.NonAuto)
|
||||
sb.AppendLine("\tDrive will not exit emulation automatically");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,21 +37,26 @@ using System.Linq;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
public static ModeHeader? DecodeModeHeader10(byte[] modeResponse, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
if(modeResponse == null || modeResponse.Length < 8) return null;
|
||||
if(modeResponse == null ||
|
||||
modeResponse.Length < 8)
|
||||
return null;
|
||||
|
||||
ushort modeLength = (ushort)((modeResponse[0] << 8) + modeResponse[1]);
|
||||
ushort blockDescLength = (ushort)((modeResponse[6] << 8) + modeResponse[7]);
|
||||
|
||||
if(modeResponse.Length < modeLength) return null;
|
||||
if(modeResponse.Length < modeLength)
|
||||
return null;
|
||||
|
||||
ModeHeader header = new ModeHeader {MediumType = (MediumTypes)modeResponse[2]};
|
||||
var header = new ModeHeader
|
||||
{
|
||||
MediumType = (MediumTypes)modeResponse[2]
|
||||
};
|
||||
|
||||
bool longLBA = (modeResponse[4] & 0x01) == 0x01;
|
||||
|
||||
@@ -59,11 +64,17 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
if(longLBA)
|
||||
{
|
||||
header.BlockDescriptors = new BlockDescriptor[blockDescLength / 16];
|
||||
|
||||
for(int i = 0; i < header.BlockDescriptors.Length; i++)
|
||||
{
|
||||
if(12 + i * 16 + 8 >= modeResponse.Length) break;
|
||||
if(12 + i * 16 + 8 >= modeResponse.Length)
|
||||
break;
|
||||
|
||||
header.BlockDescriptors[i] = new BlockDescriptor
|
||||
{
|
||||
Density = DensityType.Default
|
||||
};
|
||||
|
||||
header.BlockDescriptors[i] = new BlockDescriptor {Density = DensityType.Default};
|
||||
byte[] temp = new byte[8];
|
||||
temp[0] = modeResponse[7 + i * 16 + 8];
|
||||
temp[1] = modeResponse[6 + i * 16 + 8];
|
||||
@@ -83,11 +94,14 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
else
|
||||
{
|
||||
header.BlockDescriptors = new BlockDescriptor[blockDescLength / 8];
|
||||
|
||||
for(int i = 0; i < header.BlockDescriptors.Length; i++)
|
||||
{
|
||||
if(7 + i * 8 + 8 >= modeResponse.Length) break;
|
||||
if(7 + i * 8 + 8 >= modeResponse.Length)
|
||||
break;
|
||||
|
||||
header.BlockDescriptors[i] = new BlockDescriptor();
|
||||
|
||||
if(deviceType != PeripheralDeviceTypes.DirectAccess)
|
||||
header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + i * 8 + 8];
|
||||
else
|
||||
@@ -111,19 +125,23 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||
header.WriteProtected = (modeResponse[3] & 0x80) == 0x80;
|
||||
header.DPOFUA = (modeResponse[3] & 0x10) == 0x10;
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.SequentialAccess:
|
||||
header.WriteProtected = (modeResponse[3] & 0x80) == 0x80;
|
||||
header.Speed = (byte)(modeResponse[3] & 0x0F);
|
||||
header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.PrinterDevice:
|
||||
header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.OpticalDevice:
|
||||
header.WriteProtected = (modeResponse[3] & 0x80) == 0x80;
|
||||
header.EBC = (modeResponse[3] & 0x01) == 0x01;
|
||||
header.DPOFUA = (modeResponse[3] & 0x10) == 0x10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -136,29 +154,41 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
public static DecodedMode? DecodeMode10(byte[] modeResponse, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
ModeHeader? hdr = DecodeModeHeader10(modeResponse, deviceType);
|
||||
if(!hdr.HasValue) return null;
|
||||
|
||||
DecodedMode decoded = new DecodedMode {Header = hdr.Value};
|
||||
bool longlba = (modeResponse[4] & 0x01) == 0x01;
|
||||
int offset;
|
||||
int blkDrLength = 0;
|
||||
if(decoded.Header.BlockDescriptors != null) blkDrLength = decoded.Header.BlockDescriptors.Length;
|
||||
if(!hdr.HasValue)
|
||||
return null;
|
||||
|
||||
var decoded = new DecodedMode
|
||||
{
|
||||
Header = hdr.Value
|
||||
};
|
||||
|
||||
bool longlba = (modeResponse[4] & 0x01) == 0x01;
|
||||
int offset;
|
||||
int blkDrLength = 0;
|
||||
|
||||
if(decoded.Header.BlockDescriptors != null)
|
||||
blkDrLength = decoded.Header.BlockDescriptors.Length;
|
||||
|
||||
if(longlba)
|
||||
offset = 8 + blkDrLength * 16;
|
||||
else
|
||||
offset = 8 + blkDrLength * 8;
|
||||
|
||||
if(longlba) offset = 8 + blkDrLength * 16;
|
||||
else offset = 8 + blkDrLength * 8;
|
||||
int length = modeResponse[0] << 8;
|
||||
length += modeResponse[1];
|
||||
length += 2;
|
||||
|
||||
if(length != modeResponse.Length) return decoded;
|
||||
if(length != modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
List<ModePage> listpages = new List<ModePage>();
|
||||
|
||||
while(offset < modeResponse.Length)
|
||||
{
|
||||
bool isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
ModePage pg = new ModePage();
|
||||
byte pageNo = (byte)(modeResponse[offset] & 0x3F);
|
||||
bool isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
var pg = new ModePage();
|
||||
byte pageNo = (byte)(modeResponse[offset] & 0x3F);
|
||||
|
||||
if(pageNo == 0)
|
||||
{
|
||||
@@ -174,7 +204,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4];
|
||||
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded;
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length);
|
||||
pg.Page = (byte)(modeResponse[offset] & 0x3F);
|
||||
@@ -185,7 +216,8 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
pg.PageResponse = new byte[modeResponse[offset + 1] + 2];
|
||||
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded;
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length);
|
||||
pg.Page = (byte)(modeResponse[offset] & 0x3F);
|
||||
@@ -203,15 +235,15 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
}
|
||||
|
||||
public static byte[] EncodeModeHeader10(ModeHeader header, PeripheralDeviceTypes deviceType,
|
||||
bool longLBA = false)
|
||||
bool longLBA = false)
|
||||
{
|
||||
byte[] hdr;
|
||||
|
||||
if(header.BlockDescriptors != null)
|
||||
hdr = longLBA
|
||||
? new byte[8 + header.BlockDescriptors.Length * 16]
|
||||
: new byte[8 + header.BlockDescriptors.Length * 8];
|
||||
else hdr = new byte[8];
|
||||
hdr = longLBA ? new byte[8 + header.BlockDescriptors.Length * 16]
|
||||
: new byte[8 + header.BlockDescriptors.Length * 8];
|
||||
else
|
||||
hdr = new byte[8];
|
||||
|
||||
hdr[2] = (byte)header.MediumType;
|
||||
|
||||
@@ -219,27 +251,43 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case PeripheralDeviceTypes.DirectAccess:
|
||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||
if(header.WriteProtected) hdr[3] += 0x80;
|
||||
if(header.DPOFUA) hdr[3] += 0x10;
|
||||
if(header.WriteProtected)
|
||||
hdr[3] += 0x80;
|
||||
|
||||
if(header.DPOFUA)
|
||||
hdr[3] += 0x10;
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.SequentialAccess:
|
||||
if(header.WriteProtected) hdr[3] += 0x80;
|
||||
if(header.WriteProtected)
|
||||
hdr[3] += 0x80;
|
||||
|
||||
hdr[3] += (byte)(header.Speed & 0x0F);
|
||||
hdr[3] += (byte)((header.BufferedMode << 4) & 0x70);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.PrinterDevice:
|
||||
hdr[3] += (byte)((header.BufferedMode << 4) & 0x70);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.OpticalDevice:
|
||||
if(header.WriteProtected) hdr[3] += 0x80;
|
||||
if(header.EBC) hdr[3] += 0x01;
|
||||
if(header.DPOFUA) hdr[3] += 0x10;
|
||||
if(header.WriteProtected)
|
||||
hdr[3] += 0x80;
|
||||
|
||||
if(header.EBC)
|
||||
hdr[3] += 0x01;
|
||||
|
||||
if(header.DPOFUA)
|
||||
hdr[3] += 0x10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(longLBA) hdr[4] += 0x01;
|
||||
if(longLBA)
|
||||
hdr[4] += 0x01;
|
||||
|
||||
if(header.BlockDescriptors == null) return hdr;
|
||||
if(header.BlockDescriptors == null)
|
||||
return hdr;
|
||||
|
||||
if(longLBA)
|
||||
for(int i = 0; i < header.BlockDescriptors.Length; i++)
|
||||
@@ -262,8 +310,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
for(int i = 0; i < header.BlockDescriptors.Length; i++)
|
||||
{
|
||||
if(deviceType != PeripheralDeviceTypes.DirectAccess)
|
||||
hdr[0 + i * 8 + 8] = (byte)header.BlockDescriptors[i].Density;
|
||||
else hdr[0 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24);
|
||||
hdr[0 + i * 8 + 8] = (byte)header.BlockDescriptors[i].Density;
|
||||
else
|
||||
hdr[0 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24);
|
||||
|
||||
hdr[1 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16);
|
||||
hdr[2 + i * 8 + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8);
|
||||
hdr[3 + i * 8 + 8] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF);
|
||||
@@ -277,8 +327,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static byte[] EncodeMode10(DecodedMode mode, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
int modeSize = 0;
|
||||
if(mode.Pages != null) modeSize += mode.Pages.Sum(page => page.PageResponse.Length);
|
||||
int modeSize = 0;
|
||||
|
||||
if(mode.Pages != null)
|
||||
modeSize += mode.Pages.Sum(page => page.PageResponse.Length);
|
||||
|
||||
byte[] hdr = EncodeModeHeader10(mode.Header, deviceType);
|
||||
modeSize += hdr.Length;
|
||||
@@ -286,10 +338,12 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
Array.Copy(hdr, 0, md, 0, hdr.Length);
|
||||
|
||||
if(mode.Pages == null) return md;
|
||||
if(mode.Pages == null)
|
||||
return md;
|
||||
|
||||
{
|
||||
int offset = hdr.Length;
|
||||
|
||||
foreach(ModePage page in mode.Pages)
|
||||
{
|
||||
Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length);
|
||||
|
||||
@@ -37,21 +37,26 @@ using System.Linq;
|
||||
|
||||
namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
|
||||
SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||||
public static partial class Modes
|
||||
{
|
||||
public static ModeHeader? DecodeModeHeader6(byte[] modeResponse, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
if(modeResponse == null || modeResponse.Length < 4 || modeResponse.Length < modeResponse[0] + 1)
|
||||
if(modeResponse == null ||
|
||||
modeResponse.Length < 4 ||
|
||||
modeResponse.Length < modeResponse[0] + 1)
|
||||
return null;
|
||||
|
||||
ModeHeader header = new ModeHeader {MediumType = (MediumTypes)modeResponse[1]};
|
||||
var header = new ModeHeader
|
||||
{
|
||||
MediumType = (MediumTypes)modeResponse[1]
|
||||
};
|
||||
|
||||
if(modeResponse[3] > 0)
|
||||
{
|
||||
header.BlockDescriptors = new BlockDescriptor[modeResponse[3] / 8];
|
||||
|
||||
for(int i = 0; i < header.BlockDescriptors.Length; i++)
|
||||
{
|
||||
header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + i * 8 + 4];
|
||||
@@ -70,19 +75,23 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||
header.WriteProtected = (modeResponse[2] & 0x80) == 0x80;
|
||||
header.DPOFUA = (modeResponse[2] & 0x10) == 0x10;
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.SequentialAccess:
|
||||
header.WriteProtected = (modeResponse[2] & 0x80) == 0x80;
|
||||
header.Speed = (byte)(modeResponse[2] & 0x0F);
|
||||
header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.PrinterDevice:
|
||||
header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.OpticalDevice:
|
||||
header.WriteProtected = (modeResponse[2] & 0x80) == 0x80;
|
||||
header.EBC = (modeResponse[2] & 0x01) == 0x01;
|
||||
header.DPOFUA = (modeResponse[2] & 0x10) == 0x10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -95,24 +104,33 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
public static DecodedMode? DecodeMode6(byte[] modeResponse, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
ModeHeader? hdr = DecodeModeHeader6(modeResponse, deviceType);
|
||||
if(!hdr.HasValue) return null;
|
||||
|
||||
DecodedMode decoded = new DecodedMode {Header = hdr.Value};
|
||||
int blkDrLength = 0;
|
||||
if(decoded.Header.BlockDescriptors != null) blkDrLength = decoded.Header.BlockDescriptors.Length;
|
||||
if(!hdr.HasValue)
|
||||
return null;
|
||||
|
||||
var decoded = new DecodedMode
|
||||
{
|
||||
Header = hdr.Value
|
||||
};
|
||||
|
||||
int blkDrLength = 0;
|
||||
|
||||
if(decoded.Header.BlockDescriptors != null)
|
||||
blkDrLength = decoded.Header.BlockDescriptors.Length;
|
||||
|
||||
int offset = 4 + blkDrLength * 8;
|
||||
int length = modeResponse[0] + 1;
|
||||
|
||||
if(length != modeResponse.Length) return decoded;
|
||||
if(length != modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
List<ModePage> listpages = new List<ModePage>();
|
||||
|
||||
while(offset < modeResponse.Length)
|
||||
{
|
||||
bool isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
ModePage pg = new ModePage();
|
||||
byte pageNo = (byte)(modeResponse[offset] & 0x3F);
|
||||
bool isSubpage = (modeResponse[offset] & 0x40) == 0x40;
|
||||
var pg = new ModePage();
|
||||
byte pageNo = (byte)(modeResponse[offset] & 0x3F);
|
||||
|
||||
if(pageNo == 0)
|
||||
{
|
||||
@@ -126,10 +144,13 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
if(isSubpage)
|
||||
{
|
||||
if(offset + 3 >= modeResponse.Length) break;
|
||||
if(offset + 3 >= modeResponse.Length)
|
||||
break;
|
||||
|
||||
pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4];
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded;
|
||||
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length);
|
||||
pg.Page = (byte)(modeResponse[offset] & 0x3F);
|
||||
@@ -138,10 +159,13 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset + 1 >= modeResponse.Length) break;
|
||||
if(offset + 1 >= modeResponse.Length)
|
||||
break;
|
||||
|
||||
pg.PageResponse = new byte[modeResponse[offset + 1] + 2];
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length) return decoded;
|
||||
|
||||
if(pg.PageResponse.Length + offset > modeResponse.Length)
|
||||
return decoded;
|
||||
|
||||
Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length);
|
||||
pg.Page = (byte)(modeResponse[offset] & 0x3F);
|
||||
@@ -160,8 +184,7 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static byte[] EncodeModeHeader6(ModeHeader header, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
byte[] hdr = header.BlockDescriptors != null
|
||||
? new byte[4 + header.BlockDescriptors.Length * 8]
|
||||
byte[] hdr = header.BlockDescriptors != null ? new byte[4 + header.BlockDescriptors.Length * 8]
|
||||
: new byte[4];
|
||||
|
||||
hdr[1] = (byte)header.MediumType;
|
||||
@@ -170,25 +193,40 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
{
|
||||
case PeripheralDeviceTypes.DirectAccess:
|
||||
case PeripheralDeviceTypes.MultiMediaDevice:
|
||||
if(header.WriteProtected) hdr[2] += 0x80;
|
||||
if(header.DPOFUA) hdr[2] += 0x10;
|
||||
if(header.WriteProtected)
|
||||
hdr[2] += 0x80;
|
||||
|
||||
if(header.DPOFUA)
|
||||
hdr[2] += 0x10;
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.SequentialAccess:
|
||||
if(header.WriteProtected) hdr[2] += 0x80;
|
||||
if(header.WriteProtected)
|
||||
hdr[2] += 0x80;
|
||||
|
||||
hdr[2] += (byte)(header.Speed & 0x0F);
|
||||
hdr[2] += (byte)((header.BufferedMode << 4) & 0x70);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.PrinterDevice:
|
||||
hdr[2] += (byte)((header.BufferedMode << 4) & 0x70);
|
||||
|
||||
break;
|
||||
case PeripheralDeviceTypes.OpticalDevice:
|
||||
if(header.WriteProtected) hdr[2] += 0x80;
|
||||
if(header.EBC) hdr[2] += 0x01;
|
||||
if(header.DPOFUA) hdr[2] += 0x10;
|
||||
if(header.WriteProtected)
|
||||
hdr[2] += 0x80;
|
||||
|
||||
if(header.EBC)
|
||||
hdr[2] += 0x01;
|
||||
|
||||
if(header.DPOFUA)
|
||||
hdr[2] += 0x10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(header.BlockDescriptors == null) return hdr;
|
||||
if(header.BlockDescriptors == null)
|
||||
return hdr;
|
||||
|
||||
hdr[3] = (byte)(header.BlockDescriptors.Length * 8);
|
||||
|
||||
@@ -208,8 +246,10 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
public static byte[] EncodeMode6(DecodedMode mode, PeripheralDeviceTypes deviceType)
|
||||
{
|
||||
int modeSize = 0;
|
||||
if(mode.Pages != null) modeSize += mode.Pages.Sum(page => page.PageResponse.Length);
|
||||
int modeSize = 0;
|
||||
|
||||
if(mode.Pages != null)
|
||||
modeSize += mode.Pages.Sum(page => page.PageResponse.Length);
|
||||
|
||||
byte[] hdr = EncodeModeHeader6(mode.Header, deviceType);
|
||||
modeSize += hdr.Length;
|
||||
@@ -217,10 +257,12 @@ namespace DiscImageChef.Decoders.SCSI
|
||||
|
||||
Array.Copy(hdr, 0, md, 0, hdr.Length);
|
||||
|
||||
if(mode.Pages == null) return md;
|
||||
if(mode.Pages == null)
|
||||
return md;
|
||||
|
||||
{
|
||||
int offset = hdr.Length;
|
||||
|
||||
foreach(ModePage page in mode.Pages)
|
||||
{
|
||||
Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user