REFACTOR: Reformat code.

This commit is contained in:
2017-12-19 20:33:03 +00:00
parent 77edc7c91c
commit e6f6ace80b
704 changed files with 82627 additions and 83641 deletions

View File

@@ -138,10 +138,7 @@ namespace DiscImageChef.Checksums
StringBuilder adlerOutput = new StringBuilder(); StringBuilder adlerOutput = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { adlerOutput.Append(hash[i].ToString("x2")); }
{
adlerOutput.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -175,10 +172,7 @@ namespace DiscImageChef.Checksums
StringBuilder adlerOutput = new StringBuilder(); StringBuilder adlerOutput = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { adlerOutput.Append(hash[i].ToString("x2")); }
{
adlerOutput.Append(hash[i].ToString("x2"));
}
return adlerOutput.ToString(); return adlerOutput.ToString();
} }
@@ -193,5 +187,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -48,34 +48,27 @@ namespace DiscImageChef.Checksums
switch(buffer.Length) switch(buffer.Length)
{ {
case 2448: case 2448:
{ {
byte[] subchannel = new byte[96]; byte[] subchannel = new byte[96];
byte[] channel = new byte[2352]; byte[] channel = new byte[2352];
Array.Copy(buffer, 0, channel, 0, 2352); Array.Copy(buffer, 0, channel, 0, 2352);
Array.Copy(buffer, 2352, subchannel, 0, 96); Array.Copy(buffer, 2352, subchannel, 0, 96);
bool? channelStatus = CheckCDSectorChannel(channel); bool? channelStatus = CheckCDSectorChannel(channel);
bool? subchannelStatus = CheckCDSectorSubChannel(subchannel); bool? subchannelStatus = CheckCDSectorSubChannel(subchannel);
bool? status = null; bool? status = null;
if(channelStatus == null && subchannelStatus == null) if(channelStatus == null && subchannelStatus == null) status = null;
status = null; if(channelStatus == false || subchannelStatus == false) status = false;
if(channelStatus == false || subchannelStatus == false) if(channelStatus == null && subchannelStatus == true) status = true;
status = false; if(channelStatus == true && subchannelStatus == null) status = true;
if(channelStatus == null && subchannelStatus == true) if(channelStatus == true && subchannelStatus == true) status = true;
status = true;
if(channelStatus == true && subchannelStatus == null)
status = true;
if(channelStatus == true && subchannelStatus == true)
status = true;
return status; return status;
} }
case 2352: case 2352: return CheckCDSectorChannel(buffer);
return CheckCDSectorChannel(buffer); default: return null;
default:
return null;
} }
} }
@@ -92,15 +85,8 @@ namespace DiscImageChef.Checksums
} }
} }
static bool CheckECC( static bool CheckECC(byte[] address, byte[] data, uint major_count, uint minor_count, uint major_mult,
byte[] address, uint minor_inc, byte[] ecc)
byte[] data,
uint major_count,
uint minor_count,
uint major_mult,
uint minor_inc,
byte[] ecc
)
{ {
uint size = major_count * minor_count; uint size = major_count * minor_count;
uint major; uint major;
@@ -113,31 +99,19 @@ namespace DiscImageChef.Checksums
for(minor = 0; minor < minor_count; minor++) for(minor = 0; minor < minor_count; minor++)
{ {
byte temp; byte temp;
if(index < 4) if(index < 4) { temp = address[index]; }
{ else { temp = data[index - 4]; }
temp = address[index];
}
else
{
temp = data[index - 4];
}
index += minor_inc; index += minor_inc;
if(index >= size) if(index >= size) { index -= size; }
{
index -= size;
}
ecc_a ^= temp; ecc_a ^= temp;
ecc_b ^= temp; ecc_b ^= temp;
ecc_a = ECC_F_Table[ecc_a]; ecc_a = ECC_F_Table[ecc_a];
} }
ecc_a = ECC_B_Table[ECC_F_Table[ecc_a] ^ ecc_b]; ecc_a = ECC_B_Table[ECC_F_Table[ecc_a] ^ ecc_b];
if( if(ecc[major] != (ecc_a) || ecc[major + major_count] != (ecc_a ^ ecc_b)) { return false; }
ecc[major] != (ecc_a) ||
ecc[major + major_count] != (ecc_a ^ ecc_b))
{
return false;
}
} }
return true; return true;
} }
@@ -145,49 +119,44 @@ namespace DiscImageChef.Checksums
{ {
ECCInit(); ECCInit();
if( if(channel[0x000] == 0x00 && // sync (12 bytes)
channel[0x000] == 0x00 && // sync (12 bytes) channel[0x001] == 0xFF && channel[0x002] == 0xFF && channel[0x003] == 0xFF && channel[0x004] == 0xFF &&
channel[0x001] == 0xFF && channel[0x005] == 0xFF && channel[0x006] == 0xFF && channel[0x007] == 0xFF && channel[0x008] == 0xFF &&
channel[0x002] == 0xFF && channel[0x009] == 0xFF && channel[0x00A] == 0xFF && channel[0x00B] == 0x00)
channel[0x003] == 0xFF &&
channel[0x004] == 0xFF &&
channel[0x005] == 0xFF &&
channel[0x006] == 0xFF &&
channel[0x007] == 0xFF &&
channel[0x008] == 0xFF &&
channel[0x009] == 0xFF &&
channel[0x00A] == 0xFF &&
channel[0x00B] == 0x00)
{ {
DicConsole.DebugWriteLine("CD checksums", "Data sector, address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums", "Data sector, address {0:X2}:{1:X2}:{2:X2}", channel[0x00C],
channel[0x00D], channel[0x00E]);
if(channel[0x00F] == 0x00) // mode (1 byte) if(channel[0x00F] == 0x00) // mode (1 byte)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 0 sector at address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums", "Mode 0 sector at address {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
for(int i = 0x010; i < 0x930; i++) for(int i = 0x010; i < 0x930; i++)
{ {
if(channel[i] != 0x00) if(channel[i] != 0x00)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 0 sector with error at address: {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 0 sector with error at address: {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
return false; return false;
} }
} }
return true; return true;
} }
else if(channel[0x00F] == 0x01) // mode (1 byte) else if(channel[0x00F] == 0x01) // mode (1 byte)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
if(channel[0x814] != 0x00 || // reserved (8 bytes) if(channel[0x814] != 0x00 || // reserved (8 bytes)
channel[0x815] != 0x00 || channel[0x815] != 0x00 || channel[0x816] != 0x00 || channel[0x817] != 0x00 ||
channel[0x816] != 0x00 || channel[0x818] != 0x00 || channel[0x819] != 0x00 || channel[0x81A] != 0x00 ||
channel[0x817] != 0x00 || channel[0x81B] != 0x00)
channel[0x818] != 0x00 ||
channel[0x819] != 0x00 ||
channel[0x81A] != 0x00 ||
channel[0x81B] != 0x00)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector with data in reserved bytes at address: {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 1 sector with data in reserved bytes at address: {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
return false; return false;
} }
@@ -207,12 +176,15 @@ namespace DiscImageChef.Checksums
bool FailedECC_Q = CheckECC(address, data2, 52, 43, 86, 88, ecc_q); bool FailedECC_Q = CheckECC(address, data2, 52, 43, 86, 88, ecc_q);
if(FailedECC_P) if(FailedECC_P)
DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check",
channel[0x00C], channel[0x00D], channel[0x00E]);
if(FailedECC_Q) if(FailedECC_Q)
DicConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check",
channel[0x00C], channel[0x00D], channel[0x00E]);
if(FailedECC_P || FailedECC_Q) if(FailedECC_P || FailedECC_Q) return false;
return false;
/* TODO: This is not working /* TODO: This is not working
byte[] SectorForCheck = new byte[0x810]; byte[] SectorForCheck = new byte[0x810];
@@ -232,13 +204,17 @@ namespace DiscImageChef.Checksums
} }
else if(channel[0x00F] == 0x02) // mode (1 byte) else if(channel[0x00F] == 0x02) // mode (1 byte)
{ {
DicConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2 if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2
{ {
if(channel[0x010] != channel[0x014] || channel[0x011] != channel[0x015] || channel[0x012] != channel[0x016] || channel[0x013] != channel[0x017]) if(channel[0x010] != channel[0x014] || channel[0x011] != channel[0x015] ||
channel[0x012] != channel[0x016] || channel[0x013] != channel[0x017])
{ {
DicConsole.DebugWriteLine("CD checksums", "Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
} }
/* TODO: This is not working /* TODO: This is not working
@@ -257,9 +233,12 @@ namespace DiscImageChef.Checksums
} }
else else
{ {
if(channel[0x010] != channel[0x014] || channel[0x011] != channel[0x015] || channel[0x012] != channel[0x016] || channel[0x013] != channel[0x017]) if(channel[0x010] != channel[0x014] || channel[0x011] != channel[0x015] ||
channel[0x012] != channel[0x016] || channel[0x013] != channel[0x017])
{ {
DicConsole.DebugWriteLine("CD checksums", "Subheader copies differ in mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Subheader copies differ in mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}",
channel[0x00C], channel[0x00D], channel[0x00E]);
} }
byte[] address = new byte[4]; byte[] address = new byte[4];
@@ -281,12 +260,15 @@ namespace DiscImageChef.Checksums
bool FailedECC_Q = CheckECC(address, data2, 52, 43, 86, 88, ecc_q); bool FailedECC_Q = CheckECC(address, data2, 52, 43, 86, 88, ecc_q);
if(FailedECC_P) if(FailedECC_P)
DicConsole.DebugWriteLine("CD checksums", "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check",
channel[0x00C], channel[0x00D], channel[0x00E]);
if(FailedECC_Q) if(FailedECC_Q)
DicConsole.DebugWriteLine("CD checksums", "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check",
channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]);
if(FailedECC_P || FailedECC_Q) if(FailedECC_P || FailedECC_Q) return false;
return false;
/* TODO: This is not working /* TODO: This is not working
byte[] SectorForCheck = new byte[0x808]; byte[] SectorForCheck = new byte[0x808];
@@ -307,10 +289,13 @@ namespace DiscImageChef.Checksums
} }
else else
{ {
DicConsole.DebugWriteLine("CD checksums", "Unknown mode {0} sector at address: {1:X2}:{2:X2}:{3:X2}", channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]); DicConsole.DebugWriteLine("CD checksums",
"Unknown mode {0} sector at address: {1:X2}:{2:X2}:{3:X2}",
channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]);
return null; return null;
} }
} }
return null; return null;
} }
@@ -328,8 +313,7 @@ namespace DiscImageChef.Checksums
byte[] CDSubRWPack4 = new byte[24]; byte[] CDSubRWPack4 = new byte[24];
int i = 0; int i = 0;
for(int j = 0; j < 12; j++) for(int j = 0; j < 12; j++) QSubChannel[j] = 0;
QSubChannel[j] = 0;
for(int j = 0; j < 18; j++) for(int j = 0; j < 18; j++)
{ {
CDTextPack1[j] = 0; CDTextPack1[j] = 0;
@@ -360,82 +344,46 @@ namespace DiscImageChef.Checksums
i = 0; i = 0;
for(int j = 0; j < 18; j++) for(int j = 0; j < 18; j++)
{ {
if(j < 18) if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x3F) << 2));
CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x3F) << 2)); if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j++] | ((subchannel[i] & 0xC0) >> 4));
if(j < 18) if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x0F) << 4));
CDTextPack1[j] = (byte)(CDTextPack1[j++] | ((subchannel[i] & 0xC0) >> 4)); if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18) if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x03) << 6));
CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x0F) << 4)); if(j < 18) CDTextPack1[j] = (byte)(CDTextPack1[j] | (subchannel[i++] & 0x3F));
if(j < 18)
CDTextPack1[j] = (byte)(CDTextPack1[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18)
CDTextPack1[j] = (byte)(CDTextPack1[j] | ((subchannel[i++] & 0x03) << 6));
if(j < 18)
CDTextPack1[j] = (byte)(CDTextPack1[j] | (subchannel[i++] & 0x3F));
} }
for(int j = 0; j < 18; j++) for(int j = 0; j < 18; j++)
{ {
if(j < 18) if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x3F) << 2));
CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x3F) << 2)); if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j++] | ((subchannel[i] & 0xC0) >> 4));
if(j < 18) if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x0F) << 4));
CDTextPack2[j] = (byte)(CDTextPack2[j++] | ((subchannel[i] & 0xC0) >> 4)); if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18) if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x03) << 6));
CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x0F) << 4)); if(j < 18) CDTextPack2[j] = (byte)(CDTextPack2[j] | (subchannel[i++] & 0x3F));
if(j < 18)
CDTextPack2[j] = (byte)(CDTextPack2[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18)
CDTextPack2[j] = (byte)(CDTextPack2[j] | ((subchannel[i++] & 0x03) << 6));
if(j < 18)
CDTextPack2[j] = (byte)(CDTextPack2[j] | (subchannel[i++] & 0x3F));
} }
for(int j = 0; j < 18; j++) for(int j = 0; j < 18; j++)
{ {
if(j < 18) if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x3F) << 2));
CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x3F) << 2)); if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j++] | ((subchannel[i] & 0xC0) >> 4));
if(j < 18) if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x0F) << 4));
CDTextPack3[j] = (byte)(CDTextPack3[j++] | ((subchannel[i] & 0xC0) >> 4)); if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18) if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x03) << 6));
CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x0F) << 4)); if(j < 18) CDTextPack3[j] = (byte)(CDTextPack3[j] | (subchannel[i++] & 0x3F));
if(j < 18)
CDTextPack3[j] = (byte)(CDTextPack3[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18)
CDTextPack3[j] = (byte)(CDTextPack3[j] | ((subchannel[i++] & 0x03) << 6));
if(j < 18)
CDTextPack3[j] = (byte)(CDTextPack3[j] | (subchannel[i++] & 0x3F));
} }
for(int j = 0; j < 18; j++) for(int j = 0; j < 18; j++)
{ {
if(j < 18) if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x3F) << 2));
CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x3F) << 2)); if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j++] | ((subchannel[i] & 0xC0) >> 4));
if(j < 18) if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x0F) << 4));
CDTextPack4[j] = (byte)(CDTextPack4[j++] | ((subchannel[i] & 0xC0) >> 4)); if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18) if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x03) << 6));
CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x0F) << 4)); if(j < 18) CDTextPack4[j] = (byte)(CDTextPack4[j] | (subchannel[i++] & 0x3F));
if(j < 18)
CDTextPack4[j] = (byte)(CDTextPack4[j++] | ((subchannel[i] & 0x3C) >> 2));
if(j < 18)
CDTextPack4[j] = (byte)(CDTextPack4[j] | ((subchannel[i++] & 0x03) << 6));
if(j < 18)
CDTextPack4[j] = (byte)(CDTextPack4[j] | (subchannel[i++] & 0x3F));
} }
i = 0; i = 0;
for(int j = 0; j < 24; j++) for(int j = 0; j < 24; j++) { CDSubRWPack1[j] = (byte)(subchannel[i++] & 0x3F); }
{ for(int j = 0; j < 24; j++) { CDSubRWPack2[j] = (byte)(subchannel[i++] & 0x3F); }
CDSubRWPack1[j] = (byte)(subchannel[i++] & 0x3F); for(int j = 0; j < 24; j++) { CDSubRWPack3[j] = (byte)(subchannel[i++] & 0x3F); }
} for(int j = 0; j < 24; j++) { CDSubRWPack4[j] = (byte)(subchannel[i++] & 0x3F); }
for(int j = 0; j < 24; j++)
{
CDSubRWPack2[j] = (byte)(subchannel[i++] & 0x3F);
}
for(int j = 0; j < 24; j++)
{
CDSubRWPack3[j] = (byte)(subchannel[i++] & 0x3F);
}
for(int j = 0; j < 24; j++)
{
CDSubRWPack4[j] = (byte)(subchannel[i++] & 0x3F);
}
switch(CDSubRWPack1[0]) switch(CDSubRWPack1[0])
{ {
@@ -461,7 +409,10 @@ namespace DiscImageChef.Checksums
DicConsole.DebugWriteLine("CD checksums", "Detected User Pack in subchannel"); DicConsole.DebugWriteLine("CD checksums", "Detected User Pack in subchannel");
break; break;
default: default:
DicConsole.DebugWriteLine("CD checksums", "Detected unknown Pack type in subchannel: mode {0}, item {1}", Convert.ToString(CDSubRWPack1[0] & 0x38, 2), Convert.ToString(CDSubRWPack1[0] & 0x07, 2)); DicConsole.DebugWriteLine("CD checksums",
"Detected unknown Pack type in subchannel: mode {0}, item {1}",
Convert.ToString(CDSubRWPack1[0] & 0x38, 2),
Convert.ToString(CDSubRWPack1[0] & 0x07, 2));
break; break;
} }
@@ -474,7 +425,8 @@ namespace DiscImageChef.Checksums
if(QSubChannelCRC != CalculatedQCRC) if(QSubChannelCRC != CalculatedQCRC)
{ {
DicConsole.DebugWriteLine("CD checksums", "Q subchannel CRC 0x{0:X4}, expected 0x{1:X4}", CalculatedQCRC, QSubChannelCRC); DicConsole.DebugWriteLine("CD checksums", "Q subchannel CRC 0x{0:X4}, expected 0x{1:X4}",
CalculatedQCRC, QSubChannelCRC);
status = false; status = false;
} }
@@ -487,7 +439,8 @@ namespace DiscImageChef.Checksums
if(CDTextPack1CRC != CalculatedCDTP1CRC && CDTextPack1CRC != 0) if(CDTextPack1CRC != CalculatedCDTP1CRC && CDTextPack1CRC != 0)
{ {
DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 1 CRC 0x{0:X4}, expected 0x{1:X4}", CDTextPack1CRC, CalculatedCDTP1CRC); DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 1 CRC 0x{0:X4}, expected 0x{1:X4}",
CDTextPack1CRC, CalculatedCDTP1CRC);
status = false; status = false;
} }
} }
@@ -498,11 +451,13 @@ namespace DiscImageChef.Checksums
byte[] CDTextPack2ForCRC = new byte[16]; byte[] CDTextPack2ForCRC = new byte[16];
Array.Copy(CDTextPack2, 0, CDTextPack2ForCRC, 0, 16); Array.Copy(CDTextPack2, 0, CDTextPack2ForCRC, 0, 16);
ushort CalculatedCDTP2CRC = CalculateCCITT_CRC16(CDTextPack2ForCRC); ushort CalculatedCDTP2CRC = CalculateCCITT_CRC16(CDTextPack2ForCRC);
DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP2 0x{0:X4}, Calc CDTP2 0x{1:X4}", CDTextPack2CRC, CalculatedCDTP2CRC); DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP2 0x{0:X4}, Calc CDTP2 0x{1:X4}", CDTextPack2CRC,
CalculatedCDTP2CRC);
if(CDTextPack2CRC != CalculatedCDTP2CRC && CDTextPack2CRC != 0) if(CDTextPack2CRC != CalculatedCDTP2CRC && CDTextPack2CRC != 0)
{ {
DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 2 CRC 0x{0:X4}, expected 0x{1:X4}", CDTextPack2CRC, CalculatedCDTP2CRC); DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 2 CRC 0x{0:X4}, expected 0x{1:X4}",
CDTextPack2CRC, CalculatedCDTP2CRC);
status = false; status = false;
} }
} }
@@ -513,11 +468,13 @@ namespace DiscImageChef.Checksums
byte[] CDTextPack3ForCRC = new byte[16]; byte[] CDTextPack3ForCRC = new byte[16];
Array.Copy(CDTextPack3, 0, CDTextPack3ForCRC, 0, 16); Array.Copy(CDTextPack3, 0, CDTextPack3ForCRC, 0, 16);
ushort CalculatedCDTP3CRC = CalculateCCITT_CRC16(CDTextPack3ForCRC); ushort CalculatedCDTP3CRC = CalculateCCITT_CRC16(CDTextPack3ForCRC);
DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP3 0x{0:X4}, Calc CDTP3 0x{1:X4}", CDTextPack3CRC, CalculatedCDTP3CRC); DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP3 0x{0:X4}, Calc CDTP3 0x{1:X4}", CDTextPack3CRC,
CalculatedCDTP3CRC);
if(CDTextPack3CRC != CalculatedCDTP3CRC && CDTextPack3CRC != 0) if(CDTextPack3CRC != CalculatedCDTP3CRC && CDTextPack3CRC != 0)
{ {
DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 3 CRC 0x{0:X4}, expected 0x{1:X4}", CDTextPack3CRC, CalculatedCDTP3CRC); DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 3 CRC 0x{0:X4}, expected 0x{1:X4}",
CDTextPack3CRC, CalculatedCDTP3CRC);
status = false; status = false;
} }
} }
@@ -528,11 +485,13 @@ namespace DiscImageChef.Checksums
byte[] CDTextPack4ForCRC = new byte[16]; byte[] CDTextPack4ForCRC = new byte[16];
Array.Copy(CDTextPack4, 0, CDTextPack4ForCRC, 0, 16); Array.Copy(CDTextPack4, 0, CDTextPack4ForCRC, 0, 16);
ushort CalculatedCDTP4CRC = CalculateCCITT_CRC16(CDTextPack4ForCRC); ushort CalculatedCDTP4CRC = CalculateCCITT_CRC16(CDTextPack4ForCRC);
DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP4 0x{0:X4}, Calc CDTP4 0x{1:X4}", CDTextPack4CRC, CalculatedCDTP4CRC); DicConsole.DebugWriteLine("CD checksums", "Cyclic CDTP4 0x{0:X4}, Calc CDTP4 0x{1:X4}", CDTextPack4CRC,
CalculatedCDTP4CRC);
if(CDTextPack4CRC != CalculatedCDTP4CRC && CDTextPack4CRC != 0) if(CDTextPack4CRC != CalculatedCDTP4CRC && CDTextPack4CRC != 0)
{ {
DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 4 CRC 0x{0:X4}, expected 0x{1:X4}", CDTextPack4CRC, CalculatedCDTP4CRC); DicConsole.DebugWriteLine("CD checksums", "CD-Text Pack 4 CRC 0x{0:X4}, expected 0x{1:X4}",
CDTextPack4CRC, CalculatedCDTP4CRC);
status = false; status = false;
} }
} }
@@ -542,38 +501,26 @@ namespace DiscImageChef.Checksums
static readonly ushort[] CCITT_CRC16Table = static readonly ushort[] CCITT_CRC16Table =
{ {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
}; };
static ushort CalculateCCITT_CRC16(byte[] buffer) static ushort CalculateCCITT_CRC16(byte[] buffer)
@@ -583,10 +530,10 @@ namespace DiscImageChef.Checksums
{ {
CRC16 = (ushort)(CCITT_CRC16Table[(CRC16 >> 8) ^ buffer[i]] ^ (CRC16 << 8)); CRC16 = (ushort)(CCITT_CRC16Table[(CRC16 >> 8) ^ buffer[i]] ^ (CRC16 << 8));
} }
CRC16 = (ushort)~CRC16; CRC16 = (ushort)~CRC16;
return CRC16; return CRC16;
} }
} }
} }

View File

@@ -59,10 +59,9 @@ namespace DiscImageChef.Checksums
{ {
ushort entry = (ushort)i; ushort entry = (ushort)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (ushort)((entry >> 1) ^ crc16Poly);
entry = (ushort)((entry >> 1) ^ crc16Poly); else entry = (ushort)(entry >> 1);
else
entry = (ushort)(entry >> 1);
table[i] = entry; table[i] = entry;
} }
} }
@@ -74,8 +73,7 @@ namespace DiscImageChef.Checksums
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) hashInt = (ushort)((hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xFF)]);
hashInt = (ushort)((hashInt >> 8) ^ table[data[i] ^ (hashInt & 0xFF)]);
} }
/// <summary> /// <summary>
@@ -143,10 +141,9 @@ namespace DiscImageChef.Checksums
{ {
ushort entry = (ushort)i; ushort entry = (ushort)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (ushort)((entry >> 1) ^ crc16Poly);
entry = (ushort)((entry >> 1) ^ crc16Poly); else entry = (ushort)(entry >> 1);
else
entry = (ushort)(entry >> 1);
localTable[i] = entry; localTable[i] = entry;
} }
@@ -158,10 +155,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc16Output = new StringBuilder(); StringBuilder crc16Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc16Output.Append(hash[i].ToString("x2")); }
{
crc16Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -199,10 +193,9 @@ namespace DiscImageChef.Checksums
{ {
ushort entry = (ushort)i; ushort entry = (ushort)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (ushort)((entry >> 1) ^ polynomial);
entry = (ushort)((entry >> 1) ^ polynomial); else entry = (ushort)(entry >> 1);
else
entry = (ushort)(entry >> 1);
localTable[i] = entry; localTable[i] = entry;
} }
@@ -214,10 +207,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc16Output = new StringBuilder(); StringBuilder crc16Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc16Output.Append(hash[i].ToString("x2")); }
{
crc16Output.Append(hash[i].ToString("x2"));
}
return crc16Output.ToString(); return crc16Output.ToString();
} }
@@ -232,5 +222,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -59,10 +59,9 @@ namespace DiscImageChef.Checksums
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ crc32Poly;
entry = (entry >> 1) ^ crc32Poly; else entry = entry >> 1;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
} }
@@ -74,8 +73,7 @@ namespace DiscImageChef.Checksums
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ hashInt & 0xff];
hashInt = (hashInt >> 8) ^ table[data[i] ^ hashInt & 0xff];
} }
/// <summary> /// <summary>
@@ -143,10 +141,9 @@ namespace DiscImageChef.Checksums
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ crc32Poly;
entry = (entry >> 1) ^ crc32Poly; else entry = entry >> 1;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -159,10 +156,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc32Output = new StringBuilder(); StringBuilder crc32Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc32Output.Append(hash[i].ToString("x2")); }
{
crc32Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -200,15 +194,13 @@ namespace DiscImageChef.Checksums
{ {
uint entry = (uint)i; uint entry = (uint)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial;
entry = (entry >> 1) ^ polynomial; else entry = entry >> 1;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ localhashInt & 0xff];
localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ localhashInt & 0xff];
localhashInt ^= crc32Seed; localhashInt ^= crc32Seed;
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
@@ -216,10 +208,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc32Output = new StringBuilder(); StringBuilder crc32Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc32Output.Append(hash[i].ToString("x2")); }
{
crc32Output.Append(hash[i].ToString("x2"));
}
return crc32Output.ToString(); return crc32Output.ToString();
} }
@@ -234,6 +223,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -58,10 +58,9 @@ namespace DiscImageChef.Checksums
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ crc64Poly;
entry = (entry >> 1) ^ crc64Poly; else entry = entry >> 1;
else
entry = entry >> 1;
table[i] = entry; table[i] = entry;
} }
} }
@@ -73,8 +72,7 @@ namespace DiscImageChef.Checksums
/// <param name="len">Length of buffer to hash.</param> /// <param name="len">Length of buffer to hash.</param>
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) hashInt = (hashInt >> 8) ^ table[data[i] ^ hashInt & 0xff];
hashInt = (hashInt >> 8) ^ table[data[i] ^ hashInt & 0xff];
} }
/// <summary> /// <summary>
@@ -142,10 +140,9 @@ namespace DiscImageChef.Checksums
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ crc64Poly;
entry = (entry >> 1) ^ crc64Poly; else entry = entry >> 1;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
@@ -158,10 +155,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc64Output = new StringBuilder(); StringBuilder crc64Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc64Output.Append(hash[i].ToString("x2")); }
{
crc64Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -199,15 +193,13 @@ namespace DiscImageChef.Checksums
{ {
ulong entry = (ulong)i; ulong entry = (ulong)i;
for(int j = 0; j < 8; j++) for(int j = 0; j < 8; j++)
if((entry & 1) == 1) if((entry & 1) == 1) entry = (entry >> 1) ^ polynomial;
entry = (entry >> 1) ^ polynomial; else entry = entry >> 1;
else
entry = entry >> 1;
localTable[i] = entry; localTable[i] = entry;
} }
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ localhashInt & 0xff];
localhashInt = (localhashInt >> 8) ^ localTable[data[i] ^ localhashInt & 0xff];
localhashInt ^= crc64Seed; localhashInt ^= crc64Seed;
BigEndianBitConverter.IsLittleEndian = BigEndianBitConverter.IsLittleEndian; BigEndianBitConverter.IsLittleEndian = BigEndianBitConverter.IsLittleEndian;
@@ -215,10 +207,7 @@ namespace DiscImageChef.Checksums
StringBuilder crc64Output = new StringBuilder(); StringBuilder crc64Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { crc64Output.Append(hash[i].ToString("x2")); }
{
crc64Output.Append(hash[i].ToString("x2"));
}
return crc64Output.ToString(); return crc64Output.ToString();
} }
@@ -233,6 +222,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -453,3 +453,4 @@ namespace DiscImageChef.Checksums
} }
} }
*/ */

View File

@@ -87,10 +87,7 @@ namespace DiscImageChef.Checksums
_md5Provider.TransformFinalBlock(new byte[0], 0, 0); _md5Provider.TransformFinalBlock(new byte[0], 0, 0);
StringBuilder md5Output = new StringBuilder(); StringBuilder md5Output = new StringBuilder();
for(int i = 0; i < _md5Provider.Hash.Length; i++) for(int i = 0; i < _md5Provider.Hash.Length; i++) { md5Output.Append(_md5Provider.Hash[i].ToString("x2")); }
{
md5Output.Append(_md5Provider.Hash[i].ToString("x2"));
}
return md5Output.ToString(); return md5Output.ToString();
} }
@@ -118,10 +115,7 @@ namespace DiscImageChef.Checksums
hash = _md5Provider.ComputeHash(fileStream); hash = _md5Provider.ComputeHash(fileStream);
StringBuilder md5Output = new StringBuilder(); StringBuilder md5Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { md5Output.Append(hash[i].ToString("x2")); }
{
md5Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +133,7 @@ namespace DiscImageChef.Checksums
hash = _md5Provider.ComputeHash(data, 0, (int)len); hash = _md5Provider.ComputeHash(data, 0, (int)len);
StringBuilder md5Output = new StringBuilder(); StringBuilder md5Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { md5Output.Append(hash[i].ToString("x2")); }
{
md5Output.Append(hash[i].ToString("x2"));
}
return md5Output.ToString(); return md5Output.ToString();
} }
@@ -157,5 +148,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -54,5 +54,4 @@ using System.Reflection;
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]

View File

@@ -118,10 +118,7 @@ namespace DiscImageChef.Checksums
hash = _ripemd160Provider.ComputeHash(fileStream); hash = _ripemd160Provider.ComputeHash(fileStream);
StringBuilder ripemd160Output = new StringBuilder(); StringBuilder ripemd160Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { ripemd160Output.Append(hash[i].ToString("x2")); }
{
ripemd160Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +136,7 @@ namespace DiscImageChef.Checksums
hash = _ripemd160Provider.ComputeHash(data, 0, (int)len); hash = _ripemd160Provider.ComputeHash(data, 0, (int)len);
StringBuilder ripemd160Output = new StringBuilder(); StringBuilder ripemd160Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { ripemd160Output.Append(hash[i].ToString("x2")); }
{
ripemd160Output.Append(hash[i].ToString("x2"));
}
return ripemd160Output.ToString(); return ripemd160Output.ToString();
} }
@@ -157,5 +151,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -94,52 +94,51 @@ namespace DiscImageChef.Checksums
switch(m) switch(m)
{ {
case 2: case 2:
Pp = new[] { 1, 1, 1 }; Pp = new[] {1, 1, 1};
break; break;
case 3: case 3:
Pp = new[] { 1, 1, 0, 1 }; Pp = new[] {1, 1, 0, 1};
break; break;
case 4: case 4:
Pp = new[] { 1, 1, 0, 0, 1 }; Pp = new[] {1, 1, 0, 0, 1};
break; break;
case 5: case 5:
Pp = new[] { 1, 0, 1, 0, 0, 1 }; Pp = new[] {1, 0, 1, 0, 0, 1};
break; break;
case 6: case 6:
Pp = new[] { 1, 1, 0, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 0, 0, 0, 1};
break; break;
case 7: case 7:
Pp = new[] { 1, 0, 0, 1, 0, 0, 0, 1 }; Pp = new[] {1, 0, 0, 1, 0, 0, 0, 1};
break; break;
case 8: case 8:
Pp = new[] { 1, 0, 1, 1, 1, 0, 0, 0, 1 }; Pp = new[] {1, 0, 1, 1, 1, 0, 0, 0, 1};
break; break;
case 9: case 9:
Pp = new[] { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; Pp = new[] {1, 0, 0, 0, 1, 0, 0, 0, 0, 1};
break; break;
case 10: case 10:
Pp = new[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; Pp = new[] {1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1};
break; break;
case 11: case 11:
Pp = new[] { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; Pp = new[] {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
break; break;
case 12: case 12:
Pp = new[] { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1};
break; break;
case 13: case 13:
Pp = new[] { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
break; break;
case 14: case 14:
Pp = new[] { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
break; break;
case 15: case 15:
Pp = new[] { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
break; break;
case 16: case 16:
Pp = new[] { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 }; Pp = new[] {1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1};
break; break;
default: default: throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive");
throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive");
} }
MM = m; MM = m;
@@ -149,7 +148,6 @@ namespace DiscImageChef.Checksums
Alpha_to = new int[n + 1]; Alpha_to = new int[n + 1];
Index_of = new int[n + 1]; Index_of = new int[n + 1];
Gg = new int[NN - KK + 1]; Gg = new int[NN - KK + 1];
generate_gf(); generate_gf();
@@ -165,6 +163,7 @@ namespace DiscImageChef.Checksums
x -= NN; x -= NN;
x = (x >> MM) + (x & NN); x = (x >> MM) + (x & NN);
} }
return x; return x;
} }
@@ -176,22 +175,19 @@ namespace DiscImageChef.Checksums
static void CLEAR(ref int[] a, int n) static void CLEAR(ref int[] a, int n)
{ {
int ci; int ci;
for(ci = (n) - 1; ci >= 0; ci--) for(ci = (n) - 1; ci >= 0; ci--) (a)[ci] = 0;
(a)[ci] = 0;
} }
static void COPY(ref int[] a, ref int[] b, int n) static void COPY(ref int[] a, ref int[] b, int n)
{ {
int ci; int ci;
for(ci = (n) - 1; ci >= 0; ci--) for(ci = (n) - 1; ci >= 0; ci--) (a)[ci] = (b)[ci];
(a)[ci] = (b)[ci];
} }
static void COPYDOWN(ref int[] a, ref int[] b, int n) static void COPYDOWN(ref int[] a, ref int[] b, int n)
{ {
int ci; int ci;
for(ci = (n) - 1; ci >= 0; ci--) for(ci = (n) - 1; ci >= 0; ci--) (a)[ci] = (b)[ci];
(a)[ci] = (b)[ci];
} }
/* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
@@ -235,10 +231,10 @@ namespace DiscImageChef.Checksums
Alpha_to[i] = mask; Alpha_to[i] = mask;
Index_of[Alpha_to[i]] = i; Index_of[Alpha_to[i]] = i;
/* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
if(Pp[i] != 0) if(Pp[i] != 0) Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */
Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */
mask <<= 1; /* single left-shift */ mask <<= 1; /* single left-shift */
} }
Index_of[Alpha_to[MM]] = MM; Index_of[Alpha_to[MM]] = MM;
/* /*
* Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
@@ -248,12 +244,11 @@ namespace DiscImageChef.Checksums
mask >>= 1; mask >>= 1;
for(i = MM + 1; i < NN; i++) for(i = MM + 1; i < NN; i++)
{ {
if(Alpha_to[i - 1] >= mask) if(Alpha_to[i - 1] >= mask) Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1); else Alpha_to[i] = Alpha_to[i - 1] << 1;
else
Alpha_to[i] = Alpha_to[i - 1] << 1;
Index_of[Alpha_to[i]] = i; Index_of[Alpha_to[i]] = i;
} }
Index_of[0] = A0; Index_of[0] = A0;
Alpha_to[NN] = 0; Alpha_to[NN] = 0;
} }
@@ -276,7 +271,7 @@ namespace DiscImageChef.Checksums
int i, j; int i, j;
Gg[0] = Alpha_to[B0]; Gg[0] = Alpha_to[B0];
Gg[1] = 1; /* g(x) = (X+@**B0) initially */ Gg[1] = 1; /* g(x) = (X+@**B0) initially */
for(i = 2; i <= NN - KK; i++) for(i = 2; i <= NN - KK; i++)
{ {
Gg[i] = 1; Gg[i] = 1;
@@ -285,16 +280,13 @@ namespace DiscImageChef.Checksums
* (@**(B0+i-1) + x) * (@**(B0+i-1) + x)
*/ */
for(j = i - 1; j > 0; j--) for(j = i - 1; j > 0; j--)
if(Gg[j] != 0) if(Gg[j] != 0) Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];
Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)]; else Gg[j] = Gg[j - 1];
else
Gg[j] = Gg[j - 1];
/* Gg[0] can never be zero */ /* Gg[0] can never be zero */
Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)]; Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];
} }
/* convert Gg[] to index form for quicker encoding */ /* convert Gg[] to index form for quicker encoding */
for(i = 0; i <= NN - KK; i++) for(i = 0; i <= NN - KK; i++) Gg[i] = Index_of[Gg[i]];
Gg[i] = Index_of[Gg[i]];
} }
/* /*
@@ -322,31 +314,31 @@ namespace DiscImageChef.Checksums
CLEAR(ref bb, NN - KK); CLEAR(ref bb, NN - KK);
for(i = KK - 1; i >= 0; i--) for(i = KK - 1; i >= 0; i--)
{ {
if(MM != 8) if(MM != 8) { if(data[i] > NN) return -1; /* Illegal symbol */ }
{
if(data[i] > NN)
return -1; /* Illegal symbol */
}
feedback = Index_of[data[i] ^ bb[NN - KK - 1]]; feedback = Index_of[data[i] ^ bb[NN - KK - 1]];
if(feedback != A0) if(feedback != A0)
{ /* feedback term is non-zero */ {
/* feedback term is non-zero */
for(j = NN - KK - 1; j > 0; j--) for(j = NN - KK - 1; j > 0; j--)
if(Gg[j] != A0) if(Gg[j] != A0) bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];
bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)]; else bb[j] = bb[j - 1];
else
bb[j] = bb[j - 1];
bb[0] = Alpha_to[modnn(Gg[0] + feedback)]; bb[0] = Alpha_to[modnn(Gg[0] + feedback)];
} }
else else
{ /* feedback term is zero. encoder becomes a {
* single-byte shifter */ /* feedback term is zero. encoder becomes a
for(j = NN - KK - 1; j > 0; j--) * single-byte shifter */
bb[j] = bb[j - 1]; for(j = NN - KK - 1; j > 0; j--) bb[j] = bb[j - 1];
bb[0] = 0; bb[0] = 0;
} }
} }
return 0; return 0;
} }
throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); throw new UnauthorizedAccessException("Trying to calculate RS without initializing!");
} }
@@ -392,11 +384,8 @@ namespace DiscImageChef.Checksums
/* data[] is in polynomial form, copy and convert to index form */ /* data[] is in polynomial form, copy and convert to index form */
for(i = NN - 1; i >= 0; i--) for(i = NN - 1; i >= 0; i--)
{ {
if(MM != 8) if(MM != 8) { if(data[i] > NN) return -1; /* Illegal symbol */ }
{
if(data[i] > NN)
return -1; /* Illegal symbol */
}
recd[i] = Index_of[data[i]]; recd[i] = Index_of[data[i]];
} }
/* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)
@@ -407,13 +396,15 @@ namespace DiscImageChef.Checksums
{ {
tmp = 0; tmp = 0;
for(j = 0; j < NN; j++) for(j = 0; j < NN; j++)
if(recd[j] != A0) /* recd[j] in index form */ if(recd[j] != A0) /* recd[j] in index form */
tmp ^= Alpha_to[modnn(recd[j] + (B0 + i - 1) * j)]; tmp ^= Alpha_to[modnn(recd[j] + (B0 + i - 1) * j)];
syn_error |= tmp; /* set flag if non-zero syndrome =>
syn_error |= tmp; /* set flag if non-zero syndrome =>
* error */ * error */
/* store syndrome in index form */ /* store syndrome in index form */
s[i] = Index_of[tmp]; s[i] = Index_of[tmp];
} }
if(syn_error == 0) if(syn_error == 0)
{ {
/* /*
@@ -422,6 +413,7 @@ namespace DiscImageChef.Checksums
*/ */
return 0; return 0;
} }
CLEAR(ref lambda, NN - KK); CLEAR(ref lambda, NN - KK);
lambda[0] = 1; lambda[0] = 1;
if(no_eras > 0) if(no_eras > 0)
@@ -434,15 +426,14 @@ namespace DiscImageChef.Checksums
for(j = i + 1; j > 0; j--) for(j = i + 1; j > 0; j--)
{ {
tmp = Index_of[lambda[j - 1]]; tmp = Index_of[lambda[j - 1]];
if(tmp != A0) if(tmp != A0) lambda[j] ^= Alpha_to[modnn(u + tmp)];
lambda[j] ^= Alpha_to[modnn(u + tmp)];
} }
} }
#if DEBUG #if DEBUG
/* find roots of the erasure location polynomial */ /* find roots of the erasure location polynomial */
for(i = 1; i <= no_eras; i++) for(i = 1; i <= no_eras; i++) reg[i] = Index_of[lambda[i]];
reg[i] = Index_of[lambda[i]];
count = 0; count = 0;
for(i = 1; i <= NN; i++) for(i = 1; i <= NN; i++)
{ {
@@ -453,6 +444,7 @@ namespace DiscImageChef.Checksums
reg[j] = modnn(reg[j] + j); reg[j] = modnn(reg[j] + j);
q ^= Alpha_to[reg[j]]; q ^= Alpha_to[reg[j]];
} }
if(q == 0) if(q == 0)
{ {
/* store root and error location /* store root and error location
@@ -463,20 +455,22 @@ namespace DiscImageChef.Checksums
count++; count++;
} }
} }
if(count != no_eras) if(count != no_eras)
{ {
DicConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n"); DicConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n");
return -1; return -1;
} }
DicConsole.DebugWriteLine("Reed Solomon", "\n Erasure positions as determined by roots of Eras Loc Poly:\n"); DicConsole.DebugWriteLine("Reed Solomon",
for(i = 0; i < count; i++) "\n Erasure positions as determined by roots of Eras Loc Poly:\n");
DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]); for(i = 0; i < count; i++) DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
DicConsole.DebugWriteLine("Reed Solomon", "\n"); DicConsole.DebugWriteLine("Reed Solomon", "\n");
#endif #endif
} }
for(i = 0; i < NN - KK + 1; i++)
b[i] = Index_of[lambda[i]]; for(i = 0; i < NN - KK + 1; i++) b[i] = Index_of[lambda[i]];
/* /*
* Begin Berlekamp-Massey algorithm to determine error+erasure * Begin Berlekamp-Massey algorithm to determine error+erasure
@@ -485,7 +479,8 @@ namespace DiscImageChef.Checksums
r = no_eras; r = no_eras;
el = no_eras; el = no_eras;
while(++r <= NN - KK) while(++r <= NN - KK)
{ /* r is the step number */ {
/* r is the step number */
/* Compute discrepancy at the r-th step in poly-form */ /* Compute discrepancy at the r-th step in poly-form */
discr_r = 0; discr_r = 0;
for(i = 0; i < r; i++) for(i = 0; i < r; i++)
@@ -495,7 +490,8 @@ namespace DiscImageChef.Checksums
discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])]; discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
} }
} }
discr_r = Index_of[discr_r]; /* Index form */
discr_r = Index_of[discr_r]; /* Index form */
if(discr_r == A0) if(discr_r == A0)
{ {
/* 2 lines below: B(x) <-- x*B(x) */ /* 2 lines below: B(x) <-- x*B(x) */
@@ -508,11 +504,10 @@ namespace DiscImageChef.Checksums
t[0] = lambda[0]; t[0] = lambda[0];
for(i = 0; i < NN - KK; i++) for(i = 0; i < NN - KK; i++)
{ {
if(b[i] != A0) if(b[i] != A0) t[i + 1] = lambda[i + 1] ^ Alpha_to[modnn(discr_r + b[i])];
t[i + 1] = lambda[i + 1] ^ Alpha_to[modnn(discr_r + b[i])]; else t[i + 1] = lambda[i + 1];
else
t[i + 1] = lambda[i + 1];
} }
if(2 * el <= r + no_eras - 1) if(2 * el <= r + no_eras - 1)
{ {
el = r + no_eras - el; el = r + no_eras - el;
@@ -529,6 +524,7 @@ namespace DiscImageChef.Checksums
COPYDOWN(ref b, ref b, NN - KK); COPYDOWN(ref b, ref b, NN - KK);
b[0] = A0; b[0] = A0;
} }
COPY(ref lambda, ref t, NN - KK + 1); COPY(ref lambda, ref t, NN - KK + 1);
} }
} }
@@ -538,8 +534,7 @@ namespace DiscImageChef.Checksums
for(i = 0; i < NN - KK + 1; i++) for(i = 0; i < NN - KK + 1; i++)
{ {
lambda[i] = Index_of[lambda[i]]; lambda[i] = Index_of[lambda[i]];
if(lambda[i] != A0) if(lambda[i] != A0) deg_lambda = i;
deg_lambda = i;
} }
/* /*
* Find roots of the error+erasure locator polynomial. By Chien * Find roots of the error+erasure locator polynomial. By Chien
@@ -548,7 +543,7 @@ namespace DiscImageChef.Checksums
int temp = reg[0]; int temp = reg[0];
COPY(ref reg, ref lambda, NN - KK); COPY(ref reg, ref lambda, NN - KK);
reg[0] = temp; reg[0] = temp;
count = 0; /* Number of roots of lambda(x) */ count = 0; /* Number of roots of lambda(x) */
for(i = 1; i <= NN; i++) for(i = 1; i <= NN; i++)
{ {
q = 1; q = 1;
@@ -558,6 +553,7 @@ namespace DiscImageChef.Checksums
reg[j] = modnn(reg[j] + j); reg[j] = modnn(reg[j] + j);
q ^= Alpha_to[reg[j]]; q ^= Alpha_to[reg[j]];
} }
if(q == 0) if(q == 0)
{ {
/* store root (index-form) and error location number */ /* store root (index-form) and error location number */
@@ -569,8 +565,8 @@ namespace DiscImageChef.Checksums
#if DEBUG #if DEBUG
DicConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t"); DicConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t");
for(i = 0; i < count; i++) for(i = 0; i < count; i++) DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
DicConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]);
DicConsole.DebugWriteLine("Reed Solomon", "\n"); DicConsole.DebugWriteLine("Reed Solomon", "\n");
#endif #endif
@@ -593,13 +589,13 @@ namespace DiscImageChef.Checksums
j = (deg_lambda < i) ? deg_lambda : i; j = (deg_lambda < i) ? deg_lambda : i;
for(; j >= 0; j--) for(; j >= 0; j--)
{ {
if((s[i + 1 - j] != A0) && (lambda[j] != A0)) if((s[i + 1 - j] != A0) && (lambda[j] != A0)) tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
} }
if(tmp != 0)
deg_omega = i; if(tmp != 0) deg_omega = i;
omega[i] = Index_of[tmp]; omega[i] = Index_of[tmp];
} }
omega[NN - KK] = A0; omega[NN - KK] = A0;
/* /*
@@ -611,18 +607,18 @@ namespace DiscImageChef.Checksums
num1 = 0; num1 = 0;
for(i = deg_omega; i >= 0; i--) for(i = deg_omega; i >= 0; i--)
{ {
if(omega[i] != A0) if(omega[i] != A0) num1 ^= Alpha_to[modnn(omega[i] + i * root[j])];
num1 ^= Alpha_to[modnn(omega[i] + i * root[j])];
} }
num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)]; num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
den = 0; den = 0;
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
for(i = min(deg_lambda, NN - KK - 1) & ~1; i >= 0; i -= 2) for(i = min(deg_lambda, NN - KK - 1) & ~1; i >= 0; i -= 2)
{ {
if(lambda[i + 1] != A0) if(lambda[i + 1] != A0) den ^= Alpha_to[modnn(lambda[i + 1] + i * root[j])];
den ^= Alpha_to[modnn(lambda[i + 1] + i * root[j])];
} }
if(den == 0) if(den == 0)
{ {
DicConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n"); DicConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n");
@@ -634,9 +630,11 @@ namespace DiscImageChef.Checksums
data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])]; data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
} }
} }
return count; return count;
} }
throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); throw new UnauthorizedAccessException("Trying to calculate RS without initializing!");
} }
} }
} }

View File

@@ -118,10 +118,7 @@ namespace DiscImageChef.Checksums
hash = _sha1Provider.ComputeHash(fileStream); hash = _sha1Provider.ComputeHash(fileStream);
StringBuilder sha1Output = new StringBuilder(); StringBuilder sha1Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha1Output.Append(hash[i].ToString("x2")); }
{
sha1Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +136,7 @@ namespace DiscImageChef.Checksums
hash = _sha1Provider.ComputeHash(data, 0, (int)len); hash = _sha1Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha1Output = new StringBuilder(); StringBuilder sha1Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha1Output.Append(hash[i].ToString("x2")); }
{
sha1Output.Append(hash[i].ToString("x2"));
}
return sha1Output.ToString(); return sha1Output.ToString();
} }
@@ -157,5 +151,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -118,10 +118,7 @@ namespace DiscImageChef.Checksums
hash = _sha256Provider.ComputeHash(fileStream); hash = _sha256Provider.ComputeHash(fileStream);
StringBuilder sha256Output = new StringBuilder(); StringBuilder sha256Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha256Output.Append(hash[i].ToString("x2")); }
{
sha256Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +136,7 @@ namespace DiscImageChef.Checksums
hash = _sha256Provider.ComputeHash(data, 0, (int)len); hash = _sha256Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha256Output = new StringBuilder(); StringBuilder sha256Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha256Output.Append(hash[i].ToString("x2")); }
{
sha256Output.Append(hash[i].ToString("x2"));
}
return sha256Output.ToString(); return sha256Output.ToString();
} }
@@ -157,5 +151,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -118,10 +118,7 @@ namespace DiscImageChef.Checksums
hash = _sha384Provider.ComputeHash(fileStream); hash = _sha384Provider.ComputeHash(fileStream);
StringBuilder sha384Output = new StringBuilder(); StringBuilder sha384Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha384Output.Append(hash[i].ToString("x2")); }
{
sha384Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +136,7 @@ namespace DiscImageChef.Checksums
hash = _sha384Provider.ComputeHash(data, 0, (int)len); hash = _sha384Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha384Output = new StringBuilder(); StringBuilder sha384Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha384Output.Append(hash[i].ToString("x2")); }
{
sha384Output.Append(hash[i].ToString("x2"));
}
return sha384Output.ToString(); return sha384Output.ToString();
} }
@@ -157,5 +151,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -118,10 +118,7 @@ namespace DiscImageChef.Checksums
hash = _sha512Provider.ComputeHash(fileStream); hash = _sha512Provider.ComputeHash(fileStream);
StringBuilder sha512Output = new StringBuilder(); StringBuilder sha512Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha512Output.Append(hash[i].ToString("x2")); }
{
sha512Output.Append(hash[i].ToString("x2"));
}
fileStream.Close(); fileStream.Close();
@@ -139,10 +136,7 @@ namespace DiscImageChef.Checksums
hash = _sha512Provider.ComputeHash(data, 0, (int)len); hash = _sha512Provider.ComputeHash(data, 0, (int)len);
StringBuilder sha512Output = new StringBuilder(); StringBuilder sha512Output = new StringBuilder();
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++) { sha512Output.Append(hash[i].ToString("x2")); }
{
sha512Output.Append(hash[i].ToString("x2"));
}
return sha512Output.ToString(); return sha512Output.ToString();
} }
@@ -157,5 +151,4 @@ namespace DiscImageChef.Checksums
return Data(data, (uint)data.Length, out hash); return Data(data, (uint)data.Length, out hash);
} }
} }
} }

View File

@@ -58,14 +58,11 @@ namespace DiscImageChef.Checksums
const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH + 20); const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH + 20);
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
readonly byte[] b64 = readonly byte[] b64 =
{0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, {
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31,
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
}; };
struct roll_state struct roll_state
@@ -118,8 +115,7 @@ namespace DiscImageChef.Checksums
{ {
self = new fuzzy_state(); self = new fuzzy_state();
self.bh = new blockhash_context[NUM_BLOCKHASHES]; self.bh = new blockhash_context[NUM_BLOCKHASHES];
for(int i = 0; i < NUM_BLOCKHASHES; i++) for(int i = 0; i < NUM_BLOCKHASHES; i++) self.bh[i].digest = new byte[SPAMSUM_LENGTH];
self.bh[i].digest = new byte[SPAMSUM_LENGTH];
self.bhstart = 0; self.bhstart = 0;
self.bhend = 1; self.bhend = 1;
@@ -180,8 +176,7 @@ namespace DiscImageChef.Checksums
{ {
uint obh, nbh; uint obh, nbh;
if(self.bhend >= NUM_BLOCKHASHES) if(self.bhend >= NUM_BLOCKHASHES) return;
return;
if(self.bhend == 0) // assert if(self.bhend == 0) // assert
throw new Exception("Assertion failed"); throw new Exception("Assertion failed");
@@ -198,20 +193,15 @@ namespace DiscImageChef.Checksums
void fuzzy_try_reduce_blockhash() void fuzzy_try_reduce_blockhash()
{ {
if(self.bhstart >= self.bhend) if(self.bhstart >= self.bhend) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
if(self.bhend - self.bhstart < 2) if(self.bhend - self.bhstart < 2)
/* Need at least two working hashes. */ /* Need at least two working hashes. */ return;
return; if((ulong)SSDEEP_BS(self.bhstart) * SPAMSUM_LENGTH >= self.total_size)
if((ulong)SSDEEP_BS(self.bhstart) * SPAMSUM_LENGTH >=
self.total_size)
/* Initial blocksize estimate would select this or a smaller /* Initial blocksize estimate would select this or a smaller
* blocksize. */ * blocksize. */ return;
return;
if(self.bh[self.bhstart + 1].dlen < SPAMSUM_LENGTH / 2) if(self.bh[self.bhstart + 1].dlen < SPAMSUM_LENGTH / 2)
/* Estimate adjustment would select this blocksize. */ /* Estimate adjustment would select this blocksize. */ return;
return;
/* At this point we are clearly no longer interested in the /* At this point we are clearly no longer interested in the
* start_blocksize. Get rid of it. */ * start_blocksize. Get rid of it. */
++self.bhstart; ++self.bhstart;
@@ -239,8 +229,7 @@ namespace DiscImageChef.Checksums
if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1) if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1)
/* Once this condition is false for one bs, it is /* Once this condition is false for one bs, it is
* automatically false for all further bs. I.e. if * automatically false for all further bs. I.e. if
* h === -1 (mod 2*bs) then h === -1 (mod bs). */ * h === -1 (mod 2*bs) then h === -1 (mod bs). */ break;
break;
/* We have hit a reset point. We now emit hashes which are /* We have hit a reset point. We now emit hashes which are
* based on all characters in the piece of the message between * based on all characters in the piece of the message between
* the last reset point and this one */ * the last reset point and this one */
@@ -268,8 +257,7 @@ namespace DiscImageChef.Checksums
self.bh[i].halfdigest = 0; self.bh[i].halfdigest = 0;
} }
} }
else else fuzzy_try_reduce_blockhash();
fuzzy_try_reduce_blockhash();
} }
} }
@@ -281,8 +269,7 @@ namespace DiscImageChef.Checksums
public void Update(byte[] data, uint len) public void Update(byte[] data, uint len)
{ {
self.total_size += len; self.total_size += len;
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++) fuzzy_engine_step(data[i]);
fuzzy_engine_step(data[i]);
} }
/// <summary> /// <summary>
@@ -313,26 +300,20 @@ namespace DiscImageChef.Checksums
while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self.total_size) while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < self.total_size)
{ {
++bi; ++bi;
if(bi >= NUM_BLOCKHASHES) if(bi >= NUM_BLOCKHASHES) { throw new OverflowException("The input exceeds data types."); }
{
throw new OverflowException("The input exceeds data types.");
}
} }
/* Adapt blocksize guess to actual digest length. */ /* Adapt blocksize guess to actual digest length. */
while(bi >= self.bhend) while(bi >= self.bhend) --bi;
--bi; while(bi > self.bhstart && self.bh[bi].dlen < SPAMSUM_LENGTH / 2) --bi;
while(bi > self.bhstart && self.bh[bi].dlen < SPAMSUM_LENGTH / 2)
--bi; if((bi > 0 && self.bh[bi].dlen < SPAMSUM_LENGTH / 2)) throw new Exception("Assertion failed");
if((bi > 0 && self.bh[bi].dlen < SPAMSUM_LENGTH / 2))
throw new Exception("Assertion failed");
sb.AppendFormat("{0}:", SSDEEP_BS(bi)); sb.AppendFormat("{0}:", SSDEEP_BS(bi));
i = Encoding.ASCII.GetBytes(sb.ToString()).Length; i = Encoding.ASCII.GetBytes(sb.ToString()).Length;
if(i <= 0) if(i <= 0)
/* Maybe snprintf has set errno here? */ /* Maybe snprintf has set errno here? */ throw new OverflowException("The input exceeds data types.");
throw new OverflowException("The input exceeds data types."); if(i >= remain) throw new Exception("Assertion failed");
if(i >= remain)
throw new Exception("Assertion failed");
remain -= i; remain -= i;
Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i); Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i);
@@ -340,21 +321,18 @@ namespace DiscImageChef.Checksums
result_off += i; result_off += i;
i = (int)self.bh[bi].dlen; i = (int)self.bh[bi].dlen;
if(i > remain) if(i > remain) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
Array.Copy(self.bh[bi].digest, 0, result, result_off, i); Array.Copy(self.bh[bi].digest, 0, result, result_off, i);
result_off += i; result_off += i;
remain -= i; remain -= i;
if(h != 0) if(h != 0)
{ {
if(remain <= 0) if(remain <= 0) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
result[result_off] = b64[self.bh[bi].h % 64]; result[result_off] = b64[self.bh[bi].h % 64];
if(i < 3 || if(i < 3 || result[result_off] != result[result_off - 1] ||
result[result_off] != result[result_off - 1] || result[result_off] != result[result_off - 2] || result[result_off] != result[result_off - 3])
result[result_off] != result[result_off - 2] ||
result[result_off] != result[result_off - 3])
{ {
++result_off; ++result_off;
--remain; --remain;
@@ -362,42 +340,39 @@ namespace DiscImageChef.Checksums
} }
else if(self.bh[bi].digest[i] != 0) else if(self.bh[bi].digest[i] != 0)
{ {
if(remain <= 0) if(remain <= 0) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
result[result_off] = self.bh[bi].digest[i]; result[result_off] = self.bh[bi].digest[i];
if(i < 3 || if(i < 3 || result[result_off] != result[result_off - 1] ||
result[result_off] != result[result_off - 1] || result[result_off] != result[result_off - 2] || result[result_off] != result[result_off - 3])
result[result_off] != result[result_off - 2] ||
result[result_off] != result[result_off - 3])
{ {
++result_off; ++result_off;
--remain; --remain;
} }
} }
if(remain <= 0)
throw new Exception("Assertion failed"); if(remain <= 0) throw new Exception("Assertion failed");
result[result_off++] = 0x3A; // ':' result[result_off++] = 0x3A; // ':'
--remain; --remain;
if(bi < self.bhend - 1) if(bi < self.bhend - 1)
{ {
++bi; ++bi;
i = (int)self.bh[bi].dlen; i = (int)self.bh[bi].dlen;
if(i > remain) if(i > remain) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
Array.Copy(self.bh[bi].digest, 0, result, result_off, i); Array.Copy(self.bh[bi].digest, 0, result, result_off, i);
result_off += i; result_off += i;
remain -= i; remain -= i;
if(h != 0) if(h != 0)
{ {
if(remain <= 0) if(remain <= 0) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
h = self.bh[bi].halfh; h = self.bh[bi].halfh;
result[result_off] = b64[h % 64]; result[result_off] = b64[h % 64];
if(i < 3 || if(i < 3 || result[result_off] != result[result_off - 1] ||
result[result_off] != result[result_off - 1] || result[result_off] != result[result_off - 2] || result[result_off] != result[result_off - 3])
result[result_off] != result[result_off - 2] ||
result[result_off] != result[result_off - 3])
{ {
++result_off; ++result_off;
--remain; --remain;
@@ -408,13 +383,11 @@ namespace DiscImageChef.Checksums
i = self.bh[bi].halfdigest; i = self.bh[bi].halfdigest;
if(i != 0) if(i != 0)
{ {
if(remain <= 0) if(remain <= 0) throw new Exception("Assertion failed");
throw new Exception("Assertion failed");
result[result_off] = (byte)i; result[result_off] = (byte)i;
if(i < 3 || if(i < 3 || result[result_off] != result[result_off - 1] ||
result[result_off] != result[result_off - 1] || result[result_off] != result[result_off - 2] || result[result_off] != result[result_off - 3])
result[result_off] != result[result_off - 2] ||
result[result_off] != result[result_off - 3])
{ {
++result_off; ++result_off;
--remain; --remain;
@@ -424,15 +397,15 @@ namespace DiscImageChef.Checksums
} }
else if(h != 0) else if(h != 0)
{ {
if(self.bh[bi].dlen != 0) if(self.bh[bi].dlen != 0) throw new Exception("Assertion failed");
throw new Exception("Assertion failed"); if(remain <= 0) throw new Exception("Assertion failed");
if(remain <= 0)
throw new Exception("Assertion failed");
result[result_off++] = b64[self.bh[bi].h % 64]; result[result_off++] = b64[self.bh[bi].h % 64];
/* No need to bother with FUZZY_FLAG_ELIMSEQ, because this /* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
* digest has length 1. */ * digest has length 1. */
--remain; --remain;
} }
result[result_off] = 0; result[result_off] = 0;
return 0; return 0;
} }
@@ -515,8 +488,7 @@ namespace DiscImageChef.Checksums
for(int i = 0; i < CString.Length; i++) for(int i = 0; i < CString.Length; i++)
{ {
if(CString[i] == 0) if(CString[i] == 0) break;
break;
sb.Append(Encoding.ASCII.GetString(CString, i, 1)); sb.Append(Encoding.ASCII.GetString(CString, i, 1));
} }
@@ -524,5 +496,4 @@ namespace DiscImageChef.Checksums
return sb.ToString(); return sb.ToString();
} }
} }
} }

View File

@@ -883,4 +883,4 @@ namespace DiscImageChef.CommonTypes
FlashDrive FlashDrive
#endregion Generic hard disks #endregion Generic hard disks
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@@ -56,7 +56,10 @@ namespace DiscImageChef.CommonTypes
/// <summary>Information that does not find space in this struct</summary> /// <summary>Information that does not find space in this struct</summary>
public string Description; public string Description;
/// <summary>LBA of last partition sector</summary> /// <summary>LBA of last partition sector</summary>
public ulong End { get { return Start + Length - 1; }} public ulong End
{
get { return Start + Length - 1; }
}
/// <summary>Name of partition scheme that contains this partition</summary> /// <summary>Name of partition scheme that contains this partition</summary>
public string Scheme; public string Scheme;
@@ -67,10 +70,8 @@ namespace DiscImageChef.CommonTypes
public override bool Equals(Object obj) public override bool Equals(Object obj)
{ {
if(obj == null || !(obj is Partition)) if(obj == null || !(obj is Partition)) return false;
return false; else return Equals((Partition)obj);
else
return Equals((Partition)obj);
} }
public override int GetHashCode() public override int GetHashCode()
@@ -80,11 +81,9 @@ namespace DiscImageChef.CommonTypes
public int CompareTo(Partition other) public int CompareTo(Partition other)
{ {
if(Start == other.Start && End == other.End) if(Start == other.Start && End == other.End) return 0;
return 0;
if(Start > other.Start || End > other.End) if(Start > other.Start || End > other.End) return 1;
return 1;
return -1; return -1;
} }
@@ -125,5 +124,4 @@ namespace DiscImageChef.CommonTypes
return operand1.CompareTo(operand2) <= 0; return operand1.CompareTo(operand2) <= 0;
} }
} }
} }

View File

@@ -54,5 +54,4 @@ using System.Reflection;
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]

View File

@@ -33,13 +33,19 @@
namespace DiscImageChef.Console namespace DiscImageChef.Console
{ {
public delegate void WriteLineHandler(string format, params object[] arg); public delegate void WriteLineHandler(string format, params object[] arg);
public delegate void ErrorWriteLineHandler(string format, params object[] arg); public delegate void ErrorWriteLineHandler(string format, params object[] arg);
public delegate void VerboseWriteLineHandler(string format, params object[] arg); public delegate void VerboseWriteLineHandler(string format, params object[] arg);
public delegate void DebugWriteLineHandler(string format, params object[] arg); public delegate void DebugWriteLineHandler(string format, params object[] arg);
public delegate void WriteHandler(string format, params object[] arg); public delegate void WriteHandler(string format, params object[] arg);
public delegate void ErrorWriteHandler(string format, params object[] arg); public delegate void ErrorWriteHandler(string format, params object[] arg);
public delegate void VerboseWriteHandler(string format, params object[] arg); public delegate void VerboseWriteHandler(string format, params object[] arg);
public delegate void DebugWriteHandler(string format, params object[] arg); public delegate void DebugWriteHandler(string format, params object[] arg);
public static class DicConsole public static class DicConsole
@@ -56,124 +62,102 @@ namespace DiscImageChef.Console
public static void WriteLine(string format, params object[] arg) public static void WriteLine(string format, params object[] arg)
{ {
if(WriteLineEvent != null) if(WriteLineEvent != null) WriteLineEvent(format, arg);
WriteLineEvent(format, arg);
} }
public static void ErrorWriteLine(string format, params object[] arg) public static void ErrorWriteLine(string format, params object[] arg)
{ {
if(ErrorWriteLineEvent != null) if(ErrorWriteLineEvent != null) ErrorWriteLineEvent(format, arg);
ErrorWriteLineEvent(format, arg);
} }
public static void VerboseWriteLine(string format, params object[] arg) public static void VerboseWriteLine(string format, params object[] arg)
{ {
if(VerboseWriteLineEvent != null) if(VerboseWriteLineEvent != null) VerboseWriteLineEvent(format, arg);
VerboseWriteLineEvent(format, arg);
} }
public static void DebugWriteLine(string module, string format, params object[] arg) public static void DebugWriteLine(string module, string format, params object[] arg)
{ {
if(DebugWriteLineEvent != null) if(DebugWriteLineEvent != null) DebugWriteLineEvent("DEBUG (" + module + "): " + format, arg);
DebugWriteLineEvent("DEBUG (" + module + "): " + format, arg);
} }
public static void WriteLine() public static void WriteLine()
{ {
if(WriteLineEvent != null) if(WriteLineEvent != null) WriteLineEvent("", null);
WriteLineEvent("", null);
} }
public static void ErrorWriteLine() public static void ErrorWriteLine()
{ {
if(ErrorWriteLineEvent != null) if(ErrorWriteLineEvent != null) ErrorWriteLineEvent("", null);
ErrorWriteLineEvent("", null);
} }
public static void VerboseWriteLine() public static void VerboseWriteLine()
{ {
if(VerboseWriteLineEvent != null) if(VerboseWriteLineEvent != null) VerboseWriteLineEvent("", null);
VerboseWriteLineEvent("", null);
} }
public static void DebugWriteLine() public static void DebugWriteLine()
{ {
if(DebugWriteLineEvent != null) if(DebugWriteLineEvent != null) DebugWriteLineEvent("", null);
DebugWriteLineEvent("", null);
} }
public static void Write(string format, params object[] arg) public static void Write(string format, params object[] arg)
{ {
if(WriteEvent != null) if(WriteEvent != null) WriteEvent(format, arg);
WriteEvent(format, arg);
} }
public static void ErrorWrite(string format, params object[] arg) public static void ErrorWrite(string format, params object[] arg)
{ {
if(ErrorWriteEvent != null) if(ErrorWriteEvent != null) ErrorWriteEvent(format, arg);
ErrorWriteEvent(format, arg);
} }
public static void VerboseWrite(string format, params object[] arg) public static void VerboseWrite(string format, params object[] arg)
{ {
if(VerboseWriteEvent != null) if(VerboseWriteEvent != null) VerboseWriteEvent(format, arg);
VerboseWriteEvent(format, arg);
} }
public static void DebugWrite(string module, string format, params object[] arg) public static void DebugWrite(string module, string format, params object[] arg)
{ {
if(DebugWriteEvent != null) if(DebugWriteEvent != null) DebugWriteEvent("DEBUG (" + module + "): " + format, arg);
DebugWriteEvent("DEBUG (" + module + "): " + format, arg);
} }
public static void Write() public static void Write()
{ {
if(WriteEvent != null) if(WriteEvent != null) WriteEvent("", null);
WriteEvent("", null);
} }
public static void ErrorWrite() public static void ErrorWrite()
{ {
if(ErrorWriteEvent != null) if(ErrorWriteEvent != null) ErrorWriteEvent("", null);
ErrorWriteEvent("", null);
} }
public static void VerboseWrite() public static void VerboseWrite()
{ {
if(VerboseWriteEvent != null) if(VerboseWriteEvent != null) VerboseWriteEvent("", null);
VerboseWriteEvent("", null);
} }
public static void DebugWrite() public static void DebugWrite()
{ {
if(DebugWriteEvent != null) if(DebugWriteEvent != null) DebugWriteEvent("", null);
DebugWriteEvent("", null);
} }
public static void WriteLine(string format) public static void WriteLine(string format)
{ {
if(WriteLineEvent != null) if(WriteLineEvent != null) WriteLineEvent("{0}", format);
WriteLineEvent("{0}", format);
} }
public static void ErrorWriteLine(string format) public static void ErrorWriteLine(string format)
{ {
if(ErrorWriteLineEvent != null) if(ErrorWriteLineEvent != null) ErrorWriteLineEvent("{0}", format);
ErrorWriteLineEvent("{0}", format);
} }
public static void VerboseWriteLine(string format) public static void VerboseWriteLine(string format)
{ {
if(VerboseWriteLineEvent != null) if(VerboseWriteLineEvent != null) VerboseWriteLineEvent("{0}", format);
VerboseWriteLineEvent("{0}", format);
} }
public static void DebugWriteLine(string module, string format) public static void DebugWriteLine(string module, string format)
{ {
if(DebugWriteLineEvent != null) if(DebugWriteLineEvent != null) DebugWriteLineEvent("{0}", "DEBUG (" + module + "): " + format);
DebugWriteLineEvent("{0}", "DEBUG (" + module + "): " + format);
} }
} }
} }

View File

@@ -54,5 +54,4 @@ using System.Reflection;
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]

View File

@@ -30,7 +30,6 @@
// Copyright © 2011-2018 Natalia Portillo // Copyright © 2011-2018 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -69,8 +68,7 @@ namespace DiscImageChef.Core
public static void InitProgress() public static void InitProgress()
{ {
if(InitProgressEvent != null) if(InitProgressEvent != null) InitProgressEvent();
InitProgressEvent();
} }
public static void UpdateProgress(string text, int current, int maximum) public static void UpdateProgress(string text, int current, int maximum)
@@ -81,8 +79,7 @@ namespace DiscImageChef.Core
public static void EndProgress() public static void EndProgress()
{ {
if(EndProgressEvent != null) if(EndProgressEvent != null) EndProgressEvent();
EndProgressEvent();
} }
public static BenchmarkResults Do(int bufferSize, int blockSize) public static BenchmarkResults Do(int bufferSize, int blockSize)
@@ -108,6 +105,7 @@ namespace DiscImageChef.Core
rnd.NextBytes(tmp); rnd.NextBytes(tmp);
ms.Write(tmp, 0, blockSize); ms.Write(tmp, 0, blockSize);
} }
EndProgress(); EndProgress();
end = DateTime.Now; end = DateTime.Now;
@@ -116,10 +114,8 @@ namespace DiscImageChef.Core
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -128,13 +124,12 @@ namespace DiscImageChef.Core
byte[] tmp = new byte[blockSize]; byte[] tmp = new byte[blockSize];
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
} }
EndProgress(); EndProgress();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.readTime = (end - start).TotalSeconds; results.readTime = (end - start).TotalSeconds;
results.readSpeed = (bufferSize / 1048576) / (end - start).TotalSeconds; results.readSpeed = (bufferSize / 1048576) / (end - start).TotalSeconds;
@@ -144,10 +139,8 @@ namespace DiscImageChef.Core
((Adler32Context)ctx).Init(); ((Adler32Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -157,16 +150,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((Adler32Context)ctx).Update(tmp); ((Adler32Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((Adler32Context)ctx).End(); ((Adler32Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("Adler32", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("Adler32",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion Adler32 #endregion Adler32
@@ -175,10 +172,8 @@ namespace DiscImageChef.Core
((CRC16Context)ctx).Init(); ((CRC16Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -188,16 +183,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((CRC16Context)ctx).Update(tmp); ((CRC16Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((CRC16Context)ctx).End(); ((CRC16Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("CRC16", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("CRC16",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion CRC16 #endregion CRC16
@@ -206,10 +205,8 @@ namespace DiscImageChef.Core
((CRC32Context)ctx).Init(); ((CRC32Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -219,16 +216,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((CRC32Context)ctx).Update(tmp); ((CRC32Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((CRC32Context)ctx).End(); ((CRC32Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("CRC32", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("CRC32",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion CRC32 #endregion CRC32
@@ -237,10 +238,8 @@ namespace DiscImageChef.Core
((CRC64Context)ctx).Init(); ((CRC64Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -250,16 +249,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((CRC64Context)ctx).Update(tmp); ((CRC64Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((CRC64Context)ctx).End(); ((CRC64Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("CRC64", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("CRC64",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion CRC64 #endregion CRC64
@@ -268,10 +271,8 @@ namespace DiscImageChef.Core
((MD5Context)ctx).Init(); ((MD5Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -281,16 +282,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((MD5Context)ctx).Update(tmp); ((MD5Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((MD5Context)ctx).End(); ((MD5Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("MD5", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("MD5",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion MD5 #endregion MD5
@@ -299,10 +304,8 @@ namespace DiscImageChef.Core
((RIPEMD160Context)ctx).Init(); ((RIPEMD160Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -312,16 +315,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((RIPEMD160Context)ctx).Update(tmp); ((RIPEMD160Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((RIPEMD160Context)ctx).End(); ((RIPEMD160Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("RIPEMD160", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("RIPEMD160",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion RIPEMD160 #endregion RIPEMD160
@@ -330,10 +337,8 @@ namespace DiscImageChef.Core
((SHA1Context)ctx).Init(); ((SHA1Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -343,16 +348,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((SHA1Context)ctx).Update(tmp); ((SHA1Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((SHA1Context)ctx).End(); ((SHA1Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("SHA1", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("SHA1",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion SHA1 #endregion SHA1
@@ -361,10 +370,8 @@ namespace DiscImageChef.Core
((SHA256Context)ctx).Init(); ((SHA256Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -374,16 +381,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((SHA256Context)ctx).Update(tmp); ((SHA256Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((SHA256Context)ctx).End(); ((SHA256Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("SHA256", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("SHA256",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion SHA256 #endregion SHA256
@@ -392,10 +403,8 @@ namespace DiscImageChef.Core
((SHA384Context)ctx).Init(); ((SHA384Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -405,16 +414,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((SHA384Context)ctx).Update(tmp); ((SHA384Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((SHA384Context)ctx).End(); ((SHA384Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("SHA384", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("SHA384",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion SHA384 #endregion SHA384
@@ -423,10 +436,8 @@ namespace DiscImageChef.Core
((SHA512Context)ctx).Init(); ((SHA512Context)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -436,16 +447,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((SHA512Context)ctx).Update(tmp); ((SHA512Context)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((SHA512Context)ctx).End(); ((SHA512Context)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("SHA512", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("SHA512",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion SHA512 #endregion SHA512
@@ -454,10 +469,8 @@ namespace DiscImageChef.Core
((SpamSumContext)ctx).Init(); ((SpamSumContext)ctx).Init();
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -467,16 +480,20 @@ namespace DiscImageChef.Core
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
((SpamSumContext)ctx).Update(tmp); ((SpamSumContext)ctx).Update(tmp);
} }
EndProgress(); EndProgress();
((SpamSumContext)ctx).End(); ((SpamSumContext)ctx).End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entries.Add("SpamSum", new BenchmarkEntry() { timeSpan = (end - start).TotalSeconds, speed = (bufferSize / 1048576) / (end - start).TotalSeconds }); results.entries.Add("SpamSum",
new BenchmarkEntry()
{
timeSpan = (end - start).TotalSeconds,
speed = (bufferSize / 1048576) / (end - start).TotalSeconds
});
results.separateTime += (end - start).TotalSeconds; results.separateTime += (end - start).TotalSeconds;
#endregion SpamSum #endregion SpamSum
@@ -484,10 +501,8 @@ namespace DiscImageChef.Core
ulong[] entTable = new ulong[256]; ulong[] entTable = new ulong[256];
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
start = DateTime.Now; start = DateTime.Now;
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
@@ -495,9 +510,9 @@ namespace DiscImageChef.Core
UpdateProgress("Entropying block {0} of {1}.", i + 1, bufferSize / blockSize); UpdateProgress("Entropying block {0} of {1}.", i + 1, bufferSize / blockSize);
byte[] tmp = new byte[blockSize]; byte[] tmp = new byte[blockSize];
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
foreach(byte b in tmp) foreach(byte b in tmp) entTable[b]++;
entTable[b]++;
} }
EndProgress(); EndProgress();
double entropy = 0; double entropy = 0;
foreach(ulong l in entTable) foreach(ulong l in entTable)
@@ -507,12 +522,11 @@ namespace DiscImageChef.Core
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
entropy += -(frequency * Math.Log(frequency, 2)); entropy += -(frequency * Math.Log(frequency, 2));
} }
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.entropyTime = (end - start).TotalSeconds; results.entropyTime = (end - start).TotalSeconds;
results.entropySpeed = (bufferSize / 1048576) / (end - start).TotalSeconds; results.entropySpeed = (bufferSize / 1048576) / (end - start).TotalSeconds;
@@ -524,21 +538,21 @@ namespace DiscImageChef.Core
InitProgress(); InitProgress();
for(int i = 0; i < bufferSize / blockSize; i++) for(int i = 0; i < bufferSize / blockSize; i++)
{ {
UpdateProgress("Checksumming block {0} of {1} with all algorithms at the same time.", i + 1, bufferSize / blockSize); UpdateProgress("Checksumming block {0} of {1} with all algorithms at the same time.", i + 1,
bufferSize / blockSize);
byte[] tmp = new byte[blockSize]; byte[] tmp = new byte[blockSize];
ms.Read(tmp, 0, blockSize); ms.Read(tmp, 0, blockSize);
allChecksums.Update(tmp); allChecksums.Update(tmp);
} }
EndProgress(); EndProgress();
allChecksums.End(); allChecksums.End();
end = DateTime.Now; end = DateTime.Now;
mem = GC.GetTotalMemory(false); mem = GC.GetTotalMemory(false);
if(mem > results.maxMemory) if(mem > results.maxMemory) results.maxMemory = mem;
results.maxMemory = mem; if(mem < results.minMemory) results.minMemory = mem;
if(mem < results.minMemory)
results.minMemory = mem;
results.totalTime = (end - start).TotalSeconds; results.totalTime = (end - start).TotalSeconds;
results.totalSpeed = (bufferSize / 1048576) / results.totalTime; results.totalSpeed = (bufferSize / 1048576) / results.totalTime;
@@ -549,4 +563,4 @@ namespace DiscImageChef.Core
return results; return results;
} }
} }
} }

View File

@@ -30,7 +30,6 @@
// Copyright © 2011-2018 Natalia Portillo // Copyright © 2011-2018 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
@@ -268,37 +267,21 @@ namespace DiscImageChef.Core
spamsumThread.Start(spamsumPkt); spamsumThread.Start(spamsumPkt);
} }
while(adlerThread.IsAlive || crc16Thread.IsAlive || while(adlerThread.IsAlive || crc16Thread.IsAlive || crc32Thread.IsAlive || crc64Thread.IsAlive ||
crc32Thread.IsAlive || crc64Thread.IsAlive || md5Thread.IsAlive || ripemd160Thread.IsAlive || sha1Thread.IsAlive || sha256Thread.IsAlive ||
md5Thread.IsAlive || ripemd160Thread.IsAlive || sha384Thread.IsAlive || sha512Thread.IsAlive || spamsumThread.IsAlive) { }
sha1Thread.IsAlive || sha256Thread.IsAlive ||
sha384Thread.IsAlive || sha512Thread.IsAlive ||
spamsumThread.IsAlive)
{
}
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) adlerThread = new Thread(updateAdler);
adlerThread = new Thread(updateAdler); if(enabled.HasFlag(EnableChecksum.SpamSum)) crc16Thread = new Thread(updateCRC16);
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) crc32Thread = new Thread(updateCRC32);
crc16Thread = new Thread(updateCRC16); if(enabled.HasFlag(EnableChecksum.SpamSum)) crc64Thread = new Thread(updateCRC64);
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) md5Thread = new Thread(updateMD5);
crc32Thread = new Thread(updateCRC32); if(enabled.HasFlag(EnableChecksum.SpamSum)) ripemd160Thread = new Thread(updateRIPEMD160);
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) sha1Thread = new Thread(updateSHA1);
crc64Thread = new Thread(updateCRC64); if(enabled.HasFlag(EnableChecksum.SpamSum)) sha256Thread = new Thread(updateSHA256);
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) sha384Thread = new Thread(updateSHA384);
md5Thread = new Thread(updateMD5); if(enabled.HasFlag(EnableChecksum.SpamSum)) sha512Thread = new Thread(updateSHA512);
if(enabled.HasFlag(EnableChecksum.SpamSum)) if(enabled.HasFlag(EnableChecksum.SpamSum)) spamsumThread = new Thread(updateSpamSum);
ripemd160Thread = new Thread(updateRIPEMD160);
if(enabled.HasFlag(EnableChecksum.SpamSum))
sha1Thread = new Thread(updateSHA1);
if(enabled.HasFlag(EnableChecksum.SpamSum))
sha256Thread = new Thread(updateSHA256);
if(enabled.HasFlag(EnableChecksum.SpamSum))
sha384Thread = new Thread(updateSHA384);
if(enabled.HasFlag(EnableChecksum.SpamSum))
sha512Thread = new Thread(updateSHA512);
if(enabled.HasFlag(EnableChecksum.SpamSum))
spamsumThread = new Thread(updateSpamSum);
} }
public List<ChecksumType> End() public List<ChecksumType> End()
@@ -546,15 +529,10 @@ namespace DiscImageChef.Core
spamsumThreadData.Start(spamsumPktData); spamsumThreadData.Start(spamsumPktData);
} }
while(adlerThreadData.IsAlive || crc16ThreadData.IsAlive || crc32ThreadData.IsAlive ||
while(adlerThreadData.IsAlive || crc16ThreadData.IsAlive || crc64ThreadData.IsAlive || md5ThreadData.IsAlive || ripemd160ThreadData.IsAlive ||
crc32ThreadData.IsAlive || crc64ThreadData.IsAlive || sha1ThreadData.IsAlive || sha256ThreadData.IsAlive || sha384ThreadData.IsAlive ||
md5ThreadData.IsAlive || ripemd160ThreadData.IsAlive || sha512ThreadData.IsAlive || spamsumThreadData.IsAlive) { }
sha1ThreadData.IsAlive || sha256ThreadData.IsAlive ||
sha384ThreadData.IsAlive || sha512ThreadData.IsAlive ||
spamsumThreadData.IsAlive)
{
}
List<ChecksumType> dataChecksums = new List<ChecksumType>(); List<ChecksumType> dataChecksums = new List<ChecksumType>();
ChecksumType chk; ChecksumType chk;
@@ -651,7 +629,6 @@ namespace DiscImageChef.Core
} }
#region Threading helpers #region Threading helpers
struct adlerPacket struct adlerPacket
{ {
public Adler32Context context; public Adler32Context context;
@@ -772,7 +749,6 @@ namespace DiscImageChef.Core
{ {
((spamsumPacket)packet).context.Update(((spamsumPacket)packet).data); ((spamsumPacket)packet).context.Update(((spamsumPacket)packet).data);
} }
#endregion Threading helpers #endregion Threading helpers
} }
} }

View File

@@ -46,8 +46,7 @@ namespace DiscImageChef.Core
public void Close() public void Close()
{ {
if(dataFs != null) if(dataFs != null) dataFs.Close();
dataFs.Close();
} }
public int Read(byte[] array, int offset, int count) public int Read(byte[] array, int offset, int count)
@@ -91,7 +90,10 @@ namespace DiscImageChef.Core
dataFs.Write(data, offset, count); dataFs.Write(data, offset, count);
} }
public long Position { get { return dataFs.Position; }} public long Position
{
get { return dataFs.Position; }
}
public static void WriteTo(string who, string outputPrefix, string outputSuffix, string what, byte[] data) public static void WriteTo(string who, string outputPrefix, string outputSuffix, string what, byte[] data)
{ {
@@ -99,14 +101,14 @@ namespace DiscImageChef.Core
WriteTo(who, outputPrefix + outputSuffix, data, what); WriteTo(who, outputPrefix + outputSuffix, data, what);
} }
public static void WriteTo(string who, string filename, byte[] data, string whatWriting = null, bool overwrite = false) public static void WriteTo(string who, string filename, byte[] data, string whatWriting = null,
bool overwrite = false)
{ {
if(!string.IsNullOrEmpty(filename)) if(!string.IsNullOrEmpty(filename))
{ {
if(File.Exists(filename)) if(File.Exists(filename))
{ {
if(overwrite) if(overwrite) File.Delete(filename);
File.Delete(filename);
else else
{ {
DicConsole.ErrorWriteLine("Not overwriting file {0}", filename); DicConsole.ErrorWriteLine("Not overwriting file {0}", filename);
@@ -121,11 +123,8 @@ namespace DiscImageChef.Core
outputFs.Write(data, 0, data.Length); outputFs.Write(data, 0, data.Length);
outputFs.Close(); outputFs.Close();
} }
catch catch { DicConsole.ErrorWriteLine("Unable to write file {0}", filename); }
{
DicConsole.ErrorWriteLine("Unable to write file {0}", filename);
}
} }
} }
} }
} }

View File

@@ -30,21 +30,23 @@
// Copyright © 2011-2018 Natalia Portillo // Copyright © 2011-2018 Natalia Portillo
// ****************************************************************************/ // ****************************************************************************/
namespace DiscImageChef.Core namespace DiscImageChef.Core
{ {
/// <summary> /// <summary>
/// Initializates a progress indicator (e.g. makes a progress bar visible) /// Initializates a progress indicator (e.g. makes a progress bar visible)
/// </summary> /// </summary>
public delegate void InitProgressHandler(); public delegate void InitProgressHandler();
/// <summary> /// <summary>
/// Updates a progress indicator with text /// Updates a progress indicator with text
/// </summary> /// </summary>
public delegate void UpdateProgressHandler(string text, long current, long maximum); public delegate void UpdateProgressHandler(string text, long current, long maximum);
/// <summary> /// <summary>
/// Pulses a progress indicator with indeterminate boundaries /// Pulses a progress indicator with indeterminate boundaries
/// </summary> /// </summary>
public delegate void PulseProgressHandler(string text); public delegate void PulseProgressHandler(string text);
/// <summary> /// <summary>
/// Uninitializates a progress indicator (e.g. adds a newline to the console) /// Uninitializates a progress indicator (e.g. adds a newline to the console)
/// </summary> /// </summary>
@@ -54,14 +56,17 @@ namespace DiscImageChef.Core
/// Initializates a secondary progress indicator (e.g. makes a progress bar visible) /// Initializates a secondary progress indicator (e.g. makes a progress bar visible)
/// </summary> /// </summary>
public delegate void InitProgressHandler2(); public delegate void InitProgressHandler2();
/// <summary> /// <summary>
/// Updates a secondary progress indicator with text /// Updates a secondary progress indicator with text
/// </summary> /// </summary>
public delegate void UpdateProgressHandler2(string text, long current, long maximum); public delegate void UpdateProgressHandler2(string text, long current, long maximum);
/// <summary> /// <summary>
/// Pulses a secondary progress indicator with indeterminate boundaries /// Pulses a secondary progress indicator with indeterminate boundaries
/// </summary> /// </summary>
public delegate void PulseProgressHandler2(string text); public delegate void PulseProgressHandler2(string text);
/// <summary> /// <summary>
/// Uninitializates a secondary progress indicator (e.g. adds a newline to the console) /// Uninitializates a secondary progress indicator (e.g. adds a newline to the console)
/// </summary> /// </summary>
@@ -71,14 +76,18 @@ namespace DiscImageChef.Core
/// Initializates two progress indicators (e.g. makes a progress bar visible) /// Initializates two progress indicators (e.g. makes a progress bar visible)
/// </summary> /// </summary>
public delegate void InitTwoProgressHandler(); public delegate void InitTwoProgressHandler();
/// <summary> /// <summary>
/// Updates two progress indicators with text /// Updates two progress indicators with text
/// </summary> /// </summary>
public delegate void UpdateTwoProgressHandler(string text, long current, long maximum, string text2, long current2, long maximum2); public delegate void UpdateTwoProgressHandler(string text, long current, long maximum, string text2, long current2,
long maximum2);
/// <summary> /// <summary>
/// Pulses a progress indicator with indeterminate boundaries /// Pulses a progress indicator with indeterminate boundaries
/// </summary> /// </summary>
public delegate void PulseTwoProgressHandler(string text, string text2); public delegate void PulseTwoProgressHandler(string text, string text2);
/// <summary> /// <summary>
/// Uninitializates a progress indicator (e.g. adds a newline to the console) /// Uninitializates a progress indicator (e.g. adds a newline to the console)
/// </summary> /// </summary>
@@ -88,4 +97,4 @@ namespace DiscImageChef.Core
/// Updates a status indicator /// Updates a status indicator
/// </summary> /// </summary>
public delegate void UpdateStatusHandler(string text); public delegate void UpdateStatusHandler(string text);
} }

View File

@@ -50,7 +50,9 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
public class ATA public class ATA
{ {
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding) public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
ref DumpLog dumpLog, Encoding encoding)
{ {
bool aborted; bool aborted;
MHDDLog mhddLog; MHDDLog mhddLog;
@@ -60,8 +62,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.ErrorWriteLine("Raw dumping not yet supported in ATA devices."); DicConsole.ErrorWriteLine("Raw dumping not yet supported in ATA devices.");
if(force) if(force) DicConsole.ErrorWriteLine("Continuing...");
DicConsole.ErrorWriteLine("Continuing...");
else else
{ {
DicConsole.ErrorWriteLine("Aborting..."); DicConsole.ErrorWriteLine("Aborting...");
@@ -80,10 +81,8 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
Decoders.ATA.Identify.IdentifyDevice ataId = Decoders.ATA.Identify.Decode(cmdBuf).Value; Decoders.ATA.Identify.IdentifyDevice ataId = Decoders.ATA.Identify.Decode(cmdBuf).Value;
CICMMetadataType sidecar = new CICMMetadataType() CICMMetadataType sidecar =
{ new CICMMetadataType() {BlockMedia = new BlockMediaType[] {new BlockMediaType()}};
BlockMedia = new BlockMediaType[] { new BlockMediaType() }
};
if(dev.IsUSB) if(dev.IsUSB)
{ {
@@ -123,7 +122,8 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
if(tuple.Code == TupleCodes.CISTPL_MANFID) if(tuple.Code == TupleCodes.CISTPL_MANFID)
{ {
ManufacturerIdentificationTuple manfid = CIS.DecodeManufacturerIdentificationTuple(tuple); ManufacturerIdentificationTuple manfid =
CIS.DecodeManufacturerIdentificationTuple(tuple);
if(manfid != null) if(manfid != null)
{ {
@@ -141,7 +141,8 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer; sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product; sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
sidecar.BlockMedia[0].PCMCIA.Compliance = string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion); sidecar.BlockMedia[0].PCMCIA.Compliance =
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation; sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
} }
} }
@@ -170,10 +171,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksum dataChk; Checksum dataChk;
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
DataFile dumpFile; DataFile dumpFile;
@@ -189,6 +187,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine(ataReader.ErrorMessage); DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
return; return;
} }
uint blockSize = ataReader.LogicalBlockSize; uint blockSize = ataReader.LogicalBlockSize;
uint physicalsectorsize = ataReader.PhysicalBlockSize; uint physicalsectorsize = ataReader.PhysicalBlockSize;
if(ataReader.FindReadCommand()) if(ataReader.FindReadCommand())
@@ -204,21 +203,27 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine(ataReader.ErrorMessage); DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
return; return;
} }
uint blocksToRead = ataReader.BlocksToRead; uint blocksToRead = ataReader.BlocksToRead;
ushort cylinders = ataReader.Cylinders; ushort cylinders = ataReader.Cylinders;
byte heads = ataReader.Heads; byte heads = ataReader.Heads;
byte sectors = ataReader.Sectors; byte sectors = ataReader.Sectors;
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize); dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads, sectors); dumpLog.WriteLine("Device reports {0} cylinders {1} heads {2} sectors per track.", cylinders, heads,
sectors);
dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead); dumpLog.WriteLine("Device can read {0} blocks at a time.", blocksToRead);
dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize); dumpLog.WriteLine("Device reports {0} bytes per logical block.", blockSize);
dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize); dumpLog.WriteLine("Device reports {0} bytes per physical block.", physicalsectorsize);
bool removable = false || (!dev.IsCompactFlash && ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable)); bool removable = false || (!dev.IsCompactFlash &&
ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify
.GeneralConfigurationBit
.Removable));
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(ataReader.IsLBA, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(ataReader.IsLBA, removable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
dev.PlatformID, ref resume, ref currentTry, ref extents);
if(currentTry == null || extents == null) if(currentTry == null || extents == null)
throw new Exception("Could not process resume file, not continuing..."); throw new Exception("Could not process resume file, not continuing...");
@@ -229,8 +234,7 @@ namespace DiscImageChef.Core.Devices.Dumping
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile); ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
dumpFile = new DataFile(outputPrefix + ".bin"); dumpFile = new DataFile(outputPrefix + ".bin");
if(resume.NextBlock > 0) if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpFile.Seek(resume.NextBlock, blockSize); dumpFile.Seek(resume.NextBlock, blockSize);
@@ -244,14 +248,11 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
blocksToRead = (byte)(blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -267,12 +268,10 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
else else
{ {
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
resume.BadBlocks.Add(b);
if(duration < 500) if(duration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, duration);
else
mhddLog.Write(i, duration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpFile.Write(new byte[blockSize * blocksToRead]); dumpFile.Write(new byte[blockSize * blocksToRead]);
@@ -285,14 +284,18 @@ namespace DiscImageChef.Core.Devices.Dumping
GC.Collect(); GC.Collect();
resume.NextBlock = i + blocksToRead; resume.NextBlock = i + blocksToRead;
} }
end = DateTime.Now; end = DateTime.Now;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000),
devicePath);
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted) if(resume.BadBlocks.Count > 0 && !aborted)
@@ -301,7 +304,7 @@ namespace DiscImageChef.Core.Devices.Dumping
bool forward = true; bool forward = true;
bool runningPersistent = false; bool runningPersistent = false;
repeatRetryLba: repeatRetryLba:
ulong[] tmpArray = resume.BadBlocks.ToArray(); ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray) foreach(ulong badSector in tmpArray)
{ {
@@ -312,7 +315,9 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "");
bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration); bool error = ataReader.ReadBlock(out cmdBuf, badSector, out duration);
@@ -325,8 +330,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile.WriteAt(cmdBuf, badSector, blockSize); dumpFile.WriteAt(cmdBuf, badSector, blockSize);
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass); dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
} }
else if(runningPersistent) else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
} }
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0) if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
@@ -367,13 +371,12 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", Cy, Hd, Sc, currentSpeed); DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", Cy, Hd,
Sc, currentSpeed);
bool error = ataReader.ReadCHS(out cmdBuf, Cy, Hd, Sc, out duration); bool error = ataReader.ReadCHS(out cmdBuf, Cy, Hd, Sc, out duration);
@@ -390,10 +393,8 @@ namespace DiscImageChef.Core.Devices.Dumping
else else
{ {
resume.BadBlocks.Add(currentBlock); resume.BadBlocks.Add(currentBlock);
if(duration < 500) if(duration < 500) mhddLog.Write(currentBlock, 65535);
mhddLog.Write(currentBlock, 65535); else mhddLog.Write(currentBlock, duration);
else
mhddLog.Write(currentBlock, duration);
ibgLog.Write(currentBlock, 0); ibgLog.Write(currentBlock, 0);
dumpFile.Write(new byte[blockSize]); dumpFile.Write(new byte[blockSize]);
@@ -408,15 +409,20 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
} }
end = DateTime.Now; end = DateTime.Now;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000),
devicePath);
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
} }
dataChk = new Checksum(); dataChk = new Checksum();
dumpFile.Seek(0, SeekOrigin.Begin); dumpFile.Seek(0, SeekOrigin.Begin);
blocksToRead = 500; blocksToRead = 500;
@@ -430,8 +436,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
blocksToRead = (byte)(blocks - i);
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -446,11 +451,13 @@ namespace DiscImageChef.Core.Devices.Dumping
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
dumpFile.Close(); dumpFile.Close();
end = DateTime.UtcNow; end = DateTime.UtcNow;
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
PluginBase plugins = new PluginBase(); PluginBase plugins = new PluginBase();
plugins.RegisterAllPlugins(encoding); plugins.RegisterAllPlugins(encoding);
@@ -468,15 +475,8 @@ namespace DiscImageChef.Core.Devices.Dumping
_imageFormat = ImageFormat.Detect(inputFilter); _imageFormat = ImageFormat.Detect(inputFilter);
PartitionType[] xmlFileSysInfo = null; PartitionType[] xmlFileSysInfo = null;
try try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
{ catch { _imageFormat = null; }
if(!_imageFormat.OpenImage(inputFilter))
_imageFormat = null;
}
catch
{
_imageFormat = null;
}
if(_imageFormat != null) if(_imageFormat != null)
{ {
@@ -500,8 +500,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Type = partitions[i].Type Type = partitions[i].Type
}; };
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.", dumpLog
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); .WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
i, partitions[i].Start, partitions[i].End, partitions[i].Type,
partitions[i].Scheme);
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -523,8 +525,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
} }
} }
else else
@@ -532,11 +533,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Getting filesystem for whole device."); dumpLog.WriteLine("Getting filesystem for whole device.");
xmlFileSysInfo = new PartitionType[1]; xmlFileSysInfo = new PartitionType[1];
xmlFileSysInfo[0] = new PartitionType xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
{
EndSector = (int)(blocks - 1),
StartSector = 0
};
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
Partition wholePart = new Partition Partition wholePart = new Partition
@@ -566,8 +563,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
} }
} }
@@ -577,8 +573,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash, out xmlDskTyp, out xmlDskSubTyp); Metadata.MediaType.MediaTypeToString(MediaType.CompactFlash, out xmlDskTyp, out xmlDskSubTyp);
else if(dev.IsPCMCIA) else if(dev.IsPCMCIA)
Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI, out xmlDskTyp, out xmlDskSubTyp); Metadata.MediaType.MediaTypeToString(MediaType.PCCardTypeI, out xmlDskTyp, out xmlDskSubTyp);
else else Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
Metadata.MediaType.MediaTypeToString(MediaType.GENERIC_HDD, out xmlDskTyp, out xmlDskSubTyp);
sidecar.BlockMedia[0].DiskType = xmlDskTyp; sidecar.BlockMedia[0].DiskType = xmlDskTyp;
sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp; sidecar.BlockMedia[0].DiskSubType = xmlDskSubTyp;
// TODO: Implement device firmware revision // TODO: Implement device firmware revision
@@ -595,8 +590,7 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.BlockMedia[0].Model = dev.Model; sidecar.BlockMedia[0].Model = dev.Model;
sidecar.BlockMedia[0].Serial = dev.Serial; sidecar.BlockMedia[0].Serial = dev.Serial;
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize); sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
if(xmlFileSysInfo != null) if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
if(cylinders > 0 && heads > 0 && sectors > 0) if(cylinders > 0 && heads > 0 && sectors > 0)
{ {
sidecar.BlockMedia[0].Cylinders = cylinders; sidecar.BlockMedia[0].Cylinders = cylinders;
@@ -609,31 +603,31 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000)); (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed); DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count); DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count);
if(resume.BadBlocks.Count > 0) if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
resume.BadBlocks.Sort();
DicConsole.WriteLine(); DicConsole.WriteLine();
if(!aborted) if(!aborted)
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
} }
Statistics.AddMedia(MediaType.GENERIC_HDD, true); Statistics.AddMedia(MediaType.GENERIC_HDD, true);
} }
else else DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
DicConsole.ErrorWriteLine("Unable to communicate with ATA device.");
} }
} }
} }

View File

@@ -47,23 +47,17 @@ namespace DiscImageChef.Core.Devices.Dumping
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct AlcoholHeader struct AlcoholHeader
{ {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string signature;
public string signature; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] version;
public AlcoholMediumType type; public AlcoholMediumType type;
public ushort sessions; public ushort sessions;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public ushort[] unknown1;
public ushort[] unknown1;
public ushort bcaLength; public ushort bcaLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public uint[] unknown2;
public uint[] unknown2;
public uint bcaOffset; public uint bcaOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public uint[] unknown3;
public uint[] unknown3;
public uint structuresOffset; public uint structuresOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public uint[] unknown4;
public uint[] unknown4;
public uint sessionOffset; public uint sessionOffset;
public uint dpmOffset; public uint dpmOffset;
} }
@@ -99,14 +93,12 @@ namespace DiscImageChef.Core.Devices.Dumping
public byte pframe; public byte pframe;
public uint extraOffset; public uint extraOffset;
public ushort sectorSize; public ushort sectorSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] public byte[] unknown;
public byte[] unknown;
public uint startLba; public uint startLba;
public ulong startOffset; public ulong startOffset;
public uint files; public uint files;
public uint footerOffset; public uint footerOffset;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public byte[] unknown2;
public byte[] unknown2;
} }
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -172,24 +164,23 @@ namespace DiscImageChef.Core.Devices.Dumping
header = new AlcoholHeader header = new AlcoholHeader
{ {
signature = "MEDIA DESCRIPTOR", signature = "MEDIA DESCRIPTOR",
unknown1 = new ushort[] { 0x0002, 0x0000 }, unknown1 = new ushort[] {0x0002, 0x0000},
unknown2 = new uint[2], unknown2 = new uint[2],
unknown3 = new uint[6], unknown3 = new uint[6],
unknown4 = new uint[3], unknown4 = new uint[3],
version = new byte[] { 1, 5 } version = new byte[] {1, 5}
}; };
header.version[0] = 1; header.version[0] = 1;
header.version[1] = 5; header.version[1] = 5;
tracks = new List<AlcoholTrack>(); tracks = new List<AlcoholTrack>();
sessions = new List<AlcoholSession>(); sessions = new List<AlcoholSession>();
trackLengths = new Dictionary<byte, uint>(); trackLengths = new Dictionary<byte, uint>();
footer = new AlcoholFooter { widechar = 1 }; footer = new AlcoholFooter {widechar = 1};
} }
public void Close() public void Close()
{ {
if(sessions.Count == 0 || tracks.Count == 0) if(sessions.Count == 0 || tracks.Count == 0) return;
return;
// Calculate first offsets // Calculate first offsets
header.sessions = (ushort)sessions.Count; header.sessions = (ushort)sessions.Count;
@@ -201,7 +192,7 @@ namespace DiscImageChef.Core.Devices.Dumping
for(int i = 0; i < sessionsArray.Length; i++) for(int i = 0; i < sessionsArray.Length; i++)
{ {
sessionsArray[i].allBlocks = (byte)(((sessionsArray[i].lastTrack - sessionsArray[i].firstTrack) + 1) + sessionsArray[i].allBlocks = (byte)(((sessionsArray[i].lastTrack - sessionsArray[i].firstTrack) + 1) +
sessionsArray[i].nonTrackBlocks); sessionsArray[i].nonTrackBlocks);
sessionsArray[i].trackOffset = (uint)nextOffset; sessionsArray[i].trackOffset = (uint)nextOffset;
nextOffset += sessionsArray[i].allBlocks * 80; nextOffset += sessionsArray[i].allBlocks * 80;
} }
@@ -214,10 +205,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(tracksArray[i].point >= 0xA0) continue; if(tracksArray[i].point >= 0xA0) continue;
if(!trackLengths.TryGetValue(tracksArray[i].point, out uint trkLen)) continue; if(!trackLengths.TryGetValue(tracksArray[i].point, out uint trkLen)) continue;
if(tracksArray[i].mode == AlcoholTrackMode.DVD) if(tracksArray[i].mode == AlcoholTrackMode.DVD) { tracksArray[i].extraOffset = trkLen; }
{
tracksArray[i].extraOffset = trkLen;
}
else else
{ {
AlcoholTrackExtra extra = new AlcoholTrackExtra(); AlcoholTrackExtra extra = new AlcoholTrackExtra();
@@ -247,15 +235,15 @@ namespace DiscImageChef.Core.Devices.Dumping
nextOffset += 4100; nextOffset += 4100;
} }
for(int i = 0; i < tracksArray.Length; i++) for(int i = 0; i < tracksArray.Length; i++) tracksArray[i].footerOffset = (uint)nextOffset;
tracksArray[i].footerOffset = (uint)nextOffset;
footer.filenameOffset = (uint)(nextOffset + 16); footer.filenameOffset = (uint)(nextOffset + 16);
byte[] filename = Encoding.Unicode.GetBytes(outputPrefix + extension); byte[] filename = Encoding.Unicode.GetBytes(outputPrefix + extension);
// Open descriptor file here // Open descriptor file here
FileStream descriptorFile = new FileStream(outputPrefix + ".mds", FileMode.Create, FileAccess.ReadWrite, FileShare.None); FileStream descriptorFile =
new FileStream(outputPrefix + ".mds", FileMode.Create, FileAccess.ReadWrite, FileShare.None);
byte[] tmp = new byte[88]; byte[] tmp = new byte[88];
IntPtr hdrPtr = Marshal.AllocHGlobal(88); IntPtr hdrPtr = Marshal.AllocHGlobal(88);
@@ -284,7 +272,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Marshal.FreeHGlobal(trkPtr); Marshal.FreeHGlobal(trkPtr);
} }
if(header.type == AlcoholMediumType.CD || header.type == AlcoholMediumType.CDR || header.type == AlcoholMediumType.CDRW) if(header.type == AlcoholMediumType.CD || header.type == AlcoholMediumType.CDR ||
header.type == AlcoholMediumType.CDRW)
{ {
foreach(AlcoholTrackExtra extra in extrasArray) foreach(AlcoholTrackExtra extra in extrasArray)
{ {
@@ -429,8 +418,7 @@ namespace DiscImageChef.Core.Devices.Dumping
case TrackType.CDMode2Form2: case TrackType.CDMode2Form2:
trkArray[i].mode = AlcoholTrackMode.Mode2F2; trkArray[i].mode = AlcoholTrackMode.Mode2F2;
break; break;
default: default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
} }
switch(subMode) switch(subMode)
@@ -447,8 +435,7 @@ namespace DiscImageChef.Core.Devices.Dumping
case TrackSubchannelType.Q16: case TrackSubchannelType.Q16:
case TrackSubchannelType.Q16Interleaved: case TrackSubchannelType.Q16Interleaved:
throw new FeatureUnsupportedImageException("Specified subchannel type is not supported."); throw new FeatureUnsupportedImageException("Specified subchannel type is not supported.");
default: default: throw new ArgumentOutOfRangeException(nameof(subMode), subMode, null);
throw new ArgumentOutOfRangeException(nameof(subMode), subMode, null);
} }
tracks = new List<AlcoholTrack>(trkArray); tracks = new List<AlcoholTrack>(trkArray);
@@ -472,8 +459,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if(trackLengths.ContainsKey(point)) if(trackLengths.ContainsKey(point)) trackLengths.Remove(point);
trackLengths.Remove(point);
trackLengths.Add(point, (uint)length); trackLengths.Add(point, (uint)length);
@@ -481,18 +467,15 @@ namespace DiscImageChef.Core.Devices.Dumping
for(int i = 0; i < sess.Length; i++) for(int i = 0; i < sess.Length; i++)
{ {
if(sess[i].firstTrack == point) if(sess[i].firstTrack == point) sess[i].sessionStart = (int)startLba;
sess[i].sessionStart = (int)startLba; if(sess[i].lastTrack == point) sess[i].sessionEnd = (int)(startLba + length);
if(sess[i].lastTrack == point)
sess[i].sessionEnd = (int)(startLba + length);
} }
sessions = new List<AlcoholSession>(sess); sessions = new List<AlcoholSession>(sess);
} }
public void AddTrack(byte adrCtl, byte tno, byte point, byte min, byte sec, byte frame, byte zero, byte pmin, public void AddTrack(byte adrCtl, byte tno, byte point, byte min, byte sec, byte frame, byte zero, byte pmin,
byte psec, byte pframe, byte session) byte psec, byte pframe, byte session)
{ {
AlcoholTrack trk = new AlcoholTrack AlcoholTrack trk = new AlcoholTrack
{ {
@@ -519,11 +502,7 @@ namespace DiscImageChef.Core.Devices.Dumping
AlcoholSession[] sess = sessions.ToArray(); AlcoholSession[] sess = sessions.ToArray();
for(int i = 0; i < sess.Length; i++) for(int i = 0; i < sess.Length; i++) { if(sess[i].sessionSequence == session) sess[i].nonTrackBlocks++; }
{
if(sess[i].sessionSequence == session)
sess[i].nonTrackBlocks++;
}
sessions = new List<AlcoholSession>(sess); sessions = new List<AlcoholSession>(sess);
} }
@@ -540,8 +519,7 @@ namespace DiscImageChef.Core.Devices.Dumping
this.pfi = new byte[2048]; this.pfi = new byte[2048];
Array.Copy(pfi, 4, this.pfi, 0, 2048); Array.Copy(pfi, 4, this.pfi, 0, 2048);
} }
else else this.pfi = pfi;
this.pfi = pfi;
} }
public void AddDMI(byte[] dmi) public void AddDMI(byte[] dmi)
@@ -551,8 +529,7 @@ namespace DiscImageChef.Core.Devices.Dumping
this.dmi = new byte[2048]; this.dmi = new byte[2048];
Array.Copy(dmi, 4, this.dmi, 0, 2048); Array.Copy(dmi, 4, this.dmi, 0, 2048);
} }
else else this.dmi = dmi;
this.dmi = dmi;
} }
public void SetExtension(string extension) public void SetExtension(string extension)
@@ -560,4 +537,4 @@ namespace DiscImageChef.Core.Devices.Dumping
this.extension = extension; this.extension = extension;
} }
} }
} }

View File

@@ -51,7 +51,10 @@ namespace DiscImageChef.Core.Devices.Dumping
internal class CompactDisc internal class CompactDisc
{ {
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Resume resume, ref DumpLog dumpLog, Alcohol120 alcohol, bool dumpLeadIn) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
ref MediaType dskType, bool separateSubchannel, ref Resume resume,
ref DumpLog dumpLog, Alcohol120 alcohol, bool dumpLeadIn)
{ {
MHDDLog mhddLog; MHDDLog mhddLog;
IBGLog ibgLog; IBGLog ibgLog;
@@ -76,10 +79,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ulong errored = 0; ulong errored = 0;
DataFile dumpFile = null; DataFile dumpFile = null;
bool aborted = false; bool aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
// We discarded all discs that falsify a TOC before requesting a real TOC // We discarded all discs that falsify a TOC before requesting a real TOC
// No TOC, no CD (or an empty one) // No TOC, no CD (or an empty one)
@@ -124,10 +124,13 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Disc Information"); dumpLog.WriteLine("Reading Disc Information");
sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf, MmcDiscInformationDataTypes.DiscInformation, dev.Timeout, out duration); sense = dev.ReadDiscInformation(out cmdBuf, out senseBuf,
MmcDiscInformationDataTypes.DiscInformation, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo = Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf); Decoders.SCSI.MMC.DiscInformation.StandardDiscInformation? discInfo =
Decoders.SCSI.MMC.DiscInformation.Decode000b(cmdBuf);
if(discInfo.HasValue) if(discInfo.HasValue)
{ {
// If it is a read-only CD, check CD type if available // If it is a read-only CD, check CD type if available
@@ -172,21 +175,20 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
foreach(FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors) foreach(FullTOC.TrackDataDescriptor track in toc.Value.TrackDescriptors)
{ {
if(track.TNO == 1 && if(track.TNO == 1 && ((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack || (TOC_CONTROL)(track.CONTROL & 0x0D) ==
(TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)) TOC_CONTROL.DataTrackIncremental))
{ {
allFirstSessionTracksAreAudio &= firstTrackLastSession != 1; allFirstSessionTracksAreAudio &= firstTrackLastSession != 1;
} }
if((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack || if((TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
(TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental) (TOC_CONTROL)(track.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
{ {
hasDataTrack = true; hasDataTrack = true;
allFirstSessionTracksAreAudio &= track.TNO >= firstTrackLastSession; allFirstSessionTracksAreAudio &= track.TNO >= firstTrackLastSession;
} }
else else hasAudioTrack = true;
hasAudioTrack = true;
hasVideoTrack |= track.ADR == 4; hasVideoTrack |= track.ADR == 4;
} }
@@ -194,12 +196,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2) if(hasDataTrack && hasAudioTrack && allFirstSessionTracksAreAudio && sessions == 2)
dskType = MediaType.CDPLUS; dskType = MediaType.CDPLUS;
if(!hasDataTrack && hasAudioTrack && sessions == 1) if(!hasDataTrack && hasAudioTrack && sessions == 1) dskType = MediaType.CDDA;
dskType = MediaType.CDDA; if(hasDataTrack && !hasAudioTrack && sessions == 1) dskType = MediaType.CDROM;
if(hasDataTrack && !hasAudioTrack && sessions == 1) if(hasVideoTrack && !hasDataTrack && sessions == 1) dskType = MediaType.CDV;
dskType = MediaType.CDROM;
if(hasVideoTrack && !hasDataTrack && sessions == 1)
dskType = MediaType.CDV;
} }
dumpLog.WriteLine("Reading PMA"); dumpLog.WriteLine("Reading PMA");
@@ -244,10 +243,8 @@ namespace DiscImageChef.Core.Devices.Dumping
blockSize = 2448; blockSize = 2448;
subSize = 96; subSize = 96;
int sectorSize; int sectorSize;
if(separateSubchannel) if(separateSubchannel) sectorSize = (int)(blockSize - subSize);
sectorSize = (int)(blockSize - subSize); else sectorSize = (int)blockSize;
else
sectorSize = (int)blockSize;
if(toc == null) if(toc == null)
{ {
@@ -271,15 +268,17 @@ namespace DiscImageChef.Core.Devices.Dumping
sessionsForAlcohol[trk.SessionNumber - 1].EndTrack = trk.POINT; sessionsForAlcohol[trk.SessionNumber - 1].EndTrack = trk.POINT;
} }
} }
alcohol.AddSessions(sessionsForAlcohol); alcohol.AddSessions(sessionsForAlcohol);
foreach(FullTOC.TrackDataDescriptor trk in toc.Value.TrackDescriptors) foreach(FullTOC.TrackDataDescriptor trk in toc.Value.TrackDescriptors)
{ {
alcohol.AddTrack((byte)((trk.ADR << 4) & trk.CONTROL), trk.TNO, trk.POINT, trk.Min, trk.Sec, trk.Frame, alcohol.AddTrack((byte)((trk.ADR << 4) & trk.CONTROL), trk.TNO, trk.POINT, trk.Min, trk.Sec, trk.Frame,
trk.Zero, trk.PMIN, trk.PSEC, trk.PFRAME, trk.SessionNumber); trk.Zero, trk.PMIN, trk.PSEC, trk.PFRAME, trk.SessionNumber);
} }
FullTOC.TrackDataDescriptor[] sortedTracks = toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray(); FullTOC.TrackDataDescriptor[] sortedTracks =
toc.Value.TrackDescriptors.OrderBy(track => track.POINT).ToArray();
List<TrackType> trackList = new List<TrackType>(); List<TrackType> trackList = new List<TrackType>();
long lastSector = 0; long lastSector = 0;
string lastMSF = null; string lastMSF = null;
@@ -291,22 +290,18 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
TrackType track = new TrackType TrackType track = new TrackType
{ {
Sequence = new TrackSequenceType Sequence = new TrackSequenceType {Session = trk.SessionNumber, TrackNumber = trk.POINT}
{
Session = trk.SessionNumber,
TrackNumber = trk.POINT
}
}; };
if((TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrack || if((TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
(TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental) (TOC_CONTROL)(trk.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
track.TrackType1 = TrackTypeTrackType.mode1; track.TrackType1 = TrackTypeTrackType.mode1;
else else track.TrackType1 = TrackTypeTrackType.audio;
track.TrackType1 = TrackTypeTrackType.audio;
if(trk.PHOUR > 0) if(trk.PHOUR > 0)
track.StartMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME, trk.PHOUR); track.StartMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC,
else trk.PFRAME, trk.PHOUR);
track.StartMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME); else track.StartMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", trk.PMIN, trk.PSEC, trk.PFRAME);
track.StartSector = trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME - 150; track.StartSector = trk.PHOUR * 3600 * 75 + trk.PMIN * 60 * 75 + trk.PSEC * 75 + trk.PFRAME -
150;
trackList.Add(track); trackList.Add(track);
} }
else if(trk.POINT == 0xA2) else if(trk.POINT == 0xA2)
@@ -346,17 +341,15 @@ namespace DiscImageChef.Core.Devices.Dumping
phour = trk.PHOUR; phour = trk.PHOUR;
} }
if(phour > 0) if(phour > 0) lastMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour);
lastMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour); else lastMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
else
lastMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150; lastSector = phour * 3600 * 75 + pmin * 60 * 75 + psec * 75 + pframe - 150;
} }
} }
} }
TrackType[] tracks = trackList.ToArray(); TrackType[] tracks = trackList.ToArray();
for(int t = 1; t < tracks.Length;t++) for(int t = 1; t < tracks.Length; t++)
{ {
tracks[t - 1].EndSector = tracks[t].StartSector - 1; tracks[t - 1].EndSector = tracks[t].StartSector - 1;
int phour = 0, pmin = 0, psec = 0; int phour = 0, pmin = 0, psec = 0;
@@ -380,9 +373,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(phour > 0) if(phour > 0)
tracks[t - 1].EndMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour); tracks[t - 1].EndMSF = string.Format("{3:D2}:{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe, phour);
else else tracks[t - 1].EndMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
tracks[t - 1].EndMSF = string.Format("{0:D2}:{1:D2}:{2:D2}", pmin, psec, pframe);
} }
tracks[tracks.Length - 1].EndMSF = lastMSF; tracks[tracks.Length - 1].EndMSF = lastMSF;
tracks[tracks.Length - 1].EndSector = lastSector; tracks[tracks.Length - 1].EndSector = lastSector;
blocks = (ulong)(lastSector + 1); blocks = (ulong)(lastSector + 1);
@@ -393,23 +386,21 @@ namespace DiscImageChef.Core.Devices.Dumping
return; return;
} }
if(dumpRaw) if(dumpRaw) { throw new NotImplementedException("Raw CD dumping not yet implemented"); }
{
throw new NotImplementedException("Raw CD dumping not yet implemented");
}
else else
{ {
// TODO: Check subchannel capabilities // TODO: Check subchannel capabilities
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, 1, MmcSectorTypes.AllTypes, false,
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration); false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
MmcSubchannel.Raw, dev.Timeout, out duration);
if(readcd) if(readcd) DicConsole.WriteLine("Using MMC READ CD command.");
DicConsole.WriteLine("Using MMC READ CD command.");
} }
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(true, true, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(true, true, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID,
ref resume, ref currentTry, ref extents);
if(currentTry == null || extents == null) if(currentTry == null || extents == null)
throw new Exception("Could not process resume file, not continuing..."); throw new Exception("Could not process resume file, not continuing...");
@@ -503,14 +494,13 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
if(readcd) if(readcd)
{ {
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, sense = dev.ReadCd(out readBuffer, out senseBuf, 0, blockSize, blocksToRead,
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration); MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
if(dev.Error || sense) true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out duration);
blocksToRead /= 2; if(dev.Error || sense) blocksToRead /= 2;
} }
if(!dev.Error || blocksToRead == 1) if(!dev.Error || blocksToRead == 1) break;
break;
} }
if(dev.Error || sense) if(dev.Error || sense)
@@ -532,17 +522,14 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile = new DataFile(outputPrefix + ".bin"); dumpFile = new DataFile(outputPrefix + ".bin");
alcohol.SetExtension(".bin"); alcohol.SetExtension(".bin");
DataFile subFile = null; DataFile subFile = null;
if(separateSubchannel) if(separateSubchannel) subFile = new DataFile(outputPrefix + ".sub");
subFile = new DataFile(outputPrefix + ".sub");
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
ibgLog = new IBGLog(outputPrefix + ".ibg", 0x0008); ibgLog = new IBGLog(outputPrefix + ".ibg", 0x0008);
dumpFile.Seek(resume.NextBlock, (ulong)sectorSize); dumpFile.Seek(resume.NextBlock, (ulong)sectorSize);
if(separateSubchannel) if(separateSubchannel) subFile.Seek(resume.NextBlock, subSize);
subFile.Seek(resume.NextBlock, subSize);
if(resume.NextBlock > 0) if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
start = DateTime.UtcNow; start = DateTime.UtcNow;
for(int t = 0; t < tracks.Count(); t++) for(int t = 0; t < tracks.Count(); t++)
@@ -560,11 +547,7 @@ namespace DiscImageChef.Core.Devices.Dumping
tracks[t].Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * sectorSize; tracks[t].Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * sectorSize;
tracks[t].SubChannel = new SubChannelType tracks[t].SubChannel = new SubChannelType
{ {
Image = new ImageType Image = new ImageType {format = "rw_raw", offsetSpecified = true},
{
format = "rw_raw",
offsetSpecified = true
},
Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * subSize Size = (tracks[t].EndSector - tracks[t].StartSector + 1) * subSize
}; };
if(separateSubchannel) if(separateSubchannel)
@@ -578,8 +561,9 @@ namespace DiscImageChef.Core.Devices.Dumping
tracks[t].SubChannel.Image.Value = tracks[t].Image.Value; tracks[t].SubChannel.Image.Value = tracks[t].Image.Value;
} }
alcohol.SetTrackSizes((byte)(t + 1), sectorSize, tracks[t].StartSector, dumpFile.Position, (tracks[t].EndSector - tracks[t].StartSector + 1)); alcohol.SetTrackSizes((byte)(t + 1), sectorSize, tracks[t].StartSector, dumpFile.Position,
(tracks[t].EndSector - tracks[t].StartSector + 1));
bool checkedDataFormat = false; bool checkedDataFormat = false;
for(ulong i = resume.NextBlock; i <= (ulong)tracks[t].EndSector; i += blocksToRead) for(ulong i = resume.NextBlock; i <= (ulong)tracks[t].EndSector; i += blocksToRead)
@@ -597,18 +581,18 @@ namespace DiscImageChef.Core.Devices.Dumping
blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i); blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks, currentSpeed, t + 1); DicConsole.Write("\rReading sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks,
currentSpeed, t + 1);
if(readcd) if(readcd)
{ {
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, blockSize, blocksToRead,
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration); MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
} }
@@ -625,14 +609,12 @@ namespace DiscImageChef.Core.Devices.Dumping
subFile.Write(readBuffer, (int)(sectorSize + b * blockSize), (int)subSize); subFile.Write(readBuffer, (int)(sectorSize + b * blockSize), (int)subSize);
} }
} }
else else dumpFile.Write(readBuffer);
dumpFile.Write(readBuffer);
} }
else else
{ {
// TODO: Reset device after X errors // TODO: Reset device after X errors
if(stopOnError) if(stopOnError) return; // TODO: Return more cleanly
return; // TODO: Return more cleanly
// Write empty data // Write empty data
if(separateSubchannel) if(separateSubchannel)
@@ -640,17 +622,15 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile.Write(new byte[sectorSize * blocksToRead]); dumpFile.Write(new byte[sectorSize * blocksToRead]);
subFile.Write(new byte[subSize * blocksToRead]); subFile.Write(new byte[subSize * blocksToRead]);
} }
else else dumpFile.Write(new byte[blockSize * blocksToRead]);
dumpFile.Write(new byte[blockSize * blocksToRead]);
errored += blocksToRead; errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
resume.BadBlocks.Add(b);
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
if(cmdDuration < 500) Decoders.SCSI.Sense.PrettifySense(senseBuf));
mhddLog.Write(i, 65535); if(cmdDuration < 500) mhddLog.Write(i, 65535);
else else mhddLog.Write(i, cmdDuration);
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i); dumpLog.WriteLine("Error reading {0} sectors from sector {1}.", blocksToRead, i);
@@ -660,7 +640,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
byte[] sync = new byte[12]; byte[] sync = new byte[12];
Array.Copy(readBuffer, 0, sync, 0, 12); Array.Copy(readBuffer, 0, sync, 0, 12);
if(sync.SequenceEqual(new byte[] { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 })) if(sync.SequenceEqual(new byte[]
{
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
}))
{ {
switch(readBuffer[15]) switch(readBuffer[15])
{ {
@@ -711,21 +694,25 @@ namespace DiscImageChef.Core.Devices.Dumping
case TrackTypeTrackType.mode0: case TrackTypeTrackType.mode0:
trkType = ImagePlugins.TrackType.Data; trkType = ImagePlugins.TrackType.Data;
break; break;
default: default: throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException();
} }
alcohol.SetTrackTypes((byte)(t + 1), trkType, alcohol.SetTrackTypes((byte)(t + 1), trkType,
separateSubchannel ? TrackSubchannelType.None : TrackSubchannelType.RawInterleaved); separateSubchannel
? TrackSubchannelType.None
: TrackSubchannelType.RawInterleaved);
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
end = DateTime.UtcNow; end = DateTime.UtcNow;
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
#region Compact Disc Error handling #region Compact Disc Error handling
if(resume.BadBlocks.Count > 0 && !aborted) if(resume.BadBlocks.Count > 0 && !aborted)
@@ -734,7 +721,7 @@ namespace DiscImageChef.Core.Devices.Dumping
bool forward = true; bool forward = true;
bool runningPersistent = false; bool runningPersistent = false;
cdRepeatRetry: cdRepeatRetry:
ulong[] tmpArray = resume.BadBlocks.ToArray(); ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray) foreach(ulong badSector in tmpArray)
{ {
@@ -747,12 +734,15 @@ namespace DiscImageChef.Core.Devices.Dumping
double cmdDuration = 0; double cmdDuration = 0;
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "");
if(readcd) if(readcd)
{ {
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)badSector, blockSize, blocksToRead,
true, true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration); MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, MmcSubchannel.Raw, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
} }
@@ -764,14 +754,13 @@ namespace DiscImageChef.Core.Devices.Dumping
extents.Add(badSector); extents.Add(badSector);
dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass); dumpLog.WriteLine("Correctly retried sector {0} in pass {1}.", badSector, pass);
} }
if(separateSubchannel) if(separateSubchannel)
{ {
dumpFile.WriteAt(readBuffer, badSector, (uint)sectorSize, 0, sectorSize); dumpFile.WriteAt(readBuffer, badSector, (uint)sectorSize, 0, sectorSize);
subFile.WriteAt(readBuffer, badSector, subSize, sectorSize, (int)subSize); subFile.WriteAt(readBuffer, badSector, subSize, sectorSize, (int)subSize);
} }
else else dumpFile.WriteAt(readBuffer, badSector, blockSize);
dumpFile.WriteAt(readBuffer, badSector, blockSize);
} }
} }
@@ -791,47 +780,39 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!runningPersistent && persistent) if(!runningPersistent && persistent)
{ {
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
dev.Timeout, out duration);
if(sense) if(sense)
{ {
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
if(!sense) 0x01, dev.Timeout, out duration);
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType); if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
} }
else else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
if(currentMode.HasValue) if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
currentModePage = currentMode.Value.Pages[0];
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
{ new Decoders.SCSI.Modes.ModePage_01_MMC {PS = false, ReadRetryCount = 255, Parameter = 0x20};
PS = false,
ReadRetryCount = 255,
Parameter = 0x20
};
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
Pages = new Decoders.SCSI.Modes.ModePage[] Pages = new Decoders.SCSI.Modes.ModePage[]
{ {
new Decoders.SCSI.Modes.ModePage new Decoders.SCSI.Modes.ModePage
{ {
Page = 0x01, Page = 0x01,
Subpage = 0x00, Subpage = 0x00,
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC) PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
} }
} }
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType); md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
runningPersistent = true; runningPersistent = true;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -845,32 +826,26 @@ namespace DiscImageChef.Core.Devices.Dumping
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
Pages = new Decoders.SCSI.Modes.ModePage[] Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
{
currentModePage.Value
}
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType); md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
#endregion Compact Disc Error handling #endregion Compact Disc Error handling
resume.BadBlocks.Sort(); resume.BadBlocks.Sort();
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents); currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
dataChk = new Checksum(); dataChk = new Checksum();
dumpFile.Seek(0, SeekOrigin.Begin); dumpFile.Seek(0, SeekOrigin.Begin);
if(separateSubchannel) if(separateSubchannel) subFile.Seek(0, SeekOrigin.Begin);
subFile.Seek(0, SeekOrigin.Begin);
blocksToRead = 500; blocksToRead = 500;
dumpLog.WriteLine("Checksum starts."); dumpLog.WriteLine("Checksum starts.");
@@ -890,7 +865,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(((ulong)tracks[t].EndSector + 1 - i) < blocksToRead) if(((ulong)tracks[t].EndSector + 1 - i) < blocksToRead)
blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i); blocksToRead = (uint)((ulong)tracks[t].EndSector + 1 - i);
DicConsole.Write("\rChecksumming sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks, currentSpeed, t + 1); DicConsole.Write("\rChecksumming sector {0} of {1} at track {3} ({2:F3} MiB/sec.)", i, blocks,
currentSpeed, t + 1);
DateTime chkStart = DateTime.UtcNow; DateTime chkStart = DateTime.UtcNow;
byte[] dataToCheck = new byte[blockSize * blocksToRead]; byte[] dataToCheck = new byte[blockSize * blocksToRead];
@@ -913,6 +889,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dataChk.Update(dataToCheck); dataChk.Update(dataToCheck);
trkChk.Update(dataToCheck); trkChk.Update(dataToCheck);
} }
DateTime chkEnd = DateTime.UtcNow; DateTime chkEnd = DateTime.UtcNow;
double chkDuration = (chkEnd - chkStart).TotalMilliseconds; double chkDuration = (chkEnd - chkStart).TotalMilliseconds;
@@ -924,16 +901,16 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
tracks[t].Checksums = trkChk.End().ToArray(); tracks[t].Checksums = trkChk.End().ToArray();
if(separateSubchannel) if(separateSubchannel) tracks[t].SubChannel.Checksums = subChk.End().ToArray();
tracks[t].SubChannel.Checksums = subChk.End().ToArray(); else tracks[t].SubChannel.Checksums = tracks[t].Checksums;
else
tracks[t].SubChannel.Checksums = tracks[t].Checksums;
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
dumpFile.Close(); dumpFile.Close();
end = DateTime.UtcNow; end = DateTime.UtcNow;
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
// TODO: Correct this // TODO: Correct this
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray(); sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
@@ -944,7 +921,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Value = outputPrefix + ".bin" Value = outputPrefix + ".bin"
}; };
sidecar.OpticalDisc[0].Sessions = toc.Value.LastCompleteSession; sidecar.OpticalDisc[0].Sessions = toc.Value.LastCompleteSession;
sidecar.OpticalDisc[0].Tracks = new[] { tracks.Count() }; sidecar.OpticalDisc[0].Tracks = new[] {tracks.Count()};
sidecar.OpticalDisc[0].Track = tracks; sidecar.OpticalDisc[0].Track = tracks;
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp); Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
@@ -955,10 +932,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
alcohol.Close(); alcohol.Close();
@@ -967,4 +944,4 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);
} }
} }
} }

View File

@@ -42,7 +42,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
internal static class MMC internal static class MMC
{ {
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
ref MediaType dskType, bool separateSubchannel, ref Metadata.Resume resume,
ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
{ {
byte[] cmdBuf = null; byte[] cmdBuf = null;
byte[] senseBuf = null; byte[] senseBuf = null;
@@ -60,7 +63,8 @@ namespace DiscImageChef.Core.Devices.Dumping
// TODO: Log not only what is it reading, but if it was read correctly or not. // TODO: Log not only what is it reading, but if it was read correctly or not.
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration); sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf); Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf);
@@ -164,7 +168,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(compactDisc) if(compactDisc)
{ {
CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, alcohol, dumpLeadIn); CompactDisc.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, alcohol,
dumpLeadIn);
return; return;
} }
@@ -176,17 +182,19 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.Unknown && blocks > 0) if(dskType == MediaType.Unknown && blocks > 0)
{ {
dumpLog.WriteLine("Reading Physical Format Information"); dumpLog.WriteLine("Reading Physical Format Information");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
Decoders.DVD.PFI.PhysicalFormatInformation? nintendoPfi = Decoders.DVD.PFI.Decode(cmdBuf); Decoders.DVD.PFI.PhysicalFormatInformation? nintendoPfi = Decoders.DVD.PFI.Decode(cmdBuf);
if(nintendoPfi != null) if(nintendoPfi != null)
{ {
if(nintendoPfi.Value.DiskCategory == Decoders.DVD.DiskCategory.Nintendo && if(nintendoPfi.Value.DiskCategory == Decoders.DVD.DiskCategory.Nintendo &&
nintendoPfi.Value.PartVersion == 15) nintendoPfi.Value.PartVersion == 15)
{ {
dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented."); dumpLog.WriteLine("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
throw new NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented."); throw new
NotImplementedException("Dumping Nintendo GameCube or Wii discs is not yet implemented.");
} }
} }
} }
@@ -194,18 +202,16 @@ namespace DiscImageChef.Core.Devices.Dumping
#endregion Nintendo #endregion Nintendo
#region All DVD and HD DVD types #region All DVD and HD DVD types
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL ||
dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR ||
dskType == MediaType.DVDPRWDL || dskType == MediaType.DVDR || dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || dskType == MediaType.DVDROM ||
dskType == MediaType.DVDRAM || dskType == MediaType.DVDRDL || dskType == MediaType.DVDRW || dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR ||
dskType == MediaType.DVDROM || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL || dskType == MediaType.HDDVDROM ||
dskType == MediaType.DVDRWDL || dskType == MediaType.HDDVDR || dskType == MediaType.HDDVDRW || dskType == MediaType.HDDVDRWDL)
dskType == MediaType.HDDVDRAM || dskType == MediaType.HDDVDRDL ||
dskType == MediaType.HDDVDROM || dskType == MediaType.HDDVDRW ||
dskType == MediaType.HDDVDRWDL)
{ {
dumpLog.WriteLine("Reading Physical Format Information"); dumpLog.WriteLine("Reading Physical Format Information");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
alcohol.AddPFI(cmdBuf); alcohol.AddPFI(cmdBuf);
@@ -242,10 +248,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dskType = MediaType.DVDPRWDL; dskType = MediaType.DVDPRWDL;
break; break;
case Decoders.DVD.DiskCategory.DVDR: case Decoders.DVD.DiskCategory.DVDR:
if(decPfi.PartVersion == 6) if(decPfi.PartVersion == 6) dskType = MediaType.DVDRDL;
dskType = MediaType.DVDRDL; else dskType = MediaType.DVDR;
else
dskType = MediaType.DVDR;
break; break;
case Decoders.DVD.DiskCategory.DVDRAM: case Decoders.DVD.DiskCategory.DVDRAM:
dskType = MediaType.DVDRAM; dskType = MediaType.DVDRAM;
@@ -254,10 +258,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dskType = MediaType.DVDROM; dskType = MediaType.DVDROM;
break; break;
case Decoders.DVD.DiskCategory.DVDRW: case Decoders.DVD.DiskCategory.DVDRW:
if(decPfi.PartVersion == 3) if(decPfi.PartVersion == 3) dskType = MediaType.DVDRWDL;
dskType = MediaType.DVDRWDL; else dskType = MediaType.DVDRW;
else
dskType = MediaType.DVDRW;
break; break;
case Decoders.DVD.DiskCategory.HDDVDR: case Decoders.DVD.DiskCategory.HDDVDR:
dskType = MediaType.HDDVDR; dskType = MediaType.HDDVDR;
@@ -272,10 +274,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dskType = MediaType.HDDVDRW; dskType = MediaType.HDDVDRW;
break; break;
case Decoders.DVD.DiskCategory.Nintendo: case Decoders.DVD.DiskCategory.Nintendo:
if(decPfi.DiscSize == Decoders.DVD.DVDSize.Eighty) if(decPfi.DiscSize == Decoders.DVD.DVDSize.Eighty) dskType = MediaType.GOD;
dskType = MediaType.GOD; else dskType = MediaType.WOD;
else
dskType = MediaType.WOD;
break; break;
case Decoders.DVD.DiskCategory.UMD: case Decoders.DVD.DiskCategory.UMD:
dskType = MediaType.UMD; dskType = MediaType.UMD;
@@ -286,13 +286,14 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Disc Manufacturing Information"); dumpLog.WriteLine("Reading Disc Manufacturing Information");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DiscManufacturingInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
if(Decoders.Xbox.DMI.IsXbox(cmdBuf) || Decoders.Xbox.DMI.IsXbox360(cmdBuf)) if(Decoders.Xbox.DMI.IsXbox(cmdBuf) || Decoders.Xbox.DMI.IsXbox360(cmdBuf))
{ {
if(Decoders.Xbox.DMI.IsXbox(cmdBuf)) if(Decoders.Xbox.DMI.IsXbox(cmdBuf)) dskType = MediaType.XGD;
dskType = MediaType.XGD;
else if(Decoders.Xbox.DMI.IsXbox360(cmdBuf)) else if(Decoders.Xbox.DMI.IsXbox360(cmdBuf))
{ {
dskType = MediaType.XGD2; dskType = MediaType.XGD2;
@@ -307,15 +308,18 @@ namespace DiscImageChef.Core.Devices.Dumping
sense = dev.ScsiInquiry(out byte[] inqBuf, out senseBuf); sense = dev.ScsiInquiry(out byte[] inqBuf, out senseBuf);
if(sense || !Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue || if(sense || !Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue ||
(Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue && !Decoders.SCSI.Inquiry.Decode(inqBuf).Value.KreonPresent)) (Decoders.SCSI.Inquiry.Decode(inqBuf).HasValue &&
!Decoders.SCSI.Inquiry.Decode(inqBuf).Value.KreonPresent))
{ {
dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware."); dumpLog.WriteLine("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
throw new NotImplementedException("Dumping Xbox Game Discs requires a drive with Kreon firmware."); throw new
NotImplementedException("Dumping Xbox Game Discs requires a drive with Kreon firmware.");
} }
if(dumpRaw && !force) if(dumpRaw && !force)
{ {
DicConsole.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); DicConsole
.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
// TODO: Exit more gracefully // TODO: Exit more gracefully
return; return;
} }
@@ -324,7 +328,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
alcohol.AddDMI(cmdBuf); alcohol.AddDMI(cmdBuf);
if(cmdBuf.Length == 2052) if(cmdBuf.Length == 2052)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -345,7 +349,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM) if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM)
{ {
dumpLog.WriteLine("Reading Lead-in Copyright Information."); dumpLog.WriteLine("Reading Lead-in Copyright Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.CopyrightInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
if(Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue) if(Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).HasValue)
@@ -360,7 +366,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].CMI.Image, tmpBuf); DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].CMI.Image, tmpBuf);
Decoders.DVD.CSS_CPRM.LeadInCopyright cpy = Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).Value; Decoders.DVD.CSS_CPRM.LeadInCopyright cpy =
Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(cmdBuf).Value;
if(cpy.CopyrightType != Decoders.DVD.CopyrightType.NoProtection) if(cpy.CopyrightType != Decoders.DVD.CopyrightType.NoProtection)
sidecar.OpticalDisc[0].CopyProtection = cpy.CopyrightType.ToString(); sidecar.OpticalDisc[0].CopyProtection = cpy.CopyrightType.ToString();
} }
@@ -369,11 +376,11 @@ namespace DiscImageChef.Core.Devices.Dumping
#endregion DVD-ROM #endregion DVD-ROM
#region DVD-ROM and HD DVD-ROM #region DVD-ROM and HD DVD-ROM
if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM || if(dskType == MediaType.DVDDownload || dskType == MediaType.DVDROM || dskType == MediaType.HDDVDROM)
dskType == MediaType.HDDVDROM)
{ {
dumpLog.WriteLine("Reading Burst Cutting Area."); dumpLog.WriteLine("Reading Burst Cutting Area.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.BurstCuttingArea, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -394,7 +401,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.DVDRAM || dskType == MediaType.HDDVDRAM) if(dskType == MediaType.DVDRAM || dskType == MediaType.HDDVDRAM)
{ {
dumpLog.WriteLine("Reading Disc Description Structure."); dumpLog.WriteLine("Reading Disc Description Structure.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DVDRAM_DDS, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
if(Decoders.DVD.DDS.Decode(cmdBuf).HasValue) if(Decoders.DVD.DDS.Decode(cmdBuf).HasValue)
@@ -412,7 +420,9 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Spare Area Information."); dumpLog.WriteLine("Reading Spare Area Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DVDRAM_SpareAreaInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
if(Decoders.DVD.Spare.Decode(cmdBuf).HasValue) if(Decoders.DVD.Spare.Decode(cmdBuf).HasValue)
@@ -435,7 +445,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW) if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW)
{ {
dumpLog.WriteLine("Reading Pre-Recorded Information."); dumpLog.WriteLine("Reading Pre-Recorded Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.PreRecordedInfo, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -455,7 +466,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDR) if(dskType == MediaType.DVDR || dskType == MediaType.DVDRW || dskType == MediaType.HDDVDR)
{ {
dumpLog.WriteLine("Reading Media Identifier."); dumpLog.WriteLine("Reading Media Identifier.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DVDR_MediaIdentifier, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -470,7 +483,9 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Recordable Physical Information."); dumpLog.WriteLine("Reading Recordable Physical Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DVDR_PhysicalInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -487,11 +502,12 @@ namespace DiscImageChef.Core.Devices.Dumping
#endregion DVD-R, DVD-RW and HD DVD-R #endregion DVD-R, DVD-RW and HD DVD-R
#region All DVD+ #region All DVD+
if(dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || if(dskType == MediaType.DVDPR || dskType == MediaType.DVDPRDL || dskType == MediaType.DVDPRW ||
dskType == MediaType.DVDPRW || dskType == MediaType.DVDPRWDL) dskType == MediaType.DVDPRWDL)
{ {
dumpLog.WriteLine("Reading ADdress In Pregroove."); dumpLog.WriteLine("Reading ADdress In Pregroove.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.ADIP, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -506,7 +522,8 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Disc Control Blocks."); dumpLog.WriteLine("Reading Disc Control Blocks.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DCB, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -526,7 +543,9 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dskType == MediaType.HDDVDROM) if(dskType == MediaType.HDDVDROM)
{ {
dumpLog.WriteLine("Reading Lead-in Copyright Information."); dumpLog.WriteLine("Reading Lead-in Copyright Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.HDDVD_CopyrightInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -544,10 +563,11 @@ namespace DiscImageChef.Core.Devices.Dumping
#region All Blu-ray #region All Blu-ray
if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDROM || if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDROM ||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL) dskType == MediaType.BDRXL || dskType == MediaType.BDREXL)
{ {
dumpLog.WriteLine("Reading Disc Information."); dumpLog.WriteLine("Reading Disc Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
MmcDiscStructureFormat.DiscInformation, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
if(Decoders.Bluray.DI.Decode(cmdBuf).HasValue) if(Decoders.Bluray.DI.Decode(cmdBuf).HasValue)
@@ -565,7 +585,8 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading PAC."); dumpLog.WriteLine("Reading PAC.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
MmcDiscStructureFormat.PAC, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -581,12 +602,12 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
#endregion All Blu-ray #endregion All Blu-ray
#region BD-ROM only #region BD-ROM only
if(dskType == MediaType.BDROM) if(dskType == MediaType.BDROM)
{ {
dumpLog.WriteLine("Reading Burst Cutting Area."); dumpLog.WriteLine("Reading Burst Cutting Area.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
MmcDiscStructureFormat.BD_BurstCuttingArea, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -604,11 +625,12 @@ namespace DiscImageChef.Core.Devices.Dumping
#endregion BD-ROM only #endregion BD-ROM only
#region Writable Blu-ray only #region Writable Blu-ray only
if(dskType == MediaType.BDR || dskType == MediaType.BDRE || if(dskType == MediaType.BDR || dskType == MediaType.BDRE || dskType == MediaType.BDRXL ||
dskType == MediaType.BDRXL || dskType == MediaType.BDREXL) dskType == MediaType.BDREXL)
{ {
dumpLog.WriteLine("Reading Disc Definition Structure."); dumpLog.WriteLine("Reading Disc Definition Structure.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
MmcDiscStructureFormat.BD_DDS, 0, dev.Timeout, out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -623,7 +645,9 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Reading Spare Area Information."); dumpLog.WriteLine("Reading Spare Area Information.");
sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0, MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout, out duration); sense = dev.ReadDiscStructure(out cmdBuf, out senseBuf, MmcDiscStructureMediaType.BD, 0, 0,
MmcDiscStructureFormat.BD_SpareAreaInformation, 0, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
tmpBuf = new byte[cmdBuf.Length - 4]; tmpBuf = new byte[cmdBuf.Length - 4];
@@ -641,11 +665,13 @@ namespace DiscImageChef.Core.Devices.Dumping
if(isXbox) if(isXbox)
{ {
XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, ref resume, ref dumpLog, encoding); XGD.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
ref sidecar, ref dskType, ref resume, ref dumpLog, encoding);
return; return;
} }
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, true, ref resume, ref dumpLog, encoding, alcohol); SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar,
ref dskType, true, ref resume, ref dumpLog, encoding, alcohol);
} }
} }
} }

View File

@@ -39,9 +39,11 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
public static class NVMe public static class NVMe
{ {
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding) public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
ref DumpLog dumpLog, Encoding encoding)
{ {
throw new NotImplementedException("NVMe devices not yet supported."); throw new NotImplementedException("NVMe devices not yet supported.");
} }
} }
} }

View File

@@ -40,45 +40,51 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
public static class ResumeSupport public static class ResumeSupport
{ {
public static void Process(bool isLba, bool removable, ulong blocks, string Manufacturer, string Model, string Serial, Interop.PlatformID platform, ref Resume resume, ref DumpHardwareType currentTry, ref ExtentsULong extents) public static void Process(bool isLba, bool removable, ulong blocks, string Manufacturer, string Model,
string Serial, Interop.PlatformID platform, ref Resume resume,
ref DumpHardwareType currentTry, ref ExtentsULong extents)
{ {
if(resume != null) if(resume != null)
{ {
if(!isLba) if(!isLba) throw new NotImplementedException("Resuming CHS devices is currently not supported.");
throw new NotImplementedException("Resuming CHS devices is currently not supported.");
if(resume.Removable != removable) if(resume.Removable != removable)
throw new Exception(string.Format("Resume file specifies a {0} device but you're requesting to dump a {1} device, not continuing...", throw new
resume.Removable ? "removable" : "non removable", Exception(string.Format("Resume file specifies a {0} device but you're requesting to dump a {1} device, not continuing...",
removable ? "removable" : "non removable")); resume.Removable ? "removable" : "non removable",
removable ? "removable" : "non removable"));
if(resume.LastBlock != blocks - 1) if(resume.LastBlock != blocks - 1)
throw new Exception(string.Format("Resume file specifies a device with {0} blocks but you're requesting to dump one with {1} blocks, not continuing...", throw new
resume.LastBlock + 1, blocks)); Exception(string.Format("Resume file specifies a device with {0} blocks but you're requesting to dump one with {1} blocks, not continuing...",
resume.LastBlock + 1, blocks));
foreach(DumpHardwareType oldtry in resume.Tries) foreach(DumpHardwareType oldtry in resume.Tries)
{ {
if(oldtry.Manufacturer != Manufacturer && !removable) if(oldtry.Manufacturer != Manufacturer && !removable)
throw new Exception(string.Format("Resume file specifies a device manufactured by {0} but you're requesting to dump one by {1}, not continuing...", throw new
oldtry.Manufacturer, Manufacturer)); Exception(string.Format("Resume file specifies a device manufactured by {0} but you're requesting to dump one by {1}, not continuing...",
oldtry.Manufacturer, Manufacturer));
if(oldtry.Model != Model && !removable) if(oldtry.Model != Model && !removable)
throw new Exception(string.Format("Resume file specifies a device model {0} but you're requesting to dump model {1}, not continuing...", throw new
oldtry.Model, Model)); Exception(string.Format("Resume file specifies a device model {0} but you're requesting to dump model {1}, not continuing...",
oldtry.Model, Model));
if(oldtry.Serial != Serial && !removable) if(oldtry.Serial != Serial && !removable)
throw new Exception(string.Format("Resume file specifies a device with serial {0} but you're requesting to dump one with serial {1}, not continuing...", throw new
oldtry.Serial, Serial)); Exception(string.Format("Resume file specifies a device with serial {0} but you're requesting to dump one with serial {1}, not continuing...",
oldtry.Serial, Serial));
if(oldtry.Software == null) if(oldtry.Software == null) throw new Exception("Found corrupt resume file, cannot continue...");
throw new Exception("Found corrupt resume file, cannot continue...");
if(oldtry.Software.Name == "DiscImageChef" && oldtry.Software.OperatingSystem == platform.ToString() && oldtry.Software.Version == Version.GetVersion()) if(oldtry.Software.Name == "DiscImageChef" &&
oldtry.Software.OperatingSystem == platform.ToString() &&
oldtry.Software.Version == Version.GetVersion())
{ {
if(removable && (oldtry.Manufacturer != Manufacturer || oldtry.Model != Model || oldtry.Serial != Serial)) if(removable && (oldtry.Manufacturer != Manufacturer || oldtry.Model != Model ||
continue; oldtry.Serial != Serial)) continue;
currentTry = oldtry; currentTry = oldtry;
extents = ExtentsConverter.FromMetadata(currentTry.Extents); extents = ExtentsConverter.FromMetadata(currentTry.Extents);
break; break;
@@ -120,4 +126,4 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
} }
} }

View File

@@ -51,7 +51,10 @@ namespace DiscImageChef.Core.Devices.Dumping
internal static class SBC internal static class SBC
{ {
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding, Alcohol120 alcohol = null) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
ref MediaType dskType, bool opticalDisc, ref Metadata.Resume resume,
ref DumpLog dumpLog, Encoding encoding, Alcohol120 alcohol = null)
{ {
MHDDLog mhddLog; MHDDLog mhddLog;
IBGLog ibgLog; IBGLog ibgLog;
@@ -80,10 +83,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ulong errored = 0; ulong errored = 0;
DataFile dumpFile = null; DataFile dumpFile = null;
bool aborted = false; bool aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
dumpLog.WriteLine("Initializing reader."); dumpLog.WriteLine("Initializing reader.");
Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw); Reader scsiReader = new Reader(dev, dev.Timeout, null, dumpRaw);
@@ -99,8 +99,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(blocks != 0 && blockSize != 0) if(blocks != 0 && blockSize != 0)
{ {
blocks++; blocks++;
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", blocks,
blocks, blockSize, blocks * (ulong)blockSize); blockSize, blocks * (ulong)blockSize);
} }
// Check how many blocks to read, if error show and return // Check how many blocks to read, if error show and return
if(scsiReader.GetBlocksToRead()) if(scsiReader.GetBlocksToRead())
@@ -109,6 +109,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine(scsiReader.ErrorMessage); DicConsole.ErrorWriteLine(scsiReader.ErrorMessage);
return; return;
} }
blocksToRead = scsiReader.BlocksToRead; blocksToRead = scsiReader.BlocksToRead;
logicalBlockSize = blockSize; logicalBlockSize = blockSize;
physicalBlockSize = scsiReader.PhysicalBlockSize; physicalBlockSize = scsiReader.PhysicalBlockSize;
@@ -121,10 +122,10 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
if(dskType == MediaType.Unknown) if(dskType == MediaType.Unknown)
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType, scsiDensityCode, blocks, blockSize); dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumType,
scsiDensityCode, blocks, blockSize);
if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage) if(dskType == MediaType.Unknown && dev.IsUSB && containsFloppyPage) dskType = MediaType.FlashDrive;
dskType = MediaType.FlashDrive;
DicConsole.WriteLine("Media identified as {0}", dskType); DicConsole.WriteLine("Media identified as {0}", dskType);
@@ -224,16 +225,17 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(evpds.Count > 0) if(evpds.Count > 0) sidecar.BlockMedia[0].SCSI.EVPD = evpds.ToArray();
sidecar.BlockMedia[0].SCSI.EVPD = evpds.ToArray();
} }
} }
dumpLog.WriteLine("Requesting MODE SENSE (10)."); dumpLog.WriteLine("Requesting MODE SENSE (10).");
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current,
0x3F, 0xFF, 5, out duration);
if(!sense || dev.Error) if(!sense || dev.Error)
{ {
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true,
ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration);
} }
Decoders.SCSI.Modes.DecodedMode? decMode = null; Decoders.SCSI.Modes.DecodedMode? decMode = null;
@@ -254,11 +256,12 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Requesting MODE SENSE (6)."); dumpLog.WriteLine("Requesting MODE SENSE (6).");
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F,
0x00, 5, out duration);
if(sense || dev.Error) if(sense || dev.Error)
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current,
if(sense || dev.Error) 0x3F, 0x00, 5, out duration);
sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration); if(sense || dev.Error) sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
@@ -278,7 +281,8 @@ namespace DiscImageChef.Core.Devices.Dumping
if(decMode.HasValue) if(decMode.HasValue)
{ {
scsiMediumType = (byte)decMode.Value.Header.MediumType; scsiMediumType = (byte)decMode.Value.Header.MediumType;
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length >= 1) if(decMode.Value.Header.BlockDescriptors != null &&
decMode.Value.Header.BlockDescriptors.Length >= 1)
scsiDensityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density; scsiDensityCode = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
foreach(Decoders.SCSI.Modes.ModePage modePage in decMode.Value.Pages) foreach(Decoders.SCSI.Modes.ModePage modePage in decMode.Value.Pages)
@@ -300,12 +304,14 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
else else
{ {
DicConsole.ErrorWriteLine("Device is capable of reading raw data but I've been unable to guess correct sector size."); DicConsole
.ErrorWriteLine("Device is capable of reading raw data but I've been unable to guess correct sector size.");
} }
if(!force) if(!force)
{ {
DicConsole.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option."); DicConsole
.ErrorWriteLine("Not continuing. If you want to continue reading cooked data when raw is not available use the force option.");
// TODO: Exit more gracefully // TODO: Exit more gracefully
return; return;
} }
@@ -315,23 +321,21 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
else else
{ {
if(longBlockSize == 37856
if(longBlockSize == 37856) // Only a block will be read, but it contains 16 sectors and command expect sector number not block number ) // Only a block will be read, but it contains 16 sectors and command expect sector number not block number
blocksToRead = 16; blocksToRead = 16;
else else blocksToRead = 1;
blocksToRead = 1; DicConsole.WriteLine("Reading {0} raw bytes ({1} cooked bytes) per sector.", longBlockSize,
DicConsole.WriteLine("Reading {0} raw bytes ({1} cooked bytes) per sector.", blockSize * blocksToRead);
longBlockSize, blockSize * blocksToRead);
physicalBlockSize = longBlockSize; physicalBlockSize = longBlockSize;
blockSize = longBlockSize; blockSize = longBlockSize;
} }
} }
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
string outputExtension = ".bin"; string outputExtension = ".bin";
if(opticalDisc && blockSize == 2048) if(opticalDisc && blockSize == 2048) outputExtension = ".iso";
outputExtension = ".iso";
mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead); mhddLog = new MHDDLog(outputPrefix + ".mhddlog.bin", dev, blocks, blockSize, blocksToRead);
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile); ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
dumpFile = new DataFile(outputPrefix + outputExtension); dumpFile = new DataFile(outputPrefix + outputExtension);
@@ -342,21 +346,22 @@ namespace DiscImageChef.Core.Devices.Dumping
if(alcohol != null && !dumpRaw) if(alcohol != null && !dumpRaw)
{ {
alcohol.AddSessions(new [] { new Session() { StartTrack = 1, EndTrack = 1, SessionSequence = 1}}); alcohol.AddSessions(new[] {new Session() {StartTrack = 1, EndTrack = 1, SessionSequence = 1}});
alcohol.AddTrack(20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); alcohol.AddTrack(20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1);
alcohol.SetExtension(outputExtension); alcohol.SetExtension(outputExtension);
alcohol.SetTrackSizes(1, (int)blockSize, 0, 0, (long)blocks); alcohol.SetTrackSizes(1, (int)blockSize, 0, 0, (long)blocks);
alcohol.SetTrackTypes(1, TrackType.Data, TrackSubchannelType.None); alcohol.SetTrackTypes(1, TrackType.Data, TrackSubchannelType.None);
} }
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(true, dev.IsRemovable, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(true, dev.IsRemovable, blocks, dev.Manufacturer, dev.Model, dev.Serial,
dev.PlatformID, ref resume, ref currentTry, ref extents);
if(currentTry == null || extents == null) if(currentTry == null || extents == null)
throw new Exception("Could not process resume file, not continuing..."); throw new Exception("Could not process resume file, not continuing...");
dumpFile.Seek(resume.NextBlock, blockSize); dumpFile.Seek(resume.NextBlock, blockSize);
if(resume.NextBlock > 0) if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
{ {
@@ -367,14 +372,11 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (uint)(blocks - i);
blocksToRead = (uint)(blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -392,19 +394,16 @@ namespace DiscImageChef.Core.Devices.Dumping
else else
{ {
// TODO: Reset device after X errors // TODO: Reset device after X errors
if(stopOnError) if(stopOnError) return; // TODO: Return more cleanly
return; // TODO: Return more cleanly
// Write empty data // Write empty data
dumpFile.Write(new byte[blockSize * blocksToRead]); dumpFile.Write(new byte[blockSize * blocksToRead]);
errored += blocksToRead; errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
resume.BadBlocks.Add(b);
if(cmdDuration < 500) if(cmdDuration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, cmdDuration);
else
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
@@ -415,14 +414,17 @@ namespace DiscImageChef.Core.Devices.Dumping
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
resume.NextBlock = i + blocksToRead; resume.NextBlock = i + blocksToRead;
} }
end = DateTime.UtcNow; end = DateTime.UtcNow;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted) if(resume.BadBlocks.Count > 0 && !aborted)
@@ -431,7 +433,7 @@ namespace DiscImageChef.Core.Devices.Dumping
bool forward = true; bool forward = true;
bool runningPersistent = false; bool runningPersistent = false;
repeatRetry: repeatRetry:
ulong[] tmpArray = resume.BadBlocks.ToArray(); ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray) foreach(ulong badSector in tmpArray)
{ {
@@ -442,7 +444,9 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "");
sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration); sense = scsiReader.ReadBlock(out readBuffer, badSector, out double cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
@@ -454,8 +458,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile.WriteAt(readBuffer, badSector, blockSize); dumpFile.WriteAt(readBuffer, badSector, blockSize);
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass); dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
} }
else if(runningPersistent) else if(runningPersistent) dumpFile.WriteAt(readBuffer, badSector, blockSize);
dumpFile.WriteAt(readBuffer, badSector, blockSize);
} }
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0) if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
@@ -474,27 +477,27 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!runningPersistent && persistent) if(!runningPersistent && persistent)
{ {
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
dev.Timeout, out duration);
if(sense) if(sense)
{ {
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
if(!sense) 0x01, dev.Timeout, out duration);
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType); if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
} }
else else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
if(currentMode.HasValue) if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
currentModePage = currentMode.Value.Pages[0];
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{ {
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
{ new Decoders.SCSI.Modes.ModePage_01_MMC
PS = false, {
ReadRetryCount = 255, PS = false,
Parameter = 0x20 ReadRetryCount = 255,
}; Parameter = 0x20
};
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
@@ -545,10 +548,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
runningPersistent = true; runningPersistent = true;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -562,25 +562,20 @@ namespace DiscImageChef.Core.Devices.Dumping
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
Pages = new Decoders.SCSI.Modes.ModePage[] Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
{
currentModePage.Value
}
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType); md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
#endregion Error handling #endregion Error handling
resume.BadBlocks.Sort(); resume.BadBlocks.Sort();
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents); currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
@@ -597,8 +592,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (uint)(blocks - i);
blocksToRead = (uint)(blocks - i);
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -615,11 +609,13 @@ namespace DiscImageChef.Core.Devices.Dumping
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
dumpFile.Close(); dumpFile.Close();
end = DateTime.UtcNow; end = DateTime.UtcNow;
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
PluginBase plugins = new PluginBase(); PluginBase plugins = new PluginBase();
plugins.RegisterAllPlugins(encoding); plugins.RegisterAllPlugins(encoding);
@@ -636,15 +632,8 @@ namespace DiscImageChef.Core.Devices.Dumping
_imageFormat = ImageFormat.Detect(inputFilter); _imageFormat = ImageFormat.Detect(inputFilter);
PartitionType[] xmlFileSysInfo = null; PartitionType[] xmlFileSysInfo = null;
try try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
{ catch { _imageFormat = null; }
if(!_imageFormat.OpenImage(inputFilter))
_imageFormat = null;
}
catch
{
_imageFormat = null;
}
if(_imageFormat != null) if(_imageFormat != null)
{ {
@@ -669,7 +658,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.", dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); i, partitions[i].Start, partitions[i].End, partitions[i].Type,
partitions[i].Scheme);
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -682,12 +672,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type); dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "PC Engine filesystem")
dskType = MediaType.SuperCDROM2; dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD; dskType = MediaType.GOD;
} }
@@ -700,27 +688,18 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
} }
} }
else else
{ {
dumpLog.WriteLine("Getting filesystem for whole device."); dumpLog.WriteLine("Getting filesystem for whole device.");
xmlFileSysInfo = new PartitionType[1]; xmlFileSysInfo = new PartitionType[1];
xmlFileSysInfo[0] = new PartitionType xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
{
EndSector = (int)(blocks - 1),
StartSector = 0
};
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
Partition wholePart = new Partition Partition wholePart =
{ new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
Name = "Whole device",
Length = blocks,
Size = blocks * blockSize
};
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -733,14 +712,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type); dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO; if(_plugin.XmlFSType.Type == "PC Engine filesystem") dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.SuperCDROM2; if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") dskType = MediaType.GOD;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD;
} }
} }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
@@ -751,14 +726,12 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
} }
} }
if(alcohol != null && !dumpRaw) if(alcohol != null && !dumpRaw) alcohol.SetMediaType(dskType);
alcohol.SetMediaType(dskType);
if(opticalDisc) if(opticalDisc)
{ {
sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray(); sidecar.OpticalDisc[0].Checksums = dataChk.End().ToArray();
@@ -771,30 +744,26 @@ namespace DiscImageChef.Core.Devices.Dumping
// TODO: Implement layers // TODO: Implement layers
//sidecar.OpticalDisc[0].Layers = new LayersType(); //sidecar.OpticalDisc[0].Layers = new LayersType();
sidecar.OpticalDisc[0].Sessions = 1; sidecar.OpticalDisc[0].Sessions = 1;
sidecar.OpticalDisc[0].Tracks = new[] { 1 }; sidecar.OpticalDisc[0].Tracks = new[] {1};
sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1]; sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1];
sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType
{ {
BytesPerSector = (int)blockSize, BytesPerSector = (int)blockSize,
Checksums = sidecar.OpticalDisc[0].Checksums, Checksums = sidecar.OpticalDisc[0].Checksums,
EndSector = (long)(blocks - 1), EndSector = (long)(blocks - 1),
Image = new ImageType Image =
{ new ImageType
format = "BINARY", {
offset = 0, format = "BINARY",
offsetSpecified = true, offset = 0,
Value = sidecar.OpticalDisc[0].Image.Value offsetSpecified = true,
}, Value = sidecar.OpticalDisc[0].Image.Value
Sequence = new TrackSequenceType },
{ Sequence = new TrackSequenceType {Session = 1, TrackNumber = 1},
Session = 1,
TrackNumber = 1
},
Size = (long)(blocks * blockSize), Size = (long)(blocks * blockSize),
StartSector = 0 StartSector = 0
}; };
if(xmlFileSysInfo != null) if(xmlFileSysInfo != null) sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
switch(dskType) switch(dskType)
{ {
case MediaType.DDCD: case MediaType.DDCD:
@@ -831,6 +800,7 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.bluray; sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.bluray;
break; break;
} }
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp); Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
sidecar.OpticalDisc[0].DiscType = xmlDskTyp; sidecar.OpticalDisc[0].DiscType = xmlDskTyp;
@@ -851,14 +821,10 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
if(!dev.IsRemovable || dev.IsUSB) if(!dev.IsRemovable || dev.IsUSB)
{ {
if(dev.Type == DeviceType.ATAPI) if(dev.Type == DeviceType.ATAPI) sidecar.BlockMedia[0].Interface = "ATAPI";
sidecar.BlockMedia[0].Interface = "ATAPI"; else if(dev.IsUSB) sidecar.BlockMedia[0].Interface = "USB";
else if(dev.IsUSB) else if(dev.IsFireWire) sidecar.BlockMedia[0].Interface = "FireWire";
sidecar.BlockMedia[0].Interface = "USB"; else sidecar.BlockMedia[0].Interface = "SCSI";
else if(dev.IsFireWire)
sidecar.BlockMedia[0].Interface = "FireWire";
else
sidecar.BlockMedia[0].Interface = "SCSI";
} }
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks; sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalBlockSize; sidecar.BlockMedia[0].PhysicalBlockSize = (int)physicalBlockSize;
@@ -867,18 +833,18 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.BlockMedia[0].Model = dev.Model; sidecar.BlockMedia[0].Model = dev.Model;
sidecar.BlockMedia[0].Serial = dev.Serial; sidecar.BlockMedia[0].Serial = dev.Serial;
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize); sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
if(xmlFileSysInfo != null) if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
if(dev.IsRemovable) if(dev.IsRemovable) sidecar.BlockMedia[0].DumpHardwareArray = resume.Tries.ToArray();
sidecar.BlockMedia[0].DumpHardwareArray = resume.Tries.ToArray();
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000)); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed); DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
@@ -889,17 +855,16 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
if(alcohol != null && !dumpRaw) if(alcohol != null && !dumpRaw) alcohol.Close();
alcohol.Close();
} }
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);
} }
} }
} }

View File

@@ -44,7 +44,9 @@ namespace DiscImageChef.Core.Devices.Dumping
public class SCSI public class SCSI
{ {
// TODO: Get cartridge serial number from Certance vendor EVPD // TODO: Get cartridge serial number from Certance vendor EVPD
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel, ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding) public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, bool separateSubchannel,
ref Metadata.Resume resume, ref DumpLog dumpLog, bool dumpLeadIn, Encoding encoding)
{ {
byte[] senseBuf = null; byte[] senseBuf = null;
bool sense = false; bool sense = false;
@@ -60,14 +62,14 @@ namespace DiscImageChef.Core.Devices.Dumping
Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
{ {
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
// Just retry, for 5 times // Just retry, for 5 times
if(decSense.Value.ASC == 0x29) if(decSense.Value.ASC == 0x29)
{ {
resets++; resets++;
if(resets < 5) if(resets < 5) goto deviceGotReset;
goto deviceGotReset;
} }
if(decSense.Value.ASC == 0x3A) if(decSense.Value.ASC == 0x3A)
@@ -78,12 +80,12 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
leftRetries--; leftRetries--;
} }
@@ -101,18 +103,19 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
leftRetries--; leftRetries--;
} }
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return; return;
} }
} }
@@ -137,24 +140,26 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
decSense.Value.SenseKey, decSense.Value.ASC, decSense.Value.ASCQ);
leftRetries--; leftRetries--;
} }
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return; return;
} }
} }
else else
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return; return;
} }
} }
@@ -170,8 +175,7 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess) if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SequentialAccess)
{ {
if(dumpRaw) if(dumpRaw) throw new ArgumentException("Tapes cannot be dumped raw.");
throw new ArgumentException("Tapes cannot be dumped raw.");
SSC.Dump(dev, outputPrefix, devicePath, ref sidecar, ref resume, ref dumpLog); SSC.Dump(dev, outputPrefix, devicePath, ref sidecar, ref resume, ref dumpLog);
return; return;
@@ -179,11 +183,13 @@ namespace DiscImageChef.Core.Devices.Dumping
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{ {
MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, dumpLeadIn, encoding); MMC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError,
ref sidecar, ref dskType, separateSubchannel, ref resume, ref dumpLog, dumpLeadIn, encoding);
return; return;
} }
SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar, ref dskType, false, ref resume, ref dumpLog, encoding); SBC.Dump(dev, devicePath, outputPrefix, retryPasses, force, dumpRaw, persistent, stopOnError, ref sidecar,
ref dskType, false, ref resume, ref dumpLog, encoding);
} }
} }
} }

View File

@@ -44,7 +44,8 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
internal static class SSC internal static class SSC
{ {
internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar, ref Metadata.Resume resume, ref DumpLog dumpLog) internal static void Dump(Device dev, string outputPrefix, string devicePath, ref CICMMetadataType sidecar,
ref Metadata.Resume resume, ref DumpLog dumpLog)
{ {
Decoders.SCSI.FixedSense? fxSense; Decoders.SCSI.FixedSense? fxSense;
bool aborted; bool aborted;
@@ -69,14 +70,16 @@ namespace DiscImageChef.Core.Devices.Dumping
if(fxSense.HasValue && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.NoSense) if(fxSense.HasValue && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.NoSense)
{ {
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ);
DicConsole.ErrorWriteLine("Drive has status error, please correct. Sense follows..."); DicConsole.ErrorWriteLine("Drive has status error, please correct. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
return; return;
} }
// Not in BOM/P // Not in BOM/P
if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 && fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest) if(fxSense.HasValue && fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x00 &&
fxSense.Value.ASCQ != 0x04 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest)
{ {
dumpLog.WriteLine("Rewinding, please wait..."); dumpLog.WriteLine("Rewinding, please wait...");
DicConsole.Write("Rewinding, please wait..."); DicConsole.Write("Rewinding, please wait...");
@@ -91,19 +94,22 @@ namespace DiscImageChef.Core.Devices.Dumping
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
} }
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ != 0x04)); while(fxSense.HasValue && fxSense.Value.ASC == 0x00 &&
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ != 0x04));
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
// And yet, did not rewind! // And yet, did not rewind!
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) || fxSense.Value.ASC != 0x00)) if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) ||
fxSense.Value.ASC != 0x00))
{ {
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
@@ -111,7 +117,8 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
// Check position // Check position
sense = dev.ReadPosition(out byte[] cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout, out duration); sense = dev.ReadPosition(out byte[] cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout,
out duration);
if(sense) if(sense)
{ {
@@ -119,12 +126,15 @@ namespace DiscImageChef.Core.Devices.Dumping
// Anyway, <=SCSI-1 tapes do not support partitions // Anyway, <=SCSI-1 tapes do not support partitions
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x20 && fxSense.Value.ASCQ != 0x00) || fxSense.Value.ASC != 0x20 && fxSense.Value.SenseKey != Decoders.SCSI.SenseKeys.IllegalRequest)) if(fxSense.HasValue && ((fxSense.Value.ASC == 0x20 && fxSense.Value.ASCQ != 0x00) ||
fxSense.Value.ASC != 0x20 && fxSense.Value.SenseKey !=
Decoders.SCSI.SenseKeys.IllegalRequest))
{ {
DicConsole.ErrorWriteLine("Could not get position. Sense follows..."); DicConsole.ErrorWriteLine("Could not get position. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Could not get position. Sense follows..."); dumpLog.WriteLine("Could not get position. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
} }
@@ -143,7 +153,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
@@ -156,27 +167,32 @@ namespace DiscImageChef.Core.Devices.Dumping
dev.RequestSense(out senseBuf, dev.Timeout, out duration); dev.RequestSense(out senseBuf, dev.Timeout, out duration);
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
} }
while(fxSense.HasValue && fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19)); while(fxSense.HasValue && fxSense.Value.ASC == 0x00 &&
(fxSense.Value.ASCQ == 0x1A || fxSense.Value.ASCQ == 0x19));
// And yet, did not rewind! // And yet, did not rewind!
if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) || fxSense.Value.ASC != 0x00)) if(fxSense.HasValue && ((fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ != 0x04) ||
fxSense.Value.ASC != 0x00))
{ {
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
sense = dev.ReadPosition(out cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout, out duration); sense = dev.ReadPosition(out cmdBuf, out senseBuf, SscPositionForms.Short, dev.Timeout,
out duration);
if(sense) if(sense)
{ {
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not rewind, please correct. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows..."); dumpLog.WriteLine("Drive could not rewind, please correct. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
@@ -193,18 +209,17 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
sidecar.BlockMedia = new BlockMediaType[1]; sidecar.BlockMedia = new BlockMediaType[1];
sidecar.BlockMedia[0] = new BlockMediaType sidecar.BlockMedia[0] = new BlockMediaType {SCSI = new SCSIType()};
{
SCSI = new SCSIType()
};
byte scsiMediumTypeTape = 0; byte scsiMediumTypeTape = 0;
byte scsiDensityCodeTape = 0; byte scsiDensityCodeTape = 0;
dumpLog.WriteLine("Requesting MODE SENSE (10)."); dumpLog.WriteLine("Requesting MODE SENSE (10).");
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF, 5, out duration); sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0xFF,
5, out duration);
if(!sense || dev.Error) if(!sense || dev.Error)
{ {
sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense10(out cmdBuf, out senseBuf, false, true, ScsiModeSensePageControl.Current, 0x3F,
0x00, 5, out duration);
} }
Decoders.SCSI.Modes.DecodedMode? decMode = null; Decoders.SCSI.Modes.DecodedMode? decMode = null;
@@ -225,11 +240,12 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
dumpLog.WriteLine("Requesting MODE SENSE (6)."); dumpLog.WriteLine("Requesting MODE SENSE (6).");
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5,
out duration);
if(sense || dev.Error) if(sense || dev.Error)
sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5, out duration); sense = dev.ModeSense6(out cmdBuf, out senseBuf, false, ScsiModeSensePageControl.Current, 0x3F, 0x00, 5,
if(sense || dev.Error) out duration);
sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration); if(sense || dev.Error) sense = dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
@@ -255,11 +271,11 @@ namespace DiscImageChef.Core.Devices.Dumping
blockSize = decMode.Value.Header.BlockDescriptors[0].BlockLength; blockSize = decMode.Value.Header.BlockDescriptors[0].BlockLength;
dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize); dumpLog.WriteLine("Device reports {0} blocks ({1} bytes).", blocks, blocks * blockSize);
} }
else else blockSize = 1;
blockSize = 1;
if(dskType == MediaType.Unknown) if(dskType == MediaType.Unknown)
dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumTypeTape, scsiDensityCodeTape, blocks, blockSize); dskType = MediaTypeFromSCSI.Get((byte)dev.SCSIType, dev.Manufacturer, dev.Model, scsiMediumTypeTape,
scsiDensityCodeTape, blocks, blockSize);
DicConsole.WriteLine("Media identified as {0}", dskType); DicConsole.WriteLine("Media identified as {0}", dskType);
@@ -280,7 +296,8 @@ namespace DiscImageChef.Core.Devices.Dumping
bool fixedLen = false; bool fixedLen = false;
uint transferLen = blockSize; uint transferLen = blockSize;
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration); sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout,
out duration);
if(sense) if(sense)
{ {
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
@@ -298,21 +315,24 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not return back. Sense follows..."); dumpLog.WriteLine("Drive could not return back. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
} }
fixedLen = true; fixedLen = true;
transferLen = 1; transferLen = 1;
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration); sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize,
dev.Timeout, out duration);
if(sense) if(sense)
{ {
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.ErrorWriteLine("Drive could not read. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not read. Sense follows..."); dumpLog.WriteLine("Drive could not read. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
} }
@@ -322,7 +342,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Drive could not read. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not read. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not read. Sense follows..."); dumpLog.WriteLine("Drive could not read. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
} }
@@ -345,7 +366,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Drive could not return back. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not return back. Sense follows...");
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpLog.WriteLine("Drive could not return back. Sense follows..."); dumpLog.WriteLine("Drive could not return back. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
} }
@@ -393,10 +415,7 @@ namespace DiscImageChef.Core.Devices.Dumping
partitionChk = new Checksum(); partitionChk = new Checksum();
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
while(currentPartition < totalPartitions) while(currentPartition < totalPartitions)
{ {
@@ -461,23 +480,24 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading block {0} ({1:F3} MiB/sec.)", currentBlock, currentSpeed); DicConsole.Write("\rReading block {0} ({1:F3} MiB/sec.)", currentBlock, currentSpeed);
sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout, out duration); sense = dev.Read6(out cmdBuf, out senseBuf, false, fixedLen, transferLen, blockSize, dev.Timeout,
out duration);
totalDuration += duration; totalDuration += duration;
if(sense) if(sense)
{ {
fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense); fxSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf, out strSense);
if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI && fxSense.Value.InformationValid) if(fxSense.Value.ASC == 0x00 && fxSense.Value.ASCQ == 0x00 && fxSense.Value.ILI &&
fxSense.Value.InformationValid)
{ {
blockSize = (uint)((int)blockSize - BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0)); blockSize = (uint)((int)blockSize -
BitConverter.ToInt32(BitConverter.GetBytes(fxSense.Value.Information), 0));
currentTapeFile.BlockSize = blockSize; currentTapeFile.BlockSize = blockSize;
DicConsole.WriteLine(); DicConsole.WriteLine();
@@ -495,7 +515,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("{0}", strSense); DicConsole.ErrorWriteLine("{0}", strSense);
dumpFile.Close(); dumpFile.Close();
dumpLog.WriteLine("Drive could not go back one block. Sense follows..."); dumpLog.WriteLine("Drive could not go back one block. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h",
fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
@@ -514,7 +535,8 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
// For sure this is an end-of-tape/partition // For sure this is an end-of-tape/partition
if(fxSense.Value.ASC == 0x00 && (fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM)) if(fxSense.Value.ASC == 0x00 &&
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM))
{ {
// TODO: Detect end of partition // TODO: Detect end of partition
endOfMedia = true; endOfMedia = true;
@@ -529,7 +551,8 @@ namespace DiscImageChef.Core.Devices.Dumping
continue; continue;
} }
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense || fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) && if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense ||
fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
(fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM)) (fxSense.Value.ASCQ == 0x02 || fxSense.Value.ASCQ == 0x05 || fxSense.Value.EOM))
{ {
// TODO: Detect end of partition // TODO: Detect end of partition
@@ -538,7 +561,8 @@ namespace DiscImageChef.Core.Devices.Dumping
continue; continue;
} }
if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense || fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) && if((fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.NoSense ||
fxSense.Value.SenseKey == Decoders.SCSI.SenseKeys.RecoveredError) &&
(fxSense.Value.ASCQ == 0x01 || fxSense.Value.Filemark)) (fxSense.Value.ASCQ == 0x01 || fxSense.Value.Filemark))
{ {
currentTapeFile.Checksums = fileChk.End().ToArray(); currentTapeFile.Checksums = fileChk.End().ToArray();
@@ -574,7 +598,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Drive could not read block. Sense follows..."); DicConsole.ErrorWriteLine("Drive could not read block. Sense follows...");
DicConsole.ErrorWriteLine("{0} {1}", fxSense.Value.SenseKey, strSense); DicConsole.ErrorWriteLine("{0} {1}", fxSense.Value.SenseKey, strSense);
dumpLog.WriteLine("Drive could not read block. Sense follows..."); dumpLog.WriteLine("Drive could not read block. Sense follows...");
dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey, fxSense.Value.ASC, fxSense.Value.ASCQ); dumpLog.WriteLine("Device not ready. Sense {0}h ASC {1:X2}h ASCQ {2:X2}h", fxSense.Value.SenseKey,
fxSense.Value.ASC, fxSense.Value.ASCQ);
return; return;
} }
@@ -602,14 +627,19 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine(); DicConsole.WriteLine();
end = DateTime.UtcNow; end = DateTime.UtcNow;
mhddLog.Close(); mhddLog.Close();
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
(end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000)); DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed); DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
@@ -628,15 +658,8 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks; sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
sidecar.BlockMedia[0].Size = (long)(currentSize); sidecar.BlockMedia[0].Size = (long)(currentSize);
sidecar.BlockMedia[0].DumpHardwareArray = new DumpHardwareType[1]; sidecar.BlockMedia[0].DumpHardwareArray = new DumpHardwareType[1];
sidecar.BlockMedia[0].DumpHardwareArray[0] = new DumpHardwareType sidecar.BlockMedia[0].DumpHardwareArray[0] = new DumpHardwareType {Extents = new ExtentType[1]};
{ sidecar.BlockMedia[0].DumpHardwareArray[0].Extents[0] = new ExtentType {Start = 0, End = blocks - 1};
Extents = new ExtentType[1]
};
sidecar.BlockMedia[0].DumpHardwareArray[0].Extents[0] = new ExtentType
{
Start = 0,
End = blocks - 1
};
sidecar.BlockMedia[0].DumpHardwareArray[0].Manufacturer = dev.Manufacturer; sidecar.BlockMedia[0].DumpHardwareArray[0].Manufacturer = dev.Manufacturer;
sidecar.BlockMedia[0].DumpHardwareArray[0].Model = dev.Model; sidecar.BlockMedia[0].DumpHardwareArray[0].Model = dev.Model;
sidecar.BlockMedia[0].DumpHardwareArray[0].Revision = dev.Revision; sidecar.BlockMedia[0].DumpHardwareArray[0].Revision = dev.Revision;
@@ -648,10 +671,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
} }
@@ -661,4 +684,4 @@ namespace DiscImageChef.Core.Devices.Dumping
return; return;
} }
} }
} }

View File

@@ -49,7 +49,9 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
public class SecureDigital public class SecureDigital
{ {
public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding) public static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref Metadata.Resume resume,
ref DumpLog dumpLog, Encoding encoding)
{ {
bool aborted; bool aborted;
MHDDLog mhddLog; MHDDLog mhddLog;
@@ -59,8 +61,7 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.ErrorWriteLine("Raw dumping is not supported in MultiMediaCard or SecureDigital devices."); DicConsole.ErrorWriteLine("Raw dumping is not supported in MultiMediaCard or SecureDigital devices.");
if(force) if(force) DicConsole.ErrorWriteLine("Continuing...");
DicConsole.ErrorWriteLine("Continuing...");
else else
{ {
DicConsole.ErrorWriteLine("Aborting..."); DicConsole.ErrorWriteLine("Aborting...");
@@ -73,10 +74,8 @@ namespace DiscImageChef.Core.Devices.Dumping
uint timeout = 5; uint timeout = 5;
double duration; double duration;
CICMMetadataType sidecar = new CICMMetadataType() CICMMetadataType sidecar =
{ new CICMMetadataType() {BlockMedia = new BlockMediaType[] {new BlockMediaType()}};
BlockMedia = new BlockMediaType[] { new BlockMediaType() }
};
uint blocksToRead = 128; uint blocksToRead = 128;
uint blockSize = 512; uint blockSize = 512;
@@ -103,15 +102,12 @@ namespace DiscImageChef.Core.Devices.Dumping
blocksToRead = ecsdDecoded.OptimalReadSize; blocksToRead = ecsdDecoded.OptimalReadSize;
blocks = ecsdDecoded.SectorCount; blocks = ecsdDecoded.SectorCount;
blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512); blockSize = (uint)(ecsdDecoded.SectorSize == 1 ? 4096 : 512);
if(ecsdDecoded.NativeSectorSize == 0) if(ecsdDecoded.NativeSectorSize == 0) physicalBlockSize = 512;
physicalBlockSize = 512; else if(ecsdDecoded.NativeSectorSize == 1) physicalBlockSize = 4096;
else if(ecsdDecoded.NativeSectorSize == 1)
physicalBlockSize = 4096;
// Supposing it's high-capacity MMC if it has Extended CSD... // Supposing it's high-capacity MMC if it has Extended CSD...
byteAddressed = false; byteAddressed = false;
} }
else else ecsd = null;
ecsd = null;
dumpLog.WriteLine("Reading CSD"); dumpLog.WriteLine("Reading CSD");
sense = dev.ReadCSD(out csd, out response, timeout, out duration); sense = dev.ReadCSD(out csd, out response, timeout, out duration);
@@ -124,13 +120,11 @@ namespace DiscImageChef.Core.Devices.Dumping
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength); blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
} }
} }
else else csd = null;
csd = null;
dumpLog.WriteLine("Reading OCR"); dumpLog.WriteLine("Reading OCR");
sense = dev.ReadOCR(out ocr, out response, timeout, out duration); sense = dev.ReadOCR(out ocr, out response, timeout, out duration);
if(sense) if(sense) ocr = null;
ocr = null;
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType(); sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
} }
@@ -143,31 +137,29 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!sense) if(!sense)
{ {
csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd); csdDecoded = Decoders.SecureDigital.Decoders.DecodeCSD(csd);
blocks = (ulong)(csdDecoded.Structure == 0 ? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2) : (csdDecoded.Size + 1) * 1024); blocks = (ulong)(csdDecoded.Structure == 0
? (csdDecoded.Size + 1) * Math.Pow(2, csdDecoded.SizeMultiplier + 2)
: (csdDecoded.Size + 1) * 1024);
blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength); blockSize = (uint)Math.Pow(2, csdDecoded.ReadBlockLength);
// Structure >=1 for SDHC/SDXC, so that's block addressed // Structure >=1 for SDHC/SDXC, so that's block addressed
byteAddressed = csdDecoded.Structure == 0; byteAddressed = csdDecoded.Structure == 0;
} }
else else csd = null;
csd = null;
dumpLog.WriteLine("Reading OCR"); dumpLog.WriteLine("Reading OCR");
sense = dev.ReadSDOCR(out ocr, out response, timeout, out duration); sense = dev.ReadSDOCR(out ocr, out response, timeout, out duration);
if(sense) if(sense) ocr = null;
ocr = null;
dumpLog.WriteLine("Reading SCR"); dumpLog.WriteLine("Reading SCR");
sense = dev.ReadSCR(out scr, out response, timeout, out duration); sense = dev.ReadSCR(out scr, out response, timeout, out duration);
if(sense) if(sense) scr = null;
scr = null;
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType(); sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
} }
dumpLog.WriteLine("Reading CID"); dumpLog.WriteLine("Reading CID");
sense = dev.ReadCID(out cid, out response, timeout, out duration); sense = dev.ReadCID(out cid, out response, timeout, out duration);
if(sense) if(sense) cid = null;
cid = null;
DumpType cidDump = null; DumpType cidDump = null;
DumpType csdDump = null; DumpType csdDump = null;
@@ -182,7 +174,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksums = Checksum.GetChecksums(cid).ToArray() Checksums = Checksum.GetChecksums(cid).ToArray()
}; };
DataFile.WriteTo("MMC/SecureDigital Dump", cidDump.Image, cid); DataFile.WriteTo("MMC/SecureDigital Dump", cidDump.Image, cid);
}; }
;
if(csd != null) if(csd != null)
{ {
csdDump = new DumpType csdDump = new DumpType
@@ -192,7 +185,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksums = Checksum.GetChecksums(csd).ToArray() Checksums = Checksum.GetChecksums(csd).ToArray()
}; };
DataFile.WriteTo("MMC/SecureDigital Dump", csdDump.Image, csd); DataFile.WriteTo("MMC/SecureDigital Dump", csdDump.Image, csd);
}; }
;
if(ecsd != null) if(ecsd != null)
{ {
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
@@ -201,8 +195,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Size = ecsd.Length, Size = ecsd.Length,
Checksums = Checksum.GetChecksums(ecsd).ToArray() Checksums = Checksum.GetChecksums(ecsd).ToArray()
}; };
DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD.Image, ecsd); DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD.Image,
}; ecsd);
}
;
if(ocr != null) if(ocr != null)
{ {
ocrDump = new DumpType ocrDump = new DumpType
@@ -212,7 +208,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksums = Checksum.GetChecksums(ocr).ToArray() Checksums = Checksum.GetChecksums(ocr).ToArray()
}; };
DataFile.WriteTo("MMC/SecureDigital Dump", ocrDump.Image, ocr); DataFile.WriteTo("MMC/SecureDigital Dump", ocrDump.Image, ocr);
}; }
;
if(scr != null) if(scr != null)
{ {
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
@@ -222,7 +219,8 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksums = Checksum.GetChecksums(scr).ToArray() Checksums = Checksum.GetChecksums(scr).ToArray()
}; };
DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].SecureDigital.SCR.Image, scr); DataFile.WriteTo("MMC/SecureDigital Dump", sidecar.BlockMedia[0].SecureDigital.SCR.Image, scr);
}; }
;
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC)
{ {
@@ -247,10 +245,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksum dataChk; Checksum dataChk;
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
DataFile dumpFile; DataFile dumpFile;
@@ -260,6 +255,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Unable to get device size."); DicConsole.ErrorWriteLine("Unable to get device size.");
return; return;
} }
dumpLog.WriteLine("Device reports {0} blocks.", blocks); dumpLog.WriteLine("Device reports {0} blocks.", blocks);
byte[] cmdBuf; byte[] cmdBuf;
@@ -267,13 +263,12 @@ namespace DiscImageChef.Core.Devices.Dumping
while(true) while(true)
{ {
error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration); error = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout,
out duration);
if(error) if(error) blocksToRead /= 2;
blocksToRead /= 2;
if(!error || blocksToRead == 1) if(!error || blocksToRead == 1) break;
break;
} }
if(error) if(error)
@@ -288,7 +283,8 @@ namespace DiscImageChef.Core.Devices.Dumping
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(true, false, blocks, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID,
ref resume, ref currentTry, ref extents);
if(currentTry == null || extents == null) if(currentTry == null || extents == null)
throw new Exception("Could not process resume file, not continuing..."); throw new Exception("Could not process resume file, not continuing...");
@@ -298,8 +294,7 @@ namespace DiscImageChef.Core.Devices.Dumping
ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile); ibgLog = new IBGLog(outputPrefix + ".ibg", currentProfile);
dumpFile = new DataFile(outputPrefix + ".bin"); dumpFile = new DataFile(outputPrefix + ".bin");
dumpFile.Seek(resume.NextBlock, blockSize); dumpFile.Seek(resume.NextBlock, blockSize);
if(resume.NextBlock > 0) if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
start = DateTime.UtcNow; start = DateTime.UtcNow;
for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead) for(ulong i = resume.NextBlock; i < blocks; i += blocksToRead)
@@ -311,19 +306,17 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
blocksToRead = (byte)(blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration); error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout,
out duration);
if(!error) if(!error)
{ {
@@ -334,12 +327,10 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
else else
{ {
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
resume.BadBlocks.Add(b);
if(duration < 500) if(duration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, duration);
else
mhddLog.Write(i, duration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpFile.Write(new byte[blockSize * blocksToRead]); dumpFile.Write(new byte[blockSize * blocksToRead]);
@@ -352,24 +343,26 @@ namespace DiscImageChef.Core.Devices.Dumping
GC.Collect(); GC.Collect();
resume.NextBlock = i + blocksToRead; resume.NextBlock = i + blocksToRead;
} }
end = DateTime.Now; end = DateTime.Now;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted) if(resume.BadBlocks.Count > 0 && !aborted)
{ {
int pass = 0; int pass = 0;
bool forward = true; bool forward = true;
bool runningPersistent = false; bool runningPersistent = false;
repeatRetryLba: repeatRetryLba:
ulong[] tmpArray = resume.BadBlocks.ToArray(); ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray) foreach(ulong badSector in tmpArray)
{ {
@@ -380,9 +373,12 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "");
error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, timeout, out duration); error = dev.Read(out cmdBuf, out response, (uint)badSector, blockSize, 1, byteAddressed, timeout,
out duration);
totalDuration += duration; totalDuration += duration;
@@ -393,8 +389,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile.WriteAt(cmdBuf, badSector, blockSize); dumpFile.WriteAt(cmdBuf, badSector, blockSize);
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass); dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
} }
else if(runningPersistent) else if(runningPersistent) dumpFile.WriteAt(cmdBuf, badSector, blockSize);
dumpFile.WriteAt(cmdBuf, badSector, blockSize);
} }
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0) if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
@@ -425,8 +420,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (byte)(blocks - i);
blocksToRead = (byte)(blocks - i);
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -441,11 +435,13 @@ namespace DiscImageChef.Core.Devices.Dumping
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
dumpFile.Close(); dumpFile.Close();
end = DateTime.UtcNow; end = DateTime.UtcNow;
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
PluginBase plugins = new PluginBase(); PluginBase plugins = new PluginBase();
plugins.RegisterAllPlugins(encoding); plugins.RegisterAllPlugins(encoding);
@@ -463,15 +459,8 @@ namespace DiscImageChef.Core.Devices.Dumping
_imageFormat = ImageFormat.Detect(inputFilter); _imageFormat = ImageFormat.Detect(inputFilter);
PartitionType[] xmlFileSysInfo = null; PartitionType[] xmlFileSysInfo = null;
try try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
{ catch { _imageFormat = null; }
if(!_imageFormat.OpenImage(inputFilter))
_imageFormat = null;
}
catch
{
_imageFormat = null;
}
if(_imageFormat != null) if(_imageFormat != null)
{ {
@@ -496,7 +485,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.", dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); i, partitions[i].Start, partitions[i].End, partitions[i].Type,
partitions[i].Scheme);
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -518,8 +508,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
} }
} }
else else
@@ -527,19 +516,11 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Getting filesystem for whole device."); dumpLog.WriteLine("Getting filesystem for whole device.");
xmlFileSysInfo = new PartitionType[1]; xmlFileSysInfo = new PartitionType[1];
xmlFileSysInfo[0] = new PartitionType xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
{
EndSector = (int)(blocks - 1),
StartSector = 0
};
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
Partition wholePart = new Partition Partition wholePart =
{ new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
Name = "Whole device",
Length = blocks,
Size = blocks * blockSize
};
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -561,8 +542,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
} }
} }
@@ -586,10 +566,8 @@ namespace DiscImageChef.Core.Devices.Dumping
format = "Raw disk image (sector by sector copy)", format = "Raw disk image (sector by sector copy)",
Value = outputPrefix + ".bin" Value = outputPrefix + ".bin"
}; };
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC) sidecar.BlockMedia[0].Interface = "MultiMediaCard";
sidecar.BlockMedia[0].Interface = "MultiMediaCard"; else if(dev.Type == DeviceType.SecureDigital) sidecar.BlockMedia[0].Interface = "SecureDigital";
else if(dev.Type == DeviceType.SecureDigital)
sidecar.BlockMedia[0].Interface = "SecureDigital";
sidecar.BlockMedia[0].LogicalBlocks = (long)blocks; sidecar.BlockMedia[0].LogicalBlocks = (long)blocks;
sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : (int)blockSize; sidecar.BlockMedia[0].PhysicalBlockSize = physicalBlockSize > 0 ? physicalBlockSize : (int)blockSize;
sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize; sidecar.BlockMedia[0].LogicalBlockSize = (int)blockSize;
@@ -597,36 +575,34 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.BlockMedia[0].Model = dev.Model; sidecar.BlockMedia[0].Model = dev.Model;
sidecar.BlockMedia[0].Serial = dev.Serial; sidecar.BlockMedia[0].Serial = dev.Serial;
sidecar.BlockMedia[0].Size = (long)(blocks * blockSize); sidecar.BlockMedia[0].Size = (long)(blocks * blockSize);
if(xmlFileSysInfo != null) if(xmlFileSysInfo != null) sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
sidecar.BlockMedia[0].FileSystemInformation = xmlFileSysInfo;
DicConsole.WriteLine(); DicConsole.WriteLine();
DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).", (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000); DicConsole.WriteLine("Took a total of {0:F3} seconds ({1:F3} processing commands, {2:F3} checksumming).",
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000)); (end - start).TotalSeconds, totalDuration / 1000, totalChkDuration / 1000);
DicConsole.WriteLine("Avegare speed: {0:F3} MiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1048576) / (totalDuration / 1000));
DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed); DicConsole.WriteLine("Fastest speed burst: {0:F3} MiB/sec.", maxSpeed);
DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed); DicConsole.WriteLine("Slowest speed burst: {0:F3} MiB/sec.", minSpeed);
DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count); DicConsole.WriteLine("{0} sectors could not be read.", resume.BadBlocks.Count);
if(resume.BadBlocks.Count > 0) if(resume.BadBlocks.Count > 0) resume.BadBlocks.Sort();
resume.BadBlocks.Sort();
DicConsole.WriteLine(); DicConsole.WriteLine();
if(!aborted) if(!aborted)
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
} }
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC) Statistics.AddMedia(MediaType.MMC, true);
Statistics.AddMedia(MediaType.MMC, true); else if(dev.Type == DeviceType.SecureDigital) Statistics.AddMedia(MediaType.SecureDigital, true);
else if(dev.Type == DeviceType.SecureDigital)
Statistics.AddMedia(MediaType.SecureDigital, true);
} }
} }
} }

View File

@@ -49,7 +49,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
internal static class XGD internal static class XGD
{ {
internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force, bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar, ref MediaType dskType, ref Metadata.Resume resume, ref DumpLog dumpLog, Encoding encoding) internal static void Dump(Device dev, string devicePath, string outputPrefix, ushort retryPasses, bool force,
bool dumpRaw, bool persistent, bool stopOnError, ref CICMMetadataType sidecar,
ref MediaType dskType, ref Metadata.Resume resume, ref DumpLog dumpLog,
Encoding encoding)
{ {
MHDDLog mhddLog; MHDDLog mhddLog;
IBGLog ibgLog; IBGLog ibgLog;
@@ -68,10 +71,7 @@ namespace DiscImageChef.Core.Devices.Dumping
Checksum dataChk; Checksum dataChk;
DataFile dumpFile = null; DataFile dumpFile = null;
bool aborted = false; bool aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
dumpLog.WriteLine("Reading Xbox Security Sector."); dumpLog.WriteLine("Reading Xbox Security Sector.");
sense = dev.KreonExtractSS(out byte[] ssBuf, out byte[] senseBuf, dev.Timeout, out double duration); sense = dev.KreonExtractSS(out byte[] ssBuf, out byte[] senseBuf, dev.Timeout, out double duration);
@@ -96,19 +96,19 @@ namespace DiscImageChef.Core.Devices.Dumping
sidecar.OpticalDisc[0].Xbox = new XboxType() sidecar.OpticalDisc[0].Xbox = new XboxType()
{ {
SecuritySectors = new XboxSecuritySectorsType[] SecuritySectors = new XboxSecuritySectorsType[]
{ {
new XboxSecuritySectorsType() new XboxSecuritySectorsType()
{ {
RequestNumber = 0, RequestNumber = 0,
RequestVersion = 1, RequestVersion = 1,
SecuritySectors = new DumpType() SecuritySectors = new DumpType()
{ {
Image = outputPrefix + ".ss.bin", Image = outputPrefix + ".ss.bin",
Size = tmpBuf.Length, Size = tmpBuf.Length,
Checksums = Checksum.GetChecksums(tmpBuf).ToArray() Checksums = Checksum.GetChecksums(tmpBuf).ToArray()
} }
} }
} }
}; };
DataFile.WriteTo("SCSI Dump", outputPrefix + ".ss.bin", ssBuf); DataFile.WriteTo("SCSI Dump", outputPrefix + ".ss.bin", ssBuf);
@@ -124,6 +124,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing."); DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
return; return;
} }
dumpLog.WriteLine("Getting video partition size."); dumpLog.WriteLine("Getting video partition size.");
sense = dev.ReadCapacity(out byte[] readBuffer, out senseBuf, dev.Timeout, out duration); sense = dev.ReadCapacity(out byte[] readBuffer, out senseBuf, dev.Timeout, out duration);
if(sense) if(sense)
@@ -132,15 +133,18 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot get disc capacity."); DicConsole.ErrorWriteLine("Cannot get disc capacity.");
return; return;
} }
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])); totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
dumpLog.WriteLine("Reading Physical Format Information."); dumpLog.WriteLine("Reading Physical Format Information.");
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration); sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
if(sense) if(sense)
{ {
dumpLog.WriteLine("Cannot get PFI."); dumpLog.WriteLine("Cannot get PFI.");
DicConsole.ErrorWriteLine("Cannot get PFI."); DicConsole.ErrorWriteLine("Cannot get PFI.");
return; return;
} }
tmpBuf = new byte[readBuffer.Length - 4]; tmpBuf = new byte[readBuffer.Length - 4];
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4); Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
sidecar.OpticalDisc[0].PFI = new DumpType sidecar.OpticalDisc[0].PFI = new DumpType
@@ -151,16 +155,19 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].PFI.Image, tmpBuf, "Locked PFI", true); DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].PFI.Image, tmpBuf, "Locked PFI", true);
DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize); DicConsole.DebugWriteLine("Dump-media command", "Video partition total size: {0} sectors", totalSize);
l0Video = Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN - Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1; l0Video = Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN -
Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1;
l1Video = totalSize - l0Video + 1; l1Video = totalSize - l0Video + 1;
dumpLog.WriteLine("Reading Disc Manufacturing Information."); dumpLog.WriteLine("Reading Disc Manufacturing Information.");
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration); sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
if(sense) if(sense)
{ {
dumpLog.WriteLine("Cannot get DMI."); dumpLog.WriteLine("Cannot get DMI.");
DicConsole.ErrorWriteLine("Cannot get DMI."); DicConsole.ErrorWriteLine("Cannot get DMI.");
return; return;
} }
tmpBuf = new byte[readBuffer.Length - 4]; tmpBuf = new byte[readBuffer.Length - 4];
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4); Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
sidecar.OpticalDisc[0].DMI = new DumpType sidecar.OpticalDisc[0].DMI = new DumpType
@@ -181,6 +188,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing."); DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
return; return;
} }
dumpLog.WriteLine("Getting game partition size."); dumpLog.WriteLine("Getting game partition size.");
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration); sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
if(sense) if(sense)
@@ -189,7 +197,9 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot get disc capacity."); DicConsole.ErrorWriteLine("Cannot get disc capacity.");
return; return;
} }
gameSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])) + 1;
gameSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])) +
1;
DicConsole.DebugWriteLine("Dump-media command", "Game partition total size: {0} sectors", gameSize); DicConsole.DebugWriteLine("Dump-media command", "Game partition total size: {0} sectors", gameSize);
// Get middle zone size // Get middle zone size
@@ -202,6 +212,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing."); DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
return; return;
} }
dumpLog.WriteLine("Getting disc size."); dumpLog.WriteLine("Getting disc size.");
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration); sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
if(sense) if(sense)
@@ -210,18 +221,22 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot get disc capacity."); DicConsole.ErrorWriteLine("Cannot get disc capacity.");
return; return;
} }
totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3])); totalSize = (ulong)((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3]));
dumpLog.WriteLine("Reading Physical Format Information."); dumpLog.WriteLine("Reading Physical Format Information.");
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration); sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.PhysicalInformation, 0, 0, out duration);
if(sense) if(sense)
{ {
dumpLog.WriteLine("Cannot get PFI."); dumpLog.WriteLine("Cannot get PFI.");
DicConsole.ErrorWriteLine("Cannot get PFI."); DicConsole.ErrorWriteLine("Cannot get PFI.");
return; return;
} }
DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", totalSize); DicConsole.DebugWriteLine("Dump-media command", "Unlocked total size: {0} sectors", totalSize);
blocks = totalSize + 1; blocks = totalSize + 1;
middleZone = totalSize - (Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN - Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1) - gameSize + 1; middleZone = totalSize - (Decoders.DVD.PFI.Decode(readBuffer).Value.Layer0EndPSN -
Decoders.DVD.PFI.Decode(readBuffer).Value.DataAreaStartPSN + 1) - gameSize + 1;
tmpBuf = new byte[readBuffer.Length - 4]; tmpBuf = new byte[readBuffer.Length - 4];
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4); Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
@@ -234,13 +249,15 @@ namespace DiscImageChef.Core.Devices.Dumping
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.PFI.Image, tmpBuf, "Unlocked PFI", true); DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.PFI.Image, tmpBuf, "Unlocked PFI", true);
dumpLog.WriteLine("Reading Disc Manufacturing Information."); dumpLog.WriteLine("Reading Disc Manufacturing Information.");
sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0, MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration); sense = dev.ReadDiscStructure(out readBuffer, out senseBuf, MmcDiscStructureMediaType.DVD, 0, 0,
MmcDiscStructureFormat.DiscManufacturingInformation, 0, 0, out duration);
if(sense) if(sense)
{ {
dumpLog.WriteLine("Cannot get DMI."); dumpLog.WriteLine("Cannot get DMI.");
DicConsole.ErrorWriteLine("Cannot get DMI."); DicConsole.ErrorWriteLine("Cannot get DMI.");
return; return;
} }
tmpBuf = new byte[readBuffer.Length - 4]; tmpBuf = new byte[readBuffer.Length - 4];
Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4); Array.Copy(readBuffer, 4, tmpBuf, 0, readBuffer.Length - 4);
sidecar.OpticalDisc[0].Xbox.DMI = new DumpType sidecar.OpticalDisc[0].Xbox.DMI = new DumpType
@@ -251,7 +268,6 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.DMI.Image, tmpBuf, "Unlocked DMI", true); DataFile.WriteTo("SCSI Dump", sidecar.OpticalDisc[0].Xbox.DMI.Image, tmpBuf, "Unlocked DMI", true);
totalSize = l0Video + l1Video + middleZone * 2 + gameSize; totalSize = l0Video + l1Video + middleZone * 2 + gameSize;
layerBreak = l0Video + middleZone + gameSize / 2; layerBreak = l0Video + middleZone + gameSize / 2;
@@ -270,7 +286,8 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Total 0 size: {0} sectors", totalSize); dumpLog.WriteLine("Total 0 size: {0} sectors", totalSize);
dumpLog.WriteLine("Real layer break: {0}", layerBreak); dumpLog.WriteLine("Real layer break: {0}", layerBreak);
bool read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, dev.Timeout, out duration); bool read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1,
false, dev.Timeout, out duration);
if(!read12) if(!read12)
{ {
dumpLog.WriteLine("Cannot read medium, aborting scan..."); dumpLog.WriteLine("Cannot read medium, aborting scan...");
@@ -285,13 +302,12 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
if(read12) if(read12)
{ {
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0, blocksToRead, false, dev.Timeout, out duration); sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0,
if(sense || dev.Error) blocksToRead, false, dev.Timeout, out duration);
blocksToRead /= 2; if(sense || dev.Error) blocksToRead /= 2;
} }
if(!dev.Error || blocksToRead == 1) if(!dev.Error || blocksToRead == 1) break;
break;
} }
if(dev.Error) if(dev.Error)
@@ -316,13 +332,14 @@ namespace DiscImageChef.Core.Devices.Dumping
uint saveBlocksToRead = blocksToRead; uint saveBlocksToRead = blocksToRead;
DumpHardwareType currentTry = null; DumpHardwareType currentTry = null;
ExtentsULong extents = null; ExtentsULong extents = null;
ResumeSupport.Process(true, true, totalSize, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID, ref resume, ref currentTry, ref extents); ResumeSupport.Process(true, true, totalSize, dev.Manufacturer, dev.Model, dev.Serial, dev.PlatformID,
ref resume, ref currentTry, ref extents);
if(currentTry == null || extents == null) if(currentTry == null || extents == null)
throw new Exception("Could not process resume file, not continuing..."); throw new Exception("Could not process resume file, not continuing...");
ulong currentSector = resume.NextBlock; ulong currentSector = resume.NextBlock;
dumpFile.Seek(resume.NextBlock, blockSize); dumpFile.Seek(resume.NextBlock, blockSize);
if(resume.NextBlock > 0) if(resume.NextBlock > 0) dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Resuming from block {0}.", resume.NextBlock);
dumpLog.WriteLine("Reading game partition."); dumpLog.WriteLine("Reading game partition.");
for(int e = 0; e <= 16; e++) for(int e = 0; e <= 16; e++)
@@ -335,8 +352,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if(currentSector >= blocks) if(currentSector >= blocks) break;
break;
ulong extentStart, extentEnd; ulong extentStart, extentEnd;
// Extents // Extents
@@ -345,11 +361,13 @@ namespace DiscImageChef.Core.Devices.Dumping
if(xboxSS.Value.Extents[e].StartPSN <= xboxSS.Value.Layer0EndPSN) if(xboxSS.Value.Extents[e].StartPSN <= xboxSS.Value.Layer0EndPSN)
extentStart = xboxSS.Value.Extents[e].StartPSN - 0x30000; extentStart = xboxSS.Value.Extents[e].StartPSN - 0x30000;
else else
extentStart = (xboxSS.Value.Layer0EndPSN + 1) * 2 - ((xboxSS.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000; extentStart = (xboxSS.Value.Layer0EndPSN + 1) * 2 -
((xboxSS.Value.Extents[e].StartPSN ^ 0xFFFFFF) + 1) - 0x30000;
if(xboxSS.Value.Extents[e].EndPSN <= xboxSS.Value.Layer0EndPSN) if(xboxSS.Value.Extents[e].EndPSN <= xboxSS.Value.Layer0EndPSN)
extentEnd = xboxSS.Value.Extents[e].EndPSN - 0x30000; extentEnd = xboxSS.Value.Extents[e].EndPSN - 0x30000;
else else
extentEnd = (xboxSS.Value.Layer0EndPSN + 1) * 2 - ((xboxSS.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000; extentEnd = (xboxSS.Value.Layer0EndPSN + 1) * 2 -
((xboxSS.Value.Extents[e].EndPSN ^ 0xFFFFFF) + 1) - 0x30000;
} }
// After last extent // After last extent
else else
@@ -358,8 +376,7 @@ namespace DiscImageChef.Core.Devices.Dumping
extentEnd = blocks; extentEnd = blocks;
} }
if(currentSector > extentEnd) if(currentSector > extentEnd) continue;
continue;
for(ulong i = currentSector; i < extentStart; i += blocksToRead) for(ulong i = currentSector; i < extentStart; i += blocksToRead)
{ {
@@ -372,19 +389,17 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((extentStart - i) < blocksToRead) if((extentStart - i) < blocksToRead) blocksToRead = (uint)(extentStart - i);
blocksToRead = (uint)(extentStart - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, totalSize, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, totalSize, currentSpeed);
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)i, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration); sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)i, blockSize,
0, blocksToRead, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -397,27 +412,26 @@ namespace DiscImageChef.Core.Devices.Dumping
else else
{ {
// TODO: Reset device after X errors // TODO: Reset device after X errors
if(stopOnError) if(stopOnError) return; // TODO: Return more cleanly
return; // TODO: Return more cleanly
// Write empty data // Write empty data
dumpFile.Write(new byte[blockSize * blocksToRead]); dumpFile.Write(new byte[blockSize * blocksToRead]);
errored += blocksToRead; errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) resume.BadBlocks.Add(b);
resume.BadBlocks.Add(b);
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
if(cmdDuration < 500) Decoders.SCSI.Sense.PrettifySense(senseBuf));
mhddLog.Write(i, 65535); if(cmdDuration < 500) mhddLog.Write(i, 65535);
else else mhddLog.Write(i, cmdDuration);
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i); dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, i);
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); string[] senseLines = Decoders
foreach(string senseLine in senseLines) .SCSI.Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
dumpLog.WriteLine(senseLine); StringSplitOptions.RemoveEmptyEntries);
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
} }
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
@@ -438,8 +452,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((extentEnd - i) < blocksToRead) if((extentEnd - i) < blocksToRead) blocksToRead = (uint)(extentEnd - i) + 1;
blocksToRead = (uint)(extentEnd - i) + 1;
mhddLog.Write(i, cmdDuration); mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, currentSpeed * 1024); ibgLog.Write(i, currentSpeed * 1024);
@@ -450,8 +463,7 @@ namespace DiscImageChef.Core.Devices.Dumping
resume.NextBlock = currentSector; resume.NextBlock = currentSector;
} }
if(!aborted) if(!aborted) currentSector = extentEnd + 1;
currentSector = extentEnd + 1;
} }
// Middle Zone D // Middle Zone D
@@ -465,10 +477,10 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if(((middleZone - 1) - middle) < blocksToRead) if(((middleZone - 1) - middle) < blocksToRead) blocksToRead = (uint)((middleZone - 1) - middle);
blocksToRead = (uint)((middleZone - 1) - middle);
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", middle + currentSector, totalSize, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", middle + currentSector, totalSize,
currentSpeed);
mhddLog.Write(middle + currentSector, cmdDuration); mhddLog.Write(middle + currentSector, cmdDuration);
ibgLog.Write(middle + currentSector, currentSpeed * 1024); ibgLog.Write(middle + currentSector, currentSpeed * 1024);
@@ -489,6 +501,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot lock drive, not continuing."); DicConsole.ErrorWriteLine("Cannot lock drive, not continuing.");
return; return;
} }
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration); sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
if(sense) if(sense)
{ {
@@ -507,19 +520,18 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if(((l0Video + l1Video) - l1) < blocksToRead) if(((l0Video + l1Video) - l1) < blocksToRead) blocksToRead = (uint)((l0Video + l1Video) - l1);
blocksToRead = (uint)((l0Video + l1Video) - l1);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > maxSpeed && currentSpeed != 0) if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed;
maxSpeed = currentSpeed; if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed;
if(currentSpeed < minSpeed && currentSpeed != 0)
minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", currentSector, totalSize, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", currentSector, totalSize,
currentSpeed);
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)l1, blockSize, 0, blocksToRead, false, dev.Timeout, out cmdDuration); sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)l1, blockSize, 0,
blocksToRead, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -532,8 +544,7 @@ namespace DiscImageChef.Core.Devices.Dumping
else else
{ {
// TODO: Reset device after X errors // TODO: Reset device after X errors
if(stopOnError) if(stopOnError) return; // TODO: Return more cleanly
return; // TODO: Return more cleanly
// Write empty data // Write empty data
dumpFile.Write(new byte[blockSize * blocksToRead]); dumpFile.Write(new byte[blockSize * blocksToRead]);
@@ -541,17 +552,17 @@ namespace DiscImageChef.Core.Devices.Dumping
// TODO: Handle errors in video partition // TODO: Handle errors in video partition
//errored += blocksToRead; //errored += blocksToRead;
//resume.BadBlocks.Add(l1); //resume.BadBlocks.Add(l1);
DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.DebugWriteLine("Dump-Media", "READ error:\n{0}",
if(cmdDuration < 500) Decoders.SCSI.Sense.PrettifySense(senseBuf));
mhddLog.Write(l1, 65535); if(cmdDuration < 500) mhddLog.Write(l1, 65535);
else else mhddLog.Write(l1, cmdDuration);
mhddLog.Write(l1, cmdDuration);
ibgLog.Write(l1, 0); ibgLog.Write(l1, 0);
dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1); dumpLog.WriteLine("Error reading {0} blocks from block {1}.", blocksToRead, l1);
string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); string[] senseLines = Decoders.SCSI.Sense.PrettifySense(senseBuf).Split(new[] {Environment.NewLine},
foreach(string senseLine in senseLines) StringSplitOptions
dumpLog.WriteLine(senseLine); .RemoveEmptyEntries);
foreach(string senseLine in senseLines) dumpLog.WriteLine(senseLine);
} }
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
@@ -569,6 +580,7 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing."); DicConsole.ErrorWriteLine("Cannot unlock drive, not continuing.");
return; return;
} }
sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration); sense = dev.ReadCapacity(out readBuffer, out senseBuf, dev.Timeout, out duration);
if(sense) if(sense)
{ {
@@ -580,21 +592,19 @@ namespace DiscImageChef.Core.Devices.Dumping
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath); ibgLog.Close(dev, blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000), devicePath);
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Dump finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000)); dumpLog.WriteLine("Average dump speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalDuration / 1000));
#region Error handling #region Error handling
if(resume.BadBlocks.Count > 0 && !aborted) if(resume.BadBlocks.Count > 0 && !aborted)
{ {
List<ulong> tmpList = new List<ulong>(); List<ulong> tmpList = new List<ulong>();
foreach(ulong ur in resume.BadBlocks) foreach(ulong ur in resume.BadBlocks) { for(ulong i = ur; i < ur + blocksToRead; i++) tmpList.Add(i); }
{
for(ulong i = ur; i < ur + blocksToRead; i++)
tmpList.Add(i);
}
tmpList.Sort(); tmpList.Sort();
@@ -604,7 +614,7 @@ namespace DiscImageChef.Core.Devices.Dumping
resume.BadBlocks = tmpList; resume.BadBlocks = tmpList;
repeatRetry: repeatRetry:
ulong[] tmpArray = resume.BadBlocks.ToArray(); ulong[] tmpArray = resume.BadBlocks.ToArray();
foreach(ulong badSector in tmpArray) foreach(ulong badSector in tmpArray)
{ {
@@ -617,9 +627,12 @@ namespace DiscImageChef.Core.Devices.Dumping
cmdDuration = 0; cmdDuration = 0;
DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1, forward ? "forward" : "reverse", runningPersistent ? "recovering partial data, " : ""); DicConsole.Write("\rRetrying sector {0}, pass {1}, {3}{2}", badSector, pass + 1,
forward ? "forward" : "reverse",
runningPersistent ? "recovering partial data, " : "");
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector, blockSize, 0, 1, false, dev.Timeout, out cmdDuration); sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, (uint)badSector,
blockSize, 0, 1, false, dev.Timeout, out cmdDuration);
totalDuration += cmdDuration; totalDuration += cmdDuration;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -629,8 +642,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpFile.WriteAt(readBuffer, badSector, blockSize); dumpFile.WriteAt(readBuffer, badSector, blockSize);
dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass); dumpLog.WriteLine("Correctly retried block {0} in pass {1}.", badSector, pass);
} }
else if(runningPersistent) else if(runningPersistent) dumpFile.WriteAt(readBuffer, badSector, blockSize);
dumpFile.WriteAt(readBuffer, badSector, blockSize);
} }
if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0) if(pass < retryPasses && !aborted && resume.BadBlocks.Count > 0)
@@ -649,27 +661,27 @@ namespace DiscImageChef.Core.Devices.Dumping
if(!runningPersistent && persistent) if(!runningPersistent && persistent)
{ {
sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense6(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01,
dev.Timeout, out duration);
if(sense) if(sense)
{ {
sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current, 0x01, dev.Timeout, out duration); sense = dev.ModeSense10(out readBuffer, out senseBuf, false, ScsiModeSensePageControl.Current,
if(!sense) 0x01, dev.Timeout, out duration);
currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType); if(!sense) currentMode = Decoders.SCSI.Modes.DecodeMode10(readBuffer, dev.SCSIType);
} }
else else currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
currentMode = Decoders.SCSI.Modes.DecodeMode6(readBuffer, dev.SCSIType);
if(currentMode.HasValue) if(currentMode.HasValue) currentModePage = currentMode.Value.Pages[0];
currentModePage = currentMode.Value.Pages[0];
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{ {
Decoders.SCSI.Modes.ModePage_01_MMC pgMMC = new Decoders.SCSI.Modes.ModePage_01_MMC Decoders.SCSI.Modes.ModePage_01_MMC pgMMC =
{ new Decoders.SCSI.Modes.ModePage_01_MMC
PS = false, {
ReadRetryCount = 255, PS = false,
Parameter = 0x20 ReadRetryCount = 255,
}; Parameter = 0x20
};
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
@@ -677,10 +689,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
new Decoders.SCSI.Modes.ModePage new Decoders.SCSI.Modes.ModePage
{ {
Page = 0x01, Page = 0x01,
Subpage = 0x00, Subpage = 0x00,
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC) PageResponse = Decoders.SCSI.Modes.EncodeModePage_01_MMC(pgMMC)
} }
} }
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
@@ -707,11 +719,11 @@ namespace DiscImageChef.Core.Devices.Dumping
Pages = new Decoders.SCSI.Modes.ModePage[] Pages = new Decoders.SCSI.Modes.ModePage[]
{ {
new Decoders.SCSI.Modes.ModePage new Decoders.SCSI.Modes.ModePage
{ {
Page = 0x01, Page = 0x01,
Subpage = 0x00, Subpage = 0x00,
PageResponse = Decoders.SCSI.Modes.EncodeModePage_01(pg) PageResponse = Decoders.SCSI.Modes.EncodeModePage_01(pg)
} }
} }
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
@@ -720,10 +732,7 @@ namespace DiscImageChef.Core.Devices.Dumping
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
runningPersistent = true; runningPersistent = true;
if(!sense && !dev.Error) if(!sense && !dev.Error)
@@ -737,25 +746,20 @@ namespace DiscImageChef.Core.Devices.Dumping
Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode Decoders.SCSI.Modes.DecodedMode md = new Decoders.SCSI.Modes.DecodedMode
{ {
Header = new Decoders.SCSI.Modes.ModeHeader(), Header = new Decoders.SCSI.Modes.ModeHeader(),
Pages = new Decoders.SCSI.Modes.ModePage[] Pages = new Decoders.SCSI.Modes.ModePage[] {currentModePage.Value}
{
currentModePage.Value
}
}; };
md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType); md6 = Decoders.SCSI.Modes.EncodeMode6(md, dev.SCSIType);
md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType); md10 = Decoders.SCSI.Modes.EncodeMode10(md, dev.SCSIType);
dumpLog.WriteLine("Sending MODE SELECT to drive."); dumpLog.WriteLine("Sending MODE SELECT to drive.");
sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration); sense = dev.ModeSelect(md6, out senseBuf, true, false, dev.Timeout, out duration);
if(sense) if(sense) { sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration); }
{
sense = dev.ModeSelect10(md10, out senseBuf, true, false, dev.Timeout, out duration);
}
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
#endregion Error handling #endregion Error handling
resume.BadBlocks.Sort(); resume.BadBlocks.Sort();
currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents); currentTry.Extents = Metadata.ExtentsConverter.ToMetadata(extents);
@@ -774,8 +778,7 @@ namespace DiscImageChef.Core.Devices.Dumping
break; break;
} }
if((blocks - i) < blocksToRead) if((blocks - i) < blocksToRead) blocksToRead = (uint)(blocks - i);
blocksToRead = (uint)(blocks - i);
DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed); DicConsole.Write("\rChecksumming sector {0} of {1} ({2:F3} MiB/sec.)", i, blocks, currentSpeed);
@@ -792,11 +795,13 @@ namespace DiscImageChef.Core.Devices.Dumping
currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000); currentSpeed = ((double)blockSize * blocksToRead / (double)1048576) / (chkDuration / (double)1000);
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
dumpFile.Close(); dumpFile.Close();
end = DateTime.UtcNow; end = DateTime.UtcNow;
dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds); dumpLog.WriteLine("Checksum finished in {0} seconds.", (end - start).TotalSeconds);
dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.", (((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000)); dumpLog.WriteLine("Average checksum speed {0:F3} KiB/sec.",
(((double)blockSize * (double)(blocks + 1)) / 1024) / (totalChkDuration / 1000));
PluginBase plugins = new PluginBase(); PluginBase plugins = new PluginBase();
plugins.RegisterAllPlugins(encoding); plugins.RegisterAllPlugins(encoding);
@@ -813,15 +818,8 @@ namespace DiscImageChef.Core.Devices.Dumping
_imageFormat = ImageFormat.Detect(inputFilter); _imageFormat = ImageFormat.Detect(inputFilter);
PartitionType[] xmlFileSysInfo = null; PartitionType[] xmlFileSysInfo = null;
try try { if(!_imageFormat.OpenImage(inputFilter)) _imageFormat = null; }
{ catch { _imageFormat = null; }
if(!_imageFormat.OpenImage(inputFilter))
_imageFormat = null;
}
catch
{
_imageFormat = null;
}
if(_imageFormat != null) if(_imageFormat != null)
{ {
@@ -846,7 +844,8 @@ namespace DiscImageChef.Core.Devices.Dumping
}; };
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.", dumpLog.WriteLine("Getting filesystems on partition {0}, starting at {1}, ending at {2}, with type {3}, under scheme {4}.",
i, partitions[i].Start, partitions[i].End, partitions[i].Type, partitions[i].Scheme); i, partitions[i].Start, partitions[i].End, partitions[i].Type,
partitions[i].Scheme);
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -859,12 +858,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type); dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "PC Engine filesystem")
dskType = MediaType.SuperCDROM2; dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD; dskType = MediaType.GOD;
} }
@@ -877,27 +874,18 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
xmlFileSysInfo[i].FileSystems = lstFs.ToArray();
} }
} }
else else
{ {
dumpLog.WriteLine("Getting filesystem for whole device."); dumpLog.WriteLine("Getting filesystem for whole device.");
xmlFileSysInfo = new PartitionType[1]; xmlFileSysInfo = new PartitionType[1];
xmlFileSysInfo[0] = new PartitionType xmlFileSysInfo[0] = new PartitionType {EndSector = (int)(blocks - 1), StartSector = 0};
{
EndSector = (int)(blocks - 1),
StartSector = 0
};
List<FileSystemType> lstFs = new List<FileSystemType>(); List<FileSystemType> lstFs = new List<FileSystemType>();
Partition wholePart = new Partition Partition wholePart =
{ new Partition {Name = "Whole device", Length = blocks, Size = blocks * blockSize};
Name = "Whole device",
Length = blocks,
Size = blocks * blockSize
};
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
@@ -910,14 +898,10 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type); dumpLog.WriteLine("Filesystem {0} found.", _plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO; if(_plugin.XmlFSType.Type == "PC Engine filesystem") dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.SuperCDROM2; if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") dskType = MediaType.GOD;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD;
} }
} }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
@@ -928,8 +912,7 @@ namespace DiscImageChef.Core.Devices.Dumping
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
xmlFileSysInfo[0].FileSystems = lstFs.ToArray();
} }
} }
@@ -946,35 +929,28 @@ namespace DiscImageChef.Core.Devices.Dumping
typeSpecified = true, typeSpecified = true,
Sectors = new SectorsType[1] Sectors = new SectorsType[1]
}; };
sidecar.OpticalDisc[0].Layers.Sectors[0] = new SectorsType sidecar.OpticalDisc[0].Layers.Sectors[0] = new SectorsType {Value = (long)layerBreak};
{
Value = (long)layerBreak
};
sidecar.OpticalDisc[0].Sessions = 1; sidecar.OpticalDisc[0].Sessions = 1;
sidecar.OpticalDisc[0].Tracks = new[] { 1 }; sidecar.OpticalDisc[0].Tracks = new[] {1};
sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1]; sidecar.OpticalDisc[0].Track = new Schemas.TrackType[1];
sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType sidecar.OpticalDisc[0].Track[0] = new Schemas.TrackType
{ {
BytesPerSector = (int)blockSize, BytesPerSector = (int)blockSize,
Checksums = sidecar.OpticalDisc[0].Checksums, Checksums = sidecar.OpticalDisc[0].Checksums,
EndSector = (long)(blocks - 1), EndSector = (long)(blocks - 1),
Image = new ImageType() Image =
{ new ImageType()
format = "BINARY", {
offset = 0, format = "BINARY",
offsetSpecified = true, offset = 0,
Value = sidecar.OpticalDisc[0].Image.Value offsetSpecified = true,
}, Value = sidecar.OpticalDisc[0].Image.Value
Sequence = new TrackSequenceType() },
{ Sequence = new TrackSequenceType() {Session = 1, TrackNumber = 1},
Session = 1,
TrackNumber = 1
},
Size = (long)(totalSize * blockSize), Size = (long)(totalSize * blockSize),
StartSector = 0 StartSector = 0
}; };
if(xmlFileSysInfo != null) if(xmlFileSysInfo != null) sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
sidecar.OpticalDisc[0].Track[0].FileSystemInformation = xmlFileSysInfo;
sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.dvd; sidecar.OpticalDisc[0].Track[0].TrackType1 = TrackTypeTrackType.dvd;
sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType); sidecar.OpticalDisc[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(dskType);
Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp); Metadata.MediaType.MediaTypeToString(dskType, out string xmlDskTyp, out string xmlDskSubTyp);
@@ -985,10 +961,10 @@ namespace DiscImageChef.Core.Devices.Dumping
{ {
DicConsole.WriteLine("Writing metadata sidecar"); DicConsole.WriteLine("Writing metadata sidecar");
FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileStream xmlFs = new FileStream(outputPrefix + ".cicm.xml", FileMode.Create);
FileMode.Create);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(CICMMetadataType));
xmlSer.Serialize(xmlFs, sidecar); xmlSer.Serialize(xmlFs, sidecar);
xmlFs.Close(); xmlFs.Close();
} }
@@ -996,4 +972,4 @@ namespace DiscImageChef.Core.Devices.Dumping
Statistics.AddMedia(dskType, true); Statistics.AddMedia(dskType, true);
} }
} }
} }

View File

@@ -48,15 +48,42 @@ namespace DiscImageChef.Core.Devices
uint physicalsectorsize; uint physicalsectorsize;
uint longBlockSize; uint longBlockSize;
public string ErrorMessage { get { return errorMessage; } } public string ErrorMessage
public ulong Blocks { get { return blocks; } } {
public uint BlocksToRead { get { return blocksToRead; } } get { return errorMessage; }
public uint LogicalBlockSize { get { return blockSize; } } }
public uint PhysicalBlockSize { get { return physicalsectorsize; } } public ulong Blocks
public uint LongBlockSize { get { return longBlockSize; } } {
public bool CanReadRaw { get { return readRaw; } } get { return blocks; }
public bool CanSeek { get { return ataSeek || seek6 || seek10; } } }
public bool CanSeekLBA { get { return ataSeekLba || seek6 || seek10; } } public uint BlocksToRead
{
get { return blocksToRead; }
}
public uint LogicalBlockSize
{
get { return blockSize; }
}
public uint PhysicalBlockSize
{
get { return physicalsectorsize; }
}
public uint LongBlockSize
{
get { return longBlockSize; }
}
public bool CanReadRaw
{
get { return readRaw; }
}
public bool CanSeek
{
get { return ataSeek || seek6 || seek10; }
}
public bool CanSeekLBA
{
get { return ataSeekLba || seek6 || seek10; }
}
public Reader(Device dev, uint timeout, byte[] identification, bool raw = false) public Reader(Device dev, uint timeout, byte[] identification, bool raw = false)
{ {
@@ -68,11 +95,9 @@ namespace DiscImageChef.Core.Devices
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA:
if(Identify.Decode(identification).HasValue) if(Identify.Decode(identification).HasValue) ataId = Identify.Decode(identification).Value;
ataId = Identify.Decode(identification).Value;
break; break;
case DeviceType.NVMe: case DeviceType.NVMe: throw new NotImplementedException("NVMe devices not yet supported.");
throw new NotImplementedException("NVMe devices not yet supported.");
} }
} }
@@ -80,11 +105,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaGetBlocks();
return AtaGetBlocks();
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiGetBlocks();
return ScsiGetBlocks();
default: default:
errorMessage = string.Format("Unknown device type {0}.", dev.Type); errorMessage = string.Format("Unknown device type {0}.", dev.Type);
return 0; return 0;
@@ -95,11 +118,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaFindReadCommand();
return AtaFindReadCommand();
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiFindReadCommand();
return ScsiFindReadCommand();
default: default:
errorMessage = string.Format("Unknown device type {0}.", dev.Type); errorMessage = string.Format("Unknown device type {0}.", dev.Type);
return true; return true;
@@ -110,11 +131,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaGetBlockSize();
return AtaGetBlockSize();
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiGetBlockSize();
return ScsiGetBlockSize();
default: default:
errorMessage = string.Format("Unknown device type {0}.", dev.Type); errorMessage = string.Format("Unknown device type {0}.", dev.Type);
return true; return true;
@@ -125,11 +144,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaGetBlocksToRead(startWithBlocks);
return AtaGetBlocksToRead(startWithBlocks);
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiGetBlocksToRead(startWithBlocks);
return ScsiGetBlocksToRead(startWithBlocks);
default: default:
errorMessage = string.Format("Unknown device type {0}.", dev.Type); errorMessage = string.Format("Unknown device type {0}.", dev.Type);
return true; return true;
@@ -150,11 +167,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaReadBlocks(out buffer, block, count, out duration);
return AtaReadBlocks(out buffer, block, count, out duration);
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiReadBlocks(out buffer, block, count, out duration);
return ScsiReadBlocks(out buffer, block, count, out duration);
default: default:
buffer = null; buffer = null;
duration = 0d; duration = 0d;
@@ -166,8 +181,7 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaReadCHS(out buffer, cylinder, head, sector, out duration);
return AtaReadCHS(out buffer, cylinder, head, sector, out duration);
default: default:
buffer = null; buffer = null;
duration = 0d; duration = 0d;
@@ -179,11 +193,9 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaSeek(block, out duration);
return AtaSeek(block, out duration);
case DeviceType.ATAPI: case DeviceType.ATAPI:
case DeviceType.SCSI: case DeviceType.SCSI: return ScsiSeek(block, out duration);
return ScsiSeek(block, out duration);
default: default:
duration = 0d; duration = 0d;
return true; return true;
@@ -194,12 +206,11 @@ namespace DiscImageChef.Core.Devices
{ {
switch(dev.Type) switch(dev.Type)
{ {
case DeviceType.ATA: case DeviceType.ATA: return AtaSeekCHS(cylinder, head, sector, out duration);
return AtaSeekCHS(cylinder, head, sector, out duration);
default: default:
duration = 0; duration = 0;
return true; return true;
} }
} }
} }
} }

View File

@@ -57,15 +57,26 @@ namespace DiscImageChef.Core.Devices
Identify.IdentifyDevice ataId; Identify.IdentifyDevice ataId;
public bool IsLBA { get { return lbaMode; } } public bool IsLBA
public ushort Cylinders { get { return cylinders; } } {
public byte Heads { get { return heads; } } get { return lbaMode; }
public byte Sectors { get { return sectors; } } }
public ushort Cylinders
{
get { return cylinders; }
}
public byte Heads
{
get { return heads; }
}
public byte Sectors
{
get { return sectors; }
}
public (uint, byte, byte) GetDeviceCHS() public (uint, byte, byte) GetDeviceCHS()
{ {
if(dev.Type != DeviceType.ATA) if(dev.Type != DeviceType.ATA) return (0, 0, 0);
return (0, 0, 0);
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0) if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0)
{ {
@@ -76,7 +87,7 @@ namespace DiscImageChef.Core.Devices
} }
if((ataId.CurrentCylinders == 0 || ataId.CurrentHeads == 0 || ataId.CurrentSectorsPerTrack == 0) && if((ataId.CurrentCylinders == 0 || ataId.CurrentHeads == 0 || ataId.CurrentSectorsPerTrack == 0) &&
(ataId.Cylinders > 0 && ataId.Heads > 0 && ataId.SectorsPerTrack > 0)) (ataId.Cylinders > 0 && ataId.Heads > 0 && ataId.SectorsPerTrack > 0))
{ {
cylinders = ataId.Cylinders; cylinders = ataId.Cylinders;
heads = (byte)ataId.Heads; heads = (byte)ataId.Heads;
@@ -166,26 +177,16 @@ namespace DiscImageChef.Core.Devices
} }
} }
if(ataReadDmaLba48) if(ataReadDmaLba48) DicConsole.WriteLine("Using ATA READ DMA EXT command.");
DicConsole.WriteLine("Using ATA READ DMA EXT command."); else if(ataReadLba48) DicConsole.WriteLine("Using ATA READ EXT command.");
else if(ataReadLba48) else if(ataReadDmaRetryLba) DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA).");
DicConsole.WriteLine("Using ATA READ EXT command."); else if(ataReadDmaLba) DicConsole.WriteLine("Using ATA READ DMA command (LBA).");
else if(ataReadDmaRetryLba) else if(ataReadRetryLba) DicConsole.WriteLine("Using ATA READ command with retries (LBA).");
DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA)."); else if(ataReadLba) DicConsole.WriteLine("Using ATA READ command (LBA).");
else if(ataReadDmaLba) else if(ataReadDmaRetry) DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
DicConsole.WriteLine("Using ATA READ DMA command (LBA)."); else if(ataReadDma) DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
else if(ataReadRetryLba) else if(ataReadRetry) DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
DicConsole.WriteLine("Using ATA READ command with retries (LBA)."); else if(ataRead) DicConsole.WriteLine("Using ATA READ command (CHS).");
else if(ataReadLba)
DicConsole.WriteLine("Using ATA READ command (LBA).");
else if(ataReadDmaRetry)
DicConsole.WriteLine("Using ATA READ DMA command with retries (CHS).");
else if(ataReadDma)
DicConsole.WriteLine("Using ATA READ DMA command (CHS).");
else if(ataReadRetry)
DicConsole.WriteLine("Using ATA READ command with retries (CHS).");
else if(ataRead)
DicConsole.WriteLine("Using ATA READ command (CHS).");
else else
{ {
errorMessage = "Could not get a working read command!"; errorMessage = "Could not get a working read command!";
@@ -197,18 +198,14 @@ namespace DiscImageChef.Core.Devices
bool AtaGetBlockSize() bool AtaGetBlockSize()
{ {
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
{ {
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000) if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
{ {
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) blockSize = 512;
blockSize = 512; else blockSize = ataId.LogicalSectorWords * 2;
else
blockSize = ataId.LogicalSectorWords * 2;
} }
else else blockSize = 512;
blockSize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
{ {
@@ -216,8 +213,7 @@ namespace DiscImageChef.Core.Devices
physicalsectorsize = blockSize * (uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF)); physicalsectorsize = blockSize * (uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF));
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
} }
else else physicalsectorsize = blockSize;
physicalsectorsize = blockSize;
} }
else else
{ {
@@ -281,17 +277,15 @@ namespace DiscImageChef.Core.Devices
error = !(!sense && (errorLba.status & 0x27) == 0 && errorLba.error == 0 && cmdBuf.Length > 0); error = !(!sense && (errorLba.status & 0x27) == 0 && errorLba.error == 0 && cmdBuf.Length > 0);
} }
if(error) if(error) blocksToRead /= 2;
blocksToRead /= 2;
if(!error || blocksToRead == 1) if(!error || blocksToRead == 1) break;
break;
} }
if(error && lbaMode) if(error && lbaMode)
{ {
blocksToRead = 1; blocksToRead = 1;
errorMessage=string.Format("Device error {0} trying to guess ideal transfer length.", dev.LastError); errorMessage = string.Format("Device error {0} trying to guess ideal transfer length.", dev.LastError);
return true; return true;
} }
@@ -351,8 +345,7 @@ namespace DiscImageChef.Core.Devices
errorByte = errorLba.error; errorByte = errorLba.error;
} }
if(error) if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error; return error;
} }
@@ -395,8 +388,7 @@ namespace DiscImageChef.Core.Devices
errorByte = errorChs.error; errorByte = errorChs.error;
} }
if(error) if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status);
return error; return error;
} }
@@ -417,4 +409,4 @@ namespace DiscImageChef.Core.Devices
return !(!sense && (errorChs.status & 0x27) == 0 && errorChs.error == 0); return !(!sense && (errorChs.status & 0x27) == 0 && errorChs.error == 0);
} }
} }
} }

View File

@@ -65,11 +65,14 @@ namespace DiscImageChef.Core.Devices
read6 = !dev.Read6(out readBuffer, out senseBuf, 0, blockSize, timeout, out duration); read6 = !dev.Read6(out readBuffer, out senseBuf, 0, blockSize, timeout, out duration);
read10 = !dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, timeout, out duration); read10 = !dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1,
timeout, out duration);
read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false, timeout, out duration); read12 = !dev.Read12(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, 1, false,
timeout, out duration);
read16 = !dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, 1, false, timeout, out duration); read16 = !dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, 1, false,
timeout, out duration);
seek6 = !dev.Seek6(out senseBuf, 0, timeout, out duration); seek6 = !dev.Seek6(out senseBuf, 0, timeout, out duration);
@@ -83,7 +86,9 @@ namespace DiscImageChef.Core.Devices
if(read6 && !read10 && !read12 && !read16 && blocks > (0x001FFFFF + 1)) if(read6 && !read10 && !read12 && !read16 && blocks > (0x001FFFFF + 1))
{ {
errorMessage = string.Format("Device only supports SCSI READ (6) but has more than {0} blocks ({1} blocks total)", 0x001FFFFF + 1, blocks); errorMessage =
string.Format("Device only supports SCSI READ (6) but has more than {0} blocks ({1} blocks total)",
0x001FFFFF + 1, blocks);
return true; return true;
} }
@@ -92,7 +97,9 @@ namespace DiscImageChef.Core.Devices
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
{ {
#pragma warning disable IDE0004 // Remove Unnecessary Cast #pragma warning disable IDE0004 // Remove Unnecessary Cast
errorMessage = string.Format("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)", (long)0xFFFFFFFF + (long)1, blocks); errorMessage =
string.Format("Device only supports SCSI READ (10) but has more than {0} blocks ({1} blocks total)",
(long)0xFFFFFFFF + (long)1, blocks);
#pragma warning restore IDE0004 // Remove Unnecessary Cast #pragma warning restore IDE0004 // Remove Unnecessary Cast
return true; return true;
} }
@@ -124,20 +131,22 @@ namespace DiscImageChef.Core.Devices
} }
}*/ }*/
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 0xFFFF, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 0xFFFF, timeout,
out duration);
if(testSense && !dev.Error) if(testSense && !dev.Error)
{ {
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
{ {
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest && if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
{ {
readRaw = true; readRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI) if(decSense.Value.InformationValid && decSense.Value.ILI)
{ {
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
readLong10 = !dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, (ushort)longBlockSize, timeout, out duration); readLong10 = !dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0,
(ushort)longBlockSize, timeout, out duration);
} }
} }
} }
@@ -147,15 +156,18 @@ namespace DiscImageChef.Core.Devices
{ {
if(blockSize == 512) if(blockSize == 512)
{ {
foreach(ushort testSize in new[] { foreach(ushort testSize in new[]
// Long sector sizes for floppies
514,
// Long sector sizes for SuperDisk
536, 558,
// Long sector sizes for 512-byte magneto-opticals
600, 610, 630 })
{ {
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout, out duration); // Long sector sizes for floppies
514,
// Long sector sizes for SuperDisk
536, 558,
// Long sector sizes for 512-byte magneto-opticals
600, 610, 630
})
{
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong16 = true; readLong16 = true;
@@ -164,7 +176,8 @@ namespace DiscImageChef.Core.Devices
break; break;
} }
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize,
timeout, out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong10 = true; readLong10 = true;
@@ -176,13 +189,16 @@ namespace DiscImageChef.Core.Devices
} }
else if(blockSize == 1024) else if(blockSize == 1024)
{ {
foreach(ushort testSize in new[] { foreach(ushort testSize in new[]
// Long sector sizes for floppies
1026,
// Long sector sizes for 1024-byte magneto-opticals
1200 })
{ {
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout, out duration); // Long sector sizes for floppies
1026,
// Long sector sizes for 1024-byte magneto-opticals
1200
})
{
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, testSize, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong16 = true; readLong16 = true;
@@ -191,7 +207,8 @@ namespace DiscImageChef.Core.Devices
break; break;
} }
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, testSize,
timeout, out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong10 = true; readLong10 = true;
@@ -203,7 +220,8 @@ namespace DiscImageChef.Core.Devices
} }
else if(blockSize == 2048) else if(blockSize == 2048)
{ {
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 2380, timeout, out duration); testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 2380, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong16 = true; readLong16 = true;
@@ -212,7 +230,8 @@ namespace DiscImageChef.Core.Devices
} }
else else
{ {
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 2380, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 2380, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong10 = true; readLong10 = true;
@@ -223,7 +242,8 @@ namespace DiscImageChef.Core.Devices
} }
else if(blockSize == 4096) else if(blockSize == 4096)
{ {
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 4760, timeout, out duration); testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 4760, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong16 = true; readLong16 = true;
@@ -232,7 +252,8 @@ namespace DiscImageChef.Core.Devices
} }
else else
{ {
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 4760, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 4760, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong10 = true; readLong10 = true;
@@ -243,7 +264,8 @@ namespace DiscImageChef.Core.Devices
} }
else if(blockSize == 8192) else if(blockSize == 8192)
{ {
testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 9424, timeout, out duration); testSense = dev.ReadLong16(out readBuffer, out senseBuf, false, 0, 9424, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong16 = true; readLong16 = true;
@@ -252,7 +274,8 @@ namespace DiscImageChef.Core.Devices
} }
else else
{ {
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 9424, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 9424, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLong10 = true; readLong10 = true;
@@ -265,38 +288,44 @@ namespace DiscImageChef.Core.Devices
if(!readRaw && dev.Manufacturer == "SYQUEST") if(!readRaw && dev.Manufacturer == "SYQUEST")
{ {
testSense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, 0xFFFF, timeout, out duration); testSense = dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, 0xFFFF, timeout,
out duration);
if(testSense) if(testSense)
{ {
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
{ {
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest && if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
{ {
readRaw = true; readRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI) if(decSense.Value.InformationValid && decSense.Value.ILI)
{ {
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
syqReadLong10 = !dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, longBlockSize, timeout, out duration); syqReadLong10 =
!dev.SyQuestReadLong10(out readBuffer, out senseBuf, 0, longBlockSize,
timeout, out duration);
} }
} }
else else
{ {
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 0xFFFF, timeout, out duration); testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 0xFFFF, timeout,
out duration);
if(testSense) if(testSense)
{ {
decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf); decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(decSense.HasValue) if(decSense.HasValue)
{ {
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest && if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
{ {
readRaw = true; readRaw = true;
if(decSense.Value.InformationValid && decSense.Value.ILI) if(decSense.Value.InformationValid && decSense.Value.ILI)
{ {
longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); longBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF);
syqReadLong6 = !dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, longBlockSize, timeout, out duration); syqReadLong6 =
!dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0,
longBlockSize, timeout, out duration);
} }
} }
} }
@@ -307,7 +336,8 @@ namespace DiscImageChef.Core.Devices
if(!readRaw && blockSize == 256) if(!readRaw && blockSize == 256)
{ {
testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 262, timeout, out duration); testSense = dev.SyQuestReadLong6(out readBuffer, out senseBuf, 0, 262, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
syqReadLong6 = true; syqReadLong6 = true;
@@ -320,10 +350,12 @@ namespace DiscImageChef.Core.Devices
else else
{ {
if(dev.Manufacturer == "HL-DT-ST") if(dev.Manufacturer == "HL-DT-ST")
hldtstReadRaw = !dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration); hldtstReadRaw =
!dev.HlDtStReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
if(dev.Manufacturer == "PLEXTOR") if(dev.Manufacturer == "PLEXTOR")
plextorReadRaw = !dev.PlextorReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration); plextorReadRaw =
!dev.PlextorReadRawDvd(out readBuffer, out senseBuf, 0, 1, timeout, out duration);
if(hldtstReadRaw || plextorReadRaw) if(hldtstReadRaw || plextorReadRaw)
{ {
@@ -334,7 +366,8 @@ namespace DiscImageChef.Core.Devices
// READ LONG (10) for some DVD drives // READ LONG (10) for some DVD drives
if(!readRaw && dev.Manufacturer == "MATSHITA") if(!readRaw && dev.Manufacturer == "MATSHITA")
{ {
testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 37856, timeout, out duration); testSense = dev.ReadLong10(out readBuffer, out senseBuf, false, false, 0, 37856, timeout,
out duration);
if(!testSense && !dev.Error) if(!testSense && !dev.Error)
{ {
readLongDvd = true; readLongDvd = true;
@@ -347,27 +380,17 @@ namespace DiscImageChef.Core.Devices
if(readRaw) if(readRaw)
{ {
if(readLong16) if(readLong16) DicConsole.WriteLine("Using SCSI READ LONG (16) command.");
DicConsole.WriteLine("Using SCSI READ LONG (16) command."); else if(readLong10 || readLongDvd) DicConsole.WriteLine("Using SCSI READ LONG (10) command.");
else if(readLong10 || readLongDvd) else if(syqReadLong10) DicConsole.WriteLine("Using SyQuest READ LONG (10) command.");
DicConsole.WriteLine("Using SCSI READ LONG (10) command."); else if(syqReadLong6) DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
else if(syqReadLong10) else if(hldtstReadRaw) DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
DicConsole.WriteLine("Using SyQuest READ LONG (10) command."); else if(plextorReadRaw) DicConsole.WriteLine("Using Plextor raw DVD reading.");
else if(syqReadLong6)
DicConsole.WriteLine("Using SyQuest READ LONG (6) command.");
else if(hldtstReadRaw)
DicConsole.WriteLine("Using HL-DT-ST raw DVD reading.");
else if(plextorReadRaw)
DicConsole.WriteLine("Using Plextor raw DVD reading.");
} }
else if(read16) else if(read16) DicConsole.WriteLine("Using SCSI READ (16) command.");
DicConsole.WriteLine("Using SCSI READ (16) command."); else if(read12) DicConsole.WriteLine("Using SCSI READ (12) command.");
else if(read12) else if(read10) DicConsole.WriteLine("Using SCSI READ (10) command.");
DicConsole.WriteLine("Using SCSI READ (12) command."); else if(read6) DicConsole.WriteLine("Using SCSI READ (6) command.");
else if(read10)
DicConsole.WriteLine("Using SCSI READ (10) command.");
else if(read6)
DicConsole.WriteLine("Using SCSI READ (6) command.");
return false; return false;
} }
@@ -396,8 +419,8 @@ namespace DiscImageChef.Core.Devices
// Not all MMC devices support READ CAPACITY, as they have READ TOC // Not all MMC devices support READ CAPACITY, as they have READ TOC
if(dev.SCSIType != Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) if(dev.SCSIType != Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{ {
errorMessage = string.Format("Unable to get media capacity\n" + errorMessage = string.Format("Unable to get media capacity\n" + "{0}",
"{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); Decoders.SCSI.Sense.PrettifySense(senseBuf));
return true; return true;
} }
@@ -431,31 +454,30 @@ namespace DiscImageChef.Core.Devices
{ {
if(read16) if(read16)
{ {
sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0, blocksToRead, false, timeout, out duration); sense = dev.Read16(out readBuffer, out senseBuf, 0, false, true, false, 0, blockSize, 0,
if(dev.Error) blocksToRead, false, timeout, out duration);
blocksToRead /= 2; if(dev.Error) blocksToRead /= 2;
} }
else if(read12) else if(read12)
{ {
sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0, blocksToRead, false, timeout, out duration); sense = dev.Read12(out readBuffer, out senseBuf, 0, false, false, false, false, 0, blockSize, 0,
if(dev.Error) blocksToRead, false, timeout, out duration);
blocksToRead /= 2; if(dev.Error) blocksToRead /= 2;
} }
else if(read10) else if(read10)
{ {
sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0, (ushort)blocksToRead, timeout, out duration); sense = dev.Read10(out readBuffer, out senseBuf, 0, false, true, false, false, 0, blockSize, 0,
if(dev.Error) (ushort)blocksToRead, timeout, out duration);
blocksToRead /= 2; if(dev.Error) blocksToRead /= 2;
} }
else if(read6) else if(read6)
{ {
sense = dev.Read6(out readBuffer, out senseBuf, 0, blockSize, (byte)blocksToRead, timeout, out duration); sense = dev.Read6(out readBuffer, out senseBuf, 0, blockSize, (byte)blocksToRead, timeout,
if(dev.Error) out duration);
blocksToRead /= 2; if(dev.Error) blocksToRead /= 2;
} }
if(!dev.Error || blocksToRead == 1) if(!dev.Error || blocksToRead == 1) break;
break;
} }
if(dev.Error) if(dev.Error)
@@ -478,37 +500,46 @@ namespace DiscImageChef.Core.Devices
if(readRaw) if(readRaw)
{ {
if(readLong16) if(readLong16)
sense = dev.ReadLong16(out buffer, out senseBuf, false, block, longBlockSize, timeout, out duration); sense = dev.ReadLong16(out buffer, out senseBuf, false, block, longBlockSize, timeout,
out duration);
else if(readLong10) else if(readLong10)
sense = dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)longBlockSize, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuf, false, false, (uint)block, (ushort)longBlockSize,
timeout, out duration);
else if(syqReadLong10) else if(syqReadLong10)
sense = dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration); sense = dev.SyQuestReadLong10(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
out duration);
else if(syqReadLong6) else if(syqReadLong6)
sense = dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration); sense = dev.SyQuestReadLong6(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
out duration);
else if(hldtstReadRaw) else if(hldtstReadRaw)
sense = dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration); sense = dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
out duration);
else if(plextorReadRaw) else if(plextorReadRaw)
sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout, out duration); sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, longBlockSize, timeout,
else out duration);
return true; else return true;
} }
else else
{ {
if(read16) if(read16)
sense = dev.Read16(out buffer, out senseBuf, 0, false, true, false, block, blockSize, 0, count, false, timeout, out duration); sense = dev.Read16(out buffer, out senseBuf, 0, false, true, false, block, blockSize, 0, count,
false, timeout, out duration);
else if(read12) else if(read12)
sense = dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, blockSize, 0, count, false, timeout, out duration); sense = dev.Read12(out buffer, out senseBuf, 0, false, false, false, false, (uint)block, blockSize,
0, count, false, timeout, out duration);
else if(read10) else if(read10)
sense = dev.Read10(out buffer, out senseBuf, 0, false, true, false, false, (uint)block, blockSize, 0, (ushort)count, timeout, out duration); sense = dev.Read10(out buffer, out senseBuf, 0, false, true, false, false, (uint)block, blockSize,
0, (ushort)count, timeout, out duration);
else if(read6) else if(read6)
sense = dev.Read6(out buffer, out senseBuf, (uint)block, blockSize, (byte)count, timeout, out duration); sense = dev.Read6(out buffer, out senseBuf, (uint)block, blockSize, (byte)count, timeout,
else out duration);
return true; else return true;
} }
if(sense || dev.Error) if(sense || dev.Error)
{ {
DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return true; return true;
} }
@@ -521,12 +552,10 @@ namespace DiscImageChef.Core.Devices
bool sense = true; bool sense = true;
duration = 0; duration = 0;
if(seek6) if(seek6) sense = dev.Seek6(out senseBuf, (uint)block, timeout, out duration);
sense = dev.Seek6(out senseBuf, (uint)block, timeout, out duration); else if(seek10) sense = dev.Seek10(out senseBuf, (uint)block, timeout, out duration);
else if(seek10)
sense = dev.Seek10(out senseBuf, (uint)block, timeout, out duration);
return sense; return sense;
} }
} }
} }

View File

@@ -42,8 +42,7 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
Decoders.ATA.AtaErrorRegistersCHS errorRegs; Decoders.ATA.AtaErrorRegistersCHS errorRegs;
byte[] buffer; byte[] buffer;
@@ -51,14 +50,11 @@ namespace DiscImageChef.Core.Devices.Report
uint timeout = 5; uint timeout = 5;
ConsoleKeyInfo pressedKey; ConsoleKeyInfo pressedKey;
if(dev.IsUSB) if(dev.IsUSB) USB.Report(dev, ref report, debug, ref removable);
USB.Report(dev, ref report, debug, ref removable);
if(dev.IsFireWire) if(dev.IsFireWire) FireWire.Report(dev, ref report, debug, ref removable);
FireWire.Report(dev, ref report, debug, ref removable);
if(dev.IsPCMCIA) if(dev.IsPCMCIA) PCMCIA.Report(dev, ref report, debug, ref removable);
PCMCIA.Report(dev, ref report, debug, ref removable);
DicConsole.WriteLine("Querying ATA IDENTIFY..."); DicConsole.WriteLine("Querying ATA IDENTIFY...");
@@ -74,7 +70,8 @@ namespace DiscImageChef.Core.Devices.Report
report.CompactFlashSpecified = true; report.CompactFlashSpecified = true;
removable = false; removable = false;
} }
else if(!removable && ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable)) else if(!removable &&
ataId.GeneralConfiguration.HasFlag(Decoders.ATA.Identify.GeneralConfigurationBit.Removable))
{ {
pressedKey = new ConsoleKeyInfo(); pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
@@ -488,9 +485,8 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2; report.ATA.WRVSectorCountMode2 = ataId.WRVSectorCountMode2;
report.ATA.WRVSectorCountMode2Specified = true; report.ATA.WRVSectorCountMode2Specified = true;
} }
if(debug) if(debug) report.ATA.Identify = buffer;
report.ATA.Identify = buffer;
if(removable) if(removable)
{ {
List<testedMediaType> mediaTests = new List<testedMediaType>(); List<testedMediaType> mediaTests = new List<testedMediaType>();
@@ -549,14 +545,17 @@ namespace DiscImageChef.Core.Devices.Report
mediaTest.BlocksSpecified = true; mediaTest.BlocksSpecified = true;
} }
if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0) if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 &&
ataId.CurrentSectorsPerTrack > 0)
{ {
mediaTest.CurrentCHS = new chsType(); mediaTest.CurrentCHS = new chsType();
mediaTest.CurrentCHS.Cylinders = ataId.CurrentCylinders; mediaTest.CurrentCHS.Cylinders = ataId.CurrentCylinders;
mediaTest.CurrentCHS.Heads = ataId.CurrentHeads; mediaTest.CurrentCHS.Heads = ataId.CurrentHeads;
mediaTest.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack; mediaTest.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack;
if(mediaTest.Blocks == 0) if(mediaTest.Blocks == 0)
mediaTest.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack); mediaTest.Blocks =
(ulong)(ataId.CurrentCylinders * ataId.CurrentHeads *
ataId.CurrentSectorsPerTrack);
mediaTest.BlocksSpecified = true; mediaTest.BlocksSpecified = true;
} }
@@ -576,8 +575,7 @@ namespace DiscImageChef.Core.Devices.Report
mediaTest.BlocksSpecified = true; mediaTest.BlocksSpecified = true;
} }
if(ataId.NominalRotationRate != 0x0000 && if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
ataId.NominalRotationRate != 0xFFFF)
{ {
if(ataId.NominalRotationRate == 0x0001) if(ataId.NominalRotationRate == 0x0001)
{ {
@@ -596,26 +594,24 @@ namespace DiscImageChef.Core.Devices.Report
uint logicalsectorsize = 0; uint logicalsectorsize = 0;
uint physicalsectorsize; uint physicalsectorsize;
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 &&
(ataId.PhysLogSectorSize & 0x4000) == 0x4000) (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
{ {
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000) if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
{ {
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
logicalsectorsize = 512; logicalsectorsize = 512;
else else logicalsectorsize = ataId.LogicalSectorWords * 2;
logicalsectorsize = ataId.LogicalSectorWords * 2;
} }
else else logicalsectorsize = 512;
logicalsectorsize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
{ {
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
physicalsectorsize = (uint)(logicalsectorsize * (1 << ataId.PhysLogSectorSize & 0xF)); physicalsectorsize =
(uint)(logicalsectorsize * (1 << ataId.PhysLogSectorSize & 0xF));
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
} }
else else physicalsectorsize = logicalsectorsize;
physicalsectorsize = logicalsectorsize;
} }
else else
{ {
@@ -631,7 +627,7 @@ namespace DiscImageChef.Core.Devices.Report
mediaTest.PhysicalBlockSizeSpecified = true; mediaTest.PhysicalBlockSizeSpecified = true;
if((ataId.LogicalAlignment & 0x8000) == 0x0000 && if((ataId.LogicalAlignment & 0x8000) == 0x0000 &&
(ataId.LogicalAlignment & 0x4000) == 0x4000) (ataId.LogicalAlignment & 0x4000) == 0x4000)
{ {
mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF); mediaTest.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
mediaTest.LogicalAlignmentSpecified = true; mediaTest.LogicalAlignmentSpecified = true;
@@ -644,15 +640,16 @@ namespace DiscImageChef.Core.Devices.Report
mediaTest.LongBlockSizeSpecified = true; mediaTest.LongBlockSizeSpecified = true;
} }
if(ataId.UnformattedBPS > logicalsectorsize && (!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516)) if(ataId.UnformattedBPS > logicalsectorsize &&
(!mediaTest.LongBlockSizeSpecified || mediaTest.LongBlockSize == 516))
{ {
mediaTest.LongBlockSize = ataId.UnformattedBPS; mediaTest.LongBlockSize = ataId.UnformattedBPS;
mediaTest.LongBlockSizeSpecified = true; mediaTest.LongBlockSizeSpecified = true;
} }
if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) && if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) &&
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) && !ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial)) ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
{ {
mediaTest.CanReadMediaSerial = true; mediaTest.CanReadMediaSerial = true;
mediaTest.CanReadMediaSerialSpecified = true; mediaTest.CanReadMediaSerialSpecified = true;
@@ -692,137 +689,213 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode...");
sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
mediaTest.SupportsRead = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); mediaTest.SupportsRead =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorschs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode...");
sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
mediaTest.SupportsReadRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadRetry =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorsretrychs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA in CHS mode..."); DicConsole.WriteLine("Trying READ DMA in CHS mode...");
sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout,
mediaTest.SupportsReadDma = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", mediaTest.SupportsReadDma =
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmachs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode...");
sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
mediaTest.SupportsReadDmaRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadDmaRetry =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmaretrychs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying SEEK in CHS mode..."); DicConsole.WriteLine("Trying SEEK in CHS mode...");
sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration); sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration);
mediaTest.SupportsSeek = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0); mediaTest.SupportsSeek =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
sense, errorChs.status, errorChs.error); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
errorChs.status, errorChs.error);
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode...");
sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
mediaTest.SupportsReadLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectors",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode...");
sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
mediaTest.SupportsReadRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadRetryLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorsretry",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA in LBA mode..."); DicConsole.WriteLine("Trying READ DMA in LBA mode...");
sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
mediaTest.SupportsReadDmaLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadDmaLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdma", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdma",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode...");
sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
mediaTest.SupportsReadDmaRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadDmaRetryLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmaretry",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying SEEK in LBA mode..."); DicConsole.WriteLine("Trying SEEK in LBA mode...");
sense = dev.Seek(out errorLba, 0, timeout, out duration); sense = dev.Seek(out errorLba, 0, timeout, out duration);
mediaTest.SupportsSeekLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0); mediaTest.SupportsSeekLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
sense, errorChs.status, errorChs.error); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
errorChs.status, errorChs.error);
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode...");
sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration);
mediaTest.SupportsReadLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadLba48 =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectors48",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA in LBA48 mode..."); DicConsole.WriteLine("Trying READ DMA in LBA48 mode...");
sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration);
mediaTest.SupportsReadDmaLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0); mediaTest.SupportsReadDmaLba48 =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 &&
readBuf.Length > 0);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdma48",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ LONG in CHS mode..."); DicConsole.WriteLine("Trying READ LONG in CHS mode...");
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, mediaTest.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, mediaTest.LongBlockSize,
mediaTest.SupportsReadLong = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", mediaTest.SupportsReadLong =
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongchs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode...");
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, mediaTest.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, mediaTest.LongBlockSize,
mediaTest.SupportsReadLongRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", mediaTest.SupportsReadLongRetry =
(!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 &&
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongretrychs",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ LONG in LBA mode..."); DicConsole.WriteLine("Trying READ LONG in LBA mode...");
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, mediaTest.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorLba, false, 0, mediaTest.LongBlockSize,
mediaTest.SupportsReadLongLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", mediaTest.SupportsReadLongLba =
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlong", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlong",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode...");
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, mediaTest.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorLba, true, 0, mediaTest.LongBlockSize,
mediaTest.SupportsReadLongRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", mediaTest.SupportsReadLongRetryLba =
(!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 &&
readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}",
sense, errorChs.status, errorChs.error, readBuf.Length); sense, errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongretry",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
readBuf);
} }
else else mediaTest.MediaIsRecognized = false;
mediaTest.MediaIsRecognized = false;
mediaTests.Add(mediaTest); mediaTests.Add(mediaTest);
} }
} }
report.ATA.RemovableMedias = mediaTests.ToArray(); report.ATA.RemovableMedias = mediaTests.ToArray();
} }
else else
@@ -846,7 +919,8 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.CHS.Cylinders = ataId.Cylinders; report.ATA.ReadCapabilities.CHS.Cylinders = ataId.Cylinders;
report.ATA.ReadCapabilities.CHS.Heads = ataId.Heads; report.ATA.ReadCapabilities.CHS.Heads = ataId.Heads;
report.ATA.ReadCapabilities.CHS.Sectors = ataId.SectorsPerTrack; report.ATA.ReadCapabilities.CHS.Sectors = ataId.SectorsPerTrack;
report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack); report.ATA.ReadCapabilities.Blocks =
(ulong)(ataId.Cylinders * ataId.Heads * ataId.SectorsPerTrack);
report.ATA.ReadCapabilities.BlocksSpecified = true; report.ATA.ReadCapabilities.BlocksSpecified = true;
} }
@@ -856,7 +930,8 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.CurrentCHS.Cylinders = ataId.CurrentCylinders; report.ATA.ReadCapabilities.CurrentCHS.Cylinders = ataId.CurrentCylinders;
report.ATA.ReadCapabilities.CurrentCHS.Heads = ataId.CurrentHeads; report.ATA.ReadCapabilities.CurrentCHS.Heads = ataId.CurrentHeads;
report.ATA.ReadCapabilities.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack; report.ATA.ReadCapabilities.CurrentCHS.Sectors = ataId.CurrentSectorsPerTrack;
report.ATA.ReadCapabilities.Blocks = (ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack); report.ATA.ReadCapabilities.Blocks =
(ulong)(ataId.CurrentCylinders * ataId.CurrentHeads * ataId.CurrentSectorsPerTrack);
report.ATA.ReadCapabilities.BlocksSpecified = true; report.ATA.ReadCapabilities.BlocksSpecified = true;
} }
@@ -876,8 +951,7 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.BlocksSpecified = true; report.ATA.ReadCapabilities.BlocksSpecified = true;
} }
if(ataId.NominalRotationRate != 0x0000 && if(ataId.NominalRotationRate != 0x0000 && ataId.NominalRotationRate != 0xFFFF)
ataId.NominalRotationRate != 0xFFFF)
{ {
if(ataId.NominalRotationRate == 0x0001) if(ataId.NominalRotationRate == 0x0001)
{ {
@@ -895,27 +969,24 @@ namespace DiscImageChef.Core.Devices.Report
uint logicalsectorsize = 0; uint logicalsectorsize = 0;
uint physicalsectorsize; uint physicalsectorsize;
if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000)
(ataId.PhysLogSectorSize & 0x4000) == 0x4000)
{ {
if((ataId.PhysLogSectorSize & 0x1000) == 0x1000) if((ataId.PhysLogSectorSize & 0x1000) == 0x1000)
{ {
if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF)
logicalsectorsize = 512; logicalsectorsize = 512;
else else logicalsectorsize = ataId.LogicalSectorWords * 2;
logicalsectorsize = ataId.LogicalSectorWords * 2;
} }
else else logicalsectorsize = 512;
logicalsectorsize = 512;
if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) if((ataId.PhysLogSectorSize & 0x2000) == 0x2000)
{ {
#pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning disable IDE0004 // Cast is necessary, otherwise incorrect value is created
physicalsectorsize = logicalsectorsize * (uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF)); physicalsectorsize = logicalsectorsize *
(uint)Math.Pow(2, (double)(ataId.PhysLogSectorSize & 0xF));
#pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created #pragma warning restore IDE0004 // Cast is necessary, otherwise incorrect value is created
} }
else else physicalsectorsize = logicalsectorsize;
physicalsectorsize = logicalsectorsize;
} }
else else
{ {
@@ -930,8 +1001,7 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.PhysicalBlockSize = physicalsectorsize; report.ATA.ReadCapabilities.PhysicalBlockSize = physicalsectorsize;
report.ATA.ReadCapabilities.PhysicalBlockSizeSpecified = true; report.ATA.ReadCapabilities.PhysicalBlockSizeSpecified = true;
if((ataId.LogicalAlignment & 0x8000) == 0x0000 && if((ataId.LogicalAlignment & 0x8000) == 0x0000 && (ataId.LogicalAlignment & 0x4000) == 0x4000)
(ataId.LogicalAlignment & 0x4000) == 0x4000)
{ {
report.ATA.ReadCapabilities.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF); report.ATA.ReadCapabilities.LogicalAlignment = (ushort)(ataId.LogicalAlignment & 0x3FFF);
report.ATA.ReadCapabilities.LogicalAlignmentSpecified = true; report.ATA.ReadCapabilities.LogicalAlignmentSpecified = true;
@@ -944,15 +1014,17 @@ namespace DiscImageChef.Core.Devices.Report
report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; report.ATA.ReadCapabilities.LongBlockSizeSpecified = true;
} }
if(ataId.UnformattedBPS > logicalsectorsize && (!report.ATA.ReadCapabilities.LongBlockSizeSpecified || report.ATA.ReadCapabilities.LongBlockSize == 516)) if(ataId.UnformattedBPS > logicalsectorsize &&
(!report.ATA.ReadCapabilities.LongBlockSizeSpecified ||
report.ATA.ReadCapabilities.LongBlockSize == 516))
{ {
report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS; report.ATA.ReadCapabilities.LongBlockSize = ataId.UnformattedBPS;
report.ATA.ReadCapabilities.LongBlockSizeSpecified = true; report.ATA.ReadCapabilities.LongBlockSizeSpecified = true;
} }
if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) && if(ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeSet) &&
!ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) && !ataId.CommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MustBeClear) &&
ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial)) ataId.EnabledCommandSet3.HasFlag(Decoders.ATA.Identify.CommandSetBit3.MediaSerial))
{ {
report.ATA.ReadCapabilities.CanReadMediaSerial = true; report.ATA.ReadCapabilities.CanReadMediaSerial = true;
report.ATA.ReadCapabilities.CanReadMediaSerialSpecified = true; report.ATA.ReadCapabilities.CanReadMediaSerialSpecified = true;
@@ -992,129 +1064,181 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in CHS mode...");
sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsRead = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsRead =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
sense, errorChs.status, errorChs.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorschs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in CHS mode...");
sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadRetry =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
sense, errorChs.status, errorChs.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorsretrychs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ DMA in CHS mode..."); DicConsole.WriteLine("Trying READ DMA in CHS mode...");
sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorChs, false, 0, 0, 1, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadDma = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadDma =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
sense, errorChs.status, errorChs.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmachs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ DMA RETRY in CHS mode...");
sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorChs, true, 0, 0, 1, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadDmaRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadDmaRetry =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0);
sense, errorChs.status, errorChs.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmaretrychs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying SEEK in CHS mode..."); DicConsole.WriteLine("Trying SEEK in CHS mode...");
sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration); sense = dev.Seek(out errorChs, 0, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsSeek = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0); report.ATA.ReadCapabilities.SupportsSeek =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0);
sense, errorChs.status, errorChs.error); DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
errorChs.status, errorChs.error);
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA mode...");
sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
sense, errorLba.status, errorLba.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectors", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) RETRY in LBA mode...");
sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadRetryLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
sense, errorLba.status, errorLba.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectorsretry", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ DMA in LBA mode..."); DicConsole.WriteLine("Trying READ DMA in LBA mode...");
sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba, false, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadDmaLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadDmaLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
sense, errorLba.status, errorLba.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdma", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdma", "_debug_" + report.ATA.Model + ".bin", "read results",
readBuf);
DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ DMA RETRY in LBA mode...");
sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba, true, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadDmaRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadDmaRetryLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0);
sense, errorLba.status, errorLba.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdmaretry", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying SEEK in LBA mode..."); DicConsole.WriteLine("Trying SEEK in LBA mode...");
sense = dev.Seek(out errorLba, 0, timeout, out duration); sense = dev.Seek(out errorLba, 0, timeout, out duration);
report.ATA.ReadCapabilities.SupportsSeekLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0); report.ATA.ReadCapabilities.SupportsSeekLba =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0);
sense, errorLba.status, errorLba.error); DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}", sense,
errorLba.status, errorLba.error);
DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode..."); DicConsole.WriteLine("Trying READ SECTOR(S) in LBA48 mode...");
sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration); sense = dev.Read(out readBuf, out errorLba48, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadLba48 =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
sense, errorLba48.status, errorLba48.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba48.status, errorLba48.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readsectors48", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ DMA in LBA48 mode..."); DicConsole.WriteLine("Trying READ DMA in LBA48 mode...");
sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration); sense = dev.ReadDma(out readBuf, out errorLba48, 0, 1, timeout, out duration);
report.ATA.ReadCapabilities.SupportsReadDmaLba48 = (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0); report.ATA.ReadCapabilities.SupportsReadDmaLba48 =
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", (!sense && (errorLba48.status & 0x01) != 0x01 && errorLba48.error == 0 && readBuf.Length > 0);
sense, errorLba48.status, errorLba48.error, readBuf.Length); DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba48.status, errorLba48.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readdma48", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ LONG in CHS mode..."); DicConsole.WriteLine("Trying READ LONG in CHS mode...");
sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorChs, false, 0, 0, 1,
report.ATA.ReadCapabilities.SupportsReadLong = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", report.ATA.ReadCapabilities.SupportsReadLong =
sense, errorChs.status, errorChs.error, readBuf.Length); (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongchs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode..."); DicConsole.WriteLine("Trying READ LONG RETRY in CHS mode...");
sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorChs, true, 0, 0, 1,
report.ATA.ReadCapabilities.SupportsReadLongRetry = (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", report.ATA.ReadCapabilities.SupportsReadLongRetry =
sense, errorChs.status, errorChs.error, readBuf.Length); (!sense && (errorChs.status & 0x01) != 0x01 && errorChs.error == 0 && readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorChs.status, errorChs.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongretrychs", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ LONG in LBA mode..."); DicConsole.WriteLine("Trying READ LONG in LBA mode...");
sense = dev.ReadLong(out readBuf, out errorLba, false, 0, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorLba, false, 0, report.ATA.ReadCapabilities.LongBlockSize,
report.ATA.ReadCapabilities.SupportsReadLongLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", report.ATA.ReadCapabilities.SupportsReadLongLba =
sense, errorLba.status, errorLba.error, readBuf.Length); (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlong", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlong", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode..."); DicConsole.WriteLine("Trying READ LONG RETRY in LBA mode...");
sense = dev.ReadLong(out readBuf, out errorLba, true, 0, report.ATA.ReadCapabilities.LongBlockSize, timeout, out duration); sense = dev.ReadLong(out readBuf, out errorLba, true, 0, report.ATA.ReadCapabilities.LongBlockSize,
report.ATA.ReadCapabilities.SupportsReadLongRetryLba = (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 && BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead); timeout, out duration);
DicConsole.DebugWriteLine("ATA Report", "Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", report.ATA.ReadCapabilities.SupportsReadLongRetryLba =
sense, errorLba.status, errorLba.error, readBuf.Length); (!sense && (errorLba.status & 0x01) != 0x01 && errorLba.error == 0 && readBuf.Length > 0 &&
BitConverter.ToUInt64(readBuf, 0) != checkCorrectRead);
DicConsole.DebugWriteLine("ATA Report",
"Sense = {0}, Status = 0x{1:X2}, Error = 0x{2:X2}, Length = {3}", sense,
errorLba.status, errorLba.error, readBuf.Length);
if(debug) if(debug)
DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + report.ATA.Model + ".bin", "read results", readBuf); DataFile.WriteTo("ATA Report", "readlongretry", "_debug_" + report.ATA.Model + ".bin",
"read results", readBuf);
} }
} }
} }
} }
} }

View File

@@ -40,8 +40,7 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
byte[] buffer; byte[] buffer;
double duration; double duration;
@@ -453,9 +452,8 @@ namespace DiscImageChef.Core.Devices.Report
report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2; report.ATAPI.WRVSectorCountMode2 = atapiId.WRVSectorCountMode2;
report.ATAPI.WRVSectorCountMode2Specified = true; report.ATAPI.WRVSectorCountMode2Specified = true;
} }
if(debug) if(debug) report.ATAPI.Identify = buffer;
report.ATAPI.Identify = buffer;
} }
} }
} }
} }

View File

@@ -41,8 +41,7 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
ConsoleKeyInfo pressedKey = new ConsoleKeyInfo(); ConsoleKeyInfo pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
@@ -73,4 +72,4 @@ namespace DiscImageChef.Core.Devices.Report
} }
} }
} }
} }

View File

@@ -40,10 +40,9 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
throw new NotImplementedException("NVMe devices not yet supported."); throw new NotImplementedException("NVMe devices not yet supported.");
} }
} }
} }

View File

@@ -75,4 +75,4 @@ namespace DiscImageChef.Core.Devices.Report
} }
} }
} }
} }

View File

@@ -43,8 +43,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
byte[] senseBuffer; byte[] senseBuffer;
byte[] buffer; byte[] buffer;
@@ -53,14 +52,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
uint timeout = 5; uint timeout = 5;
ConsoleKeyInfo pressedKey; ConsoleKeyInfo pressedKey;
if(dev.IsUSB) if(dev.IsUSB) USB.Report(dev, ref report, debug, ref removable);
USB.Report(dev, ref report, debug, ref removable);
if(dev.IsFireWire) if(dev.IsFireWire) FireWire.Report(dev, ref report, debug, ref removable);
FireWire.Report(dev, ref report, debug, ref removable);
if(dev.IsPCMCIA) if(dev.IsPCMCIA) PCMCIA.Report(dev, ref report, debug, ref removable);
PCMCIA.Report(dev, ref report, debug, ref removable);
if(!dev.IsUSB && !dev.IsFireWire && dev.IsRemovable) if(!dev.IsUSB && !dev.IsFireWire && dev.IsRemovable)
{ {
@@ -75,8 +71,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
removable = pressedKey.Key == ConsoleKey.Y; removable = pressedKey.Key == ConsoleKey.Y;
} }
if(dev.Type == DeviceType.ATAPI) if(dev.Type == DeviceType.ATAPI) ATAPI.Report(dev, ref report, debug, ref removable);
ATAPI.Report(dev, ref report, debug, ref removable);
DicConsole.WriteLine("Querying SCSI INQUIRY..."); DicConsole.WriteLine("Querying SCSI INQUIRY...");
sense = dev.ScsiInquiry(out buffer, out senseBuffer); sense = dev.ScsiInquiry(out buffer, out senseBuffer);
@@ -117,19 +112,22 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.VendorIdentification))) if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.VendorIdentification)))
{ {
report.SCSI.Inquiry.VendorIdentification = StringHandlers.CToString(inq.VendorIdentification).Trim(); report.SCSI.Inquiry.VendorIdentification =
StringHandlers.CToString(inq.VendorIdentification).Trim();
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.VendorIdentification)) if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.VendorIdentification))
report.SCSI.Inquiry.VendorIdentificationSpecified = true; report.SCSI.Inquiry.VendorIdentificationSpecified = true;
} }
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductIdentification))) if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductIdentification)))
{ {
report.SCSI.Inquiry.ProductIdentification = StringHandlers.CToString(inq.ProductIdentification).Trim(); report.SCSI.Inquiry.ProductIdentification =
StringHandlers.CToString(inq.ProductIdentification).Trim();
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductIdentification)) if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductIdentification))
report.SCSI.Inquiry.ProductIdentificationSpecified = true; report.SCSI.Inquiry.ProductIdentificationSpecified = true;
} }
if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductRevisionLevel))) if(!string.IsNullOrWhiteSpace(StringHandlers.CToString(inq.ProductRevisionLevel)))
{ {
report.SCSI.Inquiry.ProductRevisionLevel = StringHandlers.CToString(inq.ProductRevisionLevel).Trim(); report.SCSI.Inquiry.ProductRevisionLevel =
StringHandlers.CToString(inq.ProductRevisionLevel).Trim();
if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductRevisionLevel)) if(!string.IsNullOrWhiteSpace(report.SCSI.Inquiry.ProductRevisionLevel))
report.SCSI.Inquiry.ProductRevisionLevelSpecified = true; report.SCSI.Inquiry.ProductRevisionLevelSpecified = true;
} }
@@ -137,8 +135,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
{ {
foreach(ushort descriptor in inq.VersionDescriptors) foreach(ushort descriptor in inq.VersionDescriptors)
{ {
if(descriptor != 0) if(descriptor != 0) versionDescriptors.Add(descriptor);
versionDescriptors.Add(descriptor);
} }
if(versionDescriptors.Count > 0) if(versionDescriptors.Count > 0)
@@ -146,7 +143,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
report.SCSI.Inquiry.PeripheralQualifier = (Decoders.SCSI.PeripheralQualifiers)inq.PeripheralQualifier; report.SCSI.Inquiry.PeripheralQualifier = (Decoders.SCSI.PeripheralQualifiers)inq.PeripheralQualifier;
report.SCSI.Inquiry.PeripheralDeviceType = (Decoders.SCSI.PeripheralDeviceTypes)inq.PeripheralDeviceType; report.SCSI.Inquiry.PeripheralDeviceType =
(Decoders.SCSI.PeripheralDeviceTypes)inq.PeripheralDeviceType;
report.SCSI.Inquiry.AsymmetricalLUNAccess = (Decoders.SCSI.TGPSValues)inq.TPGS; report.SCSI.Inquiry.AsymmetricalLUNAccess = (Decoders.SCSI.TGPSValues)inq.TPGS;
report.SCSI.Inquiry.SPIClocking = (Decoders.SCSI.SPIClocking)inq.Clocking; report.SCSI.Inquiry.SPIClocking = (Decoders.SCSI.SPIClocking)inq.Clocking;
@@ -177,8 +175,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
report.SCSI.Inquiry.WideBus16 = inq.WBus16; report.SCSI.Inquiry.WideBus16 = inq.WBus16;
report.SCSI.Inquiry.WideBus32 = inq.WBus32; report.SCSI.Inquiry.WideBus32 = inq.WBus32;
if(debug) if(debug) report.SCSI.Inquiry.Data = buffer;
report.SCSI.Inquiry.Data = buffer;
} }
DicConsole.WriteLine("Querying list of SCSI EVPDs..."); DicConsole.WriteLine("Querying list of SCSI EVPDs...");
@@ -205,8 +202,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
} }
} }
if(evpds.Count > 0)
report.SCSI.EVPDPages = evpds.ToArray(); if(evpds.Count > 0) report.SCSI.EVPDPages = evpds.ToArray();
} }
} }
@@ -231,11 +228,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
Decoders.SCSI.PeripheralDeviceTypes devType = dev.SCSIType; Decoders.SCSI.PeripheralDeviceTypes devType = dev.SCSIType;
DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (10)..."); DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (10)...");
sense = dev.ModeSense10(out byte[] mode10Buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration); sense = dev.ModeSense10(out byte[] mode10Buffer, out senseBuffer, false, true,
ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration);
if(sense || dev.Error) if(sense || dev.Error)
{ {
DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (10)..."); DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (10)...");
sense = dev.ModeSense10(out mode10Buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration); sense = dev.ModeSense10(out mode10Buffer, out senseBuffer, false, true,
ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense10 = true; report.SCSI.SupportsModeSense10 = true;
@@ -251,19 +250,20 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (6)..."); DicConsole.WriteLine("Querying all mode pages and subpages using SCSI MODE SENSE (6)...");
sense = dev.ModeSense6(out byte[] mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F, 0xFF, timeout, out duration); sense = dev.ModeSense6(out byte[] mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default,
0x3F, 0xFF, timeout, out duration);
if(sense || dev.Error) if(sense || dev.Error)
{ {
DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (6)..."); DicConsole.WriteLine("Querying all mode pages using SCSI MODE SENSE (6)...");
sense = dev.ModeSense6(out mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F, 0x00, timeout, out duration); sense = dev.ModeSense6(out mode6Buffer, out senseBuffer, false, ScsiModeSensePageControl.Default, 0x3F,
0x00, timeout, out duration);
if(sense || dev.Error) if(sense || dev.Error)
{ {
DicConsole.WriteLine("Querying SCSI MODE SENSE (6)..."); DicConsole.WriteLine("Querying SCSI MODE SENSE (6)...");
sense = dev.ModeSense(out mode6Buffer, out senseBuffer, timeout, out duration); sense = dev.ModeSense(out mode6Buffer, out senseBuffer, timeout, out duration);
} }
} }
else else report.SCSI.SupportsModeSubpages = true;
report.SCSI.SupportsModeSubpages = true;
if(!sense && !dev.Error && !decMode.HasValue) if(!sense && !dev.Error && !decMode.HasValue)
decMode = Decoders.SCSI.Modes.DecodeMode6(mode6Buffer, devType); decMode = Decoders.SCSI.Modes.DecodeMode6(mode6Buffer, devType);
@@ -272,10 +272,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
Decoders.SCSI.Modes.ModePage_2A? cdromMode = null; Decoders.SCSI.Modes.ModePage_2A? cdromMode = null;
if(debug && report.SCSI.SupportsModeSense6) if(debug && report.SCSI.SupportsModeSense6) report.SCSI.ModeSense6Data = mode6Buffer;
report.SCSI.ModeSense6Data = mode6Buffer; if(debug && report.SCSI.SupportsModeSense10) report.SCSI.ModeSense10Data = mode10Buffer;
if(debug && report.SCSI.SupportsModeSense10)
report.SCSI.ModeSense10Data = mode10Buffer;
if(decMode.HasValue) if(decMode.HasValue)
{ {
@@ -313,8 +311,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
} }
if(modePages.Count > 0) if(modePages.Count > 0) report.SCSI.ModeSense.ModePages = modePages.ToArray();
report.SCSI.ModeSense.ModePages = modePages.ToArray();
} }
} }
@@ -372,8 +369,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
DicConsole.Write("\rWaiting for drive to become ready"); DicConsole.Write("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
@@ -388,19 +384,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
DicConsole.Write("\rWaiting for drive to become ready"); DicConsole.Write("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
mediaTest.MediaIsRecognized &= !sense; mediaTest.MediaIsRecognized &= !sense;
} }
else else mediaTest.MediaIsRecognized = false;
mediaTest.MediaIsRecognized = false;
} }
else else mediaTest.MediaIsRecognized = false;
mediaTest.MediaIsRecognized = false;
} }
if(mediaTest.MediaIsRecognized) if(mediaTest.MediaIsRecognized)
@@ -413,8 +406,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadCapacity = true; mediaTest.SupportsReadCapacity = true;
mediaTest.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1; mediaTest.Blocks =
mediaTest.BlockSize = (uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) +
(buffer[3])) + 1;
mediaTest.BlockSize =
(uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
mediaTest.BlocksSpecified = true; mediaTest.BlocksSpecified = true;
mediaTest.BlockSizeSpecified = true; mediaTest.BlockSizeSpecified = true;
} }
@@ -428,7 +424,9 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
Array.Copy(buffer, 0, temp, 0, 8); Array.Copy(buffer, 0, temp, 0, 8);
Array.Reverse(temp); Array.Reverse(temp);
mediaTest.Blocks = BitConverter.ToUInt64(temp, 0) + 1; mediaTest.Blocks = BitConverter.ToUInt64(temp, 0) + 1;
mediaTest.BlockSize = (uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11])); mediaTest.BlockSize =
(uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) +
(buffer[11]));
mediaTest.BlocksSpecified = true; mediaTest.BlocksSpecified = true;
mediaTest.BlockSizeSpecified = true; mediaTest.BlockSizeSpecified = true;
} }
@@ -436,13 +434,14 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
decMode = null; decMode = null;
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); sense = dev.ModeSense10(out buffer, out senseBuffer, false, true,
ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout,
out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense10 = true; report.SCSI.SupportsModeSense10 = true;
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
if(debug) if(debug) mediaTest.ModeSense10Data = buffer;
mediaTest.ModeSense10Data = buffer;
} }
DicConsole.WriteLine("Querying SCSI MODE SENSE..."); DicConsole.WriteLine("Querying SCSI MODE SENSE...");
@@ -452,15 +451,15 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
report.SCSI.SupportsModeSense6 = true; report.SCSI.SupportsModeSense6 = true;
if(!decMode.HasValue) if(!decMode.HasValue)
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
if(debug) if(debug) mediaTest.ModeSense6Data = buffer;
mediaTest.ModeSense6Data = buffer;
} }
if(decMode.HasValue) if(decMode.HasValue)
{ {
mediaTest.MediumType = (byte)decMode.Value.Header.MediumType; mediaTest.MediumType = (byte)decMode.Value.Header.MediumType;
mediaTest.MediumTypeSpecified = true; mediaTest.MediumTypeSpecified = true;
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) if(decMode.Value.Header.BlockDescriptors != null &&
decMode.Value.Header.BlockDescriptors.Length > 0)
{ {
mediaTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; mediaTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
mediaTest.DensitySpecified = true; mediaTest.DensitySpecified = true;
@@ -474,44 +473,61 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
mediaTest.SupportsReadLongSpecified = true; mediaTest.SupportsReadLongSpecified = true;
DicConsole.WriteLine("Trying SCSI READ (6)..."); DicConsole.WriteLine("Trying SCSI READ (6)...");
mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, mediaTest.BlockSize, timeout, out duration); mediaTest.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, mediaTest.BlockSize,
timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read6", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read6",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (10)..."); DicConsole.WriteLine("Trying SCSI READ (10)...");
mediaTest.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, timeout, out duration); mediaTest.SupportsRead10 =
!dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0,
mediaTest.BlockSize, 0, 1, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead10);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read10", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read10",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (12)..."); DicConsole.WriteLine("Trying SCSI READ (12)...");
mediaTest.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration); mediaTest.SupportsRead12 =
!dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0,
mediaTest.BlockSize, 0, 1, false, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead12);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read12", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read12",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (16)..."); DicConsole.WriteLine("Trying SCSI READ (16)...");
mediaTest.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, mediaTest.BlockSize, 0, 1, false, timeout, out duration); mediaTest.SupportsRead16 =
!dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0,
mediaTest.BlockSize, 0, 1, false, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !mediaTest.SupportsRead16);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read16", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read16",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
buffer);
mediaTest.LongBlockSize = mediaTest.BlockSize; mediaTest.LongBlockSize = mediaTest.BlockSize;
DicConsole.WriteLine("Trying SCSI READ LONG (10)..."); DicConsole.WriteLine("Trying SCSI READ LONG (10)...");
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 0xFFFF, timeout,
out duration);
if(sense && !dev.Error) if(sense && !dev.Error)
{ {
Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer); Decoders.SCSI.FixedSense? decSense = Decoders.SCSI.Sense.DecodeFixed(senseBuffer);
if(decSense.HasValue) if(decSense.HasValue)
{ {
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest && if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
if(decSense.Value.InformationValid && decSense.Value.ILI) if(decSense.Value.InformationValid && decSense.Value.ILI)
{ {
mediaTest.LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); mediaTest.LongBlockSize =
0xFFFF - (decSense.Value.Information & 0xFFFF);
mediaTest.LongBlockSizeSpecified = true; mediaTest.LongBlockSizeSpecified = true;
} }
} }
@@ -522,15 +538,18 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
{ {
if(mediaTest.BlockSize == 512) if(mediaTest.BlockSize == 512)
{ {
foreach(ushort testSize in new[] { foreach(ushort testSize in new[]
{
// Long sector sizes for floppies // Long sector sizes for floppies
514, 514,
// Long sector sizes for SuperDisk // Long sector sizes for SuperDisk
536, 558, 536, 558,
// Long sector sizes for 512-byte magneto-opticals // Long sector sizes for 512-byte magneto-opticals
600, 610, 630 }) 600, 610, 630
})
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
testSize, timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
@@ -542,13 +561,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(mediaTest.BlockSize == 1024) else if(mediaTest.BlockSize == 1024)
{ {
foreach(ushort testSize in new[] { foreach(ushort testSize in new[]
{
// Long sector sizes for floppies // Long sector sizes for floppies
1026, 1026,
// Long sector sizes for 1024-byte magneto-opticals // Long sector sizes for 1024-byte magneto-opticals
1200 }) 1200
})
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, testSize, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
testSize, timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
@@ -560,7 +582,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(mediaTest.BlockSize == 2048) else if(mediaTest.BlockSize == 2048)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380,
timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
@@ -570,7 +593,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(mediaTest.BlockSize == 4096) else if(mediaTest.BlockSize == 4096)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760,
timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
@@ -580,7 +604,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(mediaTest.BlockSize == 8192) else if(mediaTest.BlockSize == 8192)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424,
timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
mediaTest.SupportsReadLong = true; mediaTest.SupportsReadLong = true;
@@ -595,7 +620,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
pressedKey = new ConsoleKeyInfo(); pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
{ {
DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); DicConsole
.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
pressedKey = System.Console.ReadKey(); pressedKey = System.Console.ReadKey();
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
@@ -605,7 +631,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
for(ushort i = (ushort)mediaTest.BlockSize; i <= ushort.MaxValue; i++) for(ushort i = (ushort)mediaTest.BlockSize; i <= ushort.MaxValue; i++)
{ {
DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i); DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i);
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i,
timeout, out duration);
if(!sense) if(!sense)
{ {
mediaTest.LongBlockSize = i; mediaTest.LongBlockSize = i;
@@ -613,27 +640,34 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
break; break;
} }
if(i == ushort.MaxValue) if(i == ushort.MaxValue) break;
break;
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
} }
if(debug && mediaTest.SupportsReadLong && mediaTest.LongBlockSizeSpecified && mediaTest.LongBlockSize != mediaTest.BlockSize) if(debug && mediaTest.SupportsReadLong && mediaTest.LongBlockSizeSpecified &&
mediaTest.LongBlockSize != mediaTest.BlockSize)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, (ushort)mediaTest.LongBlockSize, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
(ushort)mediaTest.LongBlockSize, timeout, out duration);
if(!sense) if(!sense)
DataFile.WriteTo("SCSI Report", "readlong10", "_debug_" + mediaTest.MediumTypeName + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "readlong10",
"_debug_" + mediaTest.MediumTypeName + ".bin", "read results",
buffer);
} }
mediaTest.CanReadMediaSerialSpecified = true; mediaTest.CanReadMediaSerialSpecified = true;
DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER..."); DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER...");
mediaTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration); mediaTest.CanReadMediaSerial =
!dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
} }
mediaTests.Add(mediaTest); mediaTests.Add(mediaTest);
} }
} }
report.SCSI.RemovableMedias = mediaTests.ToArray(); report.SCSI.RemovableMedias = mediaTests.ToArray();
} }
else else
@@ -650,8 +684,10 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.ReadCapabilities.SupportsReadCapacity = true; report.SCSI.ReadCapabilities.SupportsReadCapacity = true;
report.SCSI.ReadCapabilities.Blocks = (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1; report.SCSI.ReadCapabilities.Blocks =
report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7])); (ulong)((buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3])) + 1;
report.SCSI.ReadCapabilities.BlockSize =
(uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
report.SCSI.ReadCapabilities.BlocksSpecified = true; report.SCSI.ReadCapabilities.BlocksSpecified = true;
report.SCSI.ReadCapabilities.BlockSizeSpecified = true; report.SCSI.ReadCapabilities.BlockSizeSpecified = true;
} }
@@ -665,7 +701,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
Array.Copy(buffer, 0, temp, 0, 8); Array.Copy(buffer, 0, temp, 0, 8);
Array.Reverse(temp); Array.Reverse(temp);
report.SCSI.ReadCapabilities.Blocks = BitConverter.ToUInt64(temp, 0) + 1; report.SCSI.ReadCapabilities.Blocks = BitConverter.ToUInt64(temp, 0) + 1;
report.SCSI.ReadCapabilities.BlockSize = (uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11])); report.SCSI.ReadCapabilities.BlockSize =
(uint)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11]));
report.SCSI.ReadCapabilities.BlocksSpecified = true; report.SCSI.ReadCapabilities.BlocksSpecified = true;
report.SCSI.ReadCapabilities.BlockSizeSpecified = true; report.SCSI.ReadCapabilities.BlockSizeSpecified = true;
} }
@@ -673,13 +710,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
decMode = null; decMode = null;
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current,
0x3F, 0x00, timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense10 = true; report.SCSI.SupportsModeSense10 = true;
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
if(debug) if(debug) report.SCSI.ReadCapabilities.ModeSense10Data = buffer;
report.SCSI.ReadCapabilities.ModeSense10Data = buffer;
} }
DicConsole.WriteLine("Querying SCSI MODE SENSE..."); DicConsole.WriteLine("Querying SCSI MODE SENSE...");
@@ -687,19 +724,19 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense6 = true; report.SCSI.SupportsModeSense6 = true;
if(!decMode.HasValue) if(!decMode.HasValue) decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); if(debug) report.SCSI.ReadCapabilities.ModeSense6Data = buffer;
if(debug)
report.SCSI.ReadCapabilities.ModeSense6Data = buffer;
} }
if(decMode.HasValue) if(decMode.HasValue)
{ {
report.SCSI.ReadCapabilities.MediumType = (byte)decMode.Value.Header.MediumType; report.SCSI.ReadCapabilities.MediumType = (byte)decMode.Value.Header.MediumType;
report.SCSI.ReadCapabilities.MediumTypeSpecified = true; report.SCSI.ReadCapabilities.MediumTypeSpecified = true;
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) if(decMode.Value.Header.BlockDescriptors != null &&
decMode.Value.Header.BlockDescriptors.Length > 0)
{ {
report.SCSI.ReadCapabilities.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; report.SCSI.ReadCapabilities.Density =
(byte)decMode.Value.Header.BlockDescriptors[0].Density;
report.SCSI.ReadCapabilities.DensitySpecified = true; report.SCSI.ReadCapabilities.DensitySpecified = true;
} }
} }
@@ -711,28 +748,47 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
report.SCSI.ReadCapabilities.SupportsReadLongSpecified = true; report.SCSI.ReadCapabilities.SupportsReadLongSpecified = true;
DicConsole.WriteLine("Trying SCSI READ (6)..."); DicConsole.WriteLine("Trying SCSI READ (6)...");
report.SCSI.ReadCapabilities.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0, report.SCSI.ReadCapabilities.BlockSize, timeout, out duration); report.SCSI.ReadCapabilities.SupportsRead = !dev.Read6(out buffer, out senseBuffer, 0,
report.SCSI.ReadCapabilities.BlockSize,
timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead); DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read6", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read6",
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (10)..."); DicConsole.WriteLine("Trying SCSI READ (10)...");
report.SCSI.ReadCapabilities.SupportsRead10 = !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, timeout, out duration); report.SCSI.ReadCapabilities.SupportsRead10 =
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead10); !dev.Read10(out buffer, out senseBuffer, 0, false, true, false, false, 0,
report.SCSI.ReadCapabilities.BlockSize, 0, 1, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
!report.SCSI.ReadCapabilities.SupportsRead10);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read10", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read10",
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (12)..."); DicConsole.WriteLine("Trying SCSI READ (12)...");
report.SCSI.ReadCapabilities.SupportsRead12 = !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration); report.SCSI.ReadCapabilities.SupportsRead12 =
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead12); !dev.Read12(out buffer, out senseBuffer, 0, false, true, false, false, 0,
report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
!report.SCSI.ReadCapabilities.SupportsRead12);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read12", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read12",
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
buffer);
DicConsole.WriteLine("Trying SCSI READ (16)..."); DicConsole.WriteLine("Trying SCSI READ (16)...");
report.SCSI.ReadCapabilities.SupportsRead16 = !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0, report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration); report.SCSI.ReadCapabilities.SupportsRead16 =
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}", !report.SCSI.ReadCapabilities.SupportsRead16); !dev.Read16(out buffer, out senseBuffer, 0, false, true, false, 0,
report.SCSI.ReadCapabilities.BlockSize, 0, 1, false, timeout, out duration);
DicConsole.DebugWriteLine("SCSI Report", "Sense = {0}",
!report.SCSI.ReadCapabilities.SupportsRead16);
if(debug) if(debug)
DataFile.WriteTo("SCSI Report", "read16", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "read16",
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results",
buffer);
report.SCSI.ReadCapabilities.LongBlockSize = report.SCSI.ReadCapabilities.BlockSize; report.SCSI.ReadCapabilities.LongBlockSize = report.SCSI.ReadCapabilities.BlockSize;
DicConsole.WriteLine("Trying SCSI READ LONG (10)..."); DicConsole.WriteLine("Trying SCSI READ LONG (10)...");
@@ -743,19 +799,21 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
if(decSense.HasValue) if(decSense.HasValue)
{ {
if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest && if(decSense.Value.SenseKey == Decoders.SCSI.SenseKeys.IllegalRequest &&
decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00)
{ {
report.SCSI.ReadCapabilities.SupportsReadLong = true; report.SCSI.ReadCapabilities.SupportsReadLong = true;
if(decSense.Value.InformationValid && decSense.Value.ILI) if(decSense.Value.InformationValid && decSense.Value.ILI)
{ {
report.SCSI.ReadCapabilities.LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); report.SCSI.ReadCapabilities.LongBlockSize =
0xFFFF - (decSense.Value.Information & 0xFFFF);
report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true; report.SCSI.ReadCapabilities.LongBlockSizeSpecified = true;
} }
} }
} }
} }
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize) if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize ==
report.SCSI.ReadCapabilities.BlockSize)
{ {
if(report.SCSI.ReadCapabilities.BlockSize == 512) if(report.SCSI.ReadCapabilities.BlockSize == 512)
{ {
@@ -803,7 +861,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(report.SCSI.ReadCapabilities.BlockSize == 2048) else if(report.SCSI.ReadCapabilities.BlockSize == 2048)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 2380, timeout,
out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.ReadCapabilities.SupportsReadLong = true; report.SCSI.ReadCapabilities.SupportsReadLong = true;
@@ -813,7 +872,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(report.SCSI.ReadCapabilities.BlockSize == 4096) else if(report.SCSI.ReadCapabilities.BlockSize == 4096)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 4760, timeout,
out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.ReadCapabilities.SupportsReadLong = true; report.SCSI.ReadCapabilities.SupportsReadLong = true;
@@ -823,7 +883,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
else if(report.SCSI.ReadCapabilities.BlockSize == 8192) else if(report.SCSI.ReadCapabilities.BlockSize == 8192)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, 9424, timeout,
out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.ReadCapabilities.SupportsReadLong = true; report.SCSI.ReadCapabilities.SupportsReadLong = true;
@@ -833,12 +894,14 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
} }
} }
if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize == report.SCSI.ReadCapabilities.BlockSize) if(report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSize ==
report.SCSI.ReadCapabilities.BlockSize)
{ {
pressedKey = new ConsoleKeyInfo(); pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
{ {
DicConsole.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): "); DicConsole
.Write("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (Y/N): ");
pressedKey = System.Console.ReadKey(); pressedKey = System.Console.ReadKey();
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
@@ -848,12 +911,15 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
for(ushort i = (ushort)report.SCSI.ReadCapabilities.BlockSize; i <= ushort.MaxValue; i++) for(ushort i = (ushort)report.SCSI.ReadCapabilities.BlockSize; i <= ushort.MaxValue; i++)
{ {
DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i); DicConsole.Write("\rTrying to READ LONG with a size of {0} bytes...", i);
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, i, timeout,
out duration);
if(!sense) if(!sense)
{ {
if(debug) if(debug)
{ {
FileStream bingo = new FileStream(string.Format("{0}_readlong.bin", dev.Model), FileMode.Create); FileStream bingo =
new FileStream(string.Format("{0}_readlong.bin", dev.Model),
FileMode.Create);
bingo.Write(buffer, 0, buffer.Length); bingo.Write(buffer, 0, buffer.Length);
bingo.Close(); bingo.Close();
} }
@@ -862,21 +928,27 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
break; break;
} }
if(i == ushort.MaxValue) if(i == ushort.MaxValue) break;
break;
} }
DicConsole.WriteLine(); DicConsole.WriteLine();
} }
} }
if(debug && report.SCSI.ReadCapabilities.SupportsReadLong && report.SCSI.ReadCapabilities.LongBlockSizeSpecified && report.SCSI.ReadCapabilities.LongBlockSize != report.SCSI.ReadCapabilities.BlockSize) if(debug && report.SCSI.ReadCapabilities.SupportsReadLong &&
report.SCSI.ReadCapabilities.LongBlockSizeSpecified &&
report.SCSI.ReadCapabilities.LongBlockSize != report.SCSI.ReadCapabilities.BlockSize)
{ {
sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0, (ushort)report.SCSI.ReadCapabilities.LongBlockSize, timeout, out duration); sense = dev.ReadLong10(out buffer, out senseBuffer, false, false, 0,
(ushort)report.SCSI.ReadCapabilities.LongBlockSize, timeout,
out duration);
if(!sense) if(!sense)
DataFile.WriteTo("SCSI Report", "readlong10", "_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin", "read results", buffer); DataFile.WriteTo("SCSI Report", "readlong10",
"_debug_" + report.SCSI.Inquiry.ProductIdentification + ".bin",
"read results", buffer);
} }
} }
} }
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -42,8 +42,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
{ {
internal static void Report(Device dev, ref DeviceReport report, bool debug) internal static void Report(Device dev, ref DeviceReport report, bool debug)
{ {
if(report == null) if(report == null) return;
return;
byte[] senseBuffer; byte[] senseBuffer;
byte[] buffer; byte[] buffer;
@@ -83,21 +82,29 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, false, timeout, out duration); sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, false, timeout, out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer); Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh =
Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
if(dsh.HasValue) if(dsh.HasValue)
{ {
report.SCSI.SequentialDevice.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length]; report.SCSI.SequentialDevice.SupportedDensities =
new SupportedDensity[dsh.Value.descriptors.Length];
for(int i = 0; i < dsh.Value.descriptors.Length; i++) for(int i = 0; i < dsh.Value.descriptors.Length; i++)
{ {
report.SCSI.SequentialDevice.SupportedDensities[i].BitsPerMm = dsh.Value.descriptors[i].bpmm; report.SCSI.SequentialDevice.SupportedDensities[i].BitsPerMm = dsh.Value.descriptors[i].bpmm;
report.SCSI.SequentialDevice.SupportedDensities[i].Capacity = dsh.Value.descriptors[i].capacity; report.SCSI.SequentialDevice.SupportedDensities[i].Capacity = dsh.Value.descriptors[i].capacity;
report.SCSI.SequentialDevice.SupportedDensities[i].DefaultDensity = dsh.Value.descriptors[i].defaultDensity; report.SCSI.SequentialDevice.SupportedDensities[i].DefaultDensity =
report.SCSI.SequentialDevice.SupportedDensities[i].Description = dsh.Value.descriptors[i].description; dsh.Value.descriptors[i].defaultDensity;
report.SCSI.SequentialDevice.SupportedDensities[i].Duplicate = dsh.Value.descriptors[i].duplicate; report.SCSI.SequentialDevice.SupportedDensities[i].Description =
dsh.Value.descriptors[i].description;
report.SCSI.SequentialDevice.SupportedDensities[i].Duplicate =
dsh.Value.descriptors[i].duplicate;
report.SCSI.SequentialDevice.SupportedDensities[i].Name = dsh.Value.descriptors[i].name; report.SCSI.SequentialDevice.SupportedDensities[i].Name = dsh.Value.descriptors[i].name;
report.SCSI.SequentialDevice.SupportedDensities[i].Organization = dsh.Value.descriptors[i].organization; report.SCSI.SequentialDevice.SupportedDensities[i].Organization =
report.SCSI.SequentialDevice.SupportedDensities[i].PrimaryCode = dsh.Value.descriptors[i].primaryCode; dsh.Value.descriptors[i].organization;
report.SCSI.SequentialDevice.SupportedDensities[i].SecondaryCode = dsh.Value.descriptors[i].secondaryCode; report.SCSI.SequentialDevice.SupportedDensities[i].PrimaryCode =
dsh.Value.descriptors[i].primaryCode;
report.SCSI.SequentialDevice.SupportedDensities[i].SecondaryCode =
dsh.Value.descriptors[i].secondaryCode;
report.SCSI.SequentialDevice.SupportedDensities[i].Tracks = dsh.Value.descriptors[i].tracks; report.SCSI.SequentialDevice.SupportedDensities[i].Tracks = dsh.Value.descriptors[i].tracks;
report.SCSI.SequentialDevice.SupportedDensities[i].Width = dsh.Value.descriptors[i].width; report.SCSI.SequentialDevice.SupportedDensities[i].Width = dsh.Value.descriptors[i].width;
report.SCSI.SequentialDevice.SupportedDensities[i].Writable = dsh.Value.descriptors[i].writable; report.SCSI.SequentialDevice.SupportedDensities[i].Writable = dsh.Value.descriptors[i].writable;
@@ -109,23 +116,30 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, false, timeout, out duration); sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, false, timeout, out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer); Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh =
Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
if(mtsh.HasValue) if(mtsh.HasValue)
{ {
report.SCSI.SequentialDevice.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length]; report.SCSI.SequentialDevice.SupportedMediaTypes =
new SupportedMedia[mtsh.Value.descriptors.Length];
for(int i = 0; i < mtsh.Value.descriptors.Length; i++) for(int i = 0; i < mtsh.Value.descriptors.Length; i++)
{ {
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Description = mtsh.Value.descriptors[i].description; report.SCSI.SequentialDevice.SupportedMediaTypes[i].Description =
mtsh.Value.descriptors[i].description;
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Length = mtsh.Value.descriptors[i].length; report.SCSI.SequentialDevice.SupportedMediaTypes[i].Length = mtsh.Value.descriptors[i].length;
report.SCSI.SequentialDevice.SupportedMediaTypes[i].MediumType = mtsh.Value.descriptors[i].mediumType; report.SCSI.SequentialDevice.SupportedMediaTypes[i].MediumType =
mtsh.Value.descriptors[i].mediumType;
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Name = mtsh.Value.descriptors[i].name; report.SCSI.SequentialDevice.SupportedMediaTypes[i].Name = mtsh.Value.descriptors[i].name;
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Organization = mtsh.Value.descriptors[i].organization; report.SCSI.SequentialDevice.SupportedMediaTypes[i].Organization =
mtsh.Value.descriptors[i].organization;
report.SCSI.SequentialDevice.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width; report.SCSI.SequentialDevice.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width;
if(mtsh.Value.descriptors[i].densityCodes != null) if(mtsh.Value.descriptors[i].densityCodes != null)
{ {
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length]; report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes =
new int[mtsh.Value.descriptors[i].densityCodes.Length];
for(int j = 0; j < mtsh.Value.descriptors.Length; j++) for(int j = 0; j < mtsh.Value.descriptors.Length; j++)
report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes[j] = mtsh.Value.descriptors[i].densityCodes[j]; report.SCSI.SequentialDevice.SupportedMediaTypes[i].DensityCodes[j] =
mtsh.Value.descriptors[i].densityCodes[j];
} }
} }
} }
@@ -174,8 +188,7 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
DicConsole.Write("\rWaiting for drive to become ready"); DicConsole.Write("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
@@ -190,19 +203,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
DicConsole.Write("\rWaiting for drive to become ready"); DicConsole.Write("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuffer, timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
seqTest.MediaIsRecognized &= !sense; seqTest.MediaIsRecognized &= !sense;
} }
else else seqTest.MediaIsRecognized = false;
seqTest.MediaIsRecognized = false;
} }
else else seqTest.MediaIsRecognized = false;
seqTest.MediaIsRecognized = false;
} }
if(seqTest.MediaIsRecognized) if(seqTest.MediaIsRecognized)
@@ -210,13 +220,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
decMode = null; decMode = null;
DicConsole.WriteLine("Querying SCSI MODE SENSE (10)..."); DicConsole.WriteLine("Querying SCSI MODE SENSE (10)...");
sense = dev.ModeSense10(out buffer, out senseBuffer, false, true, ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration); sense = dev.ModeSense10(out buffer, out senseBuffer, false, true,
ScsiModeSensePageControl.Current, 0x3F, 0x00, timeout, out duration);
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense10 = true; report.SCSI.SupportsModeSense10 = true;
decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType); decMode = Decoders.SCSI.Modes.DecodeMode10(buffer, dev.SCSIType);
if(debug) if(debug) seqTest.ModeSense10Data = buffer;
seqTest.ModeSense10Data = buffer;
} }
DicConsole.WriteLine("Querying SCSI MODE SENSE..."); DicConsole.WriteLine("Querying SCSI MODE SENSE...");
@@ -224,17 +234,16 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
report.SCSI.SupportsModeSense6 = true; report.SCSI.SupportsModeSense6 = true;
if(!decMode.HasValue) if(!decMode.HasValue) decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType);
decMode = Decoders.SCSI.Modes.DecodeMode6(buffer, dev.SCSIType); if(debug) seqTest.ModeSense6Data = buffer;
if(debug)
seqTest.ModeSense6Data = buffer;
} }
if(decMode.HasValue) if(decMode.HasValue)
{ {
seqTest.MediumType = (byte)decMode.Value.Header.MediumType; seqTest.MediumType = (byte)decMode.Value.Header.MediumType;
seqTest.MediumTypeSpecified = true; seqTest.MediumTypeSpecified = true;
if(decMode.Value.Header.BlockDescriptors != null && decMode.Value.Header.BlockDescriptors.Length > 0) if(decMode.Value.Header.BlockDescriptors != null &&
decMode.Value.Header.BlockDescriptors.Length > 0)
{ {
seqTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density; seqTest.Density = (byte)decMode.Value.Header.BlockDescriptors[0].Density;
seqTest.DensitySpecified = true; seqTest.DensitySpecified = true;
@@ -246,7 +255,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, true, timeout, out duration); sense = dev.ReportDensitySupport(out buffer, out senseBuffer, false, true, timeout, out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh = Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer); Decoders.SCSI.SSC.DensitySupport.DensitySupportHeader? dsh =
Decoders.SCSI.SSC.DensitySupport.DecodeDensity(buffer);
if(dsh.HasValue) if(dsh.HasValue)
{ {
seqTest.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length]; seqTest.SupportedDensities = new SupportedDensity[dsh.Value.descriptors.Length];
@@ -272,7 +282,8 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, true, timeout, out duration); sense = dev.ReportDensitySupport(out buffer, out senseBuffer, true, true, timeout, out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh = Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer); Decoders.SCSI.SSC.DensitySupport.MediaTypeSupportHeader? mtsh =
Decoders.SCSI.SSC.DensitySupport.DecodeMediumType(buffer);
if(mtsh.HasValue) if(mtsh.HasValue)
{ {
seqTest.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length]; seqTest.SupportedMediaTypes = new SupportedMedia[mtsh.Value.descriptors.Length];
@@ -286,9 +297,11 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
seqTest.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width; seqTest.SupportedMediaTypes[i].Width = mtsh.Value.descriptors[i].width;
if(mtsh.Value.descriptors[i].densityCodes != null) if(mtsh.Value.descriptors[i].densityCodes != null)
{ {
seqTest.SupportedMediaTypes[i].DensityCodes = new int[mtsh.Value.descriptors[i].densityCodes.Length]; seqTest.SupportedMediaTypes[i].DensityCodes =
new int[mtsh.Value.descriptors[i].densityCodes.Length];
for(int j = 0; j < mtsh.Value.descriptors.Length; j++) for(int j = 0; j < mtsh.Value.descriptors.Length; j++)
seqTest.SupportedMediaTypes[i].DensityCodes[j] = mtsh.Value.descriptors[i].densityCodes[j]; seqTest.SupportedMediaTypes[i].DensityCodes[j] =
mtsh.Value.descriptors[i].densityCodes[j];
} }
} }
} }
@@ -296,11 +309,13 @@ namespace DiscImageChef.Core.Devices.Report.SCSI
seqTest.CanReadMediaSerialSpecified = true; seqTest.CanReadMediaSerialSpecified = true;
DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER..."); DicConsole.WriteLine("Trying SCSI READ MEDIA SERIAL NUMBER...");
seqTest.CanReadMediaSerial = !dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration); seqTest.CanReadMediaSerial =
!dev.ReadMediaSerialNumber(out buffer, out senseBuffer, timeout, out duration);
seqTests.Add(seqTest); seqTests.Add(seqTest);
} }
} }
report.SCSI.SequentialDevice.TestedMedia = seqTests.ToArray(); report.SCSI.SequentialDevice.TestedMedia = seqTests.ToArray();
} }
} }
} }

View File

@@ -40,13 +40,10 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC) report.MultiMediaCard = new mmcsdType();
report.MultiMediaCard = new mmcsdType(); else if(dev.Type == DeviceType.SecureDigital) report.SecureDigital = new mmcsdType();
else if(dev.Type == DeviceType.SecureDigital)
report.SecureDigital = new mmcsdType();
DicConsole.WriteLine("Trying to get CID..."); DicConsole.WriteLine("Trying to get CID...");
bool sense = dev.ReadCID(out byte[] cid, out uint[] response, dev.Timeout, out double duration); bool sense = dev.ReadCID(out byte[] cid, out uint[] response, dev.Timeout, out double duration);
@@ -77,8 +74,7 @@ namespace DiscImageChef.Core.Devices.Report
report.MultiMediaCard.CID = cid; report.MultiMediaCard.CID = cid;
} }
} }
else else DicConsole.WriteLine("Could not read CID...");
DicConsole.WriteLine("Could not read CID...");
DicConsole.WriteLine("Trying to get CSD..."); DicConsole.WriteLine("Trying to get CSD...");
sense = dev.ReadCSD(out byte[] csd, out response, dev.Timeout, out duration); sense = dev.ReadCSD(out byte[] csd, out response, dev.Timeout, out duration);
@@ -87,13 +83,10 @@ namespace DiscImageChef.Core.Devices.Report
{ {
DicConsole.WriteLine("CSD obtained correctly..."); DicConsole.WriteLine("CSD obtained correctly...");
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC) report.MultiMediaCard.CSD = csd;
report.MultiMediaCard.CSD = csd; else if(dev.Type == DeviceType.SecureDigital) report.SecureDigital.CSD = csd;
else if(dev.Type == DeviceType.SecureDigital)
report.SecureDigital.CSD = csd;
} }
else else DicConsole.WriteLine("Could not read CSD...");
DicConsole.WriteLine("Could not read CSD...");
if(dev.Type == DeviceType.MMC) if(dev.Type == DeviceType.MMC)
{ {
@@ -105,8 +98,7 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("OCR obtained correctly..."); DicConsole.WriteLine("OCR obtained correctly...");
report.MultiMediaCard.OCR = ocr; report.MultiMediaCard.OCR = ocr;
} }
else else DicConsole.WriteLine("Could not read OCR...");
DicConsole.WriteLine("Could not read OCR...");
DicConsole.WriteLine("Trying to get Extended CSD..."); DicConsole.WriteLine("Trying to get Extended CSD...");
sense = dev.ReadExtendedCSD(out byte[] ecsd, out response, dev.Timeout, out duration); sense = dev.ReadExtendedCSD(out byte[] ecsd, out response, dev.Timeout, out duration);
@@ -116,8 +108,7 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("Extended CSD obtained correctly..."); DicConsole.WriteLine("Extended CSD obtained correctly...");
report.MultiMediaCard.ExtendedCSD = ecsd; report.MultiMediaCard.ExtendedCSD = ecsd;
} }
else else DicConsole.WriteLine("Could not read Extended CSD...");
DicConsole.WriteLine("Could not read Extended CSD...");
} }
else if(dev.Type == DeviceType.SecureDigital) else if(dev.Type == DeviceType.SecureDigital)
{ {
@@ -129,8 +120,7 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("OCR obtained correctly..."); DicConsole.WriteLine("OCR obtained correctly...");
report.SecureDigital.OCR = ocr; report.SecureDigital.OCR = ocr;
} }
else else DicConsole.WriteLine("Could not read OCR...");
DicConsole.WriteLine("Could not read OCR...");
DicConsole.WriteLine("Trying to get SCR..."); DicConsole.WriteLine("Trying to get SCR...");
sense = dev.ReadSCR(out byte[] scr, out response, dev.Timeout, out duration); sense = dev.ReadSCR(out byte[] scr, out response, dev.Timeout, out duration);
@@ -140,10 +130,8 @@ namespace DiscImageChef.Core.Devices.Report
DicConsole.WriteLine("SCR obtained correctly..."); DicConsole.WriteLine("SCR obtained correctly...");
report.SecureDigital.SCR = scr; report.SecureDigital.SCR = scr;
} }
else else DicConsole.WriteLine("Could not read SCR...");
DicConsole.WriteLine("Could not read SCR...");
} }
} }
} }
} }

View File

@@ -41,8 +41,7 @@ namespace DiscImageChef.Core.Devices.Report
{ {
public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable) public static void Report(Device dev, ref DeviceReport report, bool debug, ref bool removable)
{ {
if(report == null) if(report == null) return;
return;
ConsoleKeyInfo pressedKey = new ConsoleKeyInfo(); ConsoleKeyInfo pressedKey = new ConsoleKeyInfo();
while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N) while(pressedKey.Key != ConsoleKey.Y && pressedKey.Key != ConsoleKey.N)
@@ -70,9 +69,8 @@ namespace DiscImageChef.Core.Devices.Report
report.USB.RemovableMedia = pressedKey.Key == ConsoleKey.Y; report.USB.RemovableMedia = pressedKey.Key == ConsoleKey.Y;
removable = report.USB.RemovableMedia; removable = report.USB.RemovableMedia;
if(debug) if(debug) report.USB.Descriptors = dev.USBDescriptors;
report.USB.Descriptors = dev.USBDescriptors;
} }
} }
} }
} }

View File

@@ -74,6 +74,7 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.ErrorWriteLine(ataReader.ErrorMessage); DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
return results; return results;
} }
uint blockSize = ataReader.LogicalBlockSize; uint blockSize = ataReader.LogicalBlockSize;
// Check how many blocks to read, if error show and return // Check how many blocks to read, if error show and return
if(ataReader.GetBlocksToRead(64)) if(ataReader.GetBlocksToRead(64))
@@ -81,6 +82,7 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.ErrorWriteLine(ataReader.ErrorMessage); DicConsole.ErrorWriteLine(ataReader.ErrorMessage);
return results; return results;
} }
uint blocksToRead = ataReader.BlocksToRead; uint blocksToRead = ataReader.BlocksToRead;
ushort cylinders = ataReader.Cylinders; ushort cylinders = ataReader.Cylinders;
byte heads = ataReader.Heads; byte heads = ataReader.Heads;
@@ -115,10 +117,7 @@ namespace DiscImageChef.Core.Devices.Scanning
byte seekSc = (byte)rnd.Next(sectors); byte seekSc = (byte)rnd.Next(sectors);
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
if(ataReader.IsLBA) if(ataReader.IsLBA)
{ {
@@ -130,49 +129,28 @@ namespace DiscImageChef.Core.Devices.Scanning
start = DateTime.UtcNow; start = DateTime.UtcNow;
for(ulong i = 0; i < results.blocks; i += blocksToRead) for(ulong i = 0; i < results.blocks; i += blocksToRead)
{ {
if(aborted) if(aborted) break;
break;
if((results.blocks - i) < blocksToRead) if((results.blocks - i) < blocksToRead) blocksToRead = (byte)(results.blocks - i);
blocksToRead = (byte)(results.blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.maxSpeed && currentSpeed != 0) if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
results.maxSpeed = currentSpeed; if(currentSpeed < results.minSpeed && currentSpeed != 0) results.minSpeed = currentSpeed;
if(currentSpeed < results.minSpeed && currentSpeed != 0)
results.minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks,
currentSpeed);
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration); bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration);
if(!error) if(!error)
{ {
if(duration >= 500) if(duration >= 500) { results.F += blocksToRead; }
{ else if(duration >= 150) { results.E += blocksToRead; }
results.F += blocksToRead; else if(duration >= 50) { results.D += blocksToRead; }
} else if(duration >= 10) { results.C += blocksToRead; }
else if(duration >= 150) else if(duration >= 3) { results.B += blocksToRead; }
{ else { results.A += blocksToRead; }
results.E += blocksToRead;
}
else if(duration >= 50)
{
results.D += blocksToRead;
}
else if(duration >= 10)
{
results.C += blocksToRead;
}
else if(duration >= 3)
{
results.B += blocksToRead;
}
else
{
results.A += blocksToRead;
}
mhddLog.Write(i, duration); mhddLog.Write(i, duration);
ibgLog.Write(i, currentSpeed * 1024); ibgLog.Write(i, currentSpeed * 1024);
@@ -180,12 +158,10 @@ namespace DiscImageChef.Core.Devices.Scanning
else else
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
results.unreadableSectors.Add(b);
if(duration < 500) if(duration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, duration);
else
mhddLog.Write(i, duration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
@@ -195,19 +171,21 @@ namespace DiscImageChef.Core.Devices.Scanning
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
GC.Collect(); GC.Collect();
} }
end = DateTime.UtcNow; end = DateTime.UtcNow;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath); ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
(results.processingTime / 1000), devicePath);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
if(ataReader.CanSeekLBA) if(ataReader.CanSeekLBA)
{ {
for(int i = 0; i < seekTimes; i++) for(int i = 0; i < seekTimes; i++)
{ {
if(aborted) if(aborted) break;
break;
seekPos = (uint)rnd.Next((int)results.blocks); seekPos = (uint)rnd.Next((int)results.blocks);
@@ -216,10 +194,8 @@ namespace DiscImageChef.Core.Devices.Scanning
ataReader.Seek(seekPos, out seekCur); ataReader.Seek(seekPos, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.seekMax && seekCur != 0) if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
results.seekMax = seekCur; if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
if(seekCur < results.seekMin && seekCur != 0)
results.seekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.seekTotal += seekCur; results.seekTotal += seekCur;
@@ -241,8 +217,7 @@ namespace DiscImageChef.Core.Devices.Scanning
{ {
for(byte Sc = 1; Sc < sectors; Sc++) for(byte Sc = 1; Sc < sectors; Sc++)
{ {
if(aborted) if(aborted) break;
break;
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.maxSpeed && currentSpeed != 0) if(currentSpeed > results.maxSpeed && currentSpeed != 0)
@@ -251,36 +226,19 @@ namespace DiscImageChef.Core.Devices.Scanning
results.minSpeed = currentSpeed; results.minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", Cy, Hd, Sc, currentSpeed); DicConsole.Write("\rReading cylinder {0} head {1} sector {2} ({3:F3} MiB/sec.)", Cy, Hd,
Sc, currentSpeed);
bool error = ataReader.ReadCHS(out cmdBuf, Cy, Hd, Sc, out duration); bool error = ataReader.ReadCHS(out cmdBuf, Cy, Hd, Sc, out duration);
if(!error) if(!error)
{ {
if(duration >= 500) if(duration >= 500) { results.F += blocksToRead; }
{ else if(duration >= 150) { results.E += blocksToRead; }
results.F += blocksToRead; else if(duration >= 50) { results.D += blocksToRead; }
} else if(duration >= 10) { results.C += blocksToRead; }
else if(duration >= 150) else if(duration >= 3) { results.B += blocksToRead; }
{ else { results.A += blocksToRead; }
results.E += blocksToRead;
}
else if(duration >= 50)
{
results.D += blocksToRead;
}
else if(duration >= 10)
{
results.C += blocksToRead;
}
else if(duration >= 3)
{
results.B += blocksToRead;
}
else
{
results.A += blocksToRead;
}
mhddLog.Write(currentBlock, duration); mhddLog.Write(currentBlock, duration);
ibgLog.Write(currentBlock, currentSpeed * 1024); ibgLog.Write(currentBlock, currentSpeed * 1024);
@@ -289,10 +247,8 @@ namespace DiscImageChef.Core.Devices.Scanning
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
results.unreadableSectors.Add(currentBlock); results.unreadableSectors.Add(currentBlock);
if(duration < 500) if(duration < 500) mhddLog.Write(currentBlock, 65535);
mhddLog.Write(currentBlock, 65535); else mhddLog.Write(currentBlock, duration);
else
mhddLog.Write(currentBlock, duration);
ibgLog.Write(currentBlock, 0); ibgLog.Write(currentBlock, 0);
} }
@@ -306,33 +262,34 @@ namespace DiscImageChef.Core.Devices.Scanning
} }
} }
} }
end = DateTime.UtcNow; end = DateTime.UtcNow;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath); ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
(results.processingTime / 1000), devicePath);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
if(ataReader.CanSeek) if(ataReader.CanSeek)
{ {
for(int i = 0; i < seekTimes; i++) for(int i = 0; i < seekTimes; i++)
{ {
if(aborted) if(aborted) break;
break;
seekCy = (ushort)rnd.Next(cylinders); seekCy = (ushort)rnd.Next(cylinders);
seekHd = (byte)rnd.Next(heads); seekHd = (byte)rnd.Next(heads);
seekSc = (byte)rnd.Next(sectors); seekSc = (byte)rnd.Next(sectors);
DicConsole.Write("\rSeeking to cylinder {0}, head {1}, sector {2}...\t\t", seekCy, seekHd, seekSc); DicConsole.Write("\rSeeking to cylinder {0}, head {1}, sector {2}...\t\t", seekCy, seekHd,
seekSc);
ataReader.SeekCHS(seekCy, seekHd, seekSc, out seekCur); ataReader.SeekCHS(seekCy, seekHd, seekSc, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.seekMax && seekCur != 0) if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
results.seekMax = seekCur; if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
if(seekCur < results.seekMin && seekCur != 0)
results.seekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.seekTotal += seekCur; results.seekTotal += seekCur;
@@ -346,7 +303,8 @@ namespace DiscImageChef.Core.Devices.Scanning
results.processingTime /= 1000; results.processingTime /= 1000;
results.totalTime = (end - start).TotalSeconds; results.totalTime = (end - start).TotalSeconds;
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
results.avgSpeed = (((double)blockSize * (double)(results.blocks + 1)) / 1048576) / results.processingTime; results.avgSpeed = (((double)blockSize * (double)(results.blocks + 1)) / 1048576) /
results.processingTime;
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
results.seekTimes = seekTimes; results.seekTimes = seekTimes;
@@ -357,4 +315,4 @@ namespace DiscImageChef.Core.Devices.Scanning
return results; return results;
} }
} }
} }

View File

@@ -42,4 +42,4 @@ namespace DiscImageChef.Core.Devices.Scanning
throw new NotImplementedException("NVMe devices not yet supported."); throw new NotImplementedException("NVMe devices not yet supported.");
} }
} }
} }

View File

@@ -70,8 +70,7 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
@@ -90,15 +89,15 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return results; return results;
} }
} }
@@ -111,21 +110,22 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.WriteLine("\rWaiting for drive to become ready"); DicConsole.WriteLine("\rWaiting for drive to become ready");
System.Threading.Thread.Sleep(2000); System.Threading.Thread.Sleep(2000);
sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out duration);
if(!sense) if(!sense) break;
break;
leftRetries--; leftRetries--;
} }
if(sense) if(sense)
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return results; return results;
} }
} }
else else
{ {
DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.ErrorWriteLine("Error testing unit was ready:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
return results; return results;
} }
} }
@@ -140,11 +140,11 @@ namespace DiscImageChef.Core.Devices.Scanning
Reader scsiReader = null; Reader scsiReader = null;
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.DirectAccess || if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.DirectAccess ||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice || dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice ||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice || dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OCRWDevice ||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice || dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.OpticalDevice ||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice || dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.SimplifiedDevice ||
dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice) dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.WriteOnceDevice)
{ {
scsiReader = new Reader(dev, dev.Timeout, null, false); scsiReader = new Reader(dev, dev.Timeout, null, false);
results.blocks = scsiReader.GetDeviceBlocks(); results.blocks = scsiReader.GetDeviceBlocks();
@@ -153,6 +153,7 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.ErrorWriteLine("Unable to read medium."); DicConsole.ErrorWriteLine("Unable to read medium.");
return results; return results;
} }
blockSize = scsiReader.LogicalBlockSize; blockSize = scsiReader.LogicalBlockSize;
if(results.blocks != 0 && blockSize != 0) if(results.blocks != 0 && blockSize != 0)
@@ -160,7 +161,7 @@ namespace DiscImageChef.Core.Devices.Scanning
results.blocks++; results.blocks++;
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)", DicConsole.WriteLine("Media has {0} blocks of {1} bytes/each. (for a total of {2} bytes)",
results.blocks, blockSize, results.blocks * (ulong)blockSize); results.blocks, blockSize, results.blocks * (ulong)blockSize);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
} }
} }
@@ -183,7 +184,8 @@ namespace DiscImageChef.Core.Devices.Scanning
if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice) if(dev.SCSIType == Decoders.SCSI.PeripheralDeviceTypes.MultiMediaDevice)
{ {
sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out duration); sense = dev.GetConfiguration(out cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout,
out duration);
if(!sense) if(!sense)
{ {
Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf); Decoders.SCSI.MMC.Features.SeparatedFeatures ftr = Decoders.SCSI.MMC.Features.Separate(cmdBuf);
@@ -198,8 +200,7 @@ namespace DiscImageChef.Core.Devices.Scanning
case 0x000A: case 0x000A:
case 0x0020: case 0x0020:
case 0x0021: case 0x0021:
case 0x0022: case 0x0022: break;
break;
default: default:
compactDisc = false; compactDisc = false;
break; break;
@@ -212,12 +213,10 @@ namespace DiscImageChef.Core.Devices.Scanning
// We discarded all discs that falsify a TOC before requesting a real TOC // We discarded all discs that falsify a TOC before requesting a real TOC
// No TOC, no CD (or an empty one) // No TOC, no CD (or an empty one)
bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration); bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out duration);
if(!tocSense) if(!tocSense) toc = Decoders.CD.FullTOC.Decode(cmdBuf);
toc = Decoders.CD.FullTOC.Decode(cmdBuf);
} }
} }
else else compactDisc = false;
compactDisc = false;
byte[] readBuffer; byte[] readBuffer;
uint blocksToRead = 64; uint blocksToRead = 64;
@@ -239,10 +238,7 @@ namespace DiscImageChef.Core.Devices.Scanning
results.unreadableSectors = new List<ulong>(); results.unreadableSectors = new List<ulong>();
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
bool readcd = false; bool readcd = false;
@@ -254,11 +250,11 @@ namespace DiscImageChef.Core.Devices.Scanning
return results; return results;
} }
readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, readcd = !dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, 1, MmcSectorTypes.AllTypes, false, false,
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration); true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None,
MmcSubchannel.None, dev.Timeout, out duration);
if(readcd) if(readcd) DicConsole.WriteLine("Using MMC READ CD command.");
DicConsole.WriteLine("Using MMC READ CD command.");
start = DateTime.UtcNow; start = DateTime.UtcNow;
@@ -266,14 +262,13 @@ namespace DiscImageChef.Core.Devices.Scanning
{ {
if(readcd) if(readcd)
{ {
sense = dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, sense = dev.ReadCd(out readBuffer, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes,
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration); false, false, true, MmcHeaderCodes.AllHeaders, true, true,
if(dev.Error) MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out duration);
blocksToRead /= 2; if(dev.Error) blocksToRead /= 2;
} }
if(!dev.Error || blocksToRead == 1) if(!dev.Error || blocksToRead == 1) break;
break;
} }
if(dev.Error) if(dev.Error)
@@ -289,63 +284,43 @@ namespace DiscImageChef.Core.Devices.Scanning
for(ulong i = 0; i < results.blocks; i += blocksToRead) for(ulong i = 0; i < results.blocks; i += blocksToRead)
{ {
if(aborted) if(aborted) break;
break;
double cmdDuration = 0; double cmdDuration = 0;
if((results.blocks - i) < blocksToRead) if((results.blocks - i) < blocksToRead) blocksToRead = (uint)(results.blocks - i);
blocksToRead = (uint)(results.blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.maxSpeed && currentSpeed != 0) if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
results.maxSpeed = currentSpeed; if(currentSpeed < results.minSpeed && currentSpeed != 0) results.minSpeed = currentSpeed;
if(currentSpeed < results.minSpeed && currentSpeed != 0)
results.minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed);
if(readcd) if(readcd)
{ {
sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, sense = dev.ReadCd(out readBuffer, out senseBuf, (uint)i, 2352, blocksToRead,
true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration); MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true,
true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration);
results.processingTime += cmdDuration; results.processingTime += cmdDuration;
} }
if(!sense) if(!sense)
{ {
if(cmdDuration >= 500) if(cmdDuration >= 500) { results.F += blocksToRead; }
{ else if(cmdDuration >= 150) { results.E += blocksToRead; }
results.F += blocksToRead; else if(cmdDuration >= 50) { results.D += blocksToRead; }
} else if(cmdDuration >= 10) { results.C += blocksToRead; }
else if(cmdDuration >= 150) else if(cmdDuration >= 3) { results.B += blocksToRead; }
{ else { results.A += blocksToRead; }
results.E += blocksToRead;
}
else if(cmdDuration >= 50)
{
results.D += blocksToRead;
}
else if(cmdDuration >= 10)
{
results.C += blocksToRead;
}
else if(cmdDuration >= 3)
{
results.B += blocksToRead;
}
else
{
results.A += blocksToRead;
}
mhddLog.Write(i, cmdDuration); mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, currentSpeed * 1024); ibgLog.Write(i, currentSpeed * 1024);
} }
else else
{ {
DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Decoders.SCSI.Sense.PrettifySense(senseBuf)); DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}",
Decoders.SCSI.Sense.PrettifySense(senseBuf));
Decoders.SCSI.FixedSense? senseDecoded = Decoders.SCSI.Sense.DecodeFixed(senseBuf); Decoders.SCSI.FixedSense? senseDecoded = Decoders.SCSI.Sense.DecodeFixed(senseBuf);
if(senseDecoded.HasValue) if(senseDecoded.HasValue)
@@ -353,17 +328,15 @@ namespace DiscImageChef.Core.Devices.Scanning
// TODO: This error happens when changing from track type afaik. Need to solve that more cleanly // TODO: This error happens when changing from track type afaik. Need to solve that more cleanly
// LOGICAL BLOCK ADDRESS OUT OF RANGE // LOGICAL BLOCK ADDRESS OUT OF RANGE
if((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) && if((senseDecoded.Value.ASC != 0x21 || senseDecoded.Value.ASCQ != 0x00) &&
// ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors // ILLEGAL MODE FOR THIS TRACK (requesting sectors as-is, this is a firmware misconception when audio sectors
// are in a track where subchannel indicates data) // are in a track where subchannel indicates data)
(senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00)) (senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00))
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
results.unreadableSectors.Add(b);
if(cmdDuration < 500) if(cmdDuration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, cmdDuration);
else
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
@@ -371,12 +344,10 @@ namespace DiscImageChef.Core.Devices.Scanning
else else
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
results.unreadableSectors.Add(b);
if(cmdDuration < 500) if(cmdDuration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, cmdDuration);
else
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
@@ -387,11 +358,14 @@ namespace DiscImageChef.Core.Devices.Scanning
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
GC.Collect(); GC.Collect();
} }
end = DateTime.UtcNow; end = DateTime.UtcNow;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath); ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
(results.processingTime / 1000), devicePath);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
} }
else else
@@ -405,19 +379,15 @@ namespace DiscImageChef.Core.Devices.Scanning
for(ulong i = 0; i < results.blocks; i += blocksToRead) for(ulong i = 0; i < results.blocks; i += blocksToRead)
{ {
if(aborted) if(aborted) break;
break;
double cmdDuration = 0; double cmdDuration = 0;
if((results.blocks - i) < blocksToRead) if((results.blocks - i) < blocksToRead) blocksToRead = (uint)(results.blocks - i);
blocksToRead = (uint)(results.blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.maxSpeed && currentSpeed != 0) if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
results.maxSpeed = currentSpeed; if(currentSpeed < results.minSpeed && currentSpeed != 0) results.minSpeed = currentSpeed;
if(currentSpeed < results.minSpeed && currentSpeed != 0)
results.minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed);
@@ -427,18 +397,12 @@ namespace DiscImageChef.Core.Devices.Scanning
if(!sense && !dev.Error) if(!sense && !dev.Error)
{ {
if(cmdDuration >= 500) if(cmdDuration >= 500) results.F += blocksToRead;
results.F += blocksToRead; else if(cmdDuration >= 150) results.E += blocksToRead;
else if(cmdDuration >= 150) else if(cmdDuration >= 50) results.D += blocksToRead;
results.E += blocksToRead; else if(cmdDuration >= 10) results.C += blocksToRead;
else if(cmdDuration >= 50) else if(cmdDuration >= 3) results.B += blocksToRead;
results.D += blocksToRead; else results.A += blocksToRead;
else if(cmdDuration >= 10)
results.C += blocksToRead;
else if(cmdDuration >= 3)
results.B += blocksToRead;
else
results.A += blocksToRead;
mhddLog.Write(i, cmdDuration); mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, currentSpeed * 1024); ibgLog.Write(i, currentSpeed * 1024);
@@ -447,12 +411,10 @@ namespace DiscImageChef.Core.Devices.Scanning
else else
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
results.unreadableSectors.Add(b);
if(cmdDuration < 500) if(cmdDuration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, cmdDuration);
else
mhddLog.Write(i, cmdDuration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
@@ -465,7 +427,9 @@ namespace DiscImageChef.Core.Devices.Scanning
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath); ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(results.blocks + 1)) / 1024) /
(results.processingTime / 1000), devicePath);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
} }
@@ -482,23 +446,18 @@ namespace DiscImageChef.Core.Devices.Scanning
for(int i = 0; i < seekTimes; i++) for(int i = 0; i < seekTimes; i++)
{ {
if(aborted) if(aborted) break;
break;
seekPos = (uint)rnd.Next((int)results.blocks); seekPos = (uint)rnd.Next((int)results.blocks);
DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos); DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos);
if(scsiReader.CanSeek) if(scsiReader.CanSeek) scsiReader.Seek(seekPos, out seekCur);
scsiReader.Seek(seekPos, out seekCur); else scsiReader.ReadBlock(out readBuffer, seekPos, out seekCur);
else
scsiReader.ReadBlock(out readBuffer, seekPos, out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.seekMax && seekCur != 0) if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
results.seekMax = seekCur; if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
if(seekCur < results.seekMin && seekCur != 0)
results.seekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.seekTotal += seekCur; results.seekTotal += seekCur;
@@ -517,4 +476,4 @@ namespace DiscImageChef.Core.Devices.Scanning
return results; return results;
} }
} }
} }

View File

@@ -55,4 +55,4 @@ namespace DiscImageChef.Core.Devices.Scanning
public ulong blocks; public ulong blocks;
public ulong errored; public ulong errored;
} }
} }

View File

@@ -93,7 +93,9 @@ namespace DiscImageChef.Core.Devices.Scanning
if(!sense) if(!sense)
{ {
csd = Decoders.SecureDigital.Decoders.DecodeCSD(cmdBuf); csd = Decoders.SecureDigital.Decoders.DecodeCSD(cmdBuf);
results.blocks = (ulong)(csd.Structure == 0 ? (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) : (csd.Size + 1) * 1024); results.blocks = (ulong)(csd.Structure == 0
? (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2)
: (csd.Size + 1) * 1024);
blockSize = (uint)Math.Pow(2, csd.ReadBlockLength); blockSize = (uint)Math.Pow(2, csd.ReadBlockLength);
// Structure >=1 for SDHC/SDXC, so that's block addressed // Structure >=1 for SDHC/SDXC, so that's block addressed
byteAddressed = csd.Structure == 0; byteAddressed = csd.Structure == 0;
@@ -110,13 +112,12 @@ namespace DiscImageChef.Core.Devices.Scanning
while(true) while(true)
{ {
sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout, out duration); sense = dev.Read(out cmdBuf, out response, 0, blockSize, blocksToRead, byteAddressed, timeout,
out duration);
if(sense) if(sense) blocksToRead /= 2;
blocksToRead /= 2;
if(!sense || blocksToRead == 1) if(!sense || blocksToRead == 1) break;
break;
} }
if(sense) if(sense)
@@ -152,10 +153,7 @@ namespace DiscImageChef.Core.Devices.Scanning
uint seekPos = (uint)rnd.Next((int)results.blocks); uint seekPos = (uint)rnd.Next((int)results.blocks);
aborted = false; aborted = false;
System.Console.CancelKeyPress += (sender, e) => System.Console.CancelKeyPress += (sender, e) => { e.Cancel = aborted = true; };
{
e.Cancel = aborted = true;
};
DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead); DicConsole.WriteLine("Reading {0} sectors at a time.", blocksToRead);
@@ -165,49 +163,28 @@ namespace DiscImageChef.Core.Devices.Scanning
start = DateTime.UtcNow; start = DateTime.UtcNow;
for(ulong i = 0; i < results.blocks; i += blocksToRead) for(ulong i = 0; i < results.blocks; i += blocksToRead)
{ {
if(aborted) if(aborted) break;
break;
if((results.blocks - i) < blocksToRead) if((results.blocks - i) < blocksToRead) blocksToRead = (byte)(results.blocks - i);
blocksToRead = (byte)(results.blocks - i);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(currentSpeed > results.maxSpeed && currentSpeed != 0) if(currentSpeed > results.maxSpeed && currentSpeed != 0) results.maxSpeed = currentSpeed;
results.maxSpeed = currentSpeed; if(currentSpeed < results.minSpeed && currentSpeed != 0) results.minSpeed = currentSpeed;
if(currentSpeed < results.minSpeed && currentSpeed != 0)
results.minSpeed = currentSpeed;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed); DicConsole.Write("\rReading sector {0} of {1} ({2:F3} MiB/sec.)", i, results.blocks, currentSpeed);
bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed, timeout, out duration); bool error = dev.Read(out cmdBuf, out response, (uint)i, blockSize, blocksToRead, byteAddressed,
timeout, out duration);
if(!error) if(!error)
{ {
if(duration >= 500) if(duration >= 500) { results.F += blocksToRead; }
{ else if(duration >= 150) { results.E += blocksToRead; }
results.F += blocksToRead; else if(duration >= 50) { results.D += blocksToRead; }
} else if(duration >= 10) { results.C += blocksToRead; }
else if(duration >= 150) else if(duration >= 3) { results.B += blocksToRead; }
{ else { results.A += blocksToRead; }
results.E += blocksToRead;
}
else if(duration >= 50)
{
results.D += blocksToRead;
}
else if(duration >= 10)
{
results.C += blocksToRead;
}
else if(duration >= 3)
{
results.B += blocksToRead;
}
else
{
results.A += blocksToRead;
}
mhddLog.Write(i, duration); mhddLog.Write(i, duration);
ibgLog.Write(i, currentSpeed * 1024); ibgLog.Write(i, currentSpeed * 1024);
@@ -215,12 +192,10 @@ namespace DiscImageChef.Core.Devices.Scanning
else else
{ {
results.errored += blocksToRead; results.errored += blocksToRead;
for(ulong b = i; b < i + blocksToRead; b++) for(ulong b = i; b < i + blocksToRead; b++) results.unreadableSectors.Add(b);
results.unreadableSectors.Add(b);
if(duration < 500) if(duration < 500) mhddLog.Write(i, 65535);
mhddLog.Write(i, 65535); else mhddLog.Write(i, duration);
else
mhddLog.Write(i, duration);
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
@@ -230,29 +205,30 @@ namespace DiscImageChef.Core.Devices.Scanning
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
GC.Collect(); GC.Collect();
} }
end = DateTime.UtcNow; end = DateTime.UtcNow;
DicConsole.WriteLine(); DicConsole.WriteLine();
mhddLog.Close(); mhddLog.Close();
#pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values #pragma warning disable IDE0004 // Without this specific cast, it gives incorrect values
ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, (((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000), devicePath); ibgLog.Close(dev, results.blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024,
(((double)blockSize * (double)(results.blocks + 1)) / 1024) / (results.processingTime / 1000),
devicePath);
#pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values #pragma warning restore IDE0004 // Without this specific cast, it gives incorrect values
for(int i = 0; i < seekTimes; i++) for(int i = 0; i < seekTimes; i++)
{ {
if(aborted) if(aborted) break;
break;
seekPos = (uint)rnd.Next((int)results.blocks); seekPos = (uint)rnd.Next((int)results.blocks);
DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos); DicConsole.Write("\rSeeking to sector {0}...\t\t", seekPos);
dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, byteAddressed, timeout, out seekCur); dev.Read(out cmdBuf, out response, (uint)seekPos, blockSize, blocksToRead, byteAddressed, timeout,
out seekCur);
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
if(seekCur > results.seekMax && seekCur != 0) if(seekCur > results.seekMax && seekCur != 0) results.seekMax = seekCur;
results.seekMax = seekCur; if(seekCur < results.seekMin && seekCur != 0) results.seekMin = seekCur;
if(seekCur < results.seekMin && seekCur != 0)
results.seekMin = seekCur;
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator
results.seekTotal += seekCur; results.seekTotal += seekCur;
@@ -271,4 +247,4 @@ namespace DiscImageChef.Core.Devices.Scanning
return results; return results;
} }
} }
} }

View File

@@ -47,9 +47,8 @@ namespace DiscImageChef.Core
foreach(Filesystem _plugin in plugins.PluginsList.Values) foreach(Filesystem _plugin in plugins.PluginsList.Values)
{ {
if(_plugin.Identify(imagePlugin, partition)) if(_plugin.Identify(imagePlugin, partition)) id_plugins.Add(_plugin.Name.ToLower());
id_plugins.Add(_plugin.Name.ToLower());
} }
} }
} }
} }

View File

@@ -64,10 +64,8 @@ namespace DiscImageChef.Core
} }
} }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch catch { }
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
}
} }
} }
@@ -88,27 +86,18 @@ namespace DiscImageChef.Core
} }
} }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch catch { }
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
}
} }
} }
} }
// Still not recognized // Still not recognized
if(_imageFormat == null) if(_imageFormat == null) { return null; }
{
return null;
}
return _imageFormat; return _imageFormat;
} }
catch catch { return null; }
{
return null;
}
} }
} }
} }

View File

@@ -54,21 +54,22 @@ namespace DiscImageChef.Core.Logging
Type monoRunType = Type.GetType("Mono.Runtime"); Type monoRunType = Type.GetType("Mono.Runtime");
logSw.WriteLine("################# System information #################"); logSw.WriteLine("################# System information #################");
logSw.WriteLine("{0} {1} ({2}-bit)", Interop.DetectOS.GetPlatformName(platId, platVer), platVer, Environment.Is64BitOperatingSystem ? 64 : 32); logSw.WriteLine("{0} {1} ({2}-bit)", Interop.DetectOS.GetPlatformName(platId, platVer), platVer,
Environment.Is64BitOperatingSystem ? 64 : 32);
if(monoRunType != null) if(monoRunType != null)
{ {
string monoVer = "unknown version"; string monoVer = "unknown version";
MethodInfo monoDisplayName = monoRunType.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); MethodInfo monoDisplayName =
if(monoDisplayName != null) monoRunType.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
monoVer = (string)monoDisplayName.Invoke(null, null); if(monoDisplayName != null) monoVer = (string)monoDisplayName.Invoke(null, null);
logSw.WriteLine("Mono {0}", monoVer); logSw.WriteLine("Mono {0}", monoVer);
} }
else else logSw.WriteLine(".NET Framework {0}", Environment.Version);
logSw.WriteLine(".NET Framework {0}", Environment.Version);
logSw.WriteLine(); logSw.WriteLine();
logSw.WriteLine("################# Program information ################"); logSw.WriteLine("################# Program information ################");
logSw.WriteLine("DiscImageChef {0} running in {1}-bit", Version.GetVersion(), Environment.Is64BitProcess ? 64 : 32); logSw.WriteLine("DiscImageChef {0} running in {1}-bit", Version.GetVersion(),
Environment.Is64BitProcess ? 64 : 32);
#if DEBUG #if DEBUG
logSw.WriteLine("DEBUG version"); logSw.WriteLine("DEBUG version");
#endif #endif
@@ -131,4 +132,4 @@ namespace DiscImageChef.Core.Logging
} }
} }
} }
} }

View File

@@ -209,9 +209,9 @@ namespace DiscImageChef.Core.Logging
ibgStartSet = true; ibgStartSet = true;
} }
ibgSb.AppendFormat("{0:0.00},{1},{2:0},0", ibgIntSpeed / ibgSnaps / ibgDivider, ibgIntSector, ibgSampleRate).AppendLine(); ibgSb.AppendFormat("{0:0.00},{1},{2:0},0", ibgIntSpeed / ibgSnaps / ibgDivider, ibgIntSector,
if((ibgIntSpeed / ibgSnaps / ibgDivider) > ibgMaxSpeed) ibgSampleRate).AppendLine();
ibgMaxSpeed = ibgIntSpeed / ibgDivider; if((ibgIntSpeed / ibgSnaps / ibgDivider) > ibgMaxSpeed) ibgMaxSpeed = ibgIntSpeed / ibgDivider;
ibgDatePoint = DateTime.Now; ibgDatePoint = DateTime.Now;
ibgIntSpeed = 0; ibgIntSpeed = 0;
@@ -222,19 +222,17 @@ namespace DiscImageChef.Core.Logging
} }
} }
public void Close(Device dev, ulong blocks, ulong blockSize, double totalSeconds, double currentSpeed, double averageSpeed, string devicePath) public void Close(Device dev, ulong blocks, ulong blockSize, double totalSeconds, double currentSpeed,
double averageSpeed, string devicePath)
{ {
if(ibgFs != null) if(ibgFs != null)
{ {
StringBuilder ibgHeader = new StringBuilder(); StringBuilder ibgHeader = new StringBuilder();
string ibgBusType; string ibgBusType;
if(dev.IsUSB) if(dev.IsUSB) ibgBusType = "USB";
ibgBusType = "USB"; else if(dev.IsFireWire) ibgBusType = "FireWire";
else if(dev.IsFireWire) else ibgBusType = dev.Type.ToString();
ibgBusType = "FireWire";
else
ibgBusType = dev.Type.ToString();
ibgHeader.AppendLine("IBGD"); ibgHeader.AppendLine("IBGD");
ibgHeader.AppendLine(); ibgHeader.AppendLine();
@@ -246,8 +244,8 @@ namespace DiscImageChef.Core.Logging
ibgHeader.AppendFormat("SAMPLE_RATE={0}", 100).AppendLine(); ibgHeader.AppendFormat("SAMPLE_RATE={0}", 100).AppendLine();
ibgHeader.AppendLine(); ibgHeader.AppendLine();
ibgHeader.AppendFormat("DEVICE=[0:0:0] {0} {1} ({2}) ({3})", ibgHeader.AppendFormat("DEVICE=[0:0:0] {0} {1} ({2}) ({3})", dev.Manufacturer, dev.Model, devicePath,
dev.Manufacturer, dev.Model, devicePath, ibgBusType).AppendLine(); ibgBusType).AppendLine();
ibgHeader.AppendLine("DEVICE_ADDRESS=0:0:0"); ibgHeader.AppendLine("DEVICE_ADDRESS=0:0:0");
ibgHeader.AppendFormat("DEVICE_MAKEMODEL={0} {1}", dev.Manufacturer, dev.Model).AppendLine(); ibgHeader.AppendFormat("DEVICE_MAKEMODEL={0} {1}", dev.Manufacturer, dev.Model).AppendLine();
ibgHeader.AppendFormat("DEVICE_FIRMWAREVERSION={0}", dev.Revision).AppendLine(); ibgHeader.AppendFormat("DEVICE_FIRMWAREVERSION={0}", dev.Revision).AppendLine();
@@ -270,7 +268,8 @@ namespace DiscImageChef.Core.Logging
ibgHeader.AppendLine(); ibgHeader.AppendLine();
ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_START={0:0.00}", ibgStartSpeed).AppendLine(); ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_START={0:0.00}", ibgStartSpeed).AppendLine();
ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_END={0:0.00}", currentSpeed / ibgDivider).AppendLine(); ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_END={0:0.00}", currentSpeed / ibgDivider).AppendLine();
ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_AVERAGE={0:0.00}", averageSpeed / ibgDivider).AppendLine(); ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_AVERAGE={0:0.00}", averageSpeed / ibgDivider)
.AppendLine();
ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_MAX={0:0.00}", ibgMaxSpeed).AppendLine(); ibgHeader.AppendFormat(ibgCulture, "VERIFY_SPEED_MAX={0:0.00}", ibgMaxSpeed).AppendLine();
ibgHeader.AppendFormat(ibgCulture, "VERIFY_TIME_TAKEN={0:0}", Math.Floor(totalSeconds)).AppendLine(); ibgHeader.AppendFormat(ibgCulture, "VERIFY_TIME_TAKEN={0:0}", Math.Floor(totalSeconds)).AppendLine();
ibgHeader.AppendLine("[END_CONFIGURATION]"); ibgHeader.AppendLine("[END_CONFIGURATION]");
@@ -290,6 +289,4 @@ namespace DiscImageChef.Core.Logging
} }
} }
} }
} }

View File

@@ -83,8 +83,10 @@ namespace DiscImageChef.Core.Logging
fw = string.Format("F/W: {0}", dev.Revision); fw = string.Format("F/W: {0}", dev.Revision);
sn = string.Format("S/N: {0}", dev.Serial); sn = string.Format("S/N: {0}", dev.Serial);
sectors = string.Format(new System.Globalization.CultureInfo("en-US"), "SECTORS: {0:n0}", blocks); sectors = string.Format(new System.Globalization.CultureInfo("en-US"), "SECTORS: {0:n0}", blocks);
sectorsize = string.Format(new System.Globalization.CultureInfo("en-US"), "SECTOR SIZE: {0:n0} bytes", blockSize); sectorsize = string.Format(new System.Globalization.CultureInfo("en-US"), "SECTOR SIZE: {0:n0} bytes",
scanblocksize = string.Format(new System.Globalization.CultureInfo("en-US"), "SCAN BLOCK SIZE: {0:n0} sectors", blocksToRead); blockSize);
scanblocksize = string.Format(new System.Globalization.CultureInfo("en-US"),
"SCAN BLOCK SIZE: {0:n0} sectors", blocksToRead);
ver = "VER:2 "; ver = "VER:2 ";
byte[] deviceBytes = Encoding.ASCII.GetBytes(device); byte[] deviceBytes = Encoding.ASCII.GetBytes(device);
@@ -96,11 +98,10 @@ namespace DiscImageChef.Core.Logging
byte[] scanblocksizeBytes = Encoding.ASCII.GetBytes(scanblocksize); byte[] scanblocksizeBytes = Encoding.ASCII.GetBytes(scanblocksize);
byte[] verBytes = Encoding.ASCII.GetBytes(ver); byte[] verBytes = Encoding.ASCII.GetBytes(ver);
uint Pointer = (uint)(deviceBytes.Length + modeBytes.Length + fwBytes.Length + uint Pointer = (uint)(deviceBytes.Length + modeBytes.Length + fwBytes.Length + snBytes.Length +
snBytes.Length + sectorsBytes.Length + sectorsizeBytes.Length + sectorsBytes.Length + sectorsizeBytes.Length + scanblocksizeBytes.Length +
scanblocksizeBytes.Length + verBytes.Length + verBytes.Length + 2 * 9 + // New lines
2 * 9 + // New lines 4); // Pointer
4); // Pointer
byte[] newLine = new byte[2]; byte[] newLine = new byte[2];
newLine[0] = 0x0D; newLine[0] = 0x0D;
@@ -141,10 +142,7 @@ namespace DiscImageChef.Core.Logging
public void Close() public void Close()
{ {
if(mhddFs != null) if(mhddFs != null) mhddFs.Close();
mhddFs.Close();
} }
} }
} }

View File

@@ -59,9 +59,11 @@ namespace DiscImageChef.Core
if(_partplugin.GetInformation(image, out List<Partition> _partitions, imagePartition.Start)) if(_partplugin.GetInformation(image, out List<Partition> _partitions, imagePartition.Start))
{ {
partitions.AddRange(_partitions); partitions.AddRange(_partitions);
DicConsole.DebugWriteLine("Partitions", "Found {0} @ {1}", _partplugin.Name, imagePartition.Start); DicConsole.DebugWriteLine("Partitions", "Found {0} @ {1}", _partplugin.Name,
imagePartition.Start);
} }
} }
checkedLocations.Add(imagePartition.Start); checkedLocations.Add(imagePartition.Start);
} }
} }
@@ -96,7 +98,8 @@ namespace DiscImageChef.Core
DicConsole.DebugWriteLine("Partitions", "Trying {0} @ {1}", _partplugin.Name, partitions[0].Start); DicConsole.DebugWriteLine("Partitions", "Trying {0} @ {1}", _partplugin.Name, partitions[0].Start);
if(_partplugin.GetInformation(image, out List<Partition> _partitions, partitions[0].Start)) if(_partplugin.GetInformation(image, out List<Partition> _partitions, partitions[0].Start))
{ {
DicConsole.DebugWriteLine("Partitions", "Found {0} @ {1}", _partplugin.Name, partitions[0].Start); DicConsole.DebugWriteLine("Partitions", "Found {0} @ {1}", _partplugin.Name,
partitions[0].Start);
childs.AddRange(_partitions); childs.AddRange(_partitions);
} }
} }
@@ -111,10 +114,8 @@ namespace DiscImageChef.Core
foreach(Partition child in childs) foreach(Partition child in childs)
{ {
if(checkedLocations.Contains(child.Start)) if(checkedLocations.Contains(child.Start)) childPartitions.Add(child);
childPartitions.Add(child); else partitions.Add(child);
else
partitions.Add(child);
} }
} }
else else
@@ -132,39 +133,31 @@ namespace DiscImageChef.Core
{ {
List<ulong> startLocations = new List<ulong>(); List<ulong> startLocations = new List<ulong>();
foreach(Partition detectedPartition in childPartitions) foreach(Partition detectedPartition in childPartitions) startLocations.Add(detectedPartition.Start);
startLocations.Add(detectedPartition.Start);
foreach(Partition imagePartition in image.GetPartitions()) foreach(Partition imagePartition in image.GetPartitions())
{ {
if(!startLocations.Contains(imagePartition.Start)) if(!startLocations.Contains(imagePartition.Start)) childPartitions.Add(imagePartition);
childPartitions.Add(imagePartition);
} }
} }
Partition[] childArray = childPartitions.OrderBy(part => part.Start).ThenBy(part => part.Length).ThenBy(part => part.Scheme).ToArray(); Partition[] childArray = childPartitions
.OrderBy(part => part.Start).ThenBy(part => part.Length).ThenBy(part => part.Scheme).ToArray();
for(long i = 0; i < childArray.LongLength; i++) for(long i = 0; i < childArray.LongLength; i++) childArray[i].Sequence = (ulong)i;
childArray[i].Sequence = (ulong)i;
return childArray.ToList(); return childArray.ToList();
} }
public static void AddSchemesToStats(List<Partition> partitions) public static void AddSchemesToStats(List<Partition> partitions)
{ {
if(partitions == null || partitions.Count == 0) if(partitions == null || partitions.Count == 0) return;
return;
List<string> schemes = new List<string>(); List<string> schemes = new List<string>();
foreach(Partition part in partitions) foreach(Partition part in partitions) { if(!schemes.Contains(part.Scheme)) schemes.Add(part.Scheme); }
{
if(!schemes.Contains(part.Scheme))
schemes.Add(part.Scheme);
}
foreach(string scheme in schemes) foreach(string scheme in schemes) Statistics.AddPartition(scheme);
Statistics.AddPartition(scheme);
} }
} }
} }

View File

@@ -70,10 +70,7 @@ namespace DiscImageChef.Core
RegisterImagePlugin(plugin); RegisterImagePlugin(plugin);
} }
} }
catch(Exception exception) catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); }
{
DicConsole.ErrorWriteLine("Exception {0}", exception);
}
} }
assembly = Assembly.GetAssembly(typeof(PartPlugin)); assembly = Assembly.GetAssembly(typeof(PartPlugin));
@@ -88,10 +85,7 @@ namespace DiscImageChef.Core
RegisterPartPlugin(plugin); RegisterPartPlugin(plugin);
} }
} }
catch(Exception exception) catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); }
{
DicConsole.ErrorWriteLine("Exception {0}", exception);
}
} }
assembly = Assembly.GetAssembly(typeof(Filesystem)); assembly = Assembly.GetAssembly(typeof(Filesystem));
@@ -104,16 +98,13 @@ namespace DiscImageChef.Core
{ {
Filesystem plugin; Filesystem plugin;
if(encoding != null) if(encoding != null)
plugin = (Filesystem)type.GetConstructor(new Type[] { encoding.GetType() }).Invoke(new object[] { encoding }); plugin = (Filesystem)type.GetConstructor(new Type[] {encoding.GetType()})
else .Invoke(new object[] {encoding});
plugin = (Filesystem)type.GetConstructor(Type.EmptyTypes).Invoke(new object[] { }); else plugin = (Filesystem)type.GetConstructor(Type.EmptyTypes).Invoke(new object[] { });
RegisterPlugin(plugin); RegisterPlugin(plugin);
} }
} }
catch(Exception exception) catch(Exception exception) { DicConsole.ErrorWriteLine("Exception {0}", exception); }
{
DicConsole.ErrorWriteLine("Exception {0}", exception);
}
} }
} }
@@ -127,10 +118,7 @@ namespace DiscImageChef.Core
void RegisterPlugin(Filesystem plugin) void RegisterPlugin(Filesystem plugin)
{ {
if(!PluginsList.ContainsKey(plugin.Name.ToLower())) if(!PluginsList.ContainsKey(plugin.Name.ToLower())) { PluginsList.Add(plugin.Name.ToLower(), plugin); }
{
PluginsList.Add(plugin.Name.ToLower(), plugin);
}
} }
void RegisterPartPlugin(PartPlugin partplugin) void RegisterPartPlugin(PartPlugin partplugin)
@@ -141,5 +129,4 @@ namespace DiscImageChef.Core
} }
} }
} }
} }

View File

@@ -54,4 +54,4 @@ using System.Reflection;
// if desired. See the Mono documentation for more information about signing. // if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")] //[assembly: AssemblyKeyFile("")]

View File

@@ -51,11 +51,13 @@ namespace DiscImageChef.Core
#endif #endif
MemoryStream xmlStream = new MemoryStream(); MemoryStream xmlStream = new MemoryStream();
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(Metadata.DeviceReport)); System.Xml.Serialization.XmlSerializer xmlSer =
new System.Xml.Serialization.XmlSerializer(typeof(Metadata.DeviceReport));
xmlSer.Serialize(xmlStream, report); xmlSer.Serialize(xmlStream, report);
xmlStream.Seek(0, SeekOrigin.Begin); xmlStream.Seek(0, SeekOrigin.Begin);
WebRequest request = WebRequest.Create("http://discimagechef.claunia.com/api/uploadreport"); WebRequest request = WebRequest.Create("http://discimagechef.claunia.com/api/uploadreport");
((HttpWebRequest)request).UserAgent = string.Format("DiscImageChef {0}", typeof(Version).Assembly.GetName().Version); ((HttpWebRequest)request).UserAgent =
string.Format("DiscImageChef {0}", typeof(Version).Assembly.GetName().Version);
request.Method = "POST"; request.Method = "POST";
request.ContentLength = xmlStream.Length; request.ContentLength = xmlStream.Length;
request.ContentType = "application/xml"; request.ContentType = "application/xml";
@@ -64,8 +66,7 @@ namespace DiscImageChef.Core
reqStream.Close(); reqStream.Close();
WebResponse response = request.GetResponse(); WebResponse response = request.GetResponse();
if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) return;
return;
Stream data = response.GetResponseStream(); Stream data = response.GetResponseStream();
StreamReader reader = new StreamReader(data); StreamReader reader = new StreamReader(data);
@@ -90,4 +91,4 @@ namespace DiscImageChef.Core
submitThread.Start(); submitThread.Start();
} }
} }
} }

View File

@@ -40,25 +40,23 @@ namespace DiscImageChef.Core
public static partial class Sidecar public static partial class Sidecar
{ {
// TODO: Complete it // TODO: Complete it
static void AudioMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar) static void AudioMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi,
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
{ {
sidecar.AudioMedia = new [] sidecar.AudioMedia = new[]
{ {
new AudioMediaType new AudioMediaType
{ {
Checksums = imgChecksums.ToArray(), Checksums = imgChecksums.ToArray(),
Image = new ImageType Image = new ImageType
{ {
format = image.GetImageFormat(), format = image.GetImageFormat(),
offset = 0, offset = 0,
offsetSpecified = true, offsetSpecified = true,
Value = Path.GetFileName(imagePath) Value = Path.GetFileName(imagePath)
}, },
Size = fi.Length, Size = fi.Length,
Sequence = new SequenceType Sequence = new SequenceType {MediaTitle = image.GetImageName()}
{
MediaTitle = image.GetImageName()
}
} }
}; };
@@ -74,4 +72,4 @@ namespace DiscImageChef.Core
} }
} }
} }
} }

View File

@@ -47,25 +47,23 @@ namespace DiscImageChef.Core
{ {
public static partial class Sidecar public static partial class Sidecar
{ {
static void BlockMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar) static void BlockMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi,
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
{ {
sidecar.BlockMedia = new[] sidecar.BlockMedia = new[]
{ {
new BlockMediaType new BlockMediaType
{ {
Checksums = imgChecksums.ToArray(), Checksums = imgChecksums.ToArray(),
Image = new ImageType Image = new ImageType
{ {
format = image.GetImageFormat(), format = image.GetImageFormat(),
offset = 0, offset = 0,
offsetSpecified = true, offsetSpecified = true,
Value = Path.GetFileName(imagePath) Value = Path.GetFileName(imagePath)
}, },
Size = fi.Length, Size = fi.Length,
Sequence = new SequenceType Sequence = new SequenceType {MediaTitle = image.GetImageName()}
{
MediaTitle = image.GetImageName()
}
} }
}; };
@@ -89,7 +87,8 @@ namespace DiscImageChef.Core
{ {
Identify = new DumpType Identify = new DumpType
{ {
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(), Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length Size = image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length
} }
}; };
@@ -99,7 +98,8 @@ namespace DiscImageChef.Core
{ {
Identify = new DumpType Identify = new DumpType
{ {
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(), Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length Size = image.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length
} }
}; };
@@ -108,11 +108,7 @@ namespace DiscImageChef.Core
byte[] cis = image.ReadDiskTag(MediaTagType.PCMCIA_CIS); byte[] cis = image.ReadDiskTag(MediaTagType.PCMCIA_CIS);
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
{ {
CIS = new DumpType CIS = new DumpType {Checksums = Checksum.GetChecksums(cis).ToArray(), Size = cis.Length}
{
Checksums = Checksum.GetChecksums(cis).ToArray(),
Size = cis.Length
}
}; };
Tuple[] tuples = CIS.GetTuples(cis); Tuple[] tuples = CIS.GetTuples(cis);
if(tuples != null) if(tuples != null)
@@ -121,7 +117,8 @@ namespace DiscImageChef.Core
{ {
if(tuple.Code == TupleCodes.CISTPL_MANFID) if(tuple.Code == TupleCodes.CISTPL_MANFID)
{ {
ManufacturerIdentificationTuple manfid = CIS.DecodeManufacturerIdentificationTuple(tuple); ManufacturerIdentificationTuple manfid =
CIS.DecodeManufacturerIdentificationTuple(tuple);
if(manfid != null) if(manfid != null)
{ {
@@ -139,19 +136,22 @@ namespace DiscImageChef.Core
{ {
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer; sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product; sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
sidecar.BlockMedia[0].PCMCIA.Compliance = string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion); sidecar.BlockMedia[0].PCMCIA.Compliance =
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation; sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
} }
} }
} }
} }
break; break;
case MediaTagType.SCSI_INQUIRY: case MediaTagType.SCSI_INQUIRY:
sidecar.BlockMedia[0].SCSI = new SCSIType sidecar.BlockMedia[0].SCSI = new SCSIType
{ {
Inquiry = new DumpType Inquiry = new DumpType
{ {
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(), Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length Size = image.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length
} }
}; };
@@ -224,7 +224,8 @@ namespace DiscImageChef.Core
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType(); sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
{ {
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD)).ToArray(), Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD).Length Size = image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD).Length
}; };
break; break;
@@ -332,17 +333,13 @@ namespace DiscImageChef.Core
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray();
sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray();
} }
} }
else else
{ {
sidecar.BlockMedia[0].FileSystemInformation[0] = new PartitionType sidecar.BlockMedia[0].FileSystemInformation[0] =
{ new PartitionType {StartSector = 0, EndSector = (int)(image.GetSectors() - 1)};
StartSector = 0,
EndSector = (int)(image.GetSectors() - 1)
};
Partition wholePart = new Partition Partition wholePart = new Partition
{ {
@@ -372,8 +369,7 @@ namespace DiscImageChef.Core
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray();
sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray();
} }
if(image.ImageInfo.cylinders > 0 && image.ImageInfo.heads > 0 && image.ImageInfo.sectorsPerTrack > 0) if(image.ImageInfo.cylinders > 0 && image.ImageInfo.heads > 0 && image.ImageInfo.sectorsPerTrack > 0)
@@ -388,10 +384,12 @@ namespace DiscImageChef.Core
if(image.ImageInfo.readableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) if(image.ImageInfo.readableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
{ {
Decoders.ATA.Identify.IdentifyDevice? ataId = Decoders.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)); Decoders.ATA.Identify.IdentifyDevice? ataId =
Decoders.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
if(ataId.HasValue) if(ataId.HasValue)
{ {
if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 && ataId.Value.CurrentSectorsPerTrack > 0) if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 &&
ataId.Value.CurrentSectorsPerTrack > 0)
{ {
sidecar.BlockMedia[0].CylindersSpecified = true; sidecar.BlockMedia[0].CylindersSpecified = true;
sidecar.BlockMedia[0].HeadsSpecified = true; sidecar.BlockMedia[0].HeadsSpecified = true;
@@ -414,7 +412,7 @@ namespace DiscImageChef.Core
// TODO: This is more of a hack, redo it planned for >4.0 // TODO: This is more of a hack, redo it planned for >4.0
string trkFormat = null; string trkFormat = null;
switch(image.ImageInfo.mediaType) switch(image.ImageInfo.mediaType)
{ {
case MediaType.Apple32SS: case MediaType.Apple32SS:
@@ -506,10 +504,8 @@ namespace DiscImageChef.Core
break; break;
case MediaType.SHARP_525: case MediaType.SHARP_525:
case MediaType.SHARP_525_9: case MediaType.SHARP_525_9:
case MediaType.SHARP_35: case MediaType.SHARP_35: break;
break; case MediaType.SHARP_35_9: break;
case MediaType.SHARP_35_9:
break;
case MediaType.ECMA_99_15: case MediaType.ECMA_99_15:
case MediaType.ECMA_99_26: case MediaType.ECMA_99_26:
case MediaType.ECMA_100: case MediaType.ECMA_100:
@@ -536,7 +532,7 @@ namespace DiscImageChef.Core
#region SuperCardPro #region SuperCardPro
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath), string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
Path.GetFileNameWithoutExtension(imagePath) + ".scp"); Path.GetFileNameWithoutExtension(imagePath) + ".scp");
if(File.Exists(scpFilePath)) if(File.Exists(scpFilePath))
{ {
@@ -546,14 +542,8 @@ namespace DiscImageChef.Core
if(image.ImageInfo.heads <= 2 && scpImage.IdentifyImage(scpFilter)) if(image.ImageInfo.heads <= 2 && scpImage.IdentifyImage(scpFilter))
{ {
try { scpImage.OpenImage(scpFilter); }
try catch(NotImplementedException) { }
{
scpImage.OpenImage(scpFilter);
}
catch(NotImplementedException)
{
}
if((image.ImageInfo.heads == 2 && scpImage.header.heads == 0) || if((image.ImageInfo.heads == 2 && scpImage.header.heads == 0) ||
(image.ImageInfo.heads == 1 && (scpImage.header.heads == 1 || scpImage.header.heads == 2))) (image.ImageInfo.heads == 1 && (scpImage.header.heads == 1 || scpImage.header.heads == 2)))
@@ -603,22 +593,22 @@ namespace DiscImageChef.Core
scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray(); scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
scpImage.header.end + 1, image.ImageInfo.cylinders); scpImage.header.end + 1, image.ImageInfo.cylinders);
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
2, image.ImageInfo.heads); 2, image.ImageInfo.heads);
} }
} }
#endregion #endregion
#region KryoFlux #region KryoFlux
string kfFile = null; string kfFile = null;
string basename = Path.Combine(Path.GetDirectoryName(imagePath), string basename = Path.Combine(Path.GetDirectoryName(imagePath),
Path.GetFileNameWithoutExtension(imagePath)); Path.GetFileNameWithoutExtension(imagePath));
bool kfDir = false; bool kfDir = false;
if(Directory.Exists(basename)) if(Directory.Exists(basename))
@@ -630,10 +620,8 @@ namespace DiscImageChef.Core
kfDir = true; kfDir = true;
} }
} }
else if(File.Exists(basename + "00.0.raw")) else if(File.Exists(basename + "00.0.raw")) kfFile = basename + "00.0.raw";
kfFile = basename + "00.0.raw"; else if(File.Exists(basename + "00.1.raw")) kfFile = basename + "00.1.raw";
else if(File.Exists(basename + "00.1.raw"))
kfFile = basename + "00.1.raw";
if(kfFile != null) if(kfFile != null)
{ {
@@ -642,20 +630,15 @@ namespace DiscImageChef.Core
kfFilter.Open(kfFile); kfFilter.Open(kfFile);
if(image.ImageInfo.heads <= 2 && kfImage.IdentifyImage(kfFilter)) if(image.ImageInfo.heads <= 2 && kfImage.IdentifyImage(kfFilter))
{ {
try try { kfImage.OpenImage(kfFilter); }
{ catch(NotImplementedException) { }
kfImage.OpenImage(kfFilter);
}
catch(NotImplementedException)
{
}
if(kfImage.ImageInfo.heads == image.ImageInfo.heads) if(kfImage.ImageInfo.heads == image.ImageInfo.heads)
{ {
if(kfImage.ImageInfo.cylinders >= image.ImageInfo.cylinders) if(kfImage.ImageInfo.cylinders >= image.ImageInfo.cylinders)
{ {
List<BlockTrackType> kfBlockTrackTypes = new List<BlockTrackType>(); List<BlockTrackType> kfBlockTrackTypes = new List<BlockTrackType>();
long currentSector = 0; long currentSector = 0;
foreach(KeyValuePair<byte, Filter> kvp in kfImage.tracks) foreach(KeyValuePair<byte, Filter> kvp in kfImage.tracks)
@@ -667,7 +650,8 @@ namespace DiscImageChef.Core
kfBlockTrackType.Image.format = kfImage.GetImageFormat(); kfBlockTrackType.Image.format = kfImage.GetImageFormat();
kfBlockTrackType.Image.Value = kfBlockTrackType.Image.Value =
kfDir kfDir
? Path.Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())), kvp.Value.GetFilename()) ? Path.Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())),
kvp.Value.GetFilename())
: kvp.Value.GetFilename(); : kvp.Value.GetFilename();
kfBlockTrackType.Image.offset = 0; kfBlockTrackType.Image.offset = 0;
@@ -695,21 +679,21 @@ namespace DiscImageChef.Core
kfBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray(); kfBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.cylinders, image.ImageInfo.cylinders); kfImage.ImageInfo.cylinders, image.ImageInfo.cylinders);
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.heads, image.ImageInfo.heads); kfImage.ImageInfo.heads, image.ImageInfo.heads);
} }
} }
#endregion #endregion
#region DiscFerret #region DiscFerret
string dfiFilePath = Path.Combine(Path.GetDirectoryName(imagePath), string dfiFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
Path.GetFileNameWithoutExtension(imagePath) + ".dfi"); Path.GetFileNameWithoutExtension(imagePath) + ".dfi");
if(File.Exists(dfiFilePath)) if(File.Exists(dfiFilePath))
{ {
@@ -719,14 +703,8 @@ namespace DiscImageChef.Core
if(dfiImage.IdentifyImage(dfiFilter)) if(dfiImage.IdentifyImage(dfiFilter))
{ {
try { dfiImage.OpenImage(dfiFilter); }
try catch(NotImplementedException) { }
{
dfiImage.OpenImage(dfiFilter);
}
catch(NotImplementedException)
{
}
if(image.ImageInfo.heads == dfiImage.ImageInfo.heads) if(image.ImageInfo.heads == dfiImage.ImageInfo.heads)
{ {
@@ -755,7 +733,8 @@ namespace DiscImageChef.Core
dfiBlockTrackType.Format = trkFormat; dfiBlockTrackType.Format = trkFormat;
} }
if(dfiImage.trackOffsets.TryGetValue(t, out long offset) && dfiImage.trackLengths.TryGetValue(t, out long length)) if(dfiImage.trackOffsets.TryGetValue(t, out long offset) &&
dfiImage.trackLengths.TryGetValue(t, out long length))
{ {
dfiBlockTrackType.Image.offset = offset; dfiBlockTrackType.Image.offset = offset;
byte[] trackContents = new byte[length]; byte[] trackContents = new byte[length];
@@ -772,18 +751,19 @@ namespace DiscImageChef.Core
dfiBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray(); dfiBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
dfiImage.ImageInfo.cylinders, image.ImageInfo.cylinders); dfiImage.ImageInfo.cylinders, image.ImageInfo.cylinders);
} }
else else
DicConsole.ErrorWriteLine( DicConsole
"DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...", .ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
dfiImage.ImageInfo.heads, image.ImageInfo.heads); dfiImage.ImageInfo.heads, image.ImageInfo.heads);
} }
} }
#endregion #endregion
// TODO: Implement support for getting CHS from SCSI mode pages // TODO: Implement support for getting CHS from SCSI mode pages
} }
} }
} }

View File

@@ -43,36 +43,26 @@ namespace DiscImageChef.Core
CICMMetadataType sidecar = new CICMMetadataType CICMMetadataType sidecar = new CICMMetadataType
{ {
BlockMedia = new[] BlockMedia = new[]
{ {
new BlockMediaType new BlockMediaType
{ {
Image = new ImageType Image = new ImageType {format = "Directory", offsetSpecified = false, Value = folderName},
{ Sequence = new SequenceType {MediaTitle = folderName, MediaSequence = 1, TotalMedia = 1},
format = "Directory", PhysicalBlockSize = (int)blockSize,
offsetSpecified = false, LogicalBlockSize = (int)blockSize,
Value = folderName TapeInformation = new[]
}, {
Sequence = new SequenceType new TapePartitionType
{ {
MediaTitle = folderName, Image = new ImageType
MediaSequence = 1, {
TotalMedia = 1 format = "Directory",
}, offsetSpecified = false,
PhysicalBlockSize = (int)blockSize, Value = folderName
LogicalBlockSize = (int)blockSize, }
TapeInformation = new [] }
{ }
new TapePartitionType }
{
Image = new ImageType
{
format = "Directory",
offsetSpecified = false,
Value = folderName
}
}
}
}
} }
}; };
@@ -112,14 +102,16 @@ namespace DiscImageChef.Core
{ {
sector = new byte[sectorsToRead * blockSize]; sector = new byte[sectorsToRead * blockSize];
fs.Read(sector, 0, sector.Length); fs.Read(sector, 0, sector.Length);
UpdateProgress2(string.Format("Hashing block {0} of {1} on file {2} of {3}", doneSectors, sectors, i + 1, files.Count), doneSectors, sectors); UpdateProgress2(string.Format("Hashing block {0} of {1} on file {2} of {3}", doneSectors, sectors, i + 1, files.Count),
doneSectors, sectors);
doneSectors += sectorsToRead; doneSectors += sectorsToRead;
} }
else else
{ {
sector = new byte[(uint)(sectors - doneSectors) * blockSize]; sector = new byte[(uint)(sectors - doneSectors) * blockSize];
fs.Read(sector, 0, sector.Length); fs.Read(sector, 0, sector.Length);
UpdateProgress2(string.Format("Hashing block {0} of {1} on file {2} of {3}", doneSectors, sectors, i + 1, files.Count), doneSectors, sectors); UpdateProgress2(string.Format("Hashing block {0} of {1} on file {2} of {3}", doneSectors, sectors, i + 1, files.Count),
doneSectors, sectors);
doneSectors += (sectors - doneSectors); doneSectors += (sectors - doneSectors);
} }
@@ -150,32 +142,19 @@ namespace DiscImageChef.Core
{ {
sidecar.BlockMedia[0].DiskType = "Quarter-inch cartridge"; sidecar.BlockMedia[0].DiskType = "Quarter-inch cartridge";
if(totalSize <= 20 * 1048576) if(totalSize <= 20 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-11";
sidecar.BlockMedia[0].DiskSubType = "QIC-11"; else if(totalSize <= 40 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-40";
else if(totalSize <= 40 * 1048576) else if(totalSize <= 60 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-24";
sidecar.BlockMedia[0].DiskSubType = "QIC-40"; else if(totalSize <= 80 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-80";
else if(totalSize <= 60 * 1048576) else if(totalSize <= 120 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-120";
sidecar.BlockMedia[0].DiskSubType = "QIC-24"; else if(totalSize <= 150 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-150";
else if(totalSize <= 80 * 1048576) else if(totalSize <= 320 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-320";
sidecar.BlockMedia[0].DiskSubType = "QIC-80"; else if(totalSize <= 340 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-3010";
else if(totalSize <= 120 * 1048576) else if(totalSize <= 525 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-525";
sidecar.BlockMedia[0].DiskSubType = "QIC-120"; else if(totalSize <= 670 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-3020";
else if(totalSize <= 150 * 1048576) else if(totalSize <= 1200 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-3080";
sidecar.BlockMedia[0].DiskSubType = "QIC-150"; else if(totalSize <= 1350 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-1350";
else if(totalSize <= 320 * 1048576) else if(totalSize <= (long)4000 * 1048576) sidecar.BlockMedia[0].DiskSubType = "QIC-3095";
sidecar.BlockMedia[0].DiskSubType = "QIC-320";
else if(totalSize <= 340 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-3010";
else if(totalSize <= 525 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-525";
else if(totalSize <= 670 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-3020";
else if(totalSize <= 1200 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-3080";
else if(totalSize <= 1350 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-1350";
else if(totalSize <= (long)4000 * 1048576)
sidecar.BlockMedia[0].DiskSubType = "QIC-3095";
else else
{ {
sidecar.BlockMedia[0].DiskType = "Unknown tape"; sidecar.BlockMedia[0].DiskType = "Unknown tape";
@@ -191,4 +170,4 @@ namespace DiscImageChef.Core
return sidecar; return sidecar;
} }
} }
} }

View File

@@ -44,8 +44,7 @@ namespace DiscImageChef.Core
public static void InitProgress() public static void InitProgress()
{ {
if(InitProgressEvent != null) if(InitProgressEvent != null) InitProgressEvent();
InitProgressEvent();
} }
public static void UpdateProgress(string text, long current, long maximum) public static void UpdateProgress(string text, long current, long maximum)
@@ -56,14 +55,12 @@ namespace DiscImageChef.Core
public static void EndProgress() public static void EndProgress()
{ {
if(EndProgressEvent != null) if(EndProgressEvent != null) EndProgressEvent();
EndProgressEvent();
} }
public static void InitProgress2() public static void InitProgress2()
{ {
if(InitProgressEvent2 != null) if(InitProgressEvent2 != null) InitProgressEvent2();
InitProgressEvent2();
} }
public static void UpdateProgress2(string text, long current, long maximum) public static void UpdateProgress2(string text, long current, long maximum)
@@ -74,14 +71,12 @@ namespace DiscImageChef.Core
public static void EndProgress2() public static void EndProgress2()
{ {
if(EndProgressEvent2 != null) if(EndProgressEvent2 != null) EndProgressEvent2();
EndProgressEvent2();
} }
public static void UpdateStatus(string text, params object[] args) public static void UpdateStatus(string text, params object[] args)
{ {
if(UpdateStatusEvent != null) if(UpdateStatusEvent != null) UpdateStatusEvent(string.Format(text, args));
UpdateStatusEvent(string.Format(text, args));
} }
} }
} }

View File

@@ -84,4 +84,4 @@ namespace DiscImageChef.Core
return string.Format("{3}:{0:D2}:{1:D2}:{2:D2}", m, s, f, h); return string.Format("{3}:{0:D2}:{1:D2}:{2:D2}", m, s, f, h);
} }
} }
} }

View File

@@ -40,23 +40,24 @@ namespace DiscImageChef.Core
public static partial class Sidecar public static partial class Sidecar
{ {
// TODO: Complete it // TODO: Complete it
static void LinearMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar) static void LinearMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi,
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
{ {
sidecar.LinearMedia = new [] sidecar.LinearMedia = new[]
{ {
new LinearMediaType new LinearMediaType
{ {
Checksums = imgChecksums.ToArray(), Checksums = imgChecksums.ToArray(),
Image = new ImageType Image = new ImageType
{ {
format = image.GetImageFormat(), format = image.GetImageFormat(),
offset = 0, offset = 0,
offsetSpecified = true, offsetSpecified = true,
Value = Path.GetFileName(imagePath) Value = Path.GetFileName(imagePath)
}, },
Size = fi.Length Size = fi.Length
} }
}; };
} }
} }
} }

View File

@@ -41,25 +41,23 @@ namespace DiscImageChef.Core
{ {
public static partial class Sidecar public static partial class Sidecar
{ {
static void OpticalDisc(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi, PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar) static void OpticalDisc(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi,
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
{ {
sidecar.OpticalDisc = new[] sidecar.OpticalDisc = new[]
{ {
new OpticalDiscType new OpticalDiscType
{ {
Checksums = imgChecksums.ToArray(), Checksums = imgChecksums.ToArray(),
Image = new ImageType Image = new ImageType
{ {
format = image.GetImageFormat(), format = image.GetImageFormat(),
offset = 0, offset = 0,
offsetSpecified = true, offsetSpecified = true,
Value = Path.GetFileName(imagePath) Value = Path.GetFileName(imagePath)
}, },
Size = fi.Length, Size = fi.Length,
Sequence = new SequenceType Sequence = new SequenceType {MediaTitle = image.GetImageName()}
{
MediaTitle = image.GetImageName()
}
} }
}; };
@@ -86,13 +84,12 @@ namespace DiscImageChef.Core
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(), Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.CD_ATIP)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.CD_ATIP).Length Size = image.ReadDiskTag(MediaTagType.CD_ATIP).Length
}; };
Decoders.CD.ATIP.CDATIP? atip = Decoders.CD.ATIP.Decode(image.ReadDiskTag(MediaTagType.CD_ATIP)); Decoders.CD.ATIP.CDATIP?
atip = Decoders.CD.ATIP.Decode(image.ReadDiskTag(MediaTagType.CD_ATIP));
if(atip.HasValue) if(atip.HasValue)
{ {
if(atip.Value.DDCD) if(atip.Value.DDCD) dskType = atip.Value.DiscType ? MediaType.DDCDRW : MediaType.DDCDR;
dskType = atip.Value.DiscType ? MediaType.DDCDRW : MediaType.DDCDR; else dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
else
dskType = atip.Value.DiscType ? MediaType.CDRW : MediaType.CDR;
} }
break; break;
case MediaTagType.DVD_BCA: case MediaTagType.DVD_BCA:
@@ -115,7 +112,8 @@ namespace DiscImageChef.Core
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(), Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_CMI)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.DVD_CMI).Length Size = image.ReadDiskTag(MediaTagType.DVD_CMI).Length
}; };
Decoders.DVD.CSS_CPRM.LeadInCopyright? cmi = Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(image.ReadDiskTag(MediaTagType.DVD_CMI)); Decoders.DVD.CSS_CPRM.LeadInCopyright? cmi =
Decoders.DVD.CSS_CPRM.DecodeLeadInCopyright(image.ReadDiskTag(MediaTagType.DVD_CMI));
if(cmi.HasValue) if(cmi.HasValue)
{ {
switch(cmi.Value.CopyrightType) switch(cmi.Value.CopyrightType)
@@ -131,6 +129,7 @@ namespace DiscImageChef.Core
break; break;
} }
} }
break; break;
case MediaTagType.DVD_DMI: case MediaTagType.DVD_DMI:
sidecar.OpticalDisc[0].DMI = new DumpType sidecar.OpticalDisc[0].DMI = new DumpType
@@ -141,15 +140,12 @@ namespace DiscImageChef.Core
if(Decoders.Xbox.DMI.IsXbox(image.ReadDiskTag(MediaTagType.DVD_DMI))) if(Decoders.Xbox.DMI.IsXbox(image.ReadDiskTag(MediaTagType.DVD_DMI)))
{ {
dskType = MediaType.XGD; dskType = MediaType.XGD;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType { Diameter = 120 }; sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120};
} }
else if(Decoders.Xbox.DMI.IsXbox360(image.ReadDiskTag(MediaTagType.DVD_DMI))) else if(Decoders.Xbox.DMI.IsXbox360(image.ReadDiskTag(MediaTagType.DVD_DMI)))
{ {
dskType = MediaType.XGD2; dskType = MediaType.XGD2;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType sidecar.OpticalDisc[0].Dimensions = new DimensionsType {Diameter = 120};
{
Diameter = 120
};
} }
break; break;
case MediaTagType.DVD_PFI: case MediaTagType.DVD_PFI:
@@ -158,12 +154,11 @@ namespace DiscImageChef.Core
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(), Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.DVD_PFI)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.DVD_PFI).Length Size = image.ReadDiskTag(MediaTagType.DVD_PFI).Length
}; };
Decoders.DVD.PFI.PhysicalFormatInformation? pfi = Decoders.DVD.PFI.Decode(image.ReadDiskTag(MediaTagType.DVD_PFI)); Decoders.DVD.PFI.PhysicalFormatInformation? pfi =
Decoders.DVD.PFI.Decode(image.ReadDiskTag(MediaTagType.DVD_PFI));
if(pfi.HasValue) if(pfi.HasValue)
{ {
if(dskType != MediaType.XGD && if(dskType != MediaType.XGD && dskType != MediaType.XGD2 && dskType != MediaType.XGD3)
dskType != MediaType.XGD2 &&
dskType != MediaType.XGD3)
{ {
switch(pfi.Value.DiskCategory) switch(pfi.Value.DiskCategory)
{ {
@@ -211,22 +206,21 @@ namespace DiscImageChef.Core
break; break;
} }
if(dskType == MediaType.DVDR && pfi.Value.PartVersion == 6) if(dskType == MediaType.DVDR && pfi.Value.PartVersion == 6) dskType = MediaType.DVDRDL;
dskType = MediaType.DVDRDL;
if(dskType == MediaType.DVDRW && pfi.Value.PartVersion == 3) if(dskType == MediaType.DVDRW && pfi.Value.PartVersion == 3)
dskType = MediaType.DVDRWDL; dskType = MediaType.DVDRWDL;
if(dskType == MediaType.GOD && pfi.Value.DiscSize == Decoders.DVD.DVDSize.OneTwenty) if(dskType == MediaType.GOD && pfi.Value.DiscSize == Decoders.DVD.DVDSize.OneTwenty)
dskType = MediaType.WOD; dskType = MediaType.WOD;
sidecar.OpticalDisc[0].Dimensions = new DimensionsType(); sidecar.OpticalDisc[0].Dimensions = new DimensionsType();
if(dskType == MediaType.UMD) if(dskType == MediaType.UMD) sidecar.OpticalDisc[0].Dimensions.Diameter = 60;
sidecar.OpticalDisc[0].Dimensions.Diameter = 60;
else if(pfi.Value.DiscSize == Decoders.DVD.DVDSize.Eighty) else if(pfi.Value.DiscSize == Decoders.DVD.DVDSize.Eighty)
sidecar.OpticalDisc[0].Dimensions.Diameter = 80; sidecar.OpticalDisc[0].Dimensions.Diameter = 80;
else if(pfi.Value.DiscSize == Decoders.DVD.DVDSize.OneTwenty) else if(pfi.Value.DiscSize == Decoders.DVD.DVDSize.OneTwenty)
sidecar.OpticalDisc[0].Dimensions.Diameter = 120; sidecar.OpticalDisc[0].Dimensions.Diameter = 120;
} }
} }
break; break;
case MediaTagType.CD_PMA: case MediaTagType.CD_PMA:
sidecar.OpticalDisc[0].PMA = new DumpType sidecar.OpticalDisc[0].PMA = new DumpType
@@ -243,10 +237,7 @@ namespace DiscImageChef.Core
List<Session> sessions = image.GetSessions(); List<Session> sessions = image.GetSessions();
sidecar.OpticalDisc[0].Sessions = sessions != null ? sessions.Count : 1; sidecar.OpticalDisc[0].Sessions = sessions != null ? sessions.Count : 1;
} }
catch catch { sidecar.OpticalDisc[0].Sessions = 1; }
{
sidecar.OpticalDisc[0].Sessions = 1;
}
List<Track> tracks = image.GetTracks(); List<Track> tracks = image.GetTracks();
List<Schemas.TrackType> trksLst = null; List<Schemas.TrackType> trksLst = null;
@@ -297,24 +288,21 @@ namespace DiscImageChef.Core
xmlTrk.TrackType1 = TrackTypeTrackType.mode1; xmlTrk.TrackType1 = TrackTypeTrackType.mode1;
break; break;
} }
break; break;
} }
xmlTrk.Sequence = new TrackSequenceType
{ xmlTrk.Sequence =
Session = trk.TrackSession, new TrackSequenceType {Session = trk.TrackSession, TrackNumber = (int)trk.TrackSequence};
TrackNumber = (int)trk.TrackSequence
};
xmlTrk.StartSector = (long)trk.TrackStartSector; xmlTrk.StartSector = (long)trk.TrackStartSector;
xmlTrk.EndSector = (long)trk.TrackEndSector; xmlTrk.EndSector = (long)trk.TrackEndSector;
if(trk.Indexes != null && trk.Indexes.ContainsKey(0)) if(trk.Indexes != null && trk.Indexes.ContainsKey(0))
{ {
if(trk.Indexes.TryGetValue(0, out ulong idx0)) if(trk.Indexes.TryGetValue(0, out ulong idx0)) xmlTrk.StartSector = (long)idx0;
xmlTrk.StartSector = (long)idx0;
} }
if(sidecar.OpticalDisc[0].DiscType == "CD" || if(sidecar.OpticalDisc[0].DiscType == "CD" || sidecar.OpticalDisc[0].DiscType == "GD")
sidecar.OpticalDisc[0].DiscType == "GD")
{ {
xmlTrk.StartMSF = LbaToMsf(xmlTrk.StartSector); xmlTrk.StartMSF = LbaToMsf(xmlTrk.StartSector);
xmlTrk.EndMSF = LbaToMsf(xmlTrk.EndSector); xmlTrk.EndMSF = LbaToMsf(xmlTrk.EndSector);
@@ -325,11 +313,7 @@ namespace DiscImageChef.Core
xmlTrk.EndMSF = DdcdLbaToMsf(xmlTrk.EndSector); xmlTrk.EndMSF = DdcdLbaToMsf(xmlTrk.EndSector);
} }
xmlTrk.Image = new ImageType xmlTrk.Image = new ImageType {Value = Path.GetFileName(trk.TrackFile), format = trk.TrackFileType};
{
Value = Path.GetFileName(trk.TrackFile),
format = trk.TrackFileType
};
if(trk.TrackFileOffset > 0) if(trk.TrackFileOffset > 0)
{ {
@@ -369,14 +353,18 @@ namespace DiscImageChef.Core
if((sectors - doneSectors) >= sectorsToRead) if((sectors - doneSectors) >= sectorsToRead)
{ {
sector = image.ReadSectorsLong(doneSectors, sectorsToRead, (uint)xmlTrk.Sequence.TrackNumber); sector = image.ReadSectorsLong(doneSectors, sectorsToRead,
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)(trk.TrackEndSector - trk.TrackStartSector + 1)); (uint)xmlTrk.Sequence.TrackNumber);
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
doneSectors += sectorsToRead; doneSectors += sectorsToRead;
} }
else else
{ {
sector = image.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors), (uint)xmlTrk.Sequence.TrackNumber); sector = image.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors),
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)(trk.TrackEndSector - trk.TrackStartSector + 1)); (uint)xmlTrk.Sequence.TrackNumber);
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors,
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
doneSectors += (sectors - doneSectors); doneSectors += (sectors - doneSectors);
} }
@@ -394,10 +382,7 @@ namespace DiscImageChef.Core
{ {
xmlTrk.SubChannel = new SubChannelType xmlTrk.SubChannel = new SubChannelType
{ {
Image = new ImageType Image = new ImageType {Value = trk.TrackSubchannelFile},
{
Value = trk.TrackSubchannelFile
},
// TODO: Packed subchannel has different size? // TODO: Packed subchannel has different size?
Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * 96 Size = (xmlTrk.EndSector - xmlTrk.StartSector + 1) * 96
}; };
@@ -436,14 +421,19 @@ namespace DiscImageChef.Core
if((sectors - doneSectors) >= sectorsToRead) if((sectors - doneSectors) >= sectorsToRead)
{ {
sector = image.ReadSectorsTag(doneSectors, sectorsToRead, (uint)xmlTrk.Sequence.TrackNumber, SectorTagType.CDSectorSubchannel); sector = image.ReadSectorsTag(doneSectors, sectorsToRead, (uint)xmlTrk.Sequence.TrackNumber,
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors, (long)(trk.TrackEndSector - trk.TrackStartSector + 1)); SectorTagType.CDSectorSubchannel);
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
doneSectors += sectorsToRead; doneSectors += sectorsToRead;
} }
else else
{ {
sector = image.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors), (uint)xmlTrk.Sequence.TrackNumber, SectorTagType.CDSectorSubchannel); sector = image.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors),
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors, (long)(trk.TrackEndSector - trk.TrackStartSector + 1)); (uint)xmlTrk.Sequence.TrackNumber,
SectorTagType.CDSectorSubchannel);
UpdateProgress2("Hashings subchannel sector {0} of {1}", (long)doneSectors,
(long)(trk.TrackEndSector - trk.TrackStartSector + 1));
doneSectors += (sectors - doneSectors); doneSectors += (sectors - doneSectors);
} }
@@ -460,7 +450,8 @@ namespace DiscImageChef.Core
// For fast debugging, skip checksum // For fast debugging, skip checksum
//skipChecksum: //skipChecksum:
UpdateStatus("Checking filesystems on track {0} from sector {1} to {2}", xmlTrk.Sequence.TrackNumber, xmlTrk.StartSector, xmlTrk.EndSector); UpdateStatus("Checking filesystems on track {0} from sector {1} to {2}", xmlTrk.Sequence.TrackNumber,
xmlTrk.StartSector, xmlTrk.EndSector);
List<Partition> partitions = Partitions.GetAll(image); List<Partition> partitions = Partitions.GetAll(image);
Partitions.AddSchemesToStats(partitions); Partitions.AddSchemesToStats(partitions);
@@ -492,12 +483,10 @@ namespace DiscImageChef.Core
lstFs.Add(_plugin.XmlFSType); lstFs.Add(_plugin.XmlFSType);
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "PC Engine filesystem")
dskType = MediaType.SuperCDROM2; dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD; dskType = MediaType.GOD;
} }
@@ -510,8 +499,7 @@ namespace DiscImageChef.Core
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
xmlTrk.FileSystemInformation[i].FileSystems = lstFs.ToArray();
} }
} }
else else
@@ -541,14 +529,10 @@ namespace DiscImageChef.Core
lstFs.Add(_plugin.XmlFSType); lstFs.Add(_plugin.XmlFSType);
Statistics.AddFilesystem(_plugin.XmlFSType.Type); Statistics.AddFilesystem(_plugin.XmlFSType.Type);
if(_plugin.XmlFSType.Type == "Opera") if(_plugin.XmlFSType.Type == "Opera") dskType = MediaType.ThreeDO;
dskType = MediaType.ThreeDO; if(_plugin.XmlFSType.Type == "PC Engine filesystem") dskType = MediaType.SuperCDROM2;
if(_plugin.XmlFSType.Type == "PC Engine filesystem") if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem") dskType = MediaType.WOD;
dskType = MediaType.SuperCDROM2; if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem") dskType = MediaType.GOD;
if(_plugin.XmlFSType.Type == "Nintendo Wii filesystem")
dskType = MediaType.WOD;
if(_plugin.XmlFSType.Type == "Nintendo Gamecube filesystem")
dskType = MediaType.GOD;
} }
} }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
@@ -559,21 +543,21 @@ namespace DiscImageChef.Core
} }
} }
if(lstFs.Count > 0) if(lstFs.Count > 0) xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
xmlTrk.FileSystemInformation[0].FileSystems = lstFs.ToArray();
} }
trksLst.Add(xmlTrk); trksLst.Add(xmlTrk);
} }
EndProgress(); EndProgress();
if(trksLst != null) if(trksLst != null) sidecar.OpticalDisc[0].Track = trksLst.ToArray();
sidecar.OpticalDisc[0].Track = trksLst.ToArray();
// All XGD3 all have the same number of blocks // All XGD3 all have the same number of blocks
if(dskType == MediaType.XGD2 && sidecar.OpticalDisc[0].Track.Length == 1) if(dskType == MediaType.XGD2 && sidecar.OpticalDisc[0].Track.Length == 1)
{ {
ulong blocks = (ulong)(sidecar.OpticalDisc[0].Track[0].EndSector - sidecar.OpticalDisc[0].Track[0].StartSector + 1); ulong blocks = (ulong)(sidecar.OpticalDisc[0].Track[0].EndSector -
sidecar.OpticalDisc[0].Track[0].StartSector + 1);
if(blocks == 25063 || // Locked (or non compatible drive) if(blocks == 25063 || // Locked (or non compatible drive)
blocks == 4229664 || // Xtreme unlock blocks == 4229664 || // Xtreme unlock
blocks == 4246304) // Wxripper unlock blocks == 4246304) // Wxripper unlock
@@ -594,14 +578,7 @@ namespace DiscImageChef.Core
{ {
new DumpHardwareType new DumpHardwareType
{ {
Extents = new[] Extents = new[] {new ExtentType {Start = 0, End = image.ImageInfo.sectors}},
{
new ExtentType
{
Start = 0,
End = image.ImageInfo.sectors
}
},
Manufacturer = image.ImageInfo.driveManufacturer, Manufacturer = image.ImageInfo.driveManufacturer,
Model = image.ImageInfo.driveModel, Model = image.ImageInfo.driveModel,
Firmware = image.ImageInfo.driveFirmwareRevision, Firmware = image.ImageInfo.driveFirmwareRevision,
@@ -616,4 +593,4 @@ namespace DiscImageChef.Core
} }
} }
} }
} }

View File

@@ -39,7 +39,8 @@ namespace DiscImageChef.Core
{ {
public static partial class Sidecar public static partial class Sidecar
{ {
public static CICMMetadataType Create(ImagePlugin image, string imagePath, System.Guid filterId, System.Text.Encoding encoding) public static CICMMetadataType Create(ImagePlugin image, string imagePath, System.Guid filterId,
System.Text.Encoding encoding)
{ {
CICMMetadataType sidecar = new CICMMetadataType(); CICMMetadataType sidecar = new CICMMetadataType();
PluginBase plugins = new PluginBase(); PluginBase plugins = new PluginBase();
@@ -102,4 +103,4 @@ namespace DiscImageChef.Core
return sidecar; return sidecar;
} }
} }
} }

View File

@@ -54,14 +54,17 @@ namespace DiscImageChef.Core
AllStats = new Stats(); AllStats = new Stats();
CurrentStats = new Stats() CurrentStats = new Stats()
{ {
OperatingSystems = new List<OsStats> OperatingSystems =
{ new List<OsStats>
new OsStats { name = Interop.DetectOS.GetRealPlatformID().ToString(), Value = 1, version = Interop.DetectOS.GetVersion() } {
}, new OsStats
Versions = new List<NameValueStats> {
{ name = Interop.DetectOS.GetRealPlatformID().ToString(),
new NameValueStats{ name = Version.GetVersion(), Value = 1 } Value = 1,
} version = Interop.DetectOS.GetVersion()
}
},
Versions = new List<NameValueStats> {new NameValueStats {name = Version.GetVersion(), Value = 1}}
}; };
XmlSerializer xs = new XmlSerializer(AllStats.GetType()); XmlSerializer xs = new XmlSerializer(AllStats.GetType());
StreamReader sr = new StreamReader(Path.Combine(Settings.Settings.StatsPath, "Statistics.xml")); StreamReader sr = new StreamReader(Path.Combine(Settings.Settings.StatsPath, "Statistics.xml"));
@@ -73,14 +76,17 @@ namespace DiscImageChef.Core
AllStats = new Stats(); AllStats = new Stats();
CurrentStats = new Stats() CurrentStats = new Stats()
{ {
OperatingSystems = new List<OsStats> OperatingSystems =
{ new List<OsStats>
new OsStats { name = Interop.DetectOS.GetRealPlatformID().ToString(), Value = 1, version = Interop.DetectOS.GetVersion() } {
}, new OsStats
Versions = new List<NameValueStats> {
{ name = Interop.DetectOS.GetRealPlatformID().ToString(),
new NameValueStats{ name = Version.GetVersion(), Value = 1 } Value = 1,
} version = Interop.DetectOS.GetVersion()
}
},
Versions = new List<NameValueStats> {new NameValueStats {name = Version.GetVersion(), Value = 1}}
}; };
} }
else else
@@ -101,7 +107,8 @@ namespace DiscImageChef.Core
OsStats old = null; OsStats old = null;
foreach(OsStats nvs in AllStats.OperatingSystems) foreach(OsStats nvs in AllStats.OperatingSystems)
{ {
if(nvs.name == Interop.DetectOS.GetRealPlatformID().ToString() && nvs.version == Interop.DetectOS.GetVersion()) if(nvs.name == Interop.DetectOS.GetRealPlatformID().ToString() &&
nvs.version == Interop.DetectOS.GetVersion())
{ {
count = nvs.Value + 1; count = nvs.Value + 1;
old = nvs; old = nvs;
@@ -109,14 +116,17 @@ namespace DiscImageChef.Core
} }
} }
if(old != null) if(old != null) AllStats.OperatingSystems.Remove(old);
AllStats.OperatingSystems.Remove(old);
count++; count++;
AllStats.OperatingSystems.Add(new OsStats { name = Interop.DetectOS.GetRealPlatformID().ToString(), Value = count, version = Interop.DetectOS.GetVersion() }); AllStats.OperatingSystems.Add(new OsStats
{
name = Interop.DetectOS.GetRealPlatformID().ToString(),
Value = count,
version = Interop.DetectOS.GetVersion()
});
} }
else if(CurrentStats != null) else if(CurrentStats != null) AllStats.OperatingSystems = CurrentStats.OperatingSystems;
AllStats.OperatingSystems = CurrentStats.OperatingSystems;
if(AllStats.Versions != null) if(AllStats.Versions != null)
{ {
@@ -133,16 +143,15 @@ namespace DiscImageChef.Core
} }
} }
if(old != null) if(old != null) AllStats.Versions.Remove(old);
AllStats.Versions.Remove(old);
count++; count++;
AllStats.Versions.Add(new NameValueStats { name = Version.GetVersion(), Value = count }); AllStats.Versions.Add(new NameValueStats {name = Version.GetVersion(), Value = count});
} }
else if(CurrentStats != null) else if(CurrentStats != null) AllStats.Versions = CurrentStats.Versions;
AllStats.Versions = CurrentStats.Versions;
FileStream fs = new FileStream(Path.Combine(Settings.Settings.StatsPath, "Statistics.xml"),
FileStream fs = new FileStream(Path.Combine(Settings.Settings.StatsPath, "Statistics.xml"), FileMode.Create); FileMode.Create);
XmlSerializer xs = new XmlSerializer(AllStats.GetType()); XmlSerializer xs = new XmlSerializer(AllStats.GetType());
xs.Serialize(fs, AllStats); xs.Serialize(fs, AllStats);
fs.Close(); fs.Close();
@@ -157,8 +166,7 @@ namespace DiscImageChef.Core
fs.Close(); fs.Close();
} }
if(Settings.Settings.Current.Stats.ShareStats) if(Settings.Settings.Current.Stats.ShareStats) SubmitStats();
SubmitStats();
} }
} }
@@ -166,18 +174,18 @@ namespace DiscImageChef.Core
{ {
Thread submitThread = new Thread(() => Thread submitThread = new Thread(() =>
{ {
if(submitStatsLock) if(submitStatsLock) return;
return;
submitStatsLock = true; submitStatsLock = true;
var statsFiles = Directory.EnumerateFiles(Settings.Settings.StatsPath, "PartialStats_*.xml", SearchOption.TopDirectoryOnly); var statsFiles = Directory.EnumerateFiles(Settings.Settings.StatsPath, "PartialStats_*.xml",
SearchOption.TopDirectoryOnly);
foreach(string statsFile in statsFiles) foreach(string statsFile in statsFiles)
{ {
try try
{ {
if(!File.Exists(statsFile)) if(!File.Exists(statsFile)) continue;
continue;
Stats stats = new Stats(); Stats stats = new Stats();
@@ -194,7 +202,8 @@ namespace DiscImageChef.Core
fs.Seek(0, SeekOrigin.Begin); fs.Seek(0, SeekOrigin.Begin);
WebRequest request = WebRequest.Create("http://discimagechef.claunia.com/api/uploadstats"); WebRequest request = WebRequest.Create("http://discimagechef.claunia.com/api/uploadstats");
((HttpWebRequest)request).UserAgent = string.Format("DiscImageChef {0}", typeof(Version).Assembly.GetName().Version); ((HttpWebRequest)request).UserAgent =
string.Format("DiscImageChef {0}", typeof(Version).Assembly.GetName().Version);
request.Method = "POST"; request.Method = "POST";
request.ContentLength = fs.Length; request.ContentLength = fs.Length;
request.ContentType = "application/xml"; request.ContentType = "application/xml";
@@ -203,8 +212,7 @@ namespace DiscImageChef.Core
reqStream.Close(); reqStream.Close();
WebResponse response = request.GetResponse(); WebResponse response = request.GetResponse();
if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) if(((HttpWebResponse)response).StatusCode != HttpStatusCode.OK) return;
return;
Stream data = response.GetResponseStream(); Stream data = response.GetResponseStream();
StreamReader reader = new StreamReader(data); StreamReader reader = new StreamReader(data);
@@ -213,8 +221,7 @@ namespace DiscImageChef.Core
data.Close(); data.Close();
response.Close(); response.Close();
fs.Close(); fs.Close();
if(responseFromServer == "ok") if(responseFromServer == "ok") File.Delete(statsFile);
File.Delete(statsFile);
} }
catch(WebException) catch(WebException)
{ {
@@ -241,11 +248,9 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.DeviceStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.DeviceStats)
{ {
if(AllStats.Commands == null) if(AllStats.Commands == null) AllStats.Commands = new CommandsStats();
AllStats.Commands = new CommandsStats();
if(CurrentStats.Commands == null) if(CurrentStats.Commands == null) CurrentStats.Commands = new CommandsStats();
CurrentStats.Commands = new CommandsStats();
switch(command) switch(command)
{ {
@@ -333,10 +338,8 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.FilesystemStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.FilesystemStats)
{ {
if(AllStats.Filesystems == null) if(AllStats.Filesystems == null) AllStats.Filesystems = new List<NameValueStats>();
AllStats.Filesystems = new List<NameValueStats>(); if(CurrentStats.Filesystems == null) CurrentStats.Filesystems = new List<NameValueStats>();
if(CurrentStats.Filesystems == null)
CurrentStats.Filesystems = new List<NameValueStats>();
NameValueStats old = null; NameValueStats old = null;
foreach(NameValueStats nvs in AllStats.Filesystems) foreach(NameValueStats nvs in AllStats.Filesystems)
@@ -392,10 +395,8 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.PartitionStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.PartitionStats)
{ {
if(AllStats.Partitions == null) if(AllStats.Partitions == null) AllStats.Partitions = new List<NameValueStats>();
AllStats.Partitions = new List<NameValueStats>(); if(CurrentStats.Partitions == null) CurrentStats.Partitions = new List<NameValueStats>();
if(CurrentStats.Partitions == null)
CurrentStats.Partitions = new List<NameValueStats>();
NameValueStats old = null; NameValueStats old = null;
foreach(NameValueStats nvs in AllStats.Partitions) foreach(NameValueStats nvs in AllStats.Partitions)
@@ -451,10 +452,8 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.FilterStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.FilterStats)
{ {
if(AllStats.Filters == null) if(AllStats.Filters == null) AllStats.Filters = new List<NameValueStats>();
AllStats.Filters = new List<NameValueStats>(); if(CurrentStats.Filters == null) CurrentStats.Filters = new List<NameValueStats>();
if(CurrentStats.Filters == null)
CurrentStats.Filters = new List<NameValueStats>();
NameValueStats old = null; NameValueStats old = null;
foreach(NameValueStats nvs in AllStats.Filters) foreach(NameValueStats nvs in AllStats.Filters)
@@ -510,10 +509,8 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaImageStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaImageStats)
{ {
if(AllStats.MediaImages == null) if(AllStats.MediaImages == null) AllStats.MediaImages = new List<NameValueStats>();
AllStats.MediaImages = new List<NameValueStats>(); if(CurrentStats.MediaImages == null) CurrentStats.MediaImages = new List<NameValueStats>();
if(CurrentStats.MediaImages == null)
CurrentStats.MediaImages = new List<NameValueStats>();
NameValueStats old = null; NameValueStats old = null;
foreach(NameValueStats nvs in AllStats.MediaImages) foreach(NameValueStats nvs in AllStats.MediaImages)
@@ -569,25 +566,18 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.DeviceStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.DeviceStats)
{ {
if(AllStats.Devices == null) if(AllStats.Devices == null) AllStats.Devices = new List<DeviceStats>();
AllStats.Devices = new List<DeviceStats>(); if(CurrentStats.Devices == null) CurrentStats.Devices = new List<DeviceStats>();
if(CurrentStats.Devices == null)
CurrentStats.Devices = new List<DeviceStats>();
string deviceBus; string deviceBus;
if(dev.IsUSB) if(dev.IsUSB) deviceBus = "USB";
deviceBus = "USB"; else if(dev.IsFireWire) deviceBus = "FireWire";
else if(dev.IsFireWire) else deviceBus = dev.Type.ToString();
deviceBus = "FireWire";
else
deviceBus = dev.Type.ToString();
DeviceStats old = null; DeviceStats old = null;
foreach(DeviceStats ds in AllStats.Devices) foreach(DeviceStats ds in AllStats.Devices)
{ {
if(ds.Manufacturer == dev.Manufacturer && if(ds.Manufacturer == dev.Manufacturer && ds.Model == dev.Model && ds.Revision == dev.Revision &&
ds.Model == dev.Model &&
ds.Revision == dev.Revision &&
ds.Bus == deviceBus) ds.Bus == deviceBus)
{ {
old = ds; old = ds;
@@ -595,8 +585,7 @@ namespace DiscImageChef.Core
} }
} }
if(old != null) if(old != null) AllStats.Devices.Remove(old);
AllStats.Devices.Remove(old);
DeviceStats nw = new DeviceStats(); DeviceStats nw = new DeviceStats();
nw.Model = dev.Model; nw.Model = dev.Model;
@@ -609,18 +598,15 @@ namespace DiscImageChef.Core
old = null; old = null;
foreach(DeviceStats ds in CurrentStats.Devices) foreach(DeviceStats ds in CurrentStats.Devices)
{ {
if(ds.Manufacturer == dev.Manufacturer && if(ds.Manufacturer == dev.Manufacturer && ds.Model == dev.Model && ds.Revision == dev.Revision &&
ds.Model == dev.Model && ds.Bus == deviceBus)
ds.Revision == dev.Revision &&
ds.Bus == deviceBus)
{ {
old = ds; old = ds;
break; break;
} }
} }
if(old != null) if(old != null) CurrentStats.Devices.Remove(old);
CurrentStats.Devices.Remove(old);
nw = new DeviceStats(); nw = new DeviceStats();
nw.Model = dev.Model; nw.Model = dev.Model;
@@ -636,10 +622,8 @@ namespace DiscImageChef.Core
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaStats)
{ {
if(AllStats.Medias == null) if(AllStats.Medias == null) AllStats.Medias = new List<MediaStats>();
AllStats.Medias = new List<MediaStats>(); if(CurrentStats.Medias == null) CurrentStats.Medias = new List<MediaStats>();
if(CurrentStats.Medias == null)
CurrentStats.Medias = new List<MediaStats>();
MediaStats old = null; MediaStats old = null;
foreach(MediaStats ms in AllStats.Medias) foreach(MediaStats ms in AllStats.Medias)
@@ -695,7 +679,8 @@ namespace DiscImageChef.Core
} }
} }
public static void AddBenchmark(Dictionary<string, double> checksums, double entropy, double all, double sequential, long maxMemory, long minMemory) public static void AddBenchmark(Dictionary<string, double> checksums, double entropy, double all,
double sequential, long maxMemory, long minMemory)
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.BenchmarkStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.BenchmarkStats)
{ {
@@ -771,7 +756,8 @@ namespace DiscImageChef.Core
} }
} }
public static void AddMediaScan(long lessThan3ms, long lessThan10ms, long lessThan50ms, long lessThan150ms, long lessThan500ms, long moreThan500ms, long total, long error, long correct) public static void AddMediaScan(long lessThan3ms, long lessThan10ms, long lessThan50ms, long lessThan150ms,
long lessThan500ms, long moreThan500ms, long total, long error, long correct)
{ {
if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaScanStats) if(Settings.Settings.Current.Stats != null && Settings.Settings.Current.Stats.MediaScanStats)
{ {
@@ -811,5 +797,4 @@ namespace DiscImageChef.Core
} }
} }
} }
} }

View File

@@ -52,4 +52,4 @@ namespace DiscImageChef.Core
return typeof(Version).Assembly.GetName().Version.ToString(); return typeof(Version).Assembly.GetName().Version.ToString();
} }
} }
} }

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="System.ValueTuple" version="4.4.0" targetFramework="net40" /> <package id="System.ValueTuple" version="4.4.0" targetFramework="net40" />
</packages> </packages>

File diff suppressed because it is too large Load Diff

View File

@@ -100,5 +100,4 @@ namespace DiscImageChef.Decoders.ATA
public byte deviceHead; public byte deviceHead;
public byte command; public byte command;
} }
} }

View File

@@ -56,12 +56,12 @@ namespace DiscImageChef.Decoders.Bluray
#region Public methods #region Public methods
public static BurstCuttingArea? Decode(byte[] BCAResponse) public static BurstCuttingArea? Decode(byte[] BCAResponse)
{ {
if(BCAResponse == null) if(BCAResponse == null) return null;
return null;
if(BCAResponse.Length != 68) if(BCAResponse.Length != 68)
{ {
DicConsole.DebugWriteLine("BD BCA decoder", "Found incorrect Blu-ray BCA size ({0} bytes)", BCAResponse.Length); DicConsole.DebugWriteLine("BD BCA decoder", "Found incorrect Blu-ray BCA size ({0} bytes)",
BCAResponse.Length);
return null; return null;
} }
@@ -80,18 +80,15 @@ namespace DiscImageChef.Decoders.Bluray
public static string Prettify(BurstCuttingArea? BCAResponse) public static string Prettify(BurstCuttingArea? BCAResponse)
{ {
if(BCAResponse == null) if(BCAResponse == null) return null;
return null;
BurstCuttingArea response = BCAResponse.Value; BurstCuttingArea response = BCAResponse.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0)
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
#endif #endif
sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:"); sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:");
@@ -132,5 +129,4 @@ namespace DiscImageChef.Decoders.Bluray
} }
#endregion Public structures #endregion Public structures
} }
} }

View File

@@ -56,12 +56,13 @@ namespace DiscImageChef.Decoders.Bluray
#region Public methods #region Public methods
public static CartridgeStatus? Decode(byte[] CSResponse) public static CartridgeStatus? Decode(byte[] CSResponse)
{ {
if(CSResponse == null) if(CSResponse == null) return null;
return null;
if(CSResponse.Length != 8) if(CSResponse.Length != 8)
{ {
DicConsole.DebugWriteLine("BD Cartridge Status decoder", "Found incorrect Blu-ray Cartridge Status size ({0} bytes)", CSResponse.Length); DicConsole.DebugWriteLine("BD Cartridge Status decoder",
"Found incorrect Blu-ray Cartridge Status size ({0} bytes)",
CSResponse.Length);
return null; return null;
} }
@@ -86,47 +87,35 @@ namespace DiscImageChef.Decoders.Bluray
public static string Prettify(CartridgeStatus? CSResponse) public static string Prettify(CartridgeStatus? CSResponse)
{ {
if(CSResponse == null) if(CSResponse == null) return null;
return null;
CartridgeStatus response = CSResponse.Value; CartridgeStatus response = CSResponse.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0) if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine();
if(response.Reserved3 != 0) if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
if(response.Reserved4 != 0) if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine();
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 #endif
if(response.Cartridge) if(response.Cartridge)
{ {
sb.AppendLine("Media is inserted in a cartridge"); sb.AppendLine("Media is inserted in a cartridge");
if(response.OUT) if(response.OUT) sb.AppendLine("Media has been taken out, or inserted in, the cartridge");
sb.AppendLine("Media has been taken out, or inserted in, the cartridge"); if(response.CWP) sb.AppendLine("Media is write protected");
if(response.CWP)
sb.AppendLine("Media is write protected");
} }
else else
{ {
sb.AppendLine("Media is not in a cartridge"); sb.AppendLine("Media is not in a cartridge");
#if DEBUG #if DEBUG
if(response.OUT) if(response.OUT) sb.AppendLine("Media has out bit marked, shouldn't");
sb.AppendLine("Media has out bit marked, shouldn't"); if(response.CWP) sb.AppendLine("Media has write protection bit marked, shouldn't");
if(response.CWP)
sb.AppendLine("Media has write protection bit marked, shouldn't");
#endif #endif
} }
return sb.ToString(); return sb.ToString();
@@ -199,5 +188,4 @@ namespace DiscImageChef.Decoders.Bluray
} }
#endregion Public structures #endregion Public structures
} }
} }

View File

@@ -63,8 +63,7 @@ namespace DiscImageChef.Decoders.Bluray
#region Public methods #region Public methods
public static DiscDefinitionStructure? Decode(byte[] DDSResponse) public static DiscDefinitionStructure? Decode(byte[] DDSResponse)
{ {
if(DDSResponse == null) if(DDSResponse == null) return null;
return null;
DiscDefinitionStructure decoded = new DiscDefinitionStructure(); DiscDefinitionStructure decoded = new DiscDefinitionStructure();
@@ -76,10 +75,11 @@ namespace DiscImageChef.Decoders.Bluray
decoded.Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4); decoded.Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4);
if(decoded.Signature != DDSIdentifier) if(decoded.Signature != DDSIdentifier)
{ {
DicConsole.DebugWriteLine("BD DDS decoder", "Found incorrect DDS signature (0x{0:X4})", decoded.Signature); DicConsole.DebugWriteLine("BD DDS decoder", "Found incorrect DDS signature (0x{0:X4})",
decoded.Signature);
return null; return null;
} }
decoded.Format = DDSResponse[6]; decoded.Format = DDSResponse[6];
decoded.Reserved3 = DDSResponse[7]; decoded.Reserved3 = DDSResponse[7];
decoded.UpdateCount = BigEndianBitConverter.ToUInt32(DDSResponse, 8); decoded.UpdateCount = BigEndianBitConverter.ToUInt32(DDSResponse, 8);
@@ -109,8 +109,7 @@ namespace DiscImageChef.Decoders.Bluray
public static string Prettify(DiscDefinitionStructure? DDSResponse) public static string Prettify(DiscDefinitionStructure? DDSResponse)
{ {
if(DDSResponse == null) if(DDSResponse == null) return null;
return null;
DiscDefinitionStructure response = DDSResponse.Value; DiscDefinitionStructure response = DDSResponse.Value;
@@ -134,24 +133,15 @@ namespace DiscImageChef.Decoders.Bluray
sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80)); sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80));
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0) if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine();
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); if(response.Reserved4 != 0) sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine();
if(response.Reserved3 != 0) if(response.Reserved5 != 0) sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine();
sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); if(response.Reserved6 != 0) sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine();
if(response.Reserved4 != 0) if(response.Reserved7 != 0) sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine();
sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine(); if(response.Reserved8 != 0) sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine();
if(response.Reserved5 != 0) if(response.Reserved9 != 0) sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine();
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 #endif
return sb.ToString(); return sb.ToString();
@@ -294,5 +284,4 @@ namespace DiscImageChef.Decoders.Bluray
} }
#endregion Public structures #endregion Public structures
} }
} }

View File

@@ -68,12 +68,13 @@ namespace DiscImageChef.Decoders.Bluray
#region Public methods #region Public methods
public static DiscInformation? Decode(byte[] DIResponse) public static DiscInformation? Decode(byte[] DIResponse)
{ {
if(DIResponse == null) if(DIResponse == null) return null;
return null;
if(DIResponse.Length != 4100) if(DIResponse.Length != 4100)
{ {
DicConsole.DebugWriteLine("BD Disc Information decoder", "Found incorrect Blu-ray Disc Information size ({0} bytes)", DIResponse.Length); DicConsole.DebugWriteLine("BD Disc Information decoder",
"Found incorrect Blu-ray Disc Information size ({0} bytes)",
DIResponse.Length);
return null; return null;
} }
@@ -90,14 +91,12 @@ namespace DiscImageChef.Decoders.Bluray
while(true) while(true)
{ {
if(offset >= 100) if(offset >= 100) break;
break;
DiscInformationUnits unit = new DiscInformationUnits(); DiscInformationUnits unit = new DiscInformationUnits();
unit.Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset); unit.Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset);
if(unit.Signature != DIUIdentifier) if(unit.Signature != DIUIdentifier) break;
break;
unit.Format = DIResponse[2 + offset]; unit.Format = DIResponse[2 + offset];
unit.UnitsPerBlock = DIResponse[3 + offset]; unit.UnitsPerBlock = DIResponse[3 + offset];
@@ -111,29 +110,31 @@ namespace DiscImageChef.Decoders.Bluray
switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier))
{ {
case DiscTypeBDROM: case DiscTypeBDROM:
{ {
unit.FormatDependentContents = new byte[52]; unit.FormatDependentContents = new byte[52];
Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 52); Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 52);
break; break;
} }
case DiscTypeBDRE: case DiscTypeBDRE:
case DiscTypeBDR: case DiscTypeBDR:
{ {
unit.FormatDependentContents = new byte[88]; unit.FormatDependentContents = new byte[88];
Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 88); Array.Copy(DIResponse, 12 + offset, unit.DiscTypeIdentifier, 0, 88);
unit.ManufacturerID = new byte[6]; unit.ManufacturerID = new byte[6];
Array.Copy(DIResponse, 100 + offset, unit.ManufacturerID, 0, 6); Array.Copy(DIResponse, 100 + offset, unit.ManufacturerID, 0, 6);
unit.MediaTypeID = new byte[3]; unit.MediaTypeID = new byte[3];
Array.Copy(DIResponse, 106 + offset, unit.MediaTypeID, 0, 3); Array.Copy(DIResponse, 106 + offset, unit.MediaTypeID, 0, 3);
unit.TimeStamp = BigEndianBitConverter.ToUInt16(DIResponse, 109 + offset); unit.TimeStamp = BigEndianBitConverter.ToUInt16(DIResponse, 109 + offset);
unit.ProductRevisionNumber = DIResponse[111 + offset]; unit.ProductRevisionNumber = DIResponse[111 + offset];
break; break;
} }
default: default:
{ {
DicConsole.DebugWriteLine("BD Disc Information decoder", "Found unknown disc type identifier \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)); DicConsole.DebugWriteLine("BD Disc Information decoder",
break; "Found unknown disc type identifier \"{0}\"",
} Encoding.ASCII.GetString(unit.DiscTypeIdentifier));
break;
}
} }
units.Add(unit); units.Add(unit);
@@ -144,8 +145,7 @@ namespace DiscImageChef.Decoders.Bluray
if(units.Count > 0) if(units.Count > 0)
{ {
decoded.Units = new DiscInformationUnits[units.Count]; decoded.Units = new DiscInformationUnits[units.Count];
for(int i = 0; i < units.Count; i++) for(int i = 0; i < units.Count; i++) decoded.Units[i] = units[i];
decoded.Units[i] = units[i];
} }
return decoded; return decoded;
@@ -153,8 +153,7 @@ namespace DiscImageChef.Decoders.Bluray
public static string Prettify(DiscInformation? DIResponse) public static string Prettify(DiscInformation? DIResponse)
{ {
if(DIResponse == null) if(DIResponse == null) return null;
return null;
DiscInformation response = DIResponse.Value; DiscInformation response = DIResponse.Value;
@@ -168,13 +167,16 @@ namespace DiscImageChef.Decoders.Bluray
if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) != DiscTypeBDROM) if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) != DiscTypeBDROM)
sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine(); sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine();
sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine(); 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();
sb.AppendFormat("Disc size/class/version: {0}", unit.DiscSizeClassVersion).AppendLine(); sb.AppendFormat("Disc size/class/version: {0}", unit.DiscSizeClassVersion).AppendLine();
if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR || if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR ||
Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE)
{ {
sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)).AppendLine(); sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID))
sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)).AppendLine(); .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 timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine();
sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine(); sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine();
} }
@@ -292,5 +294,4 @@ namespace DiscImageChef.Decoders.Bluray
} }
#endregion Public structures #endregion Public structures
} }
} }

View File

@@ -56,12 +56,13 @@ namespace DiscImageChef.Decoders.Bluray
#region Public methods #region Public methods
public static SpareAreaInformation? Decode(byte[] SAIResponse) public static SpareAreaInformation? Decode(byte[] SAIResponse)
{ {
if(SAIResponse == null) if(SAIResponse == null) return null;
return null;
if(SAIResponse.Length != 16) if(SAIResponse.Length != 16)
{ {
DicConsole.DebugWriteLine("BD Spare Area Information decoder", "Found incorrect Blu-ray Spare Area Information size ({0} bytes)", SAIResponse.Length); DicConsole.DebugWriteLine("BD Spare Area Information decoder",
"Found incorrect Blu-ray Spare Area Information size ({0} bytes)",
SAIResponse.Length);
return null; return null;
} }
@@ -81,20 +82,16 @@ namespace DiscImageChef.Decoders.Bluray
public static string Prettify(SpareAreaInformation? SAIResponse) public static string Prettify(SpareAreaInformation? SAIResponse)
{ {
if(SAIResponse == null) if(SAIResponse == null) return null;
return null;
SpareAreaInformation response = SAIResponse.Value; SpareAreaInformation response = SAIResponse.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0) if(response.Reserved3 != 0) sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved3 != 0)
sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine();
#endif #endif
sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine(); sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine();
sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine(); sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine();
@@ -144,5 +141,4 @@ namespace DiscImageChef.Decoders.Bluray
} }
#endregion Public structures #endregion Public structures
} }
} }

View File

@@ -219,8 +219,7 @@ namespace DiscImageChef.Decoders.CD
public static CDATIP? Decode(byte[] CDATIPResponse) public static CDATIP? Decode(byte[] CDATIPResponse)
{ {
if(CDATIPResponse == null) if(CDATIPResponse == null) return null;
return null;
CDATIP decoded = new CDATIP(); CDATIP decoded = new CDATIP();
@@ -228,7 +227,9 @@ namespace DiscImageChef.Decoders.CD
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); DicConsole.DebugWriteLine("CD ATIP decoder",
"Expected CD ATIP size (32 bytes) is not received size ({0} bytes), not decoding",
CDATIPResponse.Length);
return null; return null;
} }
@@ -283,8 +284,7 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDATIP? CDATIPResponse) public static string Prettify(CDATIP? CDATIPResponse)
{ {
if(CDATIPResponse == null) if(CDATIPResponse == null) return null;
return null;
CDATIP response = CDATIPResponse.Value; CDATIP response = CDATIPResponse.Value;
@@ -293,10 +293,8 @@ namespace DiscImageChef.Decoders.CD
if(response.DDCD) if(response.DDCD)
{ {
sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine(); sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine();
if(response.DiscType) if(response.DiscType) sb.AppendLine("Disc is DDCD-RW");
sb.AppendLine("Disc is DDCD-RW"); else sb.AppendLine("Disc is DDCD-R");
else
sb.AppendLine("Disc is DDCD-R");
switch(response.ReferenceSpeed) switch(response.ReferenceSpeed)
{ {
case 2: case 2:
@@ -309,9 +307,16 @@ namespace DiscImageChef.Decoders.CD
sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine();
break; 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("ATIP Start time of Lead-in: 0x{0:X6}",
sb.AppendFormat("S4 value: 0x{0:X6}", (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).AppendLine(); (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();
} }
else else
{ {
@@ -354,7 +359,8 @@ namespace DiscImageChef.Decoders.CD
sb.AppendLine("Reference speed is 2x"); sb.AppendLine("Reference speed is 2x");
break; break;
default: default:
sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed)
.AppendLine();
break; break;
} }
} }
@@ -393,21 +399,30 @@ namespace DiscImageChef.Decoders.CD
} }
} }
if(response.URU) if(response.URU) sb.AppendLine("Disc use is unrestricted");
sb.AppendLine("Disc use is unrestricted"); else sb.AppendLine("Disc use is restricted");
else
sb.AppendLine("Disc use is restricted");
sb.AppendFormat("ATIP Start time of Lead-in: {0}:{1:D2}:{2:D2}", response.LeadInStartMin, response.LeadInStartSec, response.LeadInStartFrame).AppendLine(); sb.AppendFormat("ATIP Start time of Lead-in: {0}:{1:D2}:{2:D2}", response.LeadInStartMin,
sb.AppendFormat("ATIP Last possible start time of Lead-out: {0}:{1:D2}:{2:D2}", response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame).AppendLine(); 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();
if(response.A1Valid) if(response.A1Valid)
sb.AppendFormat("A1 value: 0x{0:X6}", (response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]).AppendLine(); sb.AppendFormat("A1 value: 0x{0:X6}",
(response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2])
.AppendLine();
if(response.A2Valid) if(response.A2Valid)
sb.AppendFormat("A2 value: 0x{0:X6}", (response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]).AppendLine(); sb.AppendFormat("A2 value: 0x{0:X6}",
(response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2])
.AppendLine();
if(response.A3Valid) if(response.A3Valid)
sb.AppendFormat("A3 value: 0x{0:X6}", (response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]).AppendLine(); sb.AppendFormat("A3 value: 0x{0:X6}",
(response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2])
.AppendLine();
if(response.S4Values != null) if(response.S4Values != null)
sb.AppendFormat("S4 value: 0x{0:X6}", (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]).AppendLine(); sb.AppendFormat("S4 value: 0x{0:X6}",
(response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2])
.AppendLine();
} }
if(response.LeadInStartMin == 97) if(response.LeadInStartMin == 97)
@@ -416,20 +431,16 @@ namespace DiscImageChef.Decoders.CD
int frm = response.LeadInStartFrame - type; int frm = response.LeadInStartFrame - type;
string manufacturer = ""; string manufacturer = "";
if(response.DiscType) if(response.DiscType) sb.AppendLine("Disc uses phase change");
sb.AppendLine("Disc uses phase change");
else else
{ {
if(type < 5) if(type < 5) sb.AppendLine("Disc uses long strategy type dye (Cyanine, AZO, etc...)");
sb.AppendLine("Disc uses long strategy type dye (Cyanine, AZO, etc...)"); else sb.AppendLine("Disc uses short strategy type dye (Phthalocyanine, etc...)");
else
sb.AppendLine("Disc uses short strategy type dye (Phthalocyanine, etc...)");
} }
manufacturer = ManufacturerFromATIP(response.LeadInStartSec, frm); manufacturer = ManufacturerFromATIP(response.LeadInStartSec, frm);
if(manufacturer != "") if(manufacturer != "") sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine();
sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine();
} }
return sb.ToString(); return sb.ToString();
@@ -446,285 +457,198 @@ namespace DiscImageChef.Decoders.CD
switch(sec) switch(sec)
{ {
case 15: case 15:
if(frm == 00) if(frm == 00) return "TDK Corporation";
return "TDK Corporation"; if(frm == 10) return "Ritek Co.";
if(frm == 10) if(frm == 20) return "Mitsubishi Chemical Corporation";
return "Ritek Co."; if(frm == 30) return "NAN-YA Plastics Corporation";
if(frm == 20)
return "Mitsubishi Chemical Corporation";
if(frm == 30)
return "NAN-YA Plastics Corporation";
break; break;
case 16: case 16:
if(frm == 20) if(frm == 20) return "Shenzen SG&Gast Digital Optical Discs";
return "Shenzen SG&Gast Digital Optical Discs"; if(frm == 30) return "Grand Advance Technology Ltd.";
if(frm == 30)
return "Grand Advance Technology Ltd.";
break; break;
case 17: case 17:
if(frm == 00) if(frm == 00) return "Moser Baer India Limited";
return "Moser Baer India Limited";
break; break;
case 18: case 18:
if(frm == 10) if(frm == 10) return "Wealth Fair Investment Ltd.";
return "Wealth Fair Investment Ltd."; if(frm == 60) return "Taroko International Co. Ltd.";
if(frm == 60)
return "Taroko International Co. Ltd.";
break; break;
case 20: case 20:
if(frm == 10) if(frm == 10) return "CDA Datenträger Albrechts GmbH";
return "CDA Datenträger Albrechts GmbH";
break; break;
case 21: case 21:
if(frm == 10) if(frm == 10) return "Grupo Condor S.L.";
return "Grupo Condor S.L."; if(frm == 30) return "Bestdisc Technology Corporation";
if(frm == 30) if(frm == 40) return "Optical Disc Manufacturing Equipment";
return "Bestdisc Technology Corporation"; if(frm == 50) return "Sound Sound Multi-Media Development Ltd.";
if(frm == 40)
return "Optical Disc Manufacturing Equipment";
if(frm == 50)
return "Sound Sound Multi-Media Development Ltd.";
break; break;
case 22: case 22:
if(frm == 00) if(frm == 00) return "Woongjin Media Corp.";
return "Woongjin Media Corp."; if(frm == 10) return "Seantram Technology Inc.";
if(frm == 10) if(frm == 20) return "Advanced Digital Media";
return "Seantram Technology Inc."; if(frm == 30) return "EXIMPO";
if(frm == 20) if(frm == 40) return "CIS Technology Inc.";
return "Advanced Digital Media"; if(frm == 50) return "Hong Kong Digital Technology Co., Ltd.";
if(frm == 30) if(frm == 60) return "Acer Media Technology, Inc.";
return "EXIMPO";
if(frm == 40)
return "CIS Technology Inc.";
if(frm == 50)
return "Hong Kong Digital Technology Co., Ltd.";
if(frm == 60)
return "Acer Media Technology, Inc.";
break; break;
case 23: case 23:
if(frm == 00) if(frm == 00) return "Matsushita Electric Industrial Co., Ltd.";
return "Matsushita Electric Industrial Co., Ltd."; if(frm == 10) return "Doremi Media Co., Ltd.";
if(frm == 10) if(frm == 20) return "Nacar Media s.r.l.";
return "Doremi Media Co., Ltd."; if(frm == 30) return "Audio Distributors Co., Ltd.";
if(frm == 20) if(frm == 40) return "Victor Company of Japan, Ltd.";
return "Nacar Media s.r.l."; if(frm == 50) return "Optrom Inc.";
if(frm == 30) if(frm == 60) return "Customer Pressing Oosterhout";
return "Audio Distributors Co., Ltd.";
if(frm == 40)
return "Victor Company of Japan, Ltd.";
if(frm == 50)
return "Optrom Inc.";
if(frm == 60)
return "Customer Pressing Oosterhout";
break; break;
case 24: case 24:
if(frm == 00) if(frm == 00) return "Taiyo Yuden Company Ltd.";
return "Taiyo Yuden Company Ltd."; if(frm == 10) return "SONY Corporation";
if(frm == 10) if(frm == 20) return "Computer Support Italy s.r.l.";
return "SONY Corporation"; if(frm == 30) return "Unitech Japan Inc.";
if(frm == 20) if(frm == 40) return "kdg mediatech AG";
return "Computer Support Italy s.r.l."; if(frm == 50) return "Guann Yinn Co., Ltd.";
if(frm == 30) if(frm == 60) return "Harmonic Hall Optical Disc Ltd.";
return "Unitech Japan Inc.";
if(frm == 40)
return "kdg mediatech AG";
if(frm == 50)
return "Guann Yinn Co., Ltd.";
if(frm == 60)
return "Harmonic Hall Optical Disc Ltd.";
break; break;
case 25: case 25:
if(frm == 00) if(frm == 00) return "MPO";
return "MPO"; if(frm == 20) return "Hitachi Maxell, Ltd.";
if(frm == 20) if(frm == 30) return "Infodisc Technology Co. Ltd.";
return "Hitachi Maxell, Ltd."; if(frm == 40) return "Vivastar AG";
if(frm == 30) if(frm == 50) return "AMS Technology Inc.";
return "Infodisc Technology Co. Ltd."; if(frm == 60) return "Xcitec Inc.";
if(frm == 40)
return "Vivastar AG";
if(frm == 50)
return "AMS Technology Inc.";
if(frm == 60)
return "Xcitec Inc.";
break; break;
case 26: case 26:
if(frm == 00) if(frm == 00) return "Fornet International Pte Ltd.";
return "Fornet International Pte Ltd."; if(frm == 10) return "POSTECH Corporation";
if(frm == 10) if(frm == 20) return "SKC Co., Ltd.";
return "POSTECH Corporation"; if(frm == 30) return "Optical Disc Corporation";
if(frm == 20) if(frm == 40) return "FUJI Photo Film Co., Ltd.";
return "SKC Co., Ltd."; if(frm == 50) return "Lead Data Inc.";
if(frm == 30) if(frm == 60) return "CMC Magnetics Corporation";
return "Optical Disc Corporation";
if(frm == 40)
return "FUJI Photo Film Co., Ltd.";
if(frm == 50)
return "Lead Data Inc.";
if(frm == 60)
return "CMC Magnetics Corporation";
break; break;
case 27: case 27:
if(frm == 00) if(frm == 00) return "Digital Storage Technology Co., Ltd.";
return "Digital Storage Technology Co., Ltd."; if(frm == 10) return "Plasmon Data systems Ltd.";
if(frm == 10) if(frm == 20) return "Princo Corporation";
return "Plasmon Data systems Ltd."; if(frm == 30) return "Pioneer Video Corporation";
if(frm == 20) if(frm == 40) return "Kodak Japan Ltd.";
return "Princo Corporation"; if(frm == 50) return "Mitsui Chemicals, Inc.";
if(frm == 30) if(frm == 60) return "Ricoh Company Ltd.";
return "Pioneer Video Corporation";
if(frm == 40)
return "Kodak Japan Ltd.";
if(frm == 50)
return "Mitsui Chemicals, Inc.";
if(frm == 60)
return "Ricoh Company Ltd.";
break; break;
case 28: case 28:
if(frm == 00) if(frm == 00) return "Opti.Me.S. S.p.A.";
return "Opti.Me.S. S.p.A."; if(frm == 10) return "Gigastore Corporation";
if(frm == 10) if(frm == 20) return "Multi Media Masters & Machinary SA";
return "Gigastore Corporation"; if(frm == 30) return "Auvistar Industry Co., Ltd.";
if(frm == 20) if(frm == 40) return "King Pro Mediatek Inc.";
return "Multi Media Masters & Machinary SA"; if(frm == 50) return "Delphi Technology Inc.";
if(frm == 30) if(frm == 60) return "Friendly CD-Tek Co.";
return "Auvistar Industry Co., Ltd.";
if(frm == 40)
return "King Pro Mediatek Inc.";
if(frm == 50)
return "Delphi Technology Inc.";
if(frm == 60)
return "Friendly CD-Tek Co.";
break; break;
case 29: case 29:
if(frm == 00) if(frm == 00) return "Taeil Media Co., Ltd.";
return "Taeil Media Co., Ltd."; if(frm == 10) return "Vanguard Disc Inc.";
if(frm == 10) if(frm == 20) return "Unidisc Technology Co., Ltd.";
return "Vanguard Disc Inc."; if(frm == 30) return "Hile Optical Disc Technology Corp.";
if(frm == 20) if(frm == 40) return "Viva Magnetics Ltd.";
return "Unidisc Technology Co., Ltd."; if(frm == 50) return "General Magnetics Ltd.";
if(frm == 30)
return "Hile Optical Disc Technology Corp.";
if(frm == 40)
return "Viva Magnetics Ltd.";
if(frm == 50)
return "General Magnetics Ltd.";
break; break;
case 30: case 30:
if(frm == 10) if(frm == 10) return "CDA Datenträger Albrechts GmbH";
return "CDA Datenträger Albrechts GmbH";
break; break;
case 31: case 31:
if(frm == 00) if(frm == 00) return "Ritek Co.";
return "Ritek Co."; if(frm == 30) return "Grand Advance Technology Ltd.";
if(frm == 30)
return "Grand Advance Technology Ltd.";
break; break;
case 32: case 32:
if(frm == 00) if(frm == 00) return "TDK Corporation";
return "TDK Corporation"; if(frm == 10) return "Prodisc Technology Inc.";
if(frm == 10)
return "Prodisc Technology Inc.";
break; break;
case 34: case 34:
if(frm == 20) if(frm == 20) return "Mitsubishi Chemical Corporation";
return "Mitsubishi Chemical Corporation";
break; break;
case 42: case 42:
if(frm == 20) if(frm == 20) return "Advanced Digital Media";
return "Advanced Digital Media";
break; break;
case 45: case 45:
if(frm == 00) if(frm == 00) return "Fornet International Pte Ltd.";
return "Fornet International Pte Ltd."; if(frm == 10) return "Unitech Japan Inc.";
if(frm == 10) if(frm == 20) return "Acer Media Technology, Inc.";
return "Unitech Japan Inc."; if(frm == 40) return "CIS Technology Inc.";
if(frm == 20) if(frm == 50) return "Guann Yinn Co., Ltd.";
return "Acer Media Technology, Inc."; if(frm == 60) return "Xcitec Inc.";
if(frm == 40)
return "CIS Technology Inc.";
if(frm == 50)
return "Guann Yinn Co., Ltd.";
if(frm == 60)
return "Xcitec Inc.";
break; break;
case 46: case 46:
if(frm == 00) if(frm == 00) return "Taiyo Yuden Company Ltd.";
return "Taiyo Yuden Company Ltd."; if(frm == 10) return "Hong Kong Digital Technology Co., Ltd.";
if(frm == 10) if(frm == 20) return "Multi Media Masters & Machinary SA";
return "Hong Kong Digital Technology Co., Ltd."; if(frm == 30) return "Computer Support Italy s.r.l.";
if(frm == 20) if(frm == 40) return "FUJI Photo Film Co., Ltd.";
return "Multi Media Masters & Machinary SA"; if(frm == 50) return "Auvistar Industry Co., Ltd.";
if(frm == 30) if(frm == 60) return "CMC Magnetics Corporation";
return "Computer Support Italy s.r.l.";
if(frm == 40)
return "FUJI Photo Film Co., Ltd.";
if(frm == 50)
return "Auvistar Industry Co., Ltd.";
if(frm == 60)
return "CMC Magnetics Corporation";
break; break;
case 47: case 47:
if(frm == 10) if(frm == 10) return "Hitachi Maxell, Ltd.";
return "Hitachi Maxell, Ltd."; if(frm == 20) return "Princo Corporation";
if(frm == 20) if(frm == 40) return "POSTECH Corporation";
return "Princo Corporation"; if(frm == 50) return "Ritek Co.";
if(frm == 40) if(frm == 60) return "Prodisc Technology Inc.";
return "POSTECH Corporation";
if(frm == 50)
return "Ritek Co.";
if(frm == 60)
return "Prodisc Technology Inc.";
break; break;
case 48: case 48:
if(frm == 00) if(frm == 00) return "Ricoh Company Ltd.";
return "Ricoh Company Ltd."; if(frm == 10) return "Kodak Japan Ltd.";
if(frm == 10) if(frm == 20) return "Plasmon Data systems Ltd.";
return "Kodak Japan Ltd."; if(frm == 30) return "Pioneer Video Corporation";
if(frm == 20) if(frm == 40) return "Digital Storage Technology Co., Ltd.";
return "Plasmon Data systems Ltd."; if(frm == 50) return "Mitsui Chemicals, Inc.";
if(frm == 30) if(frm == 60) return "Lead Data Inc.";
return "Pioneer Video Corporation";
if(frm == 40)
return "Digital Storage Technology Co., Ltd.";
if(frm == 50)
return "Mitsui Chemicals, Inc.";
if(frm == 60)
return "Lead Data Inc.";
break; break;
case 49: case 49:
if(frm == 00) if(frm == 00) return "TDK Corporation";
return "TDK Corporation"; if(frm == 10) return "Gigastore Corporation";
if(frm == 10) if(frm == 20) return "King Pro Mediatek Inc.";
return "Gigastore Corporation"; if(frm == 30) return "Opti.Me.S. S.p.A.";
if(frm == 20) if(frm == 40) return "Victor Company of Japan, Ltd.";
return "King Pro Mediatek Inc."; if(frm == 60) return "Matsushita Electric Industrial Co., Ltd.";
if(frm == 30)
return "Opti.Me.S. S.p.A.";
if(frm == 40)
return "Victor Company of Japan, Ltd.";
if(frm == 60)
return "Matsushita Electric Industrial Co., Ltd.";
break; break;
case 50: case 50:
if(frm == 10) if(frm == 10) return "Vanguard Disc Inc.";
return "Vanguard Disc Inc."; if(frm == 20) return "Mitsubishi Chemical Corporation";
if(frm == 20) if(frm == 30) return "CDA Datenträger Albrechts GmbH";
return "Mitsubishi Chemical Corporation";
if(frm == 30)
return "CDA Datenträger Albrechts GmbH";
break; break;
case 51: case 51:
if(frm == 10) if(frm == 10) return "Grand Advance Technology Ltd.";
return "Grand Advance Technology Ltd."; if(frm == 20) return "Infodisc Technology Co. Ltd.";
if(frm == 20) if(frm == 50) return "Hile Optical Disc Technology Corp.";
return "Infodisc Technology Co. Ltd.";
if(frm == 50)
return "Hile Optical Disc Technology Corp.";
break; break;
} }
return ""; return "";
} }
} }
} }

View File

@@ -187,8 +187,7 @@ namespace DiscImageChef.Decoders.CD
public static CDText? Decode(byte[] CDTextResponse) public static CDText? Decode(byte[] CDTextResponse)
{ {
if(CDTextResponse == null) if(CDTextResponse == null) return null;
return null;
CDText decoded = new CDText(); CDText decoded = new CDText();
@@ -199,12 +198,13 @@ namespace DiscImageChef.Decoders.CD
decoded.Reserved2 = CDTextResponse[3]; decoded.Reserved2 = CDTextResponse[3];
decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18]; decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18];
if(decoded.DataLength == 2) if(decoded.DataLength == 2) return null;
return null;
if(decoded.DataLength + 2 != CDTextResponse.Length) 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); 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; return null;
} }
@@ -226,17 +226,14 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDText? CDTextResponse) public static string Prettify(CDText? CDTextResponse)
{ {
if(CDTextResponse == null) if(CDTextResponse == null) return null;
return null;
CDText response = CDTextResponse.Value; CDText response = CDTextResponse.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0)
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
#endif #endif
foreach(CDTextPack descriptor in response.DataPacks) foreach(CDTextPack descriptor in response.DataPacks)
@@ -245,110 +242,97 @@ namespace DiscImageChef.Decoders.CD
{ {
// Ignore NOPs // Ignore NOPs
if((descriptor.HeaderID1 & 0x80) != 0) 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 else
{ {
switch(descriptor.HeaderID1) switch(descriptor.HeaderID1)
{ {
case 0x80: case 0x80:
{ {
sb.Append("CD-Text pack contains title for "); sb.Append("CD-Text pack contains title for ");
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x81: case 0x81:
{ {
sb.Append("CD-Text pack contains performer for "); sb.Append("CD-Text pack contains performer for ");
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x82: case 0x82:
{ {
sb.Append("CD-Text pack contains songwriter for "); sb.Append("CD-Text pack contains songwriter for ");
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x83: case 0x83:
{ {
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x84: case 0x84:
{ {
sb.Append("CD-Text pack contains arranger for "); sb.Append("CD-Text pack contains arranger for ");
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x85: case 0x85:
{ {
sb.Append("CD-Text pack contains content provider's message for "); sb.Append("CD-Text pack contains content provider's message for ");
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("album");
sb.AppendLine("album"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x86: case 0x86:
{ {
sb.AppendLine("CD-Text pack contains disc identification information"); sb.AppendLine("CD-Text pack contains disc identification information");
break; break;
} }
case 0x87: case 0x87:
{ {
sb.AppendLine("CD-Text pack contains genre identification information"); sb.AppendLine("CD-Text pack contains genre identification information");
break; break;
} }
case 0x88: case 0x88:
{ {
sb.AppendLine("CD-Text pack contains table of contents information"); sb.AppendLine("CD-Text pack contains table of contents information");
break; break;
} }
case 0x89: case 0x89:
{ {
sb.AppendLine("CD-Text pack contains second table of contents information"); sb.AppendLine("CD-Text pack contains second table of contents information");
break; break;
} }
case 0x8A: case 0x8A:
case 0x8B: case 0x8B:
case 0x8C: case 0x8C:
{ {
sb.AppendLine("CD-Text pack contains reserved data"); sb.AppendLine("CD-Text pack contains reserved data");
break; break;
} }
case 0x8D: case 0x8D:
{ {
sb.AppendLine("CD-Text pack contains data reserved for content provider only"); sb.AppendLine("CD-Text pack contains data reserved for content provider only");
break; break;
} }
case 0x8E: case 0x8E:
{ {
if(descriptor.HeaderID2 == 0x00) if(descriptor.HeaderID2 == 0x00) sb.AppendLine("CD-Text pack contains UPC");
sb.AppendLine("CD-Text pack contains UPC"); else sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine();
else break;
sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); }
break;
}
case 0x8F: case 0x8F:
{ {
sb.AppendLine("CD-Text pack contains size block information"); sb.AppendLine("CD-Text pack contains size block information");
break; break;
} }
} }
switch(descriptor.HeaderID1) switch(descriptor.HeaderID1)
@@ -362,19 +346,22 @@ namespace DiscImageChef.Decoders.CD
case 0x86: case 0x86:
case 0x87: case 0x87:
case 0x8E: case 0x8E:
{ {
if(descriptor.DBCC) if(descriptor.DBCC) sb.AppendLine("Double Byte Character Code is used");
sb.AppendLine("Double Byte Character Code is used"); sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine();
sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine(); sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine();
sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine(); sb.AppendFormat("Text field: \"{0}\"",
sb.AppendFormat("Text field: \"{0}\"", StringHandlers.CToString(descriptor.TextDataField, Encoding.GetEncoding("iso-8859-1"))).AppendLine(); StringHandlers.CToString(descriptor.TextDataField,
break; Encoding.GetEncoding("iso-8859-1"))).AppendLine();
} break;
}
default: default:
{ {
sb.AppendFormat("Binary contents: {0}", PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)).AppendLine(); sb.AppendFormat("Binary contents: {0}",
break; PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28))
} .AppendLine();
break;
}
} }
sb.AppendFormat("CRC: 0x{0:X4}", descriptor.CRC).AppendLine(); sb.AppendFormat("CRC: 0x{0:X4}", descriptor.CRC).AppendLine();
@@ -390,5 +377,4 @@ namespace DiscImageChef.Decoders.CD
return Prettify(decoded); return Prettify(decoded);
} }
} }
} }

View File

@@ -95,5 +95,4 @@ namespace DiscImageChef.Decoders.CD
/// </summary> /// </summary>
ReservedMask = 0x0C ReservedMask = 0x0C
} }
} }

View File

@@ -147,8 +147,7 @@ namespace DiscImageChef.Decoders.CD
public static CDFullTOC? Decode(byte[] CDFullTOCResponse) public static CDFullTOC? Decode(byte[] CDFullTOCResponse)
{ {
if(CDFullTOCResponse == null) if(CDFullTOCResponse == null) return null;
return null;
CDFullTOC decoded = new CDFullTOC(); CDFullTOC decoded = new CDFullTOC();
@@ -161,7 +160,9 @@ namespace DiscImageChef.Decoders.CD
if(decoded.DataLength + 2 != CDFullTOCResponse.Length) if(decoded.DataLength + 2 != CDFullTOCResponse.Length)
{ {
DicConsole.DebugWriteLine("CD full TOC decoder", "Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDFullTOCResponse.Length); 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; return null;
} }
@@ -188,8 +189,7 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDFullTOC? CDFullTOCResponse) public static string Prettify(CDFullTOC? CDFullTOCResponse)
{ {
if(CDFullTOCResponse == null) if(CDFullTOCResponse == null) return null;
return null;
CDFullTOC response = CDFullTOCResponse.Value; CDFullTOC response = CDFullTOCResponse.Value;
@@ -202,8 +202,8 @@ namespace DiscImageChef.Decoders.CD
foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) foreach(TrackDataDescriptor descriptor in response.TrackDescriptors)
{ {
if((descriptor.CONTROL & 0x08) == 0x08 || if((descriptor.CONTROL & 0x08) == 0x08 ||
(descriptor.ADR != 1 && descriptor.ADR != 5 && descriptor.ADR != 4 && descriptor.ADR != 6) || (descriptor.ADR != 1 && descriptor.ADR != 5 && descriptor.ADR != 4 && descriptor.ADR != 6) ||
descriptor.TNO != 0) descriptor.TNO != 0)
{ {
sb.AppendLine("Unknown TOC entry format, printing values as-is"); sb.AppendLine("Unknown TOC entry format, printing values as-is");
sb.AppendFormat("SessionNumber = {0}", descriptor.SessionNumber).AppendLine(); sb.AppendFormat("SessionNumber = {0}", descriptor.SessionNumber).AppendLine();
@@ -232,308 +232,365 @@ namespace DiscImageChef.Decoders.CD
{ {
case 1: case 1:
case 4: case 4:
{
switch(descriptor.POINT)
{ {
switch(descriptor.POINT) case 0xA0:
{ {
case 0xA0: if(descriptor.ADR == 4)
{
sb.AppendFormat("First video track number: {0}", descriptor.PMIN).AppendLine();
switch(descriptor.PSEC)
{ {
if(descriptor.ADR == 4) case 0x10:
{ sb.AppendLine("CD-V single in NTSC format with digital stereo sound");
sb.AppendFormat("First video track number: {0}", descriptor.PMIN).AppendLine(); break;
switch(descriptor.PSEC) case 0x11:
{ sb.AppendLine("CD-V single in NTSC format with digital bilingual sound");
case 0x10: break;
sb.AppendLine("CD-V single in NTSC format with digital stereo sound"); case 0x12:
break; sb.AppendLine("CD-V disc in NTSC format with digital stereo sound");
case 0x11: break;
sb.AppendLine("CD-V single in NTSC format with digital bilingual sound"); case 0x13:
break; sb.AppendLine("CD-V disc in NTSC format with digital bilingual sound");
case 0x12: break;
sb.AppendLine("CD-V disc in NTSC format with digital stereo sound"); case 0x20:
break; sb.AppendLine("CD-V single in PAL format with digital stereo sound");
case 0x13: break;
sb.AppendLine("CD-V disc in NTSC format with digital bilingual sound"); case 0x21:
break; sb.AppendLine("CD-V single in PAL format with digital bilingual sound");
case 0x20: break;
sb.AppendLine("CD-V single in PAL format with digital stereo sound"); case 0x22:
break; sb.AppendLine("CD-V disc in PAL format with digital stereo sound");
case 0x21: break;
sb.AppendLine("CD-V single in PAL format with digital bilingual sound"); case 0x23:
break; sb.AppendLine("CD-V disc in PAL format with digital bilingual sound");
case 0x22: break;
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;
}
}
else
{
sb.AppendFormat("First track number: {0} (", descriptor.PMIN);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{
case TOC_CONTROL.TwoChanNoPreEmph:
sb.Append(StereoNoPre);
break;
case TOC_CONTROL.TwoChanPreEmph:
sb.Append(StereoPreEm);
break;
case TOC_CONTROL.FourChanNoPreEmph:
sb.Append(QuadNoPreEm);
break;
case TOC_CONTROL.FourChanPreEmph:
sb.Append(QuadPreEmph);
break;
case TOC_CONTROL.DataTrack:
sb.Append(DataUnintrp);
break;
case TOC_CONTROL.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: }
else
{
sb.AppendFormat("First track number: {0} (", descriptor.PMIN);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{ {
if(descriptor.ADR == 4) case TOC_CONTROL.TwoChanNoPreEmph:
sb.AppendFormat("Last video track number: {0}", descriptor.PMIN).AppendLine(); sb.Append(StereoNoPre);
else break;
{ case TOC_CONTROL.TwoChanPreEmph:
sb.AppendFormat("Last track number: {0} (", descriptor.PMIN); sb.Append(StereoPreEm);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D)) break;
{ case TOC_CONTROL.FourChanNoPreEmph:
case TOC_CONTROL.TwoChanNoPreEmph: sb.Append(QuadNoPreEm);
sb.Append(StereoNoPre); break;
break; case TOC_CONTROL.FourChanPreEmph:
case TOC_CONTROL.TwoChanPreEmph: sb.Append(QuadPreEmph);
sb.Append(StereoPreEm); break;
break; case TOC_CONTROL.DataTrack:
case TOC_CONTROL.FourChanNoPreEmph: sb.Append(DataUnintrp);
sb.Append(QuadNoPreEm); break;
break; case TOC_CONTROL.DataTrackIncremental:
case TOC_CONTROL.FourChanPreEmph: sb.Append(DataIncrtly);
sb.Append(QuadPreEmph); break;
break;
case TOC_CONTROL.DataTrack:
sb.Append(DataUnintrp);
break;
case TOC_CONTROL.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;
} }
case 0xA2:
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:
{
if(descriptor.ADR == 4)
sb.AppendFormat("Last video track number: {0}", descriptor.PMIN).AppendLine();
else
{
sb.AppendFormat("Last track number: {0} (", descriptor.PMIN);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{ {
case TOC_CONTROL.TwoChanNoPreEmph:
sb.Append(StereoNoPre);
break;
case TOC_CONTROL.TwoChanPreEmph:
sb.Append(StereoPreEm);
break;
case TOC_CONTROL.FourChanNoPreEmph:
sb.Append(QuadNoPreEm);
break;
case TOC_CONTROL.FourChanPreEmph:
sb.Append(QuadPreEmph);
break;
case TOC_CONTROL.DataTrack:
sb.Append(DataUnintrp);
break;
case TOC_CONTROL.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;
}
case 0xA2:
{
if(descriptor.PHOUR > 0)
sb.AppendFormat("Lead-out start position: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
descriptor.PHOUR).AppendLine();
else
sb.AppendFormat("Lead-out start position: {0:D2}:{1:D2}:{2:D2}",
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((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{
case TOC_CONTROL.TwoChanNoPreEmph:
case TOC_CONTROL.TwoChanPreEmph:
case TOC_CONTROL.FourChanNoPreEmph:
case TOC_CONTROL.FourChanPreEmph:
sb.AppendLine("Lead-out is audio type");
break;
case TOC_CONTROL.DataTrack:
case TOC_CONTROL.DataTrackIncremental:
sb.AppendLine("Lead-out is data type");
break;
}
break;
}
case 0xF0:
{
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.ADR == 4)
sb.AppendFormat("Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}",
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
descriptor.POINT).AppendLine();
else
{
string type = "Audio";
if((TOC_CONTROL)(descriptor.CONTROL & 0x0D) == TOC_CONTROL.DataTrack ||
(TOC_CONTROL)(descriptor.CONTROL & 0x0D) ==
TOC_CONTROL.DataTrackIncremental) type = "Data";
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat("Lead-out start position: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR).AppendLine(); sb.AppendFormat("{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (",
descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
descriptor.POINT, descriptor.PHOUR, type);
else else
sb.AppendFormat("Lead-out start position: {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME).AppendLine(); sb.AppendFormat("{4} track {3} starts at: {0:D2}:{1:D2}:{2:D2} (",
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
descriptor.POINT, type);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D)) switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{ {
case TOC_CONTROL.TwoChanNoPreEmph: case TOC_CONTROL.TwoChanNoPreEmph:
sb.Append(StereoNoPre);
break;
case TOC_CONTROL.TwoChanPreEmph: case TOC_CONTROL.TwoChanPreEmph:
sb.Append(StereoPreEm);
break;
case TOC_CONTROL.FourChanNoPreEmph: case TOC_CONTROL.FourChanNoPreEmph:
sb.Append(QuadNoPreEm);
break;
case TOC_CONTROL.FourChanPreEmph: case TOC_CONTROL.FourChanPreEmph:
sb.AppendLine("Lead-out is audio type"); sb.Append(QuadPreEmph);
break; break;
case TOC_CONTROL.DataTrack: case TOC_CONTROL.DataTrack:
sb.Append(DataUnintrp);
break;
case TOC_CONTROL.DataTrackIncremental: case TOC_CONTROL.DataTrackIncremental:
sb.AppendLine("Lead-out is data type"); sb.Append(DataIncrtly);
break; break;
} }
break;
}
case 0xF0:
{
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.ADR == 4)
sb.AppendFormat("Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.POINT).AppendLine();
else
{
string type = "Audio";
if((TOC_CONTROL)(descriptor.CONTROL & 0x0D) == TOC_CONTROL.DataTrack || sb.AppendLine(")");
(TOC_CONTROL)(descriptor.CONTROL & 0x0D) == TOC_CONTROL.DataTrackIncremental)
type = "Data";
if(descriptor.PHOUR > 0)
sb.AppendFormat("{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.POINT, descriptor.PHOUR, type);
else
sb.AppendFormat("{4} track {3} starts at: {0:D2}:{1:D2}:{2:D2} (", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.POINT, type);
switch((TOC_CONTROL)(descriptor.CONTROL & 0x0D))
{
case TOC_CONTROL.TwoChanNoPreEmph:
sb.Append(StereoNoPre);
break;
case TOC_CONTROL.TwoChanPreEmph:
sb.Append(StereoPreEm);
break;
case TOC_CONTROL.FourChanNoPreEmph:
sb.Append(QuadNoPreEm);
break;
case TOC_CONTROL.FourChanPreEmph:
sb.Append(QuadPreEmph);
break;
case TOC_CONTROL.DataTrack:
sb.Append(DataUnintrp);
break;
case TOC_CONTROL.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();
}
else
{
sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine();
sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine();
sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine();
sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine();
sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine();
sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine();
sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine();
sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine();
sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine();
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
}
break;
} }
//sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine();
}
else
{
sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine();
sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine();
sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine();
sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine();
sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine();
sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine();
sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine();
sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine();
sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine();
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
}
break;
} }
break;
} }
break;
}
case 5: case 5:
{
switch(descriptor.POINT)
{ {
switch(descriptor.POINT) case 0xB0:
{ {
case 0xB0: if(descriptor.PHOUR > 0)
{ {
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(); descriptor.Min, descriptor.Sec, descriptor.Frame,
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(); descriptor.HOUR).AppendLine();
} sb
else .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,
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(); descriptor.PHOUR).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(); }
} else
break; {
} sb
case 0xB1: .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)
sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN).AppendLine(); .AppendLine();
sb.AppendFormat("Number of skip track pointers: {0}", descriptor.PSEC).AppendLine(); sb
break; .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)
case 0xB2: .AppendLine();
case 0xB3: }
case 0xB4: break;
{ }
sb.AppendFormat("Skip track {0}", descriptor.Min).AppendLine(); case 0xB1:
sb.AppendFormat("Skip track {0}", descriptor.Sec).AppendLine(); {
sb.AppendFormat("Skip track {0}", descriptor.Frame).AppendLine(); sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN)
sb.AppendFormat("Skip track {0}", descriptor.Zero).AppendLine(); .AppendLine();
sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine(); sb.AppendFormat("Number of skip track pointers: {0}", descriptor.PSEC).AppendLine();
sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine(); break;
sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine(); }
break; case 0xB2:
} case 0xB3:
case 0xC0: case 0xB4:
{ {
sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine(); sb.AppendFormat("Skip track {0}", descriptor.Min).AppendLine();
if(descriptor.PHOUR > 0) sb.AppendFormat("Skip track {0}", descriptor.Sec).AppendLine();
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(); sb.AppendFormat("Skip track {0}", descriptor.Frame).AppendLine();
else sb.AppendFormat("Skip track {0}", descriptor.Zero).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(); sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine();
break; sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine();
} sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine();
case 0xC1: break;
{ }
sb.AppendFormat("Copy of information of A1 from ATIP found"); case 0xC0:
sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); {
sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine();
sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); if(descriptor.PHOUR > 0)
sb.AppendFormat("Zero = {0}", descriptor.Zero).AppendLine(); sb
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); .AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); descriptor.PHOUR).AppendLine();
break; else
} sb
case 0xCF: .AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}",
{ descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
if(descriptor.PHOUR > 0) .AppendLine();
{ break;
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}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); case 0xC1:
} {
else sb.AppendFormat("Copy of information of A1 from ATIP found");
{ sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine();
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("Sec = {0}", descriptor.Sec).AppendLine();
sb.AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine();
} sb.AppendFormat("Zero = {0}", descriptor.Zero).AppendLine();
break; sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
} sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
default: sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
{ break;
if(descriptor.POINT >= 0x01 && descriptor.POINT <= 0x40) }
{ case 0xCF:
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(); if(descriptor.PHOUR > 0)
} {
else sb
{ .AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME,
sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); descriptor.PHOUR).AppendLine();
sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); sb
sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); .AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}",
sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); descriptor.Min, descriptor.Sec, descriptor.Frame,
sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); descriptor.HOUR).AppendLine();
sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); }
sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); else
sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); {
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); sb
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); .AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}",
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME)
} .AppendLine();
break; sb
} .AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}",
descriptor.Min, descriptor.Sec, descriptor.Frame)
.AppendLine();
}
break;
}
default:
{
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}",
descriptor.Min, descriptor.Sec, descriptor.Frame)
.AppendLine();
}
else
{
sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine();
sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine();
sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine();
sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine();
sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine();
sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine();
sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine();
sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine();
sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine();
sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine();
sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine();
sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine();
}
break;
} }
break;
} }
break;
}
case 6: case 6:
{ {
uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame);
sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine(); sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine();
break; break;
} }
} }
} }
} }
@@ -547,5 +604,4 @@ namespace DiscImageChef.Decoders.CD
return Prettify(decoded); return Prettify(decoded);
} }
} }
} }

View File

@@ -134,8 +134,7 @@ namespace DiscImageChef.Decoders.CD
public static CDPMA? Decode(byte[] CDPMAResponse) public static CDPMA? Decode(byte[] CDPMAResponse)
{ {
if(CDPMAResponse == null) if(CDPMAResponse == null) return null;
return null;
CDPMA decoded = new CDPMA(); CDPMA decoded = new CDPMA();
@@ -148,7 +147,9 @@ namespace DiscImageChef.Decoders.CD
if(decoded.DataLength + 2 != CDPMAResponse.Length) if(decoded.DataLength + 2 != CDPMAResponse.Length)
{ {
DicConsole.DebugWriteLine("CD PMA decoder", "Expected CDPMA size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDPMAResponse.Length); 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; return null;
} }
@@ -174,25 +175,21 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDPMA? CDPMAResponse) public static string Prettify(CDPMA? CDPMAResponse)
{ {
if(CDPMAResponse == null) if(CDPMAResponse == null) return null;
return null;
CDPMA response = CDPMAResponse.Value; CDPMA response = CDPMAResponse.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
#if DEBUG #if DEBUG
if(response.Reserved1 != 0) if(response.Reserved1 != 0) sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine();
sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); if(response.Reserved2 != 0) sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
if(response.Reserved2 != 0)
sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine();
#endif #endif
foreach(CDPMADescriptors descriptor in response.PMADescriptors) foreach(CDPMADescriptors descriptor in response.PMADescriptors)
{ {
#if DEBUG #if DEBUG
if(descriptor.Reserved != 0) if(descriptor.Reserved != 0) sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine();
sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine();
#endif #endif
switch(descriptor.ADR) switch(descriptor.ADR)
@@ -222,19 +219,24 @@ namespace DiscImageChef.Decoders.CD
sb.Append(" (Data track, recorded incrementally)"); sb.Append(" (Data track, recorded incrementally)");
break; break;
} }
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat(" starts at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR); sb.AppendFormat(" starts at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME, descriptor.PHOUR);
else else
sb.AppendFormat(" starts at {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); sb.AppendFormat(" starts at {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME);
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat(" and ends at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); sb.AppendFormat(" and ends at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec,
descriptor.Frame, descriptor.HOUR);
else else
sb.AppendFormat(" and ends at {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame); sb.AppendFormat(" and ends at {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec,
descriptor.Frame);
sb.AppendLine(); sb.AppendLine();
} }
else else goto default;
goto default;
break; break;
case 2: case 2:
uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame);
@@ -242,58 +244,50 @@ namespace DiscImageChef.Decoders.CD
break; break;
case 3: case 3:
sb.AppendFormat("Skip track assignment {0} says that tracks ", descriptor.POINT); sb.AppendFormat("Skip track assignment {0} says that tracks ", descriptor.POINT);
if(descriptor.Min > 0) if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min);
sb.AppendFormat("{0} ", descriptor.Min); if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec);
if(descriptor.Sec > 0) if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame);
sb.AppendFormat("{0} ", descriptor.Sec); if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN);
if(descriptor.Frame > 0) if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC);
sb.AppendFormat("{0} ", descriptor.Frame); if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME);
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"); sb.AppendLine("should be skipped");
break; break;
case 4: case 4:
sb.AppendFormat("Unskip track assignment {0} says that tracks ", descriptor.POINT); sb.AppendFormat("Unskip track assignment {0} says that tracks ", descriptor.POINT);
if(descriptor.Min > 0) if(descriptor.Min > 0) sb.AppendFormat("{0} ", descriptor.Min);
sb.AppendFormat("{0} ", descriptor.Min); if(descriptor.Sec > 0) sb.AppendFormat("{0} ", descriptor.Sec);
if(descriptor.Sec > 0) if(descriptor.Frame > 0) sb.AppendFormat("{0} ", descriptor.Frame);
sb.AppendFormat("{0} ", descriptor.Sec); if(descriptor.PMIN > 0) sb.AppendFormat("{0} ", descriptor.PMIN);
if(descriptor.Frame > 0) if(descriptor.PSEC > 0) sb.AppendFormat("{0} ", descriptor.PSEC);
sb.AppendFormat("{0} ", descriptor.Frame); if(descriptor.PFRAME > 0) sb.AppendFormat("{0} ", descriptor.PFRAME);
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"); sb.AppendLine("should not be skipped");
break; break;
case 5: case 5:
sb.AppendFormat("Skip time interval assignment {0} says that from ", descriptor.POINT); sb.AppendFormat("Skip time interval assignment {0} says that from ", descriptor.POINT);
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR); sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME, descriptor.PHOUR);
else else
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME);
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec,
else descriptor.Frame, descriptor.HOUR);
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"); sb.AppendLine("should be skipped");
break; break;
case 6: case 6:
sb.AppendFormat("Unskip time interval assignment {0} says that from ", descriptor.POINT); sb.AppendFormat("Unskip time interval assignment {0} says that from ", descriptor.POINT);
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, descriptor.PHOUR); sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME, descriptor.PHOUR);
else else
sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME); sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC,
descriptor.PFRAME);
if(descriptor.PHOUR > 0) if(descriptor.PHOUR > 0)
sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR); sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec,
else descriptor.Frame, descriptor.HOUR);
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"); sb.AppendLine("should not be skipped");
break; break;
default: default:
@@ -323,5 +317,4 @@ namespace DiscImageChef.Decoders.CD
return Prettify(decoded); return Prettify(decoded);
} }
} }
} }

View File

@@ -39,177 +39,155 @@ namespace DiscImageChef.Decoders.CD
{ {
public static readonly byte[] ScrambleTable = public static readonly byte[] ScrambleTable =
{ {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x28,
0x00, 0x28, 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E, 0x9E, 0x88,
0x28, 0x1E, 0x9E, 0x88, 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0, 0x0E, 0xC8, 0x04,
0x80, 0x16, 0xE0, 0x0E, 0xC8, 0x04, 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC, 0x52, 0xD5, 0xFD, 0x9F,
0xF6, 0xEE, 0xC6, 0xCC, 0x52, 0xD5, 0xFD, 0x9F, 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28, 0x62, 0x9E, 0xA9, 0xA8, 0x7E,
0x28, 0x0A, 0x9E, 0x87, 0x28, 0x62, 0x9E, 0xA9, 0xA8, 0x7E, 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38,
0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38, 0x48, 0x12, 0xB6, 0x8D, 0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B,
0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B, 0x3B, 0x53, 0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66, 0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E,
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,
0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4, 0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84,
0x7C, 0x69, 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42,
0x88, 0x0F, 0x26, 0x84, 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, 0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4,
0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42, 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, 0x68, 0x1A, 0xAE, 0x8B, 0x14, 0x47, 0x4F, 0x72, 0xB4, 0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D,
0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4, 0x14, 0x47, 0x4F, 0x72, 0xB4, 0x25, 0xB7, 0x5B, 0xC6, 0x91, 0x92, 0xEC, 0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E,
0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D, 0xC6, 0x91, 0x92, 0xEC, 0x6D, 0x8D, 0x81, 0xE0, 0x60, 0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28,
0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E, 0x81, 0xE0, 0x60, 0x48, 0x60, 0x1E, 0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0,
0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28, 0x60, 0x1E, 0x76, 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4,
0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0, 0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31, 0xCD,
0x76, 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81, 0xCA, 0xE0,
0xDE, 0xE4, 0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7, 0x5F, 0x36, 0xB8,
0xBC, 0x13, 0x31, 0xCD, 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, 0xAE, 0xE4, 0x7C, 0x4B,
0x22, 0xFC, 0x19, 0x81, 0xCA, 0xE0, 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, 0x37, 0x2A, 0x96, 0x9F, 0x2E,
0xE5, 0x98, 0x4B, 0x2A, 0xB7, 0x5F, 0x36, 0xB8, 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7,
0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, 0xAE, 0xE4, 0x7C, 0x4B, 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C,
0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, 0x37, 0x2A, 0x96, 0x9F, 0x2E, 0xE8, 0x1C, 0x4E, 0x89, 0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC,
0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7, 0x7D, 0x92, 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48,
0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C, 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, 0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD,
0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, 0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85,
0x0A, 0xDC, 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, 0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7,
0xDB, 0x1E, 0xDB, 0x48, 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, 0x13, 0x0C, 0x0D, 0xC5, 0x01, 0x9E, 0x80, 0x68, 0x60, 0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8,
0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD, 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, 0xC8, 0x00, 0x56, 0x08, 0x4E, 0x86, 0xB4, 0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32,
0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85, 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, 0xD6, 0xBE, 0xD6, 0x95, 0x9E, 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71,
0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7, 0x01, 0x9E, 0x80, 0x68, 0x60, 0x2E, 0xC7, 0x64, 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9,
0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8, 0x08, 0x4E, 0x86, 0xB4, 0xD6, 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F,
0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32, 0xD6, 0x95, 0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2, 0xE5,
0x9E, 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71, 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, 0xA8, 0x04,
0xC7, 0x64, 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, 0xFD, 0xE3, 0x01,
0x36, 0xF9, 0xD6, 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, 0x88, 0x49, 0xA6, 0xB6,
0x2F, 0x14, 0x1C, 0x0F, 0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, 0x10, 0x4C, 0x0C, 0x35, 0xC5,
0x08, 0x13, 0x46, 0x8D, 0xF2, 0xE5, 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93,
0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, 0xA8, 0x04, 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE,
0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, 0xFD, 0xE3, 0x01, 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, 0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD,
0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, 0x88, 0x49, 0xA6, 0xB6, 0xFA, 0xF6, 0xC3, 0x06, 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, 0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84,
0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, 0x10, 0x4C, 0x0C, 0x35, 0xC5, 0xD7, 0x13, 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, 0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E,
0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93, 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, 0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2,
0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, 0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95,
0x5E, 0xCE, 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, 0x48, 0x3E, 0xB6, 0x90, 0x84, 0x6F, 0x23, 0x6C, 0x19, 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F,
0x76, 0xEC, 0x26, 0xCD, 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, 0x26, 0xE6, 0x9A, 0x75, 0xF4, 0x27, 0x07, 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20,
0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84, 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, 0x50, 0x21, 0x5D, 0xD8, 0x39, 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3,
0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E, 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, 0xE4, 0x08, 0x79, 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64,
0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2, 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, 0x70, 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B,
0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95, 0x84, 0x6F, 0x23, 0x6C, 0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, 0x3E,
0x19, 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F, 0x75, 0xF4, 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, 0x25, 0x89,
0x27, 0x07, 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20, 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, 0xFD, 0xFD, 0x81,
0x5D, 0xD8, 0x39, 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, 0x00, 0x21, 0xC0, 0x18,
0xE1, 0xA3, 0x08, 0x79, 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, 0xD8, 0x48, 0x5A, 0xB6, 0xBB,
0xAB, 0x71, 0xBF, 0x64, 0x70, 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, 0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93,
0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B, 0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, 0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E,
0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, 0x3E, 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, 0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B,
0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, 0x25, 0x89, 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, 0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7,
0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, 0xFD, 0xFD, 0x81, 0x81, 0xA0, 0x60, 0x78, 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, 0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E,
0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, 0x00, 0x21, 0xC0, 0x18, 0x50, 0x0A, 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC, 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A,
0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, 0xD8, 0x48, 0x5A, 0xB6, 0xBB, 0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2, 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE,
0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, 0xEC, 0x0D, 0x8D, 0xC5, 0x8D, 0x98, 0x65, 0xAA, 0xAB, 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF,
0xA5, 0x93, 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, 0x48, 0x60, 0x36, 0x01, 0x94, 0x00, 0x6F, 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F,
0xA8, 0x16, 0xFE, 0x8E, 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, 0x9E, 0xBE, 0x2F, 0x6C, 0x1C, 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31,
0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B, 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, 0x98, 0xE4, 0x14, 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04,
0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7, 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, 0x38, 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3,
0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E, 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, 0x18,
0xBC, 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A, 0xDC, 0x0B, 0x19, 0xC7, 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, 0x6E, 0xF3,
0x4A, 0xD2, 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE, 0x8D, 0x98, 0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, 0x29, 0xA8, 0x1E,
0x65, 0xAA, 0xAB, 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF, 0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, 0xE0, 0x76, 0xC8, 0x26,
0x01, 0x94, 0x00, 0x6F, 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, 0xEE, 0xF0, 0x4C, 0x44, 0x35,
0x94, 0x6F, 0x2F, 0x6C, 0x1C, 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, 0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB,
0x40, 0x43, 0x70, 0x31, 0xE4, 0x14, 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, 0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0,
0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04, 0x38, 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, 0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA,
0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3, 0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64, 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18,
0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, 0x18, 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB, 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C,
0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, 0x6E, 0xF3, 0x6C, 0x45, 0xED, 0xF3, 0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F, 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1,
0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, 0x29, 0xA8, 0x1E, 0xFE, 0x88, 0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1, 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71,
0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, 0xE0, 0x76, 0xC8, 0x26, 0xA7, 0x64, 0x7A, 0xAB, 0x63, 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1,
0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, 0xEE, 0xF0, 0x4C, 0xC8, 0x5C, 0x56, 0xB9, 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF,
0x44, 0x35, 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, 0x08, 0x71, 0x47, 0x0C, 0x32, 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7,
0xC6, 0xA4, 0x52, 0xFB, 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, 0x62, 0x50, 0x76, 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A,
0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0, 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, 0xD7, 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81,
0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA, 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, 0xC6,
0x64, 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18, 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, 0xAA, 0xC5,
0x95, 0xFB, 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C, 0x14, 0x69, 0xCF, 0x6E, 0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, 0xAC, 0x23, 0x3D,
0xD4, 0x2C, 0x5F, 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1, 0xBA, 0xF8, 0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, 0xE4, 0x08, 0x4B, 0x46,
0x73, 0x02, 0xA5, 0xC1, 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71, 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, 0x0D, 0xF1, 0xC5, 0x84, 0x53,
0xA7, 0x64, 0x7A, 0xAB, 0x63, 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, 0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38,
0x1E, 0xD1, 0xC8, 0x5C, 0x56, 0xB9, 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7, 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE,
0x19, 0x94, 0x0A, 0xEF, 0x47, 0x0C, 0x32, 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66, 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29,
0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7, 0x50, 0x76, 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2, 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A,
0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A, 0xD7, 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3, 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07,
0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81, 0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79, 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6,
0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, 0xC6, 0xA0, 0x52, 0xF8, 0x3D, 0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F,
0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, 0xAA, 0xC5, 0xBF, 0x13, 0x1B, 0x48, 0x0B, 0x76, 0x87, 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D,
0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, 0xAC, 0x23, 0x3D, 0xF1, 0xE1, 0x84, 0x48, 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC,
0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, 0xE4, 0x08, 0x2B, 0x15, 0xDF, 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90,
0x4B, 0x46, 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, 0x0D, 0x57, 0x2C, 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3,
0xF1, 0xC5, 0x84, 0x53, 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, 0x4D, 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47,
0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38, 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, 0xA2,
0xA7, 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE, 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, 0x89, 0xA2,
0xD4, 0x66, 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29, 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, 0x1F, 0x73, 0x48,
0xB9, 0xB5, 0xB2, 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A, 0xE5, 0xEF, 0x0B, 0x0C, 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, 0x6D, 0xD3, 0x6D, 0x9D,
0x07, 0x45, 0xC2, 0xB3, 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07, 0x0B, 0x42, 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE, 0xF0, 0x70, 0x44, 0x24, 0x33,
0x87, 0x71, 0xA2, 0xA4, 0x79, 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6, 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34, 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84,
0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F, 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88,
0xDB, 0x1F, 0x1B, 0x48, 0x0B, 0x76, 0x87, 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A, 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA,
0x04, 0x53, 0x43, 0x7D, 0xF1, 0xE1, 0x84, 0x48, 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA, 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A,
0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC, 0x2B, 0x15, 0xDF, 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79,
0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90, 0x57, 0x2C, 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40,
0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3, 0x4D, 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77,
0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47, 0x75, 0xF2, 0xA7, 0x05, 0x69, 0xE6, 0xAE, 0xCA, 0xFC, 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64,
0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, 0xA2, 0xBF, 0x39, 0x36, 0xAB, 0x56, 0xFF, 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9,
0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, 0x89, 0xA2, 0x81, 0xBE, 0xE0, 0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90,
0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, 0x1F, 0x38, 0x6C, 0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF,
0x73, 0x48, 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, 0x60, 0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C,
0x6D, 0xD3, 0x6D, 0x9D, 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56, 0xF0,
0xBE, 0xF0, 0x70, 0x44, 0x24, 0x33, 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA, 0xD4, 0x43,
0x80, 0x34, 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84, 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C, 0x6E, 0xB9, 0xEC,
0x54, 0x77, 0x7F, 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88, 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55, 0x9E, 0xBF, 0x28, 0x70,
0x08, 0x19, 0xC6, 0x8A, 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA, 0x9A, 0xC3, 0x2B, 0x11, 0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97, 0x58, 0x6E, 0xBA, 0xAC, 0x73,
0xDF, 0x4C, 0x58, 0x35, 0xFA, 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A, 0xCE, 0x93, 0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4, 0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A,
0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79, 0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91, 0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D,
0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82, 0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B,
0x5B, 0x40, 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98, 0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C,
0x7B, 0x4B, 0x63, 0x77, 0x69, 0xE6, 0xAE, 0xCA, 0xFC, 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02, 0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A,
0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64, 0x36, 0xAB, 0x56, 0xFF, 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF, 0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB,
0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9, 0x81, 0xBE, 0xE0, 0x70, 0x48, 0x24, 0x36, 0x9B, 0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4, 0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99
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 = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; public static readonly byte[] SyncMark =
{0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
public static byte[] Scramble(byte[] sector) public static byte[] Scramble(byte[] sector)
{ {
if(sector == null || sector.Length < 2352) if(sector == null || sector.Length < 2352) return sector;
return sector;
byte[] sync = new byte[12]; byte[] sync = new byte[12];
Array.Copy(sector, 0, sync, 0, 12); Array.Copy(sector, 0, sync, 0, 12);
if(!SyncMark.SequenceEqual(sync)) if(!SyncMark.SequenceEqual(sync)) return sector;
return sector;
byte[] scrambled = new byte[sector.Length]; byte[] scrambled = new byte[sector.Length];
for(int i = 0; i < 2352; i++) for(int i = 0; i < 2352; i++) scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]);
scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]);
if(sector.Length > 2352) if(sector.Length > 2352) { for(int i = 2352; i < sector.Length; i++) scrambled[i] = sector[i]; }
{
for(int i = 2352; i < sector.Length; i++)
scrambled[i] = sector[i];
}
return scrambled; return scrambled;
} }

View File

@@ -109,8 +109,7 @@ namespace DiscImageChef.Decoders.CD
public static CDSessionInfo? Decode(byte[] CDSessionInfoResponse) public static CDSessionInfo? Decode(byte[] CDSessionInfoResponse)
{ {
if(CDSessionInfoResponse == null) if(CDSessionInfoResponse == null) return null;
return null;
CDSessionInfo decoded = new CDSessionInfo(); CDSessionInfo decoded = new CDSessionInfo();
@@ -123,7 +122,9 @@ namespace DiscImageChef.Decoders.CD
if(decoded.DataLength + 2 != CDSessionInfoResponse.Length) if(decoded.DataLength + 2 != CDSessionInfoResponse.Length)
{ {
DicConsole.DebugWriteLine("CD Session Info decoder", "Expected CDSessionInfo size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDSessionInfoResponse.Length); 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; return null;
} }
@@ -134,7 +135,8 @@ namespace DiscImageChef.Decoders.CD
decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + i * 8 + 4] & 0x0F); decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + i * 8 + 4] & 0x0F);
decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + i * 8 + 4]; decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + i * 8 + 4];
decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + i * 8 + 4]; decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + i * 8 + 4];
decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + i * 8 + 4); decoded.TrackDescriptors[i].TrackStartAddress =
BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + i * 8 + 4);
} }
return decoded; return decoded;
@@ -142,8 +144,7 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDSessionInfo? CDSessionInfoResponse) public static string Prettify(CDSessionInfo? CDSessionInfoResponse)
{ {
if(CDSessionInfoResponse == null) if(CDSessionInfoResponse == null) return null;
return null;
CDSessionInfo response = CDSessionInfoResponse.Value; CDSessionInfo response = CDSessionInfoResponse.Value;
@@ -153,11 +154,12 @@ namespace DiscImageChef.Decoders.CD
sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine();
foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) 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, sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress,
(descriptor.TrackStartAddress & 0x0000FF00) >> 8, (descriptor.TrackStartAddress & 0x0000FF00) >> 8,
(descriptor.TrackStartAddress & 0x00FF0000) >> 16, (descriptor.TrackStartAddress & 0x00FF0000) >> 16,
(descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine(); (descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine();
switch((TOC_ADR)descriptor.ADR) switch((TOC_ADR)descriptor.ADR)
{ {
@@ -201,10 +203,9 @@ namespace DiscImageChef.Decoders.CD
break; break;
} }
if((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) == (byte)TOC_CONTROL.CopyPermissionMask) if((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) ==
sb.AppendLine("Digital copy of track is permitted"); (byte)TOC_CONTROL.CopyPermissionMask) sb.AppendLine("Digital copy of track is permitted");
else else sb.AppendLine("Digital copy of track is prohibited");
sb.AppendLine("Digital copy of track is prohibited");
#if DEBUG #if DEBUG
if(descriptor.Reserved1 != 0) if(descriptor.Reserved1 != 0)
@@ -226,5 +227,4 @@ namespace DiscImageChef.Decoders.CD
return Prettify(decoded); return Prettify(decoded);
} }
} }
} }

View File

@@ -111,8 +111,7 @@ namespace DiscImageChef.Decoders.CD
public static CDTOC? Decode(byte[] CDTOCResponse) public static CDTOC? Decode(byte[] CDTOCResponse)
{ {
if(CDTOCResponse == null) if(CDTOCResponse == null) return null;
return null;
CDTOC decoded = new CDTOC(); CDTOC decoded = new CDTOC();
@@ -125,7 +124,9 @@ namespace DiscImageChef.Decoders.CD
if(decoded.DataLength + 2 != CDTOCResponse.Length) if(decoded.DataLength + 2 != CDTOCResponse.Length)
{ {
DicConsole.DebugWriteLine("CD TOC decoder", "Expected CDTOC size ({0} bytes) is not received size ({1} bytes), not decoding", decoded.DataLength + 2, CDTOCResponse.Length); 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; return null;
} }
@@ -136,7 +137,8 @@ namespace DiscImageChef.Decoders.CD
decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + i * 8 + 4] & 0x0F); decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + i * 8 + 4] & 0x0F);
decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + i * 8 + 4]; decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + i * 8 + 4];
decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + i * 8 + 4]; decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + i * 8 + 4];
decoded.TrackDescriptors[i].TrackStartAddress = BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + i * 8 + 4); decoded.TrackDescriptors[i].TrackStartAddress =
BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + i * 8 + 4);
} }
return decoded; return decoded;
@@ -144,8 +146,7 @@ namespace DiscImageChef.Decoders.CD
public static string Prettify(CDTOC? CDTOCResponse) public static string Prettify(CDTOC? CDTOCResponse)
{ {
if(CDTOCResponse == null) if(CDTOCResponse == null) return null;
return null;
CDTOC response = CDTOCResponse.Value; CDTOC response = CDTOCResponse.Value;
@@ -155,14 +156,12 @@ namespace DiscImageChef.Decoders.CD
sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine(); sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine();
foreach(CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors) foreach(CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors)
{ {
if(descriptor.TrackNumber == 0xAA) if(descriptor.TrackNumber == 0xAA) sb.AppendLine("Track number: Lead-Out");
sb.AppendLine("Track number: Lead-Out"); else sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine();
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, sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress,
(descriptor.TrackStartAddress & 0x0000FF00) >> 8, (descriptor.TrackStartAddress & 0x0000FF00) >> 8,
(descriptor.TrackStartAddress & 0x00FF0000) >> 16, (descriptor.TrackStartAddress & 0x00FF0000) >> 16,
(descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine(); (descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine();
switch((TOC_ADR)descriptor.ADR) switch((TOC_ADR)descriptor.ADR)
{ {
@@ -212,10 +211,9 @@ namespace DiscImageChef.Decoders.CD
break; break;
} }
if((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) == (byte)TOC_CONTROL.CopyPermissionMask) if((descriptor.CONTROL & (byte)TOC_CONTROL.CopyPermissionMask) ==
sb.AppendLine("Digital copy of track is permitted"); (byte)TOC_CONTROL.CopyPermissionMask) sb.AppendLine("Digital copy of track is permitted");
else else sb.AppendLine("Digital copy of track is prohibited");
sb.AppendLine("Digital copy of track is prohibited");
#if DEBUG #if DEBUG
if(descriptor.Reserved1 != 0) if(descriptor.Reserved1 != 0)
@@ -237,5 +235,4 @@ namespace DiscImageChef.Decoders.CD
return Prettify(decoded); return Prettify(decoded);
} }
} }
} }

View File

@@ -74,5 +74,4 @@ namespace DiscImageChef.Decoders.DVD
public byte[] CopyrightInformation; public byte[] CopyrightInformation;
} }
} }
} }

View File

@@ -74,5 +74,4 @@ namespace DiscImageChef.Decoders.DVD
public byte[] ADIP; public byte[] ADIP;
} }
} }
} }

View File

@@ -74,5 +74,4 @@ namespace DiscImageChef.Decoders.DVD
public byte[] BCA; public byte[] BCA;
} }
} }
} }

View File

@@ -98,5 +98,4 @@ namespace DiscImageChef.Decoders.DVD
public byte[] MediaKeyBlock; public byte[] MediaKeyBlock;
} }
} }
} }

View File

@@ -117,11 +117,9 @@ namespace DiscImageChef.Decoders.DVD
public static LeadInCopyright? DecodeLeadInCopyright(byte[] response) public static LeadInCopyright? DecodeLeadInCopyright(byte[] response)
{ {
if(response == null) if(response == null) return null;
return null;
if(response.Length != 8) if(response.Length != 8) return null;
return null;
LeadInCopyright cmi = new LeadInCopyright(); LeadInCopyright cmi = new LeadInCopyright();
@@ -138,8 +136,7 @@ namespace DiscImageChef.Decoders.DVD
public static string PrettifyLeadInCopyright(LeadInCopyright? cmi) public static string PrettifyLeadInCopyright(LeadInCopyright? cmi)
{ {
if(cmi == null) if(cmi == null) return null;
return null;
LeadInCopyright decoded = cmi.Value; LeadInCopyright decoded = cmi.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -163,32 +160,21 @@ namespace DiscImageChef.Decoders.DVD
break; break;
} }
if(decoded.CopyrightType == 0) if(decoded.CopyrightType == 0) return sb.ToString();
return sb.ToString();
if(decoded.RegionInformation == 0xFF) if(decoded.RegionInformation == 0xFF) sb.AppendLine("Disc cannot be played in any region at all.");
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 if(decoded.RegionInformation == 0x00)
sb.AppendLine("Disc can be played in any region.");
else else
{ {
sb.Append("Disc can be played in the following regions:"); sb.Append("Disc can be played in the following regions:");
if((decoded.RegionInformation & 0x01) != 0x01) if((decoded.RegionInformation & 0x01) != 0x01) sb.Append(" 0");
sb.Append(" 0"); if((decoded.RegionInformation & 0x02) != 0x02) sb.Append(" 1");
if((decoded.RegionInformation & 0x02) != 0x02) if((decoded.RegionInformation & 0x04) != 0x04) sb.Append(" 2");
sb.Append(" 1"); if((decoded.RegionInformation & 0x08) != 0x08) sb.Append(" 3");
if((decoded.RegionInformation & 0x04) != 0x04) if((decoded.RegionInformation & 0x10) != 0x10) sb.Append(" 4");
sb.Append(" 2"); if((decoded.RegionInformation & 0x20) != 0x20) sb.Append(" 5");
if((decoded.RegionInformation & 0x08) != 0x08) if((decoded.RegionInformation & 0x40) != 0x40) sb.Append(" 6");
sb.Append(" 3"); if((decoded.RegionInformation & 0x80) != 0x80) sb.Append(" 7");
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(); return sb.ToString();
@@ -199,5 +185,4 @@ namespace DiscImageChef.Decoders.DVD
return PrettifyLeadInCopyright(DecodeLeadInCopyright(response)); return PrettifyLeadInCopyright(DecodeLeadInCopyright(response));
} }
} }
} }

View File

@@ -122,11 +122,9 @@ namespace DiscImageChef.Decoders.DVD
public static MediumStatus? Decode(byte[] response) public static MediumStatus? Decode(byte[] response)
{ {
if(response == null) if(response == null) return null;
return null;
if(response.Length != 8) if(response.Length != 8) return null;
return null;
MediumStatus status = new MediumStatus(); MediumStatus status = new MediumStatus();
@@ -149,22 +147,18 @@ namespace DiscImageChef.Decoders.DVD
public static string Prettify(MediumStatus? status) public static string Prettify(MediumStatus? status)
{ {
if(status == null) if(status == null) return null;
return null;
MediumStatus decoded = status.Value; MediumStatus decoded = status.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if(decoded.PWP) if(decoded.PWP) sb.AppendLine("Disc surface is set to write protected status");
sb.AppendLine("Disc surface is set to write protected status");
if(decoded.Cartridge) if(decoded.Cartridge)
{ {
sb.AppendLine("Disc comes in a cartridge"); sb.AppendLine("Disc comes in a cartridge");
if(decoded.OUT) if(decoded.OUT) sb.AppendLine("Disc has been extracted from the cartridge");
sb.AppendLine("Disc has been extracted from the cartridge"); if(decoded.CWP) sb.AppendLine("Cartridge is set to write protected");
if(decoded.CWP)
sb.AppendLine("Cartridge is set to write protected");
} }
switch(decoded.DiscType) switch(decoded.DiscType)
@@ -184,8 +178,7 @@ namespace DiscImageChef.Decoders.DVD
{ {
switch(decoded.RAMSWI) switch(decoded.RAMSWI)
{ {
case 0: case 0: break;
break;
case 1: case 1:
sb.AppendLine("Disc is write inhibited because it has been extracted from the cartridge"); sb.AppendLine("Disc is write inhibited because it has been extracted from the cartridge");
break; break;
@@ -193,7 +186,8 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc is write inhibited for an unspecified reason"); sb.AppendLine("Disc is write inhibited for an unspecified reason");
break; break;
default: default:
sb.AppendFormat("Disc has unknown reason {0} for write inhibition", decoded.RAMSWI).AppendLine(); sb.AppendFormat("Disc has unknown reason {0} for write inhibition", decoded.RAMSWI)
.AppendLine();
break; break;
} }
} }
@@ -206,5 +200,4 @@ namespace DiscImageChef.Decoders.DVD
return Prettify(Decode(response)); return Prettify(Decode(response));
} }
} }
} }

View File

@@ -196,18 +196,15 @@ namespace DiscImageChef.Decoders.DVD
public static DiscDefinitionStructure? Decode(byte[] response) public static DiscDefinitionStructure? Decode(byte[] response)
{ {
if(response == null) if(response == null) return null;
return null;
if(response.Length != 2052) if(response.Length != 2052) return null;
return null;
DiscDefinitionStructure dds = new DiscDefinitionStructure(); DiscDefinitionStructure dds = new DiscDefinitionStructure();
dds.Identifier = (ushort)((response[4] << 8) + response[5]); dds.Identifier = (ushort)((response[4] << 8) + response[5]);
if(dds.Identifier != 0x0A0A) if(dds.Identifier != 0x0A0A) return null;
return null;
// Common to both DVD-RAM versions // Common to both DVD-RAM versions
dds.DataLength = (ushort)((response[0] << 8) + response[1]); dds.DataLength = (ushort)((response[0] << 8) + response[1]);
@@ -252,7 +249,8 @@ namespace DiscImageChef.Decoders.DVD
dds.StartLSNForZone = new uint[dds.Zones]; dds.StartLSNForZone = new uint[dds.Zones];
for(int i = 0; i < dds.Zones; i++) for(int i = 0; i < dds.Zones; i++)
dds.StartLSNForZone[i] = (uint)((response[260 + i * 4 + 1] << 16) + (response[260 + i * 4 + 2] << 8) + response[260 + i * 4 + 3]); dds.StartLSNForZone[i] = (uint)((response[260 + i * 4 + 1] << 16) +
(response[260 + i * 4 + 2] << 8) + response[260 + i * 4 + 3]);
} }
return dds; return dds;
@@ -260,8 +258,7 @@ namespace DiscImageChef.Decoders.DVD
public static string Prettify(DiscDefinitionStructure? dds) public static string Prettify(DiscDefinitionStructure? dds)
{ {
if(dds == null) if(dds == null) return null;
return null;
DiscDefinitionStructure decoded = dds.Value; DiscDefinitionStructure decoded = dds.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -271,17 +268,13 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Formatting in progress."); sb.AppendLine("Formatting in progress.");
if(decoded.Groups == 24) if(decoded.Groups == 24)
{ {
if(decoded.PartialCertification) if(decoded.PartialCertification) sb.AppendLine("Formatting is only using partial certification");
sb.AppendLine("Formatting is only using partial certification"); if(decoded.FormattingOnlyAGroup) sb.AppendLine("Only a group is being formatted");
if(decoded.FormattingOnlyAGroup)
sb.AppendLine("Only a group is being formatted");
} }
} }
if(decoded.UserCertification) if(decoded.UserCertification) sb.AppendLine("Disc has been certified by an user");
sb.AppendLine("Disc has been certified by an user"); if(decoded.ManufacturerCertification) sb.AppendLine("Disc has been certified by a manufacturer");
if(decoded.ManufacturerCertification)
sb.AppendLine("Disc has been certified by a manufacturer");
sb.AppendFormat("DDS has been updated {0} times", decoded.UpdateCount).AppendLine(); sb.AppendFormat("DDS has been updated {0} times", decoded.UpdateCount).AppendLine();
@@ -303,7 +296,8 @@ namespace DiscImageChef.Decoders.DVD
if(decoded.Groups == 1) if(decoded.Groups == 1)
{ {
sb.AppendFormat("Disc has {0} zones", decoded.Zones).AppendLine(); 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("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(); sb.AppendFormat("LSN 0 is at PSN {0:X}h", decoded.LSN0Location).AppendLine();
for(int i = 0; i < decoded.StartLSNForZone.Length; i++) for(int i = 0; i < decoded.StartLSNForZone.Length; i++)
@@ -318,5 +312,4 @@ namespace DiscImageChef.Decoders.DVD
return Prettify(Decode(response)); return Prettify(Decode(response));
} }
} }
} }

View File

@@ -74,5 +74,4 @@ namespace DiscImageChef.Decoders.DVD
public byte[] DMI; public byte[] DMI;
} }
} }
} }

View File

@@ -260,5 +260,4 @@ namespace DiscImageChef.Decoders.DVD
Twelve = 0x50 Twelve = 0x50
} }
#endregion #endregion
} }

View File

@@ -236,5 +236,4 @@ namespace DiscImageChef.Decoders.DVD
public uint LBA; public uint LBA;
} }
} }
} }

View File

@@ -1049,11 +1049,9 @@ namespace DiscImageChef.Decoders.DVD
public static PhysicalFormatInformation? Decode(byte[] response) public static PhysicalFormatInformation? Decode(byte[] response)
{ {
if(response == null) if(response == null) return null;
return null;
if(response.Length < 2052) if(response.Length < 2052) return null;
return null;
PhysicalFormatInformation pfi = new PhysicalFormatInformation(); PhysicalFormatInformation pfi = new PhysicalFormatInformation();
byte[] tmp; byte[] tmp;
@@ -1073,8 +1071,10 @@ namespace DiscImageChef.Decoders.DVD
pfi.LayerType = (LayerTypeFieldMask)(response[6] & 0x07); pfi.LayerType = (LayerTypeFieldMask)(response[6] & 0x07);
pfi.LinearDensity = (LinearDensityField)((response[7] & 0xF0) >> 4); pfi.LinearDensity = (LinearDensityField)((response[7] & 0xF0) >> 4);
pfi.TrackDensity = (TrackDensityField)(response[7] & 0x0F); pfi.TrackDensity = (TrackDensityField)(response[7] & 0x0F);
pfi.DataAreaStartPSN = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); pfi.DataAreaStartPSN =
pfi.DataAreaEndPSN = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]);
pfi.DataAreaEndPSN =
(uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]);
pfi.Layer0EndPSN = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); pfi.Layer0EndPSN = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]);
pfi.BCA |= (response[20] & 0x80) == 0x80; pfi.BCA |= (response[20] & 0x80) == 0x80;
@@ -1182,13 +1182,13 @@ namespace DiscImageChef.Decoders.DVD
} }
// DVD-R and DVD-RW // DVD-R and DVD-RW
if((pfi.DiskCategory == DiskCategory.DVDR && if((pfi.DiskCategory == DiskCategory.DVDR && pfi.PartVersion < 6) ||
pfi.PartVersion < 6) || (pfi.DiskCategory == DiskCategory.DVDRW && pfi.PartVersion < 3))
(pfi.DiskCategory == DiskCategory.DVDRW &&
pfi.PartVersion < 3))
{ {
pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); pfi.CurrentBorderOutSector =
pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]);
pfi.NextBorderInSector =
(uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]);
} }
// DVD+RW // DVD+RW
@@ -1216,10 +1216,8 @@ namespace DiscImageChef.Decoders.DVD
} }
// DVD+R, DVD+RW, DVD+R DL and DVD+RW DL // DVD+R, DVD+RW, DVD+R DL and DVD+RW DL
if(pfi.DiskCategory == DiskCategory.DVDPR || if(pfi.DiskCategory == DiskCategory.DVDPR || pfi.DiskCategory == DiskCategory.DVDPRW ||
pfi.DiskCategory == DiskCategory.DVDPRW || pfi.DiskCategory == DiskCategory.DVDPRDL || pfi.DiskCategory == DiskCategory.DVDPRWDL)
pfi.DiskCategory == DiskCategory.DVDPRDL ||
pfi.DiskCategory == DiskCategory.DVDPRWDL)
{ {
pfi.VCPS |= (response[20] & 0x40) == 0x40; pfi.VCPS |= (response[20] & 0x40) == 0x40;
pfi.ApplicationCode = response[21]; pfi.ApplicationCode = response[21];
@@ -1230,13 +1228,13 @@ namespace DiscImageChef.Decoders.DVD
tmp = new byte[3]; tmp = new byte[3];
Array.Copy(response, 31, tmp, 0, 3); Array.Copy(response, 31, tmp, 0, 3);
pfi.MediaTypeID = StringHandlers.CToString(tmp); pfi.MediaTypeID = StringHandlers.CToString(tmp);
pfi.ProductRevision = pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) : response[34]; pfi.ProductRevision =
pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) : response[34];
pfi.PFIUsedInADIP = response[35]; pfi.PFIUsedInADIP = response[35];
} }
// DVD+RW // DVD+RW
if(pfi.DiskCategory == DiskCategory.DVDPRW && if(pfi.DiskCategory == DiskCategory.DVDPRW && pfi.PartVersion == 2)
pfi.PartVersion == 2)
{ {
pfi.TopFirstPulseDuration = response[55]; pfi.TopFirstPulseDuration = response[55];
pfi.MultiPulseDuration = response[56]; pfi.MultiPulseDuration = response[56];
@@ -1246,8 +1244,7 @@ namespace DiscImageChef.Decoders.DVD
} }
// DVD+R and DVD+R DL // DVD+R and DVD+R DL
if(pfi.DiskCategory == DiskCategory.DVDPR || if(pfi.DiskCategory == DiskCategory.DVDPR || pfi.DiskCategory == DiskCategory.DVDPRDL)
pfi.DiskCategory == DiskCategory.DVDPRDL)
{ {
pfi.PrimaryVelocity = response[36]; pfi.PrimaryVelocity = response[36];
pfi.UpperVelocity = response[37]; pfi.UpperVelocity = response[37];
@@ -1305,10 +1302,8 @@ namespace DiscImageChef.Decoders.DVD
} }
// DVD-R DL and DVD-RW DL // DVD-R DL and DVD-RW DL
if((pfi.DiskCategory == DiskCategory.DVDR && if((pfi.DiskCategory == DiskCategory.DVDR && pfi.PartVersion == 6) ||
pfi.PartVersion == 6) || (pfi.DiskCategory == DiskCategory.DVDRW && pfi.PartVersion == 3))
(pfi.DiskCategory == DiskCategory.DVDRW &&
pfi.PartVersion == 3))
{ {
pfi.MaxRecordingSpeed = (DVDRecordingSpeed)response[21]; pfi.MaxRecordingSpeed = (DVDRecordingSpeed)response[21];
pfi.MinRecordingSpeed = (DVDRecordingSpeed)response[22]; pfi.MinRecordingSpeed = (DVDRecordingSpeed)response[22];
@@ -1321,8 +1316,10 @@ namespace DiscImageChef.Decoders.DVD
pfi.RecordingSpeed7 = (DVDRecordingSpeed)response[29]; pfi.RecordingSpeed7 = (DVDRecordingSpeed)response[29];
pfi.Class = response[30]; pfi.Class = response[30];
pfi.ExtendedVersion = response[31]; pfi.ExtendedVersion = response[31];
pfi.CurrentBorderOutSector = (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); pfi.CurrentBorderOutSector =
pfi.NextBorderInSector = (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]);
pfi.NextBorderInSector =
(uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]);
pfi.PreRecordedControlDataInv |= (response[44] & 0x01) == 0x01; pfi.PreRecordedControlDataInv |= (response[44] & 0x01) == 0x01;
pfi.PreRecordedLeadIn |= (response[44] & 0x02) == 0x02; pfi.PreRecordedLeadIn |= (response[44] & 0x02) == 0x02;
pfi.PreRecordedLeadOut |= (response[44] & 0x08) == 0x08; pfi.PreRecordedLeadOut |= (response[44] & 0x08) == 0x08;
@@ -1335,8 +1332,7 @@ namespace DiscImageChef.Decoders.DVD
public static string Prettify(PhysicalFormatInformation? pfi) public static string Prettify(PhysicalFormatInformation? pfi)
{ {
if(pfi == null) if(pfi == null) return null;
return null;
PhysicalFormatInformation decoded = pfi.Value; PhysicalFormatInformation decoded = pfi.Value;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -1377,12 +1373,12 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-330"); sb.AppendLine("Disc claims conformation to ECMA-330");
break; break;
} }
break; break;
case DiskCategory.DVDR: case DiskCategory.DVDR:
if(decoded.PartVersion >= 6) if(decoded.PartVersion >= 6)
sb.AppendFormat(categorySentence, sizeString, "DVD-R DL", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD-R DL", decoded.PartVersion).AppendLine();
else else sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine();
sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine();
switch(decoded.PartVersion) switch(decoded.PartVersion)
{ {
case 1: case 1:
@@ -1395,12 +1391,12 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-382"); sb.AppendLine("Disc claims conformation to ECMA-382");
break; break;
} }
break; break;
case DiskCategory.DVDRW: case DiskCategory.DVDRW:
if(decoded.PartVersion >= 3) if(decoded.PartVersion >= 3)
sb.AppendFormat(categorySentence, sizeString, "DVD-RW DL", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD-RW DL", decoded.PartVersion).AppendLine();
else else sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine();
sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine();
switch(decoded.PartVersion) switch(decoded.PartVersion)
{ {
case 2: case 2:
@@ -1410,18 +1406,19 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-384"); sb.AppendLine("Disc claims conformation to ECMA-384");
break; break;
} }
break; break;
case DiskCategory.UMD: case DiskCategory.UMD:
if(decoded.DiscSize == DVDSize.OneTwenty) if(decoded.DiscSize == DVDSize.OneTwenty)
sb.AppendFormat(categorySentence, "60mm", "UMD", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, "60mm", "UMD", decoded.PartVersion).AppendLine();
else else sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine();
sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine();
switch(decoded.PartVersion) switch(decoded.PartVersion)
{ {
case 0: case 0:
sb.AppendLine("Disc claims conformation to ECMA-365"); sb.AppendLine("Disc claims conformation to ECMA-365");
break; break;
} }
break; break;
case DiskCategory.DVDPRW: case DiskCategory.DVDPRW:
sb.AppendFormat(categorySentence, sizeString, "DVD+RW", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD+RW", decoded.PartVersion).AppendLine();
@@ -1437,6 +1434,7 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-371"); sb.AppendLine("Disc claims conformation to ECMA-371");
break; break;
} }
break; break;
case DiskCategory.DVDPR: case DiskCategory.DVDPR:
sb.AppendFormat(categorySentence, sizeString, "DVD+R", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD+R", decoded.PartVersion).AppendLine();
@@ -1446,6 +1444,7 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-349"); sb.AppendLine("Disc claims conformation to ECMA-349");
break; break;
} }
break; break;
case DiskCategory.DVDPRWDL: case DiskCategory.DVDPRWDL:
sb.AppendFormat(categorySentence, sizeString, "DVD+RW DL", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD+RW DL", decoded.PartVersion).AppendLine();
@@ -1455,6 +1454,7 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-374"); sb.AppendLine("Disc claims conformation to ECMA-374");
break; break;
} }
break; break;
case DiskCategory.DVDPRDL: case DiskCategory.DVDPRDL:
sb.AppendFormat(categorySentence, sizeString, "DVD+R DL", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "DVD+R DL", decoded.PartVersion).AppendLine();
@@ -1464,6 +1464,7 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc claims conformation to ECMA-364"); sb.AppendLine("Disc claims conformation to ECMA-364");
break; break;
} }
break; break;
case DiskCategory.Nintendo: case DiskCategory.Nintendo:
if(decoded.PartVersion == 15) if(decoded.PartVersion == 15)
@@ -1472,11 +1473,9 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc is a Nintendo Gamecube Optical Disc (GOD)"); sb.AppendLine("Disc is a Nintendo Gamecube Optical Disc (GOD)");
else if(decoded.DiscSize == DVDSize.OneTwenty) else if(decoded.DiscSize == DVDSize.OneTwenty)
sb.AppendLine("Disc is a Nintendo Wii Optical Disc (WOD)"); sb.AppendLine("Disc is a Nintendo Wii Optical Disc (WOD)");
else else goto default;
goto default;
} }
else else goto default;
goto default;
break; break;
case DiskCategory.HDDVDROM: case DiskCategory.HDDVDROM:
sb.AppendFormat(categorySentence, sizeString, "HD DVD-ROM", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "HD DVD-ROM", decoded.PartVersion).AppendLine();
@@ -1491,7 +1490,8 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendFormat(categorySentence, sizeString, "HD DVD-RW", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "HD DVD-RW", decoded.PartVersion).AppendLine();
break; break;
default: default:
sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion).AppendLine(); sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion)
.AppendLine();
break; break;
} }
@@ -1516,15 +1516,14 @@ namespace DiscImageChef.Decoders.DVD
sb.AppendLine("Disc maximum transfer rate is unspecified."); sb.AppendLine("Disc maximum transfer rate is unspecified.");
break; break;
default: default:
sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate).AppendLine(); sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate)
.AppendLine();
break; break;
} }
sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine();
if(decoded.TrackPath && decoded.Layers == 1) if(decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in parallel track path");
sb.AppendLine("Layers are in parallel track path"); else if(!decoded.TrackPath && decoded.Layers == 1) sb.AppendLine("Layers are in opposite track path");
else if(!decoded.TrackPath && decoded.Layers == 1)
sb.AppendLine("Layers are in opposite track path");
switch(decoded.LinearDensity) switch(decoded.LinearDensity)
{ {
@@ -1585,14 +1584,11 @@ namespace DiscImageChef.Decoders.DVD
if(decoded.Layers == 1 && !decoded.TrackPath) if(decoded.Layers == 1 && !decoded.TrackPath)
sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine();
} }
else else sb.AppendLine("Disc is empty");
sb.AppendLine("Disc is empty");
} }
else else sb.AppendLine("Disc is empty");
sb.AppendLine("Disc is empty");
if(decoded.BCA) if(decoded.BCA) sb.AppendLine("Disc has a burst cutting area");
sb.AppendLine("Disc has a burst cutting area");
if(decoded.DiskCategory == DiskCategory.UMD) if(decoded.DiskCategory == DiskCategory.UMD)
sb.AppendFormat("Media attribute is {0}", decoded.MediaAttribute).AppendLine(); sb.AppendFormat("Media attribute is {0}", decoded.MediaAttribute).AppendLine();
@@ -1615,45 +1611,39 @@ namespace DiscImageChef.Decoders.DVD
if(decoded.PartVersion == 6) if(decoded.PartVersion == 6)
{ {
sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturer).AppendLine(); sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturer).AppendLine();
sb.AppendFormat("Disc manufacturer supplementary information is {0}", decoded.DiskManufacturerSupplementary).AppendLine(); sb.AppendFormat("Disc manufacturer supplementary information is {0}",
decoded.DiskManufacturerSupplementary).AppendLine();
} }
} }
if((decoded.DiskCategory == DiskCategory.DVDR && if((decoded.DiskCategory == DiskCategory.DVDR && decoded.PartVersion < 6) ||
decoded.PartVersion < 6) || (decoded.DiskCategory == DiskCategory.DVDRW && decoded.PartVersion < 3))
(decoded.DiskCategory == DiskCategory.DVDRW &&
decoded.PartVersion < 3))
{ {
sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector).AppendLine(); sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector)
.AppendLine();
sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector).AppendLine(); sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector).AppendLine();
} }
if(decoded.DiskCategory == DiskCategory.DVDPR || if(decoded.DiskCategory == DiskCategory.DVDPR || decoded.DiskCategory == DiskCategory.DVDPRW ||
decoded.DiskCategory == DiskCategory.DVDPRW || decoded.DiskCategory == DiskCategory.DVDPRDL || decoded.DiskCategory == DiskCategory.DVDPRWDL)
decoded.DiskCategory == DiskCategory.DVDPRDL ||
decoded.DiskCategory == DiskCategory.DVDPRWDL)
{ {
if(decoded.VCPS) if(decoded.VCPS) sb.AppendLine("Disc contains extended information for VCPS");
sb.AppendLine("Disc contains extended information for VCPS");
sb.AppendFormat("Disc application code is {0}", decoded.ApplicationCode).AppendLine(); sb.AppendFormat("Disc application code is {0}", decoded.ApplicationCode).AppendLine();
sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturerID).AppendLine(); sb.AppendFormat("Disc manufacturer is {0}", decoded.DiskManufacturerID).AppendLine();
sb.AppendFormat("Disc media type is {0}", decoded.MediaTypeID).AppendLine(); sb.AppendFormat("Disc media type is {0}", decoded.MediaTypeID).AppendLine();
sb.AppendFormat("Disc product revision is {0}", decoded.ProductRevision).AppendLine(); sb.AppendFormat("Disc product revision is {0}", decoded.ProductRevision).AppendLine();
} }
if((decoded.DiskCategory == DiskCategory.DVDR && if((decoded.DiskCategory == DiskCategory.DVDR && decoded.PartVersion >= 6) ||
decoded.PartVersion >= 6) || (decoded.DiskCategory == DiskCategory.DVDRW && decoded.PartVersion >= 3))
(decoded.DiskCategory == DiskCategory.DVDRW &&
decoded.PartVersion >= 3))
{ {
sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h", decoded.CurrentRMDExtraBorderPSN).AppendLine(); sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h",
sb.AppendFormat("PFI in extra Border zone starts at PSN {0:X}h", decoded.PFIExtraBorderPSN).AppendLine(); decoded.CurrentRMDExtraBorderPSN).AppendLine();
if(!decoded.PreRecordedControlDataInv) sb.AppendFormat("PFI in extra Border zone starts at PSN {0:X}h", decoded.PFIExtraBorderPSN)
sb.AppendLine("Control Data Zone is pre-recorded"); .AppendLine();
if(decoded.PreRecordedLeadIn) if(!decoded.PreRecordedControlDataInv) sb.AppendLine("Control Data Zone is pre-recorded");
sb.AppendLine("Lead-In is pre-recorded"); if(decoded.PreRecordedLeadIn) sb.AppendLine("Lead-In is pre-recorded");
if(decoded.PreRecordedLeadOut) if(decoded.PreRecordedLeadOut) sb.AppendLine("Lead-Out is pre-recorded");
sb.AppendLine("Lead-Out is pre-recorded");
} }
return sb.ToString(); return sb.ToString();
@@ -1664,5 +1654,4 @@ namespace DiscImageChef.Decoders.DVD
return Prettify(Decode(response)); return Prettify(Decode(response));
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More