From 6b1033317a26bd69c0e8044faf18e1fd7531bb25 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 11 Jan 2020 20:55:54 +0000 Subject: [PATCH] Remove DiscImageChef.CommonTypes dependence on DiscImageChef.Decoders. --- .../.idea/contentModel.xml | 13 +- DiscImageChef.CommonTypes | 2 +- DiscImageChef.Core/Devices/Dumping/ATA.cs | 2 +- .../Devices/Dumping/CompactDisc/Error.cs | 1 + DiscImageChef.Core/Devices/Dumping/MMC.cs | 2 +- .../Devices/Dumping/PlayStationPortable.cs | 1 + DiscImageChef.Core/Devices/Dumping/SBC.cs | 1 + DiscImageChef.Core/Devices/Dumping/SCSI.cs | 1 + DiscImageChef.Core/Devices/Dumping/XGD.cs | 1 + DiscImageChef.Core/Devices/Info/DeviceInfo.cs | 2 + DiscImageChef.Core/Devices/Info/Properties.cs | 4 +- DiscImageChef.Core/Devices/Reader.cs | 2 +- DiscImageChef.Core/Devices/ReaderATA.cs | 118 ++-- DiscImageChef.Core/Devices/ReaderSCSI.cs | 190 ++++-- DiscImageChef.Core/Devices/Report/ATA.cs | 1 + DiscImageChef.Core/Devices/Report/Scsi.cs | 6 +- DiscImageChef.Core/Devices/Scanning/ATA.cs | 155 +++-- DiscImageChef.Core/Devices/Scanning/SCSI.cs | 227 ++++--- DiscImageChef.Core/ImageInfo.cs | 113 +++- DiscImageChef.Core/Media/Info/ScsiInfo.cs | 4 +- DiscImageChef.Core/PrintScsiModePages.cs | 156 +++-- DiscImageChef.Core/Sidecar/BlockMedia.cs | 2 +- DiscImageChef.Decoders | 2 +- DiscImageChef.Devices/Device/Constructor.cs | 6 +- DiscImageChef.Devices/Device/Variables.cs | 151 ++--- DiscImageChef.Devices/FreeBSD/ListDevices.cs | 33 +- DiscImageChef.DiscImages/BlindWrite5/Read.cs | 569 +++++++++++++----- DiscImageChef.DiscImages/CHD/Read.cs | 419 ++++++++----- .../DiscImageChef/Helpers.cs | 62 +- DiscImageChef.DiscImages/RsIde/Read.cs | 17 +- DiscImageChef.DiscImages/RsIde/Write.cs | 123 ++-- DiscImageChef.DiscImages/ZZZRawImage/Read.cs | 6 +- .../Forms/frmDecodeMediaTags.xeto.cs | 2 + DiscImageChef.Gui/Forms/frmMain.xeto.cs | 1 + DiscImageChef.Gui/Panels/pnlImageInfo.xeto.cs | 6 +- DiscImageChef.Gui/Tabs/tabScsiInfo.xeto.cs | 6 +- DiscImageChef.sln.DotSettings | 2 + DiscImageChef/Commands/Device/DeviceReport.cs | 3 +- DiscImageChef/Commands/Device/Info.cs | 2 + DiscImageChef/Commands/Media/Info.cs | 2 +- 40 files changed, 1640 insertions(+), 776 deletions(-) diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml index 40b8bb4ce..b4442615b 100644 --- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml +++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml @@ -184,6 +184,18 @@ + + + + + + + + + + + + @@ -515,7 +527,6 @@ - diff --git a/DiscImageChef.CommonTypes b/DiscImageChef.CommonTypes index afa1525f0..1a2a4242e 160000 --- a/DiscImageChef.CommonTypes +++ b/DiscImageChef.CommonTypes @@ -1 +1 @@ -Subproject commit afa1525f0c9d8cb721d982f120cd0897f0089b91 +Subproject commit 1a2a4242eb1cfeefff92889a100ce158ba759b79 diff --git a/DiscImageChef.Core/Devices/Dumping/ATA.cs b/DiscImageChef.Core/Devices/Dumping/ATA.cs index 7fbc73889..d62e3a17a 100644 --- a/DiscImageChef.Core/Devices/Dumping/ATA.cs +++ b/DiscImageChef.Core/Devices/Dumping/ATA.cs @@ -39,8 +39,8 @@ using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Extents; using DiscImageChef.CommonTypes.Interfaces; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Core.Logging; -using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.PCMCIA; using Schemas; using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple; diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Error.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Error.cs index 800d24756..6961fe52e 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Error.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Error.cs @@ -34,6 +34,7 @@ using System; using System.Collections.Generic; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Extents; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; diff --git a/DiscImageChef.Core/Devices/Dumping/MMC.cs b/DiscImageChef.Core/Devices/Dumping/MMC.cs index 2640f59b0..c4df5117d 100644 --- a/DiscImageChef.Core/Devices/Dumping/MMC.cs +++ b/DiscImageChef.Core/Devices/Dumping/MMC.cs @@ -34,9 +34,9 @@ using System; using System.Collections.Generic; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.Bluray; using DiscImageChef.Decoders.DVD; -using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Devices; using Schemas; diff --git a/DiscImageChef.Core/Devices/Dumping/PlayStationPortable.cs b/DiscImageChef.Core/Devices/Dumping/PlayStationPortable.cs index 0128bd2ca..a3720337c 100644 --- a/DiscImageChef.Core/Devices/Dumping/PlayStationPortable.cs +++ b/DiscImageChef.Core/Devices/Dumping/PlayStationPortable.cs @@ -10,6 +10,7 @@ using DiscImageChef.CommonTypes.Extents; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core.Logging; using DiscImageChef.Decoders.SCSI; diff --git a/DiscImageChef.Core/Devices/Dumping/SBC.cs b/DiscImageChef.Core/Devices/Dumping/SBC.cs index 41a7eccc0..daa52fb4e 100644 --- a/DiscImageChef.Core/Devices/Dumping/SBC.cs +++ b/DiscImageChef.Core/Devices/Dumping/SBC.cs @@ -41,6 +41,7 @@ using DiscImageChef.CommonTypes.Extents; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core.Logging; using DiscImageChef.Decoders.SCSI; diff --git a/DiscImageChef.Core/Devices/Dumping/SCSI.cs b/DiscImageChef.Core/Devices/Dumping/SCSI.cs index fdf74e9a3..2fb4cbef7 100644 --- a/DiscImageChef.Core/Devices/Dumping/SCSI.cs +++ b/DiscImageChef.Core/Devices/Dumping/SCSI.cs @@ -33,6 +33,7 @@ using System.Threading; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Interfaces; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.SCSI; namespace DiscImageChef.Core.Devices.Dumping diff --git a/DiscImageChef.Core/Devices/Dumping/XGD.cs b/DiscImageChef.Core/Devices/Dumping/XGD.cs index 993cd408f..b2bd82848 100644 --- a/DiscImageChef.Core/Devices/Dumping/XGD.cs +++ b/DiscImageChef.Core/Devices/Dumping/XGD.cs @@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes.Extents; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Interop; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core.Logging; using DiscImageChef.Decoders.DVD; diff --git a/DiscImageChef.Core/Devices/Info/DeviceInfo.cs b/DiscImageChef.Core/Devices/Info/DeviceInfo.cs index 5dca4a493..459f40d4c 100644 --- a/DiscImageChef.Core/Devices/Info/DeviceInfo.cs +++ b/DiscImageChef.Core/Devices/Info/DeviceInfo.cs @@ -33,10 +33,12 @@ using System; using System.Collections.Generic; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; +using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry; namespace DiscImageChef.Core.Devices.Info { diff --git a/DiscImageChef.Core/Devices/Info/Properties.cs b/DiscImageChef.Core/Devices/Info/Properties.cs index 3dd78b0cc..e44147b06 100644 --- a/DiscImageChef.Core/Devices/Info/Properties.cs +++ b/DiscImageChef.Core/Devices/Info/Properties.cs @@ -32,10 +32,12 @@ using System.Collections.Generic; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Devices; +using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry; namespace DiscImageChef.Core.Devices.Info { @@ -44,7 +46,7 @@ namespace DiscImageChef.Core.Devices.Info public byte[] AtaIdentify { get; } public byte[] AtapiIdentify { get; } public byte[] ScsiInquiryData { get; } - public Inquiry.SCSIInquiry? ScsiInquiry { get; } + public Inquiry? ScsiInquiry { get; } public AtaErrorRegistersChs? AtaMcptError { get; } public Dictionary ScsiEvpdPages { get; } public Modes.DecodedMode? ScsiMode { get; } diff --git a/DiscImageChef.Core/Devices/Reader.cs b/DiscImageChef.Core/Devices/Reader.cs index a9aa3d7f7..4d3280124 100644 --- a/DiscImageChef.Core/Devices/Reader.cs +++ b/DiscImageChef.Core/Devices/Reader.cs @@ -32,7 +32,7 @@ using System; using DiscImageChef.CommonTypes.Enums; -using DiscImageChef.Decoders.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Devices; namespace DiscImageChef.Core.Devices diff --git a/DiscImageChef.Core/Devices/ReaderATA.cs b/DiscImageChef.Core/Devices/ReaderATA.cs index 114459617..04f083967 100644 --- a/DiscImageChef.Core/Devices/ReaderATA.cs +++ b/DiscImageChef.Core/Devices/ReaderATA.cs @@ -34,10 +34,11 @@ using System; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.Console; using DiscImageChef.Decoders.ATA; +using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify; namespace DiscImageChef.Core.Devices { - partial class Reader + internal partial class Reader { Identify.IdentifyDevice ataId; bool ataRead; @@ -60,9 +61,12 @@ namespace DiscImageChef.Core.Devices (uint, byte, byte) GetDeviceChs() { - if(dev.Type != DeviceType.ATA) return (0, 0, 0); + if(dev.Type != DeviceType.ATA) + return(0, 0, 0); - if(ataId.CurrentCylinders > 0 && ataId.CurrentHeads > 0 && ataId.CurrentSectorsPerTrack > 0) + if(ataId.CurrentCylinders > 0 && + ataId.CurrentHeads > 0 && + ataId.CurrentSectorsPerTrack > 0) { Cylinders = ataId.CurrentCylinders; Heads = (byte)ataId.CurrentHeads; @@ -70,17 +74,18 @@ namespace DiscImageChef.Core.Devices Blocks = (ulong)(Cylinders * Heads * Sectors); } - if(ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0 || - ataId.Cylinders <= 0 || - ataId.Heads <= 0 || - ataId.SectorsPerTrack <= 0) return (Cylinders, Heads, Sectors); + if((ataId.CurrentCylinders != 0 && ataId.CurrentHeads != 0 && ataId.CurrentSectorsPerTrack != 0) || + ataId.Cylinders <= 0 || + ataId.Heads <= 0 || + ataId.SectorsPerTrack <= 0) + return(Cylinders, Heads, Sectors); Cylinders = ataId.Cylinders; Heads = (byte)ataId.Heads; Sectors = (byte)ataId.SectorsPerTrack; Blocks = (ulong)(Cylinders * Heads * Sectors); - return (Cylinders, Heads, Sectors); + return(Cylinders, Heads, Sectors); } ulong AtaGetBlocks() @@ -93,7 +98,8 @@ namespace DiscImageChef.Core.Devices IsLba = true; } - if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) return Blocks; + if(!ataId.CommandSet2.HasFlag(Identify.CommandSetBit2.LBA48)) + return Blocks; Blocks = ataId.LBA48Sectors; IsLba = true; @@ -105,6 +111,7 @@ namespace DiscImageChef.Core.Devices { bool sense = dev.Read(out byte[] cmdBuf, out AtaErrorRegistersChs errorChs, false, 0, 0, 1, 1, timeout, out _); + ataRead = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0; sense = dev.Read(out cmdBuf, out errorChs, true, 0, 0, 1, 1, timeout, out _); ataReadRetry = !sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && cmdBuf.Length > 0; @@ -134,40 +141,62 @@ namespace DiscImageChef.Core.Devices if(IsLba) { - if(Blocks > 0xFFFFFFF && !ataReadLba48 && !ataReadDmaLba48) + if(Blocks > 0xFFFFFFF && + !ataReadLba48 && + !ataReadDmaLba48) { ErrorMessage = "Device needs 48-bit LBA commands but I can't issue them... Aborting."; + return true; } - if(!ataReadLba && !ataReadRetryLba && !ataReadDmaLba && !ataReadDmaRetryLba) + if(!ataReadLba && + !ataReadRetryLba && + !ataReadDmaLba && + !ataReadDmaRetryLba) { ErrorMessage = "Device needs 28-bit LBA commands but I can't issue them... Aborting."; + return true; } } else { - if(!ataRead && !ataReadRetry && !ataReadDma && !ataReadDmaRetry) + if(!ataRead && + !ataReadRetry && + !ataReadDma && + !ataReadDmaRetry) { ErrorMessage = "Device needs CHS commands but I can't issue them... Aborting."; + return true; } } - if(ataReadDmaLba48) DicConsole.WriteLine("Using ATA READ DMA EXT command."); - else if(ataReadLba48) DicConsole.WriteLine("Using ATA READ EXT command."); - else if(ataReadDmaRetryLba) DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA)."); - else if(ataReadDmaLba) DicConsole.WriteLine("Using ATA READ DMA command (LBA)."); - else if(ataReadRetryLba) DicConsole.WriteLine("Using ATA READ command with retries (LBA)."); - 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)."); + if(ataReadDmaLba48) + DicConsole.WriteLine("Using ATA READ DMA EXT command."); + else if(ataReadLba48) + DicConsole.WriteLine("Using ATA READ EXT command."); + else if(ataReadDmaRetryLba) + DicConsole.WriteLine("Using ATA READ DMA command with retries (LBA)."); + else if(ataReadDmaLba) + DicConsole.WriteLine("Using ATA READ DMA command (LBA)."); + else if(ataReadRetryLba) + DicConsole.WriteLine("Using ATA READ command with retries (LBA)."); + 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 { ErrorMessage = "Could not get a working read command!"; + return true; } @@ -176,18 +205,22 @@ namespace DiscImageChef.Core.Devices bool AtaGetBlockSize() { - if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && (ataId.PhysLogSectorSize & 0x4000) == 0x4000) + if((ataId.PhysLogSectorSize & 0x8000) == 0x0000 && + (ataId.PhysLogSectorSize & 0x4000) == 0x4000) { if((ataId.PhysLogSectorSize & 0x1000) == 0x1000) - if(ataId.LogicalSectorWords <= 255 || ataId.LogicalAlignment == 0xFFFF) + if(ataId.LogicalSectorWords <= 255 || + ataId.LogicalAlignment == 0xFFFF) LogicalBlockSize = 512; else LogicalBlockSize = ataId.LogicalSectorWords * 2; - else LogicalBlockSize = 512; + else + LogicalBlockSize = 512; if((ataId.PhysLogSectorSize & 0x2000) == 0x2000) - PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF); - else PhysicalBlockSize = LogicalBlockSize; + PhysicalBlockSize = LogicalBlockSize * (uint)Math.Pow(2, ataId.PhysLogSectorSize & 0xF); + else + PhysicalBlockSize = LogicalBlockSize; } else { @@ -208,6 +241,7 @@ namespace DiscImageChef.Core.Devices if(!IsLba) { BlocksToRead = 1; + return false; } @@ -218,6 +252,7 @@ namespace DiscImageChef.Core.Devices byte[] cmdBuf; bool sense; AtaErrorRegistersLba48 errorLba48; + if(ataReadDmaLba48) { sense = dev.ReadDma(out cmdBuf, out errorLba48, 0, (byte)BlocksToRead, timeout, out _); @@ -231,6 +266,7 @@ namespace DiscImageChef.Core.Devices else { AtaErrorRegistersLba28 errorLba; + if(ataReadDmaRetryLba) { sense = dev.ReadDma(out cmdBuf, out errorLba, true, 0, (byte)BlocksToRead, timeout, out _); @@ -253,15 +289,21 @@ namespace DiscImageChef.Core.Devices } } - if(error) BlocksToRead /= 2; + if(error) + BlocksToRead /= 2; - if(!error || BlocksToRead == 1) break; + if(!error || + BlocksToRead == 1) + break; } - if(!error || !IsLba) return false; + if(!error || + !IsLba) + return false; BlocksToRead = 1; ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length."; + return true; } @@ -293,6 +335,7 @@ namespace DiscImageChef.Core.Devices { sense = dev.ReadDma(out buffer, out errorLba, true, (uint)block, (byte)count, timeout, out duration); + error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0); status = errorLba.Status; errorByte = errorLba.Error; @@ -301,6 +344,7 @@ namespace DiscImageChef.Core.Devices { sense = dev.ReadDma(out buffer, out errorLba, false, (uint)block, (byte)count, timeout, out duration); + error = !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0 && buffer.Length > 0); status = errorLba.Status; errorByte = errorLba.Error; @@ -320,7 +364,8 @@ namespace DiscImageChef.Core.Devices errorByte = errorLba.Error; } - if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + if(error) + DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); return error; } @@ -338,6 +383,7 @@ namespace DiscImageChef.Core.Devices { sense = dev.ReadDma(out buffer, out errorChs, true, cylinder, head, sectir, 1, timeout, out duration); + error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0); status = errorChs.Status; errorByte = errorChs.Error; @@ -346,6 +392,7 @@ namespace DiscImageChef.Core.Devices { sense = dev.ReadDma(out buffer, out errorChs, false, cylinder, head, sectir, 1, timeout, out duration); + error = !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0 && buffer.Length > 0); status = errorChs.Status; errorByte = errorChs.Error; @@ -365,7 +412,8 @@ namespace DiscImageChef.Core.Devices errorByte = errorChs.Error; } - if(error) DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); + if(error) + DicConsole.DebugWriteLine("ATA Reader", "ATA ERROR: {0} STATUS: {1}", errorByte, status); return error; } @@ -373,13 +421,15 @@ namespace DiscImageChef.Core.Devices bool AtaSeek(ulong block, out double duration) { bool sense = dev.Seek(out AtaErrorRegistersLba28 errorLba, (uint)block, timeout, out duration); - return !(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0); + + return!(!sense && (errorLba.Status & 0x27) == 0 && errorLba.Error == 0); } bool AtaSeekChs(ushort cylinder, byte head, byte sector, out double duration) { bool sense = dev.Seek(out AtaErrorRegistersChs errorChs, cylinder, head, sector, timeout, out duration); - return !(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0); + + return!(!sense && (errorChs.Status & 0x27) == 0 && errorChs.Error == 0); } } } \ No newline at end of file diff --git a/DiscImageChef.Core/Devices/ReaderSCSI.cs b/DiscImageChef.Core/Devices/ReaderSCSI.cs index d06609823..51723756e 100644 --- a/DiscImageChef.Core/Devices/ReaderSCSI.cs +++ b/DiscImageChef.Core/Devices/ReaderSCSI.cs @@ -31,12 +31,13 @@ // ****************************************************************************/ using System; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.SCSI; namespace DiscImageChef.Core.Devices { - partial class Reader + internal partial class Reader { // TODO: Raw reading bool hldtstReadRaw; @@ -72,23 +73,34 @@ namespace DiscImageChef.Core.Devices seek10 = !dev.Seek10(out senseBuf, 0, timeout, out _); - if(!read6 && !read10 && !read12 && !read16) + if(!read6 && + !read10 && + !read12 && + !read16) { ErrorMessage = "Cannot read medium, aborting scan..."; + return true; } - if(read6 && !read10 && !read12 && !read16 && Blocks > 0x001FFFFF + 1) + if(read6 && + !read10 && + !read12 && + !read16 && + Blocks > 0x001FFFFF + 1) { ErrorMessage = $"Device only supports SCSI READ (6) but has more than {0x001FFFFF + 1} blocks ({Blocks} blocks total)"; + return true; } - if(!read16 && Blocks > 0xFFFFFFFF + (long)1) + if(!read16 && + Blocks > 0xFFFFFFFF + (long)1) { ErrorMessage = $"Device only supports SCSI READ (10) but has more than {0xFFFFFFFF + (long)1} blocks ({Blocks} blocks total)"; + return true; } @@ -120,17 +132,23 @@ namespace DiscImageChef.Core.Devices testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 0xFFFF, timeout, out _); FixedSense? decSense; + if(testSense && !dev.Error) { decSense = Sense.DecodeFixed(senseBuf); + if(decSense.HasValue) - if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 && + if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) { CanReadRaw = true; - if(decSense.Value.InformationValid && decSense.Value.ILI) + + if(decSense.Value.InformationValid && + decSense.Value.ILI) { LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); + readLong10 = !dev.ReadLong10(out _, out senseBuf, false, false, 0, (ushort)LongBlockSize, timeout, out _); } @@ -143,29 +161,37 @@ namespace DiscImageChef.Core.Devices { // Long sector sizes for floppies 514, + // Long sector sizes for SuperDisk 536, 558, + // Long sector sizes for 512-byte magneto-opticals 600, 610, 630 }) { ushort testSize = (ushort)i; testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong16 = true; LongBlockSize = testSize; CanReadRaw = true; + break; } testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout, out _); - if(testSense || dev.Error) continue; + + if(testSense || dev.Error) + continue; readLong10 = true; LongBlockSize = testSize; CanReadRaw = true; + break; } else if(LogicalBlockSize == 1024) @@ -173,33 +199,42 @@ namespace DiscImageChef.Core.Devices { // Long sector sizes for floppies 1026, + // Long sector sizes for 1024-byte magneto-opticals 1200 }) { ushort testSize = (ushort)i; testSense = dev.ReadLong16(out _, out senseBuf, false, 0, testSize, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong16 = true; LongBlockSize = testSize; CanReadRaw = true; + break; } testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, testSize, timeout, out _); - if(testSense || dev.Error) continue; + + if(testSense || dev.Error) + continue; readLong10 = true; LongBlockSize = testSize; CanReadRaw = true; + break; } else if(LogicalBlockSize == 2048) { testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 2380, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong16 = true; LongBlockSize = 2380; @@ -208,7 +243,9 @@ namespace DiscImageChef.Core.Devices else { testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 2380, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong10 = true; LongBlockSize = 2380; @@ -219,7 +256,9 @@ namespace DiscImageChef.Core.Devices else if(LogicalBlockSize == 4096) { testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 4760, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong16 = true; LongBlockSize = 4760; @@ -228,7 +267,9 @@ namespace DiscImageChef.Core.Devices else { testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 4760, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong10 = true; LongBlockSize = 4760; @@ -239,7 +280,9 @@ namespace DiscImageChef.Core.Devices else if(LogicalBlockSize == 8192) { testSense = dev.ReadLong16(out _, out senseBuf, false, 0, 9424, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong16 = true; LongBlockSize = 9424; @@ -248,7 +291,9 @@ namespace DiscImageChef.Core.Devices else { testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 9424, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLong10 = true; LongBlockSize = 9424; @@ -257,20 +302,27 @@ namespace DiscImageChef.Core.Devices } } - if(!CanReadRaw && dev.Manufacturer == "SYQUEST") + if(!CanReadRaw && + dev.Manufacturer == "SYQUEST") { testSense = dev.SyQuestReadLong10(out _, out senseBuf, 0, 0xFFFF, timeout, out _); + if(testSense) { decSense = Sense.DecodeFixed(senseBuf); + if(decSense.HasValue) - if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 && + if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && + decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) { CanReadRaw = true; - if(decSense.Value.InformationValid && decSense.Value.ILI) + + if(decSense.Value.InformationValid && + decSense.Value.ILI) { LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); + syqReadLong10 = !dev.SyQuestReadLong10(out _, out senseBuf, 0, LongBlockSize, timeout, out _); @@ -279,18 +331,23 @@ namespace DiscImageChef.Core.Devices else { testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 0xFFFF, timeout, out _); + if(testSense) { decSense = Sense.DecodeFixed(senseBuf); + if(decSense.HasValue) if(decSense.Value.SenseKey == SenseKeys.IllegalRequest && decSense.Value.ASC == 0x24 && decSense.Value.ASCQ == 0x00) { CanReadRaw = true; - if(decSense.Value.InformationValid && decSense.Value.ILI) + + if(decSense.Value.InformationValid && + decSense.Value.ILI) { LongBlockSize = 0xFFFF - (decSense.Value.Information & 0xFFFF); + syqReadLong6 = !dev.SyQuestReadLong6(out _, out senseBuf, 0, LongBlockSize, timeout, out _); @@ -300,10 +357,13 @@ namespace DiscImageChef.Core.Devices } } - if(!CanReadRaw && LogicalBlockSize == 256) + if(!CanReadRaw && + LogicalBlockSize == 256) { testSense = dev.SyQuestReadLong6(out _, out senseBuf, 0, 262, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { syqReadLong6 = true; LongBlockSize = 262; @@ -316,11 +376,13 @@ namespace DiscImageChef.Core.Devices { switch(dev.Manufacturer) { - case "HL-DT-ST": + case"HL-DT-ST": hldtstReadRaw = !dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _); + break; - case "PLEXTOR": + case"PLEXTOR": plextorReadRaw = !dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, timeout, out _); + break; } @@ -331,10 +393,13 @@ namespace DiscImageChef.Core.Devices } // READ LONG (10) for some DVD drives - if(!CanReadRaw && dev.Manufacturer == "MATSHITA") + if(!CanReadRaw && + dev.Manufacturer == "MATSHITA") { testSense = dev.ReadLong10(out _, out senseBuf, false, false, 0, 37856, timeout, out _); - if(!testSense && !dev.Error) + + if(!testSense && + !dev.Error) { readLongDvd = true; LongBlockSize = 37856; @@ -346,17 +411,27 @@ namespace DiscImageChef.Core.Devices if(CanReadRaw) { - if(readLong16) DicConsole.WriteLine("Using SCSI READ LONG (16) command."); - else if(readLong10 || readLongDvd) DicConsole.WriteLine("Using SCSI READ LONG (10) command."); - else if(syqReadLong10) DicConsole.WriteLine("Using SyQuest READ LONG (10) command."); - 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."); + if(readLong16) + DicConsole.WriteLine("Using SCSI READ LONG (16) command."); + else if(readLong10 || readLongDvd) + DicConsole.WriteLine("Using SCSI READ LONG (10) command."); + else if(syqReadLong10) + DicConsole.WriteLine("Using SyQuest READ LONG (10) command."); + 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) DicConsole.WriteLine("Using SCSI READ (16) command."); - else if(read12) DicConsole.WriteLine("Using SCSI READ (12) command."); - else if(read10) DicConsole.WriteLine("Using SCSI READ (10) command."); - else if(read6) DicConsole.WriteLine("Using SCSI READ (6) command."); + else if(read16) + DicConsole.WriteLine("Using SCSI READ (16) command."); + else if(read12) + DicConsole.WriteLine("Using SCSI READ (12) command."); + else if(read10) + DicConsole.WriteLine("Using SCSI READ (10) command."); + else if(read6) + DicConsole.WriteLine("Using SCSI READ (6) command."); return false; } @@ -367,6 +442,7 @@ namespace DiscImageChef.Core.Devices Blocks = 0; sense = dev.ReadCapacity(out byte[] cmdBuf, out byte[] senseBuf, timeout, out _); + if(!sense) { Blocks = (ulong)((cmdBuf[0] << 24) + (cmdBuf[1] << 16) + (cmdBuf[2] << 8) + cmdBuf[3]); @@ -398,6 +474,7 @@ namespace DiscImageChef.Core.Devices PhysicalBlockSize = LogicalBlockSize; LongBlockSize = LogicalBlockSize; + return false; } @@ -411,33 +488,45 @@ namespace DiscImageChef.Core.Devices { dev.Read16(out _, out _, 0, false, true, false, 0, LogicalBlockSize, 0, BlocksToRead, false, timeout, out _); - if(dev.Error) BlocksToRead /= 2; + + if(dev.Error) + BlocksToRead /= 2; } else if(read12) { dev.Read12(out _, out _, 0, false, false, false, false, 0, LogicalBlockSize, 0, BlocksToRead, false, timeout, out _); - if(dev.Error) BlocksToRead /= 2; + + if(dev.Error) + BlocksToRead /= 2; } else if(read10) { dev.Read10(out _, out _, 0, false, true, false, false, 0, LogicalBlockSize, 0, (ushort)BlocksToRead, timeout, out _); - if(dev.Error) BlocksToRead /= 2; + + if(dev.Error) + BlocksToRead /= 2; } else if(read6) { dev.Read6(out _, out _, 0, LogicalBlockSize, (byte)BlocksToRead, timeout, out _); - if(dev.Error) BlocksToRead /= 2; + + if(dev.Error) + BlocksToRead /= 2; } - if(!dev.Error || BlocksToRead == 1) break; + if(!dev.Error || + BlocksToRead == 1) + break; } - if(!dev.Error) return false; + if(!dev.Error) + return false; BlocksToRead = 1; ErrorMessage = $"Device error {dev.LastError} trying to guess ideal transfer length."; + return true; } @@ -467,7 +556,8 @@ namespace DiscImageChef.Core.Devices else if(plextorReadRaw) sense = dev.PlextorReadRawDvd(out buffer, out senseBuf, (uint)block, LongBlockSize, timeout, out duration); - else return true; + else + return true; else { if(read16) @@ -482,12 +572,16 @@ namespace DiscImageChef.Core.Devices else if(read6) sense = dev.Read6(out buffer, out senseBuf, (uint)block, LogicalBlockSize, (byte)count, timeout, out duration); - else return true; + else + return true; } - if(!sense && !dev.Error) return false; + if(!sense && + !dev.Error) + return false; DicConsole.DebugWriteLine("SCSI Reader", "READ error:\n{0}", Sense.PrettifySense(senseBuf)); + return sense; } @@ -496,8 +590,10 @@ namespace DiscImageChef.Core.Devices bool sense = true; duration = 0; - if(seek6) sense = dev.Seek6(out _, (uint)block, timeout, out duration); - else if(seek10) sense = dev.Seek10(out _, (uint)block, timeout, out duration); + if(seek6) + sense = dev.Seek6(out _, (uint)block, timeout, out duration); + else if(seek10) + sense = dev.Seek10(out _, (uint)block, timeout, out duration); return sense; } diff --git a/DiscImageChef.Core/Devices/Report/ATA.cs b/DiscImageChef.Core/Devices/Report/ATA.cs index c176b499a..856e2d4e7 100644 --- a/DiscImageChef.Core/Devices/Report/ATA.cs +++ b/DiscImageChef.Core/Devices/Report/ATA.cs @@ -35,6 +35,7 @@ using DiscImageChef.CommonTypes.Metadata; using DiscImageChef.Console; using DiscImageChef.Decoders.ATA; using DiscImageChef.Devices; +using Identify = DiscImageChef.CommonTypes.Structs.Devices.ATA.Identify; namespace DiscImageChef.Core.Devices.Report { diff --git a/DiscImageChef.Core/Devices/Report/Scsi.cs b/DiscImageChef.Core/Devices/Report/Scsi.cs index ec74a9a05..2f8b638cf 100644 --- a/DiscImageChef.Core/Devices/Report/Scsi.cs +++ b/DiscImageChef.Core/Devices/Report/Scsi.cs @@ -34,9 +34,11 @@ using System; using System.Collections.Generic; using System.Linq; using DiscImageChef.CommonTypes.Metadata; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; +using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry; namespace DiscImageChef.Core.Devices.Report { @@ -52,12 +54,12 @@ namespace DiscImageChef.Core.Devices.Report if(sense) return null; - Inquiry.SCSIInquiry? decodedNullable = Inquiry.Decode(buffer); + Inquiry? decodedNullable = Inquiry.Decode(buffer); if(!decodedNullable.HasValue) return null; - Inquiry.SCSIInquiry decoded = decodedNullable.Value; + Inquiry decoded = decodedNullable.Value; // Clear Seagate serial number if(decoded.SeagatePresent && diff --git a/DiscImageChef.Core/Devices/Scanning/ATA.cs b/DiscImageChef.Core/Devices/Scanning/ATA.cs index a4b06cdeb..dae35cfa4 100644 --- a/DiscImageChef.Core/Devices/Scanning/ATA.cs +++ b/DiscImageChef.Core/Devices/Scanning/ATA.cs @@ -32,38 +32,39 @@ using System; using System.Collections.Generic; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Core.Logging; -using DiscImageChef.Decoders.ATA; namespace DiscImageChef.Core.Devices.Scanning { - /// - /// Implements scanning the media from an ATA device - /// + /// Implements scanning the media from an ATA device public partial class MediaScan { - /// - /// Scans the media from an ATA device - /// + /// Scans the media from an ATA device /// Scanning results ScanResults Ata() { - ScanResults results = new ScanResults(); - bool sense; + var results = new ScanResults(); + bool sense; results.Blocks = 0; const ushort ATA_PROFILE = 0x0001; const uint TIMEOUT = 5; sense = dev.AtaIdentify(out byte[] cmdBuf, out _); - if(!sense && Identify.Decode(cmdBuf).HasValue) + + if(!sense && + Identify.Decode(cmdBuf).HasValue) { // Initializate reader - Reader ataReader = new Reader(dev, TIMEOUT, cmdBuf); + var ataReader = new Reader(dev, TIMEOUT, cmdBuf); + // Fill reader blocks results.Blocks = ataReader.GetDeviceBlocks(); + if(ataReader.FindReadCommand()) { StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + return results; } @@ -71,14 +72,17 @@ namespace DiscImageChef.Core.Devices.Scanning if(ataReader.GetBlockSize()) { StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + return results; } uint blockSize = ataReader.LogicalBlockSize; + // Check how many blocks to read, if error show and return if(ataReader.GetBlocksToRead()) { StoppingErrorMessage?.Invoke(ataReader.ErrorMessage); + return results; } @@ -108,11 +112,12 @@ namespace DiscImageChef.Core.Devices.Scanning double seekCur; - Random rnd = new Random(); + var rnd = new Random(); MhddLog mhddLog; IbgLog ibgLog; double duration; + if(ataReader.IsLba) { UpdateStatus?.Invoke($"Reading {blocksToRead} sectors at a time."); @@ -125,15 +130,23 @@ namespace DiscImageChef.Core.Devices.Scanning DateTime timeSpeedStart = DateTime.UtcNow; ulong sectorSpeedStart = 0; InitProgress?.Invoke(); + for(ulong i = 0; i < results.Blocks; i += blocksToRead) { - if(aborted) break; + if(aborted) + break; - if(results.Blocks - i < blocksToRead) blocksToRead = (byte)(results.Blocks - i); + if(results.Blocks - i < blocksToRead) + blocksToRead = (byte)(results.Blocks - i); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed; - if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed; + if(currentSpeed > results.MaxSpeed && + currentSpeed != 0) + results.MaxSpeed = currentSpeed; + + if(currentSpeed < results.MinSpeed && + currentSpeed != 0) + results.MinSpeed = currentSpeed; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", @@ -143,12 +156,18 @@ namespace DiscImageChef.Core.Devices.Scanning if(!error) { - if(duration >= 500) results.F += blocksToRead; - else if(duration >= 150) results.E += blocksToRead; - else if(duration >= 50) results.D += blocksToRead; - else if(duration >= 10) results.C += blocksToRead; - else if(duration >= 3) results.B += blocksToRead; - else results.A += blocksToRead; + if(duration >= 500) + results.F += blocksToRead; + else if(duration >= 150) + results.E += blocksToRead; + else if(duration >= 50) + results.D += blocksToRead; + else if(duration >= 10) + results.C += blocksToRead; + else if(duration >= 3) + results.B += blocksToRead; + else + results.A += blocksToRead; ScanTime?.Invoke(i, duration); mhddLog.Write(i, duration); @@ -158,7 +177,9 @@ namespace DiscImageChef.Core.Devices.Scanning { ScanUnreadable?.Invoke(i); results.Errored += blocksToRead; - for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); + + for(ulong b = i; b < i + blocksToRead; b++) + results.UnreadableSectors.Add(b); mhddLog.Write(i, duration < 500 ? 65535 : duration); @@ -168,10 +189,12 @@ namespace DiscImageChef.Core.Devices.Scanning sectorSpeedStart += blocksToRead; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; - if(elapsed < 1) continue; - currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed); - ScanSpeed?.Invoke(i, currentSpeed * 1024); + if(elapsed < 1) + continue; + + currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); + ScanSpeed?.Invoke(i, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } @@ -179,16 +202,19 @@ namespace DiscImageChef.Core.Devices.Scanning end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); + ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / + (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); InitProgress?.Invoke(); + if(ataReader.CanSeekLba) for(int i = 0; i < SEEK_TIMES; i++) { - if(aborted) break; + if(aborted) + break; uint seekPos = (uint)rnd.Next((int)results.Blocks); @@ -197,8 +223,13 @@ namespace DiscImageChef.Core.Devices.Scanning ataReader.Seek(seekPos, out seekCur); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur; - if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur; + if(seekCur > results.SeekMax && + seekCur != 0) + results.SeekMax = seekCur; + + if(seekCur < results.SeekMin && + seekCur != 0) + results.SeekMin = seekCur; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator results.SeekTotal += seekCur; @@ -219,34 +250,45 @@ namespace DiscImageChef.Core.Devices.Scanning DateTime timeSpeedStart = DateTime.UtcNow; ulong sectorSpeedStart = 0; InitProgress?.Invoke(); + for(ushort cy = 0; cy < cylinders; cy++) { for(byte hd = 0; hd < heads; hd++) { for(byte sc = 1; sc < sectors; sc++) { - if(aborted) break; + if(aborted) + break; #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; - if(currentSpeed < results.MinSpeed && currentSpeed != 0) + + if(currentSpeed < results.MinSpeed && + currentSpeed != 0) results.MinSpeed = currentSpeed; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator - PulseProgress - ?.Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)"); + PulseProgress?. + Invoke($"Reading cylinder {cy} head {hd} sector {sc} ({currentSpeed:F3} MiB/sec.)"); bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration); if(!error) { - if(duration >= 500) results.F += blocksToRead; - else if(duration >= 150) results.E += blocksToRead; - else if(duration >= 50) results.D += blocksToRead; - else if(duration >= 10) results.C += blocksToRead; - else if(duration >= 3) results.B += blocksToRead; - else results.A += blocksToRead; + if(duration >= 500) + results.F += blocksToRead; + else if(duration >= 150) + results.E += blocksToRead; + else if(duration >= 50) + results.D += blocksToRead; + else if(duration >= 10) + results.C += blocksToRead; + else if(duration >= 3) + results.B += blocksToRead; + else + results.A += blocksToRead; ScanTime?.Invoke(currentBlock, duration); mhddLog.Write(currentBlock, duration); @@ -266,10 +308,12 @@ namespace DiscImageChef.Core.Devices.Scanning currentBlock++; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; - if(elapsed < 1) continue; - currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed); - ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024); + if(elapsed < 1) + continue; + + currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); + ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } @@ -279,29 +323,37 @@ namespace DiscImageChef.Core.Devices.Scanning end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); + ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / + (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); InitProgress?.Invoke(); + if(ataReader.CanSeek) for(int i = 0; i < SEEK_TIMES; i++) { - if(aborted) break; + if(aborted) + break; ushort seekCy = (ushort)rnd.Next(cylinders); byte seekHd = (byte)rnd.Next(heads); byte seekSc = (byte)rnd.Next(sectors); - PulseProgress - ?.Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t"); + PulseProgress?. + Invoke($"\rSeeking to cylinder {seekCy}, head {seekHd}, sector {seekSc}...\t\t"); ataReader.SeekChs(seekCy, seekHd, seekSc, out seekCur); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur; - if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur; + if(seekCur > results.SeekMax && + seekCur != 0) + results.SeekMax = seekCur; + + if(seekCur < results.SeekMin && + seekCur != 0) + results.SeekMin = seekCur; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator results.SeekTotal += seekCur; @@ -313,13 +365,14 @@ namespace DiscImageChef.Core.Devices.Scanning results.ProcessingTime /= 1000; results.TotalTime = (end - start).TotalSeconds; - results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime; + results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime; results.SeekTimes = SEEK_TIMES; return results; } StoppingErrorMessage?.Invoke("Unable to communicate with ATA device."); + return results; } } diff --git a/DiscImageChef.Core/Devices/Scanning/SCSI.cs b/DiscImageChef.Core/Devices/Scanning/SCSI.cs index 501d5db9e..0b409f01d 100644 --- a/DiscImageChef.Core/Devices/Scanning/SCSI.cs +++ b/DiscImageChef.Core/Devices/Scanning/SCSI.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.Threading; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core.Logging; using DiscImageChef.Decoders.CD; @@ -42,18 +43,16 @@ using DiscImageChef.Devices; namespace DiscImageChef.Core.Devices.Scanning { - /// - /// Implements scanning the media from an SCSI device - /// + /// Implements scanning the media from an SCSI device public partial class MediaScan { ScanResults Scsi() { - ScanResults results = new ScanResults(); - MhddLog mhddLog; - IbgLog ibgLog; - byte[] senseBuf; - bool sense = false; + var results = new ScanResults(); + MhddLog mhddLog; + IbgLog ibgLog; + byte[] senseBuf; + bool sense = false; results.Blocks = 0; uint blockSize = 0; ushort currentProfile = 0x0001; @@ -61,20 +60,25 @@ namespace DiscImageChef.Core.Devices.Scanning if(dev.IsRemovable) { sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); + if(sense) { InitProgress?.Invoke(); FixedSense? decSense = Sense.DecodeFixed(senseBuf); + if(decSense.HasValue) if(decSense.Value.ASC == 0x3A) { int leftRetries = 5; + while(leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if(!sense) break; + + if(!sense) + break; leftRetries--; } @@ -82,59 +86,72 @@ namespace DiscImageChef.Core.Devices.Scanning if(sense) { StoppingErrorMessage?.Invoke("Please insert media in drive"); + return results; } } - else if(decSense.Value.ASC == 0x04 && decSense.Value.ASCQ == 0x01) + else if(decSense.Value.ASC == 0x04 && + decSense.Value.ASCQ == 0x01) { int leftRetries = 10; + while(leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if(!sense) break; + + if(!sense) + break; leftRetries--; } if(sense) { - StoppingErrorMessage - ?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + StoppingErrorMessage?. + Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + return results; } } + // These should be trapped by the OS but seems in some cases they're not else if(decSense.Value.ASC == 0x28) { int leftRetries = 10; + while(leftRetries > 0) { PulseProgress?.Invoke("Waiting for drive to become ready"); Thread.Sleep(2000); sense = dev.ScsiTestUnitReady(out senseBuf, dev.Timeout, out _); - if(!sense) break; + + if(!sense) + break; leftRetries--; } if(sense) { - StoppingErrorMessage - ?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + StoppingErrorMessage?. + Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + return results; } } else { - StoppingErrorMessage - ?.Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + StoppingErrorMessage?. + Invoke($"Error testing unit was ready:\n{Sense.PrettifySense(senseBuf)}"); + return results; } else { StoppingErrorMessage?.Invoke("Unknown testing unit was ready."); + return results; } @@ -154,19 +171,23 @@ namespace DiscImageChef.Core.Devices.Scanning case PeripheralDeviceTypes.WriteOnceDevice: scsiReader = new Reader(dev, dev.Timeout, null); results.Blocks = scsiReader.GetDeviceBlocks(); + if(scsiReader.FindReadCommand()) { StoppingErrorMessage?.Invoke("Unable to read medium."); + return results; } blockSize = scsiReader.LogicalBlockSize; - if(results.Blocks != 0 && blockSize != 0) + if(results.Blocks != 0 && + blockSize != 0) { results.Blocks++; - UpdateStatus - ?.Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)"); + + UpdateStatus?. + Invoke($"Media has {results.Blocks} blocks of {blockSize} bytes/each. (for a total of {results.Blocks * (ulong)blockSize} bytes)"); } break; @@ -174,12 +195,14 @@ namespace DiscImageChef.Core.Devices.Scanning StoppingErrorMessage?.Invoke("Scanning will never be supported on SCSI Streaming Devices." + Environment.NewLine + "It has no sense to do it, and it will put too much strain on the tape."); + return results; } if(results.Blocks == 0) { StoppingErrorMessage?.Invoke("Unable to read medium or empty medium present..."); + return results; } @@ -190,6 +213,7 @@ namespace DiscImageChef.Core.Devices.Scanning { sense = dev.GetConfiguration(out byte[] cmdBuf, out senseBuf, 0, MmcGetConfigurationRt.Current, dev.Timeout, out _); + if(!sense) { Features.SeparatedFeatures ftr = Features.Separate(cmdBuf); @@ -207,6 +231,7 @@ namespace DiscImageChef.Core.Devices.Scanning case 0x0022: break; default: compactDisc = false; + break; } } @@ -214,13 +239,17 @@ namespace DiscImageChef.Core.Devices.Scanning if(compactDisc) { currentProfile = 0x0008; + // We discarded all discs that falsify a TOC before requesting a real TOC // No TOC, no CD (or an empty one) - bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); - if(!tocSense) toc = FullTOC.Decode(cmdBuf); + bool tocSense = dev.ReadRawToc(out cmdBuf, out senseBuf, 1, dev.Timeout, out _); + + if(!tocSense) + toc = FullTOC.Decode(cmdBuf); } } - else compactDisc = false; + else + compactDisc = false; uint blocksToRead = 64; @@ -245,6 +274,7 @@ namespace DiscImageChef.Core.Devices.Scanning if(toc == null) { StoppingErrorMessage?.Invoke("Error trying to decode TOC..."); + return results; } @@ -252,7 +282,8 @@ namespace DiscImageChef.Core.Devices.Scanning MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); - if(readcd) UpdateStatus?.Invoke("Using MMC READ CD command."); + if(readcd) + UpdateStatus?.Invoke("Using MMC READ CD command."); start = DateTime.UtcNow; @@ -263,16 +294,21 @@ namespace DiscImageChef.Core.Devices.Scanning sense = dev.ReadCd(out _, out senseBuf, 0, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out _); - if(dev.Error) blocksToRead /= 2; + + if(dev.Error) + blocksToRead /= 2; } - if(!dev.Error || blocksToRead == 1) break; + if(!dev.Error || + blocksToRead == 1) + break; } if(dev.Error) { - StoppingErrorMessage - ?.Invoke($"Device error {dev.LastError} trying to guess ideal transfer length."); + StoppingErrorMessage?. + Invoke($"Device error {dev.LastError} trying to guess ideal transfer length."); + return results; } @@ -285,17 +321,25 @@ namespace DiscImageChef.Core.Devices.Scanning ulong sectorSpeedStart = 0; InitProgress?.Invoke(); + for(ulong i = 0; i < results.Blocks; i += blocksToRead) { - if(aborted) break; + if(aborted) + break; double cmdDuration = 0; - if(results.Blocks - i < blocksToRead) blocksToRead = (uint)(results.Blocks - i); + if(results.Blocks - i < blocksToRead) + blocksToRead = (uint)(results.Blocks - i); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed; - if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed; + if(currentSpeed > results.MaxSpeed && + currentSpeed != 0) + results.MaxSpeed = currentSpeed; + + if(currentSpeed < results.MinSpeed && + currentSpeed != 0) + results.MinSpeed = currentSpeed; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", @@ -306,17 +350,24 @@ namespace DiscImageChef.Core.Devices.Scanning sense = dev.ReadCd(out _, out senseBuf, (uint)i, 2352, blocksToRead, MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, MmcSubchannel.None, dev.Timeout, out cmdDuration); + results.ProcessingTime += cmdDuration; } if(!sense) { - if(cmdDuration >= 500) results.F += blocksToRead; - else if(cmdDuration >= 150) results.E += blocksToRead; - else if(cmdDuration >= 50) results.D += blocksToRead; - else if(cmdDuration >= 10) results.C += blocksToRead; - else if(cmdDuration >= 3) results.B += blocksToRead; - else results.A += blocksToRead; + if(cmdDuration >= 500) + results.F += blocksToRead; + else if(cmdDuration >= 150) + results.E += blocksToRead; + else if(cmdDuration >= 50) + results.D += blocksToRead; + else if(cmdDuration >= 10) + results.C += blocksToRead; + else if(cmdDuration >= 3) + results.B += blocksToRead; + else + results.A += blocksToRead; ScanTime?.Invoke(i, cmdDuration); mhddLog.Write(i, cmdDuration); @@ -327,17 +378,21 @@ namespace DiscImageChef.Core.Devices.Scanning DicConsole.DebugWriteLine("Media-Scan", "READ CD error:\n{0}", Sense.PrettifySense(senseBuf)); FixedSense? senseDecoded = Sense.DecodeFixed(senseBuf); + if(senseDecoded.HasValue) { // TODO: This error happens when changing from track type afaik. Need to solve that more cleanly // LOGICAL BLOCK ADDRESS OUT OF RANGE 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 // are in a track where subchannel indicates data) (senseDecoded.Value.ASC != 0x64 || senseDecoded.Value.ASCQ != 0x00)) { results.Errored += blocksToRead; - for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); + + for(ulong b = i; b < i + blocksToRead; b++) + results.UnreadableSectors.Add(b); ScanUnreadable?.Invoke(i); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); @@ -349,7 +404,9 @@ namespace DiscImageChef.Core.Devices.Scanning { ScanUnreadable?.Invoke(i); results.Errored += blocksToRead; - for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); + + for(ulong b = i; b < i + blocksToRead; b++) + results.UnreadableSectors.Add(b); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); @@ -360,10 +417,12 @@ namespace DiscImageChef.Core.Devices.Scanning sectorSpeedStart += blocksToRead; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; - if(elapsed < 1) continue; - currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed); - ScanSpeed?.Invoke(i, currentSpeed * 1024); + if(elapsed < 1) + continue; + + currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); + ScanSpeed?.Invoke(i, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } @@ -371,8 +430,9 @@ namespace DiscImageChef.Core.Devices.Scanning end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); + ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / + (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); } @@ -389,15 +449,23 @@ namespace DiscImageChef.Core.Devices.Scanning ulong sectorSpeedStart = 0; InitProgress?.Invoke(); + for(ulong i = 0; i < results.Blocks; i += blocksToRead) { - if(aborted) break; + if(aborted) + break; - if(results.Blocks - i < blocksToRead) blocksToRead = (uint)(results.Blocks - i); + if(results.Blocks - i < blocksToRead) + blocksToRead = (uint)(results.Blocks - i); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(currentSpeed > results.MaxSpeed && currentSpeed != 0) results.MaxSpeed = currentSpeed; - if(currentSpeed < results.MinSpeed && currentSpeed != 0) results.MinSpeed = currentSpeed; + if(currentSpeed > results.MaxSpeed && + currentSpeed != 0) + results.MaxSpeed = currentSpeed; + + if(currentSpeed < results.MinSpeed && + currentSpeed != 0) + results.MinSpeed = currentSpeed; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator UpdateProgress?.Invoke($"Reading sector {i} of {results.Blocks} ({currentSpeed:F3} MiB/sec.)", @@ -406,25 +474,35 @@ namespace DiscImageChef.Core.Devices.Scanning sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration); results.ProcessingTime += cmdDuration; - if(!sense && !dev.Error) + if(!sense && + !dev.Error) { - if(cmdDuration >= 500) results.F += blocksToRead; - else if(cmdDuration >= 150) results.E += blocksToRead; - else if(cmdDuration >= 50) results.D += blocksToRead; - else if(cmdDuration >= 10) results.C += blocksToRead; - else if(cmdDuration >= 3) results.B += blocksToRead; - else results.A += blocksToRead; + if(cmdDuration >= 500) + results.F += blocksToRead; + else if(cmdDuration >= 150) + results.E += blocksToRead; + else if(cmdDuration >= 50) + results.D += blocksToRead; + else if(cmdDuration >= 10) + results.C += blocksToRead; + else if(cmdDuration >= 3) + results.B += blocksToRead; + else + results.A += blocksToRead; ScanTime?.Invoke(i, cmdDuration); mhddLog.Write(i, cmdDuration); ibgLog.Write(i, currentSpeed * 1024); } + // TODO: Separate errors on kind of errors. else { ScanUnreadable?.Invoke(i); results.Errored += blocksToRead; - for(ulong b = i; b < i + blocksToRead; b++) results.UnreadableSectors.Add(b); + + for(ulong b = i; b < i + blocksToRead; b++) + results.UnreadableSectors.Add(b); mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); ibgLog.Write(i, 0); @@ -433,10 +511,12 @@ namespace DiscImageChef.Core.Devices.Scanning sectorSpeedStart += blocksToRead; double elapsed = (DateTime.UtcNow - timeSpeedStart).TotalSeconds; - if(elapsed < 1) continue; - currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed); - ScanSpeed?.Invoke(i, currentSpeed * 1024); + if(elapsed < 1) + continue; + + currentSpeed = (sectorSpeedStart * blockSize) / (1048576 * elapsed); + ScanSpeed?.Invoke(i, currentSpeed * 1024); sectorSpeedStart = 0; timeSpeedStart = DateTime.UtcNow; } @@ -444,8 +524,9 @@ namespace DiscImageChef.Core.Devices.Scanning end = DateTime.UtcNow; EndProgress?.Invoke(); mhddLog.Close(); + ibgLog.Close(dev, results.Blocks, blockSize, (end - start).TotalSeconds, currentSpeed * 1024, - blockSize * (double)(results.Blocks + 1) / 1024 / + (blockSize * (double)(results.Blocks + 1)) / 1024 / (results.ProcessingTime / 1000), devicePath); } @@ -455,24 +536,34 @@ namespace DiscImageChef.Core.Devices.Scanning results.SeekTotal = 0; const int SEEK_TIMES = 1000; - Random rnd = new Random(); + var rnd = new Random(); InitProgress?.Invoke(); + for(int i = 0; i < SEEK_TIMES; i++) { - if(aborted) break; + if(aborted) + break; uint seekPos = (uint)rnd.Next((int)results.Blocks); PulseProgress?.Invoke($"Seeking to sector {seekPos}...\t\t"); double seekCur; - if(scsiReader.CanSeek) scsiReader.Seek(seekPos, out seekCur); - else scsiReader.ReadBlock(out _, seekPos, out seekCur); + + if(scsiReader.CanSeek) + scsiReader.Seek(seekPos, out seekCur); + else + scsiReader.ReadBlock(out _, seekPos, out seekCur); #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(seekCur > results.SeekMax && seekCur != 0) results.SeekMax = seekCur; - if(seekCur < results.SeekMin && seekCur != 0) results.SeekMin = seekCur; + if(seekCur > results.SeekMax && + seekCur != 0) + results.SeekMax = seekCur; + + if(seekCur < results.SeekMin && + seekCur != 0) + results.SeekMin = seekCur; #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator results.SeekTotal += seekCur; @@ -483,7 +574,7 @@ namespace DiscImageChef.Core.Devices.Scanning results.ProcessingTime /= 1000; results.TotalTime = (end - start).TotalSeconds; - results.AvgSpeed = blockSize * (double)(results.Blocks + 1) / 1048576 / results.ProcessingTime; + results.AvgSpeed = (blockSize * (double)(results.Blocks + 1)) / 1048576 / results.ProcessingTime; results.SeekTimes = SEEK_TIMES; return results; diff --git a/DiscImageChef.Core/ImageInfo.cs b/DiscImageChef.Core/ImageInfo.cs index e0a76063b..504ec0f0a 100644 --- a/DiscImageChef.Core/ImageInfo.cs +++ b/DiscImageChef.Core/ImageInfo.cs @@ -36,6 +36,7 @@ using System.Text; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.Bluray; @@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox; using Schemas; using DDS = DiscImageChef.Decoders.DVD.DDS; using DMI = DiscImageChef.Decoders.Xbox.DMI; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; using Session = DiscImageChef.CommonTypes.Structs.Session; using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple; @@ -57,55 +59,80 @@ namespace DiscImageChef.Core public static void PrintImageInfo(IMediaImage imageFormat) { DicConsole.WriteLine("Image information:"); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Version)) DicConsole.WriteLine("Format: {0} version {1}", imageFormat.Format, imageFormat.Info.Version); - else DicConsole.WriteLine("Format: {0}", imageFormat.Format); + else + DicConsole.WriteLine("Format: {0}", imageFormat.Format); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application) && !string.IsNullOrWhiteSpace(imageFormat.Info.ApplicationVersion)) DicConsole.WriteLine("Was created with {0} version {1}", imageFormat.Info.Application, imageFormat.Info.ApplicationVersion); else if(!string.IsNullOrWhiteSpace(imageFormat.Info.Application)) DicConsole.WriteLine("Was created with {0}", imageFormat.Info.Application); + DicConsole.WriteLine("Image without headers is {0} bytes long", imageFormat.Info.ImageSize); + DicConsole.WriteLine("Contains a media of {0} sectors with a maximum sector size of {1} bytes (if all sectors are of the same size this would be {2} bytes)", imageFormat.Info.Sectors, imageFormat.Info.SectorSize, imageFormat.Info.Sectors * imageFormat.Info.SectorSize); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Creator)) DicConsole.WriteLine("Created by: {0}", imageFormat.Info.Creator); + if(imageFormat.Info.CreationTime != DateTime.MinValue) DicConsole.WriteLine("Created on {0}", imageFormat.Info.CreationTime); + if(imageFormat.Info.LastModificationTime != DateTime.MinValue) DicConsole.WriteLine("Last modified on {0}", imageFormat.Info.LastModificationTime); + DicConsole.WriteLine("Contains a media of type {0} and XML type {1}", imageFormat.Info.MediaType, imageFormat.Info.XmlMediaType); + DicConsole.WriteLine("{0} partitions", imageFormat.Info.HasPartitions ? "Has" : "Doesn't have"); - DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have"); + DicConsole.WriteLine("{0} sessions", imageFormat.Info.HasSessions ? "Has" : "Doesn't have"); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.Comments)) DicConsole.WriteLine("Comments: {0}", imageFormat.Info.Comments); - if(imageFormat.Info.MediaSequence != 0 && imageFormat.Info.LastMediaSequence != 0) + + if(imageFormat.Info.MediaSequence != 0 && + imageFormat.Info.LastMediaSequence != 0) DicConsole.WriteLine("Media is number {0} on a set of {1} medias", imageFormat.Info.MediaSequence, imageFormat.Info.LastMediaSequence); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaTitle)) DicConsole.WriteLine("Media title: {0}", imageFormat.Info.MediaTitle); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaManufacturer)) DicConsole.WriteLine("Media manufacturer: {0}", imageFormat.Info.MediaManufacturer); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaModel)) DicConsole.WriteLine("Media model: {0}", imageFormat.Info.MediaModel); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaSerialNumber)) DicConsole.WriteLine("Media serial number: {0}", imageFormat.Info.MediaSerialNumber); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaBarcode)) DicConsole.WriteLine("Media barcode: {0}", imageFormat.Info.MediaBarcode); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.MediaPartNumber)) DicConsole.WriteLine("Media part number: {0}", imageFormat.Info.MediaPartNumber); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveManufacturer)) DicConsole.WriteLine("Drive manufacturer: {0}", imageFormat.Info.DriveManufacturer); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveModel)) DicConsole.WriteLine("Drive model: {0}", imageFormat.Info.DriveModel); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveSerialNumber)) DicConsole.WriteLine("Drive serial number: {0}", imageFormat.Info.DriveSerialNumber); + if(!string.IsNullOrWhiteSpace(imageFormat.Info.DriveFirmwareRevision)) DicConsole.WriteLine("Drive firmware info: {0}", imageFormat.Info.DriveFirmwareRevision); - if(imageFormat.Info.Cylinders > 0 && imageFormat.Info.Heads > 0 && + + if(imageFormat.Info.Cylinders > 0 && + imageFormat.Info.Heads > 0 && imageFormat.Info.SectorsPerTrack > 0 && imageFormat.Info.XmlMediaType != XmlMediaType.OpticalDisc && (!(imageFormat is ITapeImage tapeImage) || !tapeImage.IsTape)) @@ -113,19 +140,25 @@ namespace DiscImageChef.Core imageFormat.Info.Cylinders, imageFormat.Info.Heads, imageFormat.Info.SectorsPerTrack); - if(imageFormat.Info.ReadableMediaTags != null && imageFormat.Info.ReadableMediaTags.Count > 0) + if(imageFormat.Info.ReadableMediaTags != null && + imageFormat.Info.ReadableMediaTags.Count > 0) { DicConsole.WriteLine("Contains {0} readable media tags:", imageFormat.Info.ReadableMediaTags.Count); + foreach(MediaTagType tag in imageFormat.Info.ReadableMediaTags.OrderBy(t => t)) DicConsole.Write("{0} ", tag); + DicConsole.WriteLine(); } - if(imageFormat.Info.ReadableSectorTags != null && imageFormat.Info.ReadableSectorTags.Count > 0) + if(imageFormat.Info.ReadableSectorTags != null && + imageFormat.Info.ReadableSectorTags.Count > 0) { DicConsole.WriteLine("Contains {0} readable sector tags:", imageFormat.Info.ReadableSectorTags.Count); + foreach(SectorTagType tag in imageFormat.Info.ReadableSectorTags.OrderBy(t => t)) DicConsole.Write("{0} ", tag); + DicConsole.WriteLine(); } @@ -139,6 +172,7 @@ namespace DiscImageChef.Core byte[] inquiry = imageFormat.ReadDiskTag(MediaTagType.SCSI_INQUIRY); scsiDeviceType = (PeripheralDeviceTypes)(inquiry[0] & 0x1F); + if(inquiry.Length >= 16) { scsiVendorId = new byte[8]; @@ -213,6 +247,7 @@ namespace DiscImageChef.Core if(toc.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(toc, 0)); + if(dataLen + 2 != toc.Length) { byte[] tmp = new byte[toc.Length + 2]; @@ -236,6 +271,7 @@ namespace DiscImageChef.Core if(pma.Length > 0) { ushort dataLen = Swapping.Swap(BitConverter.ToUInt16(pma, 0)); + if(dataLen + 2 != pma.Length) { byte[] tmp = new byte[pma.Length + 2]; @@ -257,6 +293,7 @@ namespace DiscImageChef.Core byte[] atip = imageFormat.ReadDiskTag(MediaTagType.CD_ATIP); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(atip, 0)); + if(dataLen + 4 != atip.Length) { byte[] tmp = new byte[atip.Length + 4]; @@ -279,6 +316,7 @@ namespace DiscImageChef.Core byte[] cdtext = imageFormat.ReadDiskTag(MediaTagType.CD_TEXT); uint dataLen = Swapping.Swap(BitConverter.ToUInt32(cdtext, 0)); + if(dataLen + 4 != cdtext.Length) { byte[] tmp = new byte[cdtext.Length + 4]; @@ -302,6 +340,7 @@ namespace DiscImageChef.Core DicConsole.WriteLine("CompactDisc Media Catalogue Number contained in image: {0}", Encoding.UTF8.GetString(mcn)); + DicConsole.WriteLine(); } @@ -362,6 +401,7 @@ namespace DiscImageChef.Core DicConsole.WriteLine("PCMCIA CIS:"); Tuple[] tuples = CIS.GetTuples(cis); + if(tuples != null) foreach(Tuple tuple in tuples) switch(tuple.Code) @@ -371,12 +411,15 @@ namespace DiscImageChef.Core case TupleCodes.CISTPL_DEVICEGEO: case TupleCodes.CISTPL_DEVICEGEO_A: DicConsole.WriteLine("{0}", CIS.PrettifyDeviceGeometryTuple(tuple)); + break; case TupleCodes.CISTPL_MANFID: DicConsole.WriteLine("{0}", CIS.PrettifyManufacturerIdentificationTuple(tuple)); + break; case TupleCodes.CISTPL_VERS_1: DicConsole.WriteLine("{0}", CIS.PrettifyLevel1VersionTuple(tuple)); + break; case TupleCodes.CISTPL_ALTSTR: case TupleCodes.CISTPL_BAR: @@ -414,13 +457,16 @@ namespace DiscImageChef.Core case TupleCodes.CISTPL_VERS_2: DicConsole.DebugWriteLine("Device-Info command", "Found undecoded tuple ID {0}", tuple.Code); + break; default: DicConsole.DebugWriteLine("Device-Info command", "Found unknown tuple ID 0x{0:X2}", (byte)tuple.Code); + break; } - else DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples"); + else + DicConsole.DebugWriteLine("Device-Info command", "Could not get tuples"); } if(imageFormat.Info.ReadableMediaTags != null && @@ -521,6 +567,7 @@ namespace DiscImageChef.Core if(DMI.IsXbox(xdmi)) { DMI.XboxDMI? xmi = DMI.DecodeXbox(xdmi); + if(xmi.HasValue) { DicConsole.WriteLine("Xbox DMI contained in image:"); @@ -532,6 +579,7 @@ namespace DiscImageChef.Core if(DMI.IsXbox360(xdmi)) { DMI.Xbox360DMI? xmi = DMI.DecodeXbox360(xdmi); + if(xmi.HasValue) { DicConsole.WriteLine("Xbox 360 DMI contained in image:"); @@ -555,16 +603,21 @@ namespace DiscImageChef.Core { try { - if(opticalImage.Sessions != null && opticalImage.Sessions.Count > 0) + if(opticalImage.Sessions != null && + opticalImage.Sessions.Count > 0) { DicConsole.WriteLine("Image sessions:"); + DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", "Session", "First track", "Last track", "Start", "End"); + DicConsole.WriteLine("========================================================="); + foreach(Session session in opticalImage.Sessions) DicConsole.WriteLine("{0,-9}{1,-13}{2,-12}{3,-12}{4,-12}", session.SessionSequence, session.StartTrack, session.EndTrack, session.StartSector, session.EndSector); + DicConsole.WriteLine(); } } @@ -575,18 +628,23 @@ namespace DiscImageChef.Core try { - if(opticalImage.Tracks != null && opticalImage.Tracks.Count > 0) + if(opticalImage.Tracks != null && + opticalImage.Tracks.Count > 0) { DicConsole.WriteLine("Image tracks:"); + DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", "Track", "Type", "Bps", "Raw bps", "Subchannel", "Pregap", "Start", "End"); - DicConsole - .WriteLine("================================================================================="); + + DicConsole. + WriteLine("================================================================================="); + foreach(Track track in opticalImage.Tracks) DicConsole.WriteLine("{0,-7}{1,-17}{2,-6}{3,-8}{4,-12}{5,-8}{6,-12}{7,-12}", track.TrackSequence, track.TrackType, track.TrackBytesPerSector, track.TrackRawBytesPerSector, track.TrackSubchannelType, track.TrackPregap, track.TrackStartSector, track.TrackEndSector); + DicConsole.WriteLine(); } } @@ -596,7 +654,8 @@ namespace DiscImageChef.Core } } - if(imageFormat.DumpHardware == null) return; + if(imageFormat.DumpHardware == null) + return; const string MANUFACTURER_STRING = "Manufacturer"; const string MODEL_STRING = "Model"; @@ -616,19 +675,31 @@ namespace DiscImageChef.Core foreach(DumpHardwareType dump in imageFormat.DumpHardware) { - if(dump.Manufacturer?.Length > manufacturerLen) manufacturerLen = dump.Manufacturer.Length; - if(dump.Model?.Length > modelLen) modelLen = dump.Model.Length; - if(dump.Serial?.Length > serialLen) serialLen = dump.Serial.Length; + if(dump.Manufacturer?.Length > manufacturerLen) + manufacturerLen = dump.Manufacturer.Length; + + if(dump.Model?.Length > modelLen) + modelLen = dump.Model.Length; + + if(dump.Serial?.Length > serialLen) + serialLen = dump.Serial.Length; + if(dump.Software?.Name?.Length > softwareLen) softwareLen = dump.Software.Name.Length; + if(dump.Software?.Version?.Length > versionLen) versionLen = dump.Software.Version.Length; + if(dump.Software?.OperatingSystem?.Length > osLen) osLen = dump.Software.OperatingSystem.Length; + foreach(ExtentType extent in dump.Extents) { - if($"{extent.Start}".Length > sectorLen) sectorLen = $"{extent.Start}".Length; - if($"{extent.End}".Length > sectorLen) sectorLen = $"{extent.End}".Length; + if($"{extent.Start}".Length > sectorLen) + sectorLen = $"{extent.Start}".Length; + + if($"{extent.End}".Length > sectorLen) + sectorLen = $"{extent.End}".Length; } } @@ -643,14 +714,20 @@ namespace DiscImageChef.Core char[] separator = new char[manufacturerLen + modelLen + serialLen + softwareLen + versionLen + osLen + sectorLen + sectorLen]; - for(int i = 0; i < separator.Length; i++) separator[i] = '='; + + for(int i = 0; i < separator.Length; i++) + separator[i] = '='; + string format = $"{{0,-{manufacturerLen}}}{{1,-{modelLen}}}{{2,-{serialLen}}}{{3,-{softwareLen}}}{{4,-{versionLen}}}{{5,-{osLen}}}{{6,-{sectorLen}}}{{7,-{sectorLen}}}"; DicConsole.WriteLine("Dump hardware information:"); + DicConsole.WriteLine(format, MANUFACTURER_STRING, MODEL_STRING, SERIAL_STRING, SOFTWARE_STRING, VERSION_STRING, OS_STRING, START_STRING, END_STRING); + DicConsole.WriteLine(new string(separator)); + foreach(DumpHardwareType dump in imageFormat.DumpHardware) { foreach(ExtentType extent in dump.Extents) diff --git a/DiscImageChef.Core/Media/Info/ScsiInfo.cs b/DiscImageChef.Core/Media/Info/ScsiInfo.cs index 1c924ca22..f123d545d 100644 --- a/DiscImageChef.Core/Media/Info/ScsiInfo.cs +++ b/DiscImageChef.Core/Media/Info/ScsiInfo.cs @@ -36,6 +36,7 @@ using System.Linq; using System.Threading; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core.Media.Detection; using DiscImageChef.Decoders.CD; @@ -47,6 +48,7 @@ using DiscImageChef.Decoders.Xbox; using DiscImageChef.Devices; using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo; using DMI = DiscImageChef.Decoders.Xbox.DMI; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; namespace DiscImageChef.Core.Media.Info { @@ -1289,7 +1291,7 @@ namespace DiscImageChef.Core.Media.Info if(!sense) { - Inquiry.SCSIInquiry? inq = Inquiry.Decode(inqBuffer); + var inq = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(inqBuffer); if(inq.HasValue && inq.Value.KreonPresent) diff --git a/DiscImageChef.Core/PrintScsiModePages.cs b/DiscImageChef.Core/PrintScsiModePages.cs index fc1db5834..443067320 100644 --- a/DiscImageChef.Core/PrintScsiModePages.cs +++ b/DiscImageChef.Core/PrintScsiModePages.cs @@ -30,6 +30,7 @@ // Copyright © 2011-2020 Natalia Portillo // ****************************************************************************/ +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.SCSI; @@ -41,22 +42,26 @@ namespace DiscImageChef.Core { DicConsole.WriteLine(Modes.PrettifyModeHeader(decMode.Header, devType)); - if(decMode.Pages == null) return; + if(decMode.Pages == null) + return; foreach(Modes.ModePage page in decMode.Pages) + //DicConsole.WriteLine("Page {0:X2}h subpage {1:X2}h is {2} bytes long", page.Page, page.Subpage, page.PageResponse.Length); switch(page.Page) { case 0x00: { - if(devType == PeripheralDeviceTypes.MultiMediaDevice && page.Subpage == 0) + if(devType == PeripheralDeviceTypes.MultiMediaDevice && + page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_00_SFF(page.PageResponse)); else { if(page.Subpage != 0) DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h subpage {1:X2}h", page.Page, page.Subpage); - else DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page); + else + DicConsole.WriteLine("Found unknown vendor mode page {0:X2}h", page.Page); } break; @@ -67,42 +72,53 @@ namespace DiscImageChef.Core DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice ? Modes.PrettifyModePage_01_MMC(page.PageResponse) : Modes.PrettifyModePage_01(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x02: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_02(page.PageResponse)); + else + goto default; break; } case 0x03: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_03(page.PageResponse)); + else + goto default; break; } case 0x04: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_04(page.PageResponse)); + else + goto default; break; } case 0x05: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_05(page.PageResponse)); + else + goto default; break; } case 0x06: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_06(page.PageResponse)); + else + goto default; break; } @@ -112,51 +128,64 @@ namespace DiscImageChef.Core DicConsole.WriteLine(devType == PeripheralDeviceTypes.MultiMediaDevice ? Modes.PrettifyModePage_07_MMC(page.PageResponse) : Modes.PrettifyModePage_07(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x08: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_08(page.PageResponse)); + else + goto default; break; } case 0x0A: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse)); + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_0A(page.PageResponse)); else if(page.Subpage == 1) DicConsole.WriteLine(Modes.PrettifyModePage_0A_S01(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x0B: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_0B(page.PageResponse)); + else + goto default; break; } case 0x0D: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_0D(page.PageResponse)); + else + goto default; break; } case 0x0E: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_0E(page.PageResponse)); + else + goto default; break; } case 0x0F: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_0F(page.PageResponse)); + else + goto default; break; } @@ -166,14 +195,17 @@ namespace DiscImageChef.Core DicConsole.WriteLine(devType == PeripheralDeviceTypes.SequentialAccess ? Modes.PrettifyModePage_10_SSC(page.PageResponse) : Modes.PrettifyModePage_10(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x11: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_11(page.PageResponse)); + else + goto default; break; } @@ -181,24 +213,30 @@ namespace DiscImageChef.Core case 0x13: case 0x14: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_12_13_14(page.PageResponse)); + else + goto default; break; } case 0x1A: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse)); + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_1A(page.PageResponse)); else if(page.Subpage == 1) DicConsole.WriteLine(Modes.PrettifyModePage_1A_S01(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x1B: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_1B(page.PageResponse)); + else + goto default; break; } @@ -210,14 +248,17 @@ namespace DiscImageChef.Core : Modes.PrettifyModePage_1C(page.PageResponse)); else if(page.Subpage == 1) DicConsole.WriteLine(Modes.PrettifyModePage_1C_S01(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x1D: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_1D(page.PageResponse)); + else + goto default; break; } @@ -225,7 +266,8 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE") DicConsole.WriteLine(Modes.PrettifyCertanceModePage_21(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -233,7 +275,8 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "CERTANCE") DicConsole.WriteLine(Modes.PrettifyCertanceModePage_22(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -241,14 +284,17 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "IBM") DicConsole.WriteLine(Modes.PrettifyIBMModePage_24(page.PageResponse)); - else goto default; + else + goto default; break; } case 0x2A: { - if(page.Subpage == 0) DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse)); - else goto default; + if(page.Subpage == 0) + DicConsole.WriteLine(Modes.PrettifyModePage_2A(page.PageResponse)); + else + goto default; break; } @@ -256,7 +302,8 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "IBM") DicConsole.WriteLine(Modes.PrettifyIBMModePage_2F(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -264,7 +311,8 @@ namespace DiscImageChef.Core { if(Modes.IsAppleModePage_30(page.PageResponse)) DicConsole.WriteLine("Drive identifies as Apple OEM drive"); - else goto default; + else + goto default; break; } @@ -272,7 +320,8 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "HP") DicConsole.WriteLine(Modes.PrettifyHPModePage_3B(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -280,7 +329,8 @@ namespace DiscImageChef.Core { if(StringHandlers.CToString(vendorId).Trim() == "HP") DicConsole.WriteLine(Modes.PrettifyHPModePage_3C(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -290,7 +340,8 @@ namespace DiscImageChef.Core DicConsole.WriteLine(Modes.PrettifyIBMModePage_3D(page.PageResponse)); else if(StringHandlers.CToString(vendorId).Trim() == "HP") DicConsole.WriteLine(Modes.PrettifyHPModePage_3D(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -300,7 +351,8 @@ namespace DiscImageChef.Core DicConsole.WriteLine(Modes.PrettifyFujitsuModePage_3E(page.PageResponse)); else if(StringHandlers.CToString(vendorId).Trim() == "HP") DicConsole.WriteLine(Modes.PrettifyHPModePage_3E(page.PageResponse)); - else goto default; + else + goto default; break; } @@ -309,7 +361,9 @@ namespace DiscImageChef.Core if(page.Subpage != 0) DicConsole.WriteLine("Found unknown mode page {0:X2}h subpage {1:X2}h", page.Page, page.Subpage); - else DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page); + else + DicConsole.WriteLine("Found unknown mode page {0:X2}h", page.Page); + break; } } diff --git a/DiscImageChef.Core/Sidecar/BlockMedia.cs b/DiscImageChef.Core/Sidecar/BlockMedia.cs index 90ccb0fe7..49b17abe3 100644 --- a/DiscImageChef.Core/Sidecar/BlockMedia.cs +++ b/DiscImageChef.Core/Sidecar/BlockMedia.cs @@ -681,7 +681,7 @@ namespace DiscImageChef.Core if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) { - Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)); + CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)); if(ataId.HasValue) if(ataId.Value.CurrentCylinders > 0 && diff --git a/DiscImageChef.Decoders b/DiscImageChef.Decoders index 785638f5f..1856c6ddb 160000 --- a/DiscImageChef.Decoders +++ b/DiscImageChef.Decoders @@ -1 +1 @@ -Subproject commit 785638f5f6b9d31886ca7f3f75acf406cab84398 +Subproject commit 1856c6ddb4d7881272af787498cfc771a865be54 diff --git a/DiscImageChef.Devices/Device/Constructor.cs b/DiscImageChef.Devices/Device/Constructor.cs index 2e1041f0f..20bef15a1 100644 --- a/DiscImageChef.Devices/Device/Constructor.cs +++ b/DiscImageChef.Devices/Device/Constructor.cs @@ -37,7 +37,8 @@ using System.Linq; using System.Runtime.InteropServices; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interop; -using DiscImageChef.Decoders.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SecureDigital; @@ -50,6 +51,7 @@ using FileAttributes = DiscImageChef.Devices.Windows.FileAttributes; using FileFlags = DiscImageChef.Devices.Linux.FileFlags; using FileMode = DiscImageChef.Devices.Windows.FileMode; using FileShare = DiscImageChef.Devices.Windows.FileShare; +using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry; using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID; using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString; @@ -761,7 +763,7 @@ namespace DiscImageChef.Devices if(!scsiSense) { - Inquiry.SCSIInquiry? inquiry = Inquiry.Decode(inqBuf); + Inquiry? inquiry = Inquiry.Decode(inqBuf); Type = DeviceType.SCSI; bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80); diff --git a/DiscImageChef.Devices/Device/Variables.cs b/DiscImageChef.Devices/Device/Variables.cs index 3afe926fc..8837640e0 100644 --- a/DiscImageChef.Devices/Device/Variables.cs +++ b/DiscImageChef.Devices/Device/Variables.cs @@ -32,211 +32,156 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interop; -using DiscImageChef.Decoders.SCSI; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; namespace DiscImageChef.Devices { public partial class Device { - private readonly ushort usbVendor; - private readonly ushort usbProduct; - private readonly ulong firewireGuid; - private readonly uint firewireModel; - private readonly uint firewireVendor; + readonly ushort usbVendor; + readonly ushort usbProduct; + readonly ulong firewireGuid; + readonly uint firewireModel; + readonly uint firewireVendor; // MMC and SecureDigital, values that need to be get with card idle, something that may // not be possible to do but usually is already done by the SDHCI driver. - private readonly byte[] cachedCsd; - private readonly byte[] cachedCid; - private readonly byte[] cachedScr; - private readonly byte[] cachedOcr; + readonly byte[] cachedCsd; + readonly byte[] cachedCid; + readonly byte[] cachedScr; + readonly byte[] cachedOcr; - /// - /// Gets the Platform ID for this device - /// + /// Gets the Platform ID for this device /// The Platform ID public PlatformID PlatformId { get; } - /// - /// Gets the file handle representing this device - /// + /// Gets the file handle representing this device /// The file handle public object FileHandle { get; private set; } - /// - /// Gets or sets the standard timeout for commands sent to this device - /// + /// Gets or sets the standard timeout for commands sent to this device /// The timeout in seconds public uint Timeout { get; } - /// - /// Gets a value indicating whether this is in error. - /// + /// Gets a value indicating whether this is in error. /// true if error; otherwise, false. public bool Error { get; private set; } - /// - /// Gets the last error number. - /// + /// Gets the last error number. /// The last error. public int LastError { get; private set; } - /// - /// Gets the device type. - /// + /// Gets the device type. /// The device type. public DeviceType Type { get; } - /// - /// Gets the device's manufacturer - /// + /// Gets the device's manufacturer /// The manufacturer. public string Manufacturer { get; } - /// - /// Gets the device model - /// + /// Gets the device model /// The model. public string Model { get; } - /// - /// Gets the device's firmware version. - /// + /// Gets the device's firmware version. /// The firmware version. public string FirmwareRevision { get; } - /// - /// Gets the device's serial number. - /// + /// Gets the device's serial number. /// The serial number. public string Serial { get; } - /// - /// Gets the device's SCSI peripheral device type - /// + /// Gets the device's SCSI peripheral device type /// The SCSI peripheral device type. public PeripheralDeviceTypes ScsiType { get; } - /// - /// Gets a value indicating whether this device's media is removable. - /// + /// Gets a value indicating whether this device's media is removable. /// true if this device's media is removable; otherwise, false. public bool IsRemovable { get; } - /// - /// Gets a value indicating whether this device is attached via USB. - /// + /// Gets a value indicating whether this device is attached via USB. /// true if this device is attached via USB; otherwise, false. public bool IsUsb { get; } - /// - /// Gets the USB vendor ID. - /// + /// Gets the USB vendor ID. /// The USB vendor ID. public ushort UsbVendorId => usbVendor; - /// - /// Gets the USB product ID. - /// + /// Gets the USB product ID. /// The USB product ID. public ushort UsbProductId => usbProduct; - /// - /// Gets the USB descriptors. - /// + /// Gets the USB descriptors. /// The USB descriptors. public byte[] UsbDescriptors { get; } - /// - /// Gets the USB manufacturer string. - /// + /// Gets the USB manufacturer string. /// The USB manufacturer string. public string UsbManufacturerString { get; } - /// - /// Gets the USB product string. - /// + /// Gets the USB product string. /// The USB product string. public string UsbProductString { get; } - /// - /// Gets the USB serial string. - /// + /// Gets the USB serial string. /// The USB serial string. public string UsbSerialString { get; } - /// - /// Gets a value indicating whether this device is attached via FireWire. - /// + /// Gets a value indicating whether this device is attached via FireWire. /// true if this device is attached via FireWire; otherwise, false. public bool IsFireWire { get; } - /// - /// Gets the FireWire GUID - /// + /// Gets the FireWire GUID /// The FireWire GUID. public ulong FireWireGuid => firewireGuid; - /// - /// Gets the FireWire model number - /// + /// Gets the FireWire model number /// The FireWire model. public uint FireWireModel => firewireModel; - /// - /// Gets the FireWire model name. - /// + /// Gets the FireWire model name. /// The FireWire model name. public string FireWireModelName { get; } - /// - /// Gets the FireWire vendor number. - /// + /// Gets the FireWire vendor number. /// The FireWire vendor number. public uint FireWireVendor => firewireVendor; - /// - /// Gets the FireWire vendor name. - /// + /// Gets the FireWire vendor name. /// The FireWire vendor name. public string FireWireVendorName { get; } - /// - /// Gets a value indicating whether this device is a CompactFlash device. - /// + /// Gets a value indicating whether this device is a CompactFlash device. /// true if this device is a CompactFlash device; otherwise, false. public bool IsCompactFlash { get; } - /// - /// Gets a value indicating whether this device is a PCMCIA device. - /// + /// Gets a value indicating whether this device is a PCMCIA device. /// true if this device is a PCMCIA device; otherwise, false. public bool IsPcmcia { get; } - /// - /// Contains the PCMCIA CIS if applicable - /// + /// Contains the PCMCIA CIS if applicable public byte[] Cis { get; } - private readonly Remote.Remote _remote; - private bool? _isRemoteAdmin; + readonly Remote.Remote _remote; + bool? _isRemoteAdmin; public bool IsRemoteAdmin { get { - if (_isRemoteAdmin is null) _isRemoteAdmin = _remote.IsRoot; + if(_isRemoteAdmin is null) + _isRemoteAdmin = _remote.IsRoot; return _isRemoteAdmin == true; } } - public bool IsRemote => _remote != null; - public string RemoteApplication => _remote?.ServerApplication; - public string RemoteVersion => _remote?.ServerVersion; - public string RemoteOperatingSystem => _remote?.ServerOperatingSystem; + public bool IsRemote => _remote != null; + public string RemoteApplication => _remote?.ServerApplication; + public string RemoteVersion => _remote?.ServerVersion; + public string RemoteOperatingSystem => _remote?.ServerOperatingSystem; public string RemoteOperatingSystemVersion => _remote?.ServerOperatingSystemVersion; - public string RemoteArchitecture => _remote?.ServerArchitecture; - public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0; + public string RemoteArchitecture => _remote?.ServerArchitecture; + public int RemoteProtocolVersion => _remote?.ServerProtocolVersion ?? 0; } } \ No newline at end of file diff --git a/DiscImageChef.Devices/FreeBSD/ListDevices.cs b/DiscImageChef.Devices/FreeBSD/ListDevices.cs index 2ac1dc781..d99869d1c 100644 --- a/DiscImageChef.Devices/FreeBSD/ListDevices.cs +++ b/DiscImageChef.Devices/FreeBSD/ListDevices.cs @@ -35,17 +35,15 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; -using DiscImageChef.Decoders.ATA; -using DiscImageChef.Decoders.SCSI; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using static DiscImageChef.Devices.FreeBSD.Extern; namespace DiscImageChef.Devices.FreeBSD { - static class ListDevices + internal static class ListDevices { - /// - /// Gets a list of all known storage devices on FreeBSD - /// + /// Gets a list of all known storage devices on FreeBSD /// List of devices internal static DeviceInfo[] GetList() { @@ -54,15 +52,16 @@ namespace DiscImageChef.Devices.FreeBSD foreach(string passDevice in passDevices) { - DeviceInfo deviceInfo = new DeviceInfo(); - IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite); - CamDevice camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice)); + var deviceInfo = new DeviceInfo(); + IntPtr dev = cam_open_device(passDevice, FileFlags.ReadWrite); + var camDevice = (CamDevice)Marshal.PtrToStructure(dev, typeof(CamDevice)); IntPtr ccbPtr = cam_getccb(dev); - if(ccbPtr.ToInt64() == 0) continue; + if(ccbPtr.ToInt64() == 0) + continue; - CcbGetdev cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev)); + var cgd = (CcbGetdev)Marshal.PtrToStructure(ccbPtr, typeof(CcbGetdev)); cgd.ccb_h.func_code = XptOpcode.XptGdevType; @@ -73,6 +72,7 @@ namespace DiscImageChef.Devices.FreeBSD if(error < 0) { cam_freeccb(ccbPtr); + continue; } @@ -96,6 +96,7 @@ namespace DiscImageChef.Devices.FreeBSD // Little-endian FreeBSD gives it resorted // Big-endian FreeBSD, no idea byte[] atadTneid = new byte[512]; + for(int aIndex = 0; aIndex < 512; aIndex += 2) { atadTneid[aIndex] = cgd.ident_data[aIndex + 1]; @@ -103,6 +104,7 @@ namespace DiscImageChef.Devices.FreeBSD } Identify.IdentifyDevice? idt = Identify.Decode(atadTneid); + if(idt.HasValue) { string[] separated = idt.Value.Model.Split(' '); @@ -123,12 +125,15 @@ namespace DiscImageChef.Devices.FreeBSD deviceInfo.Supported = simName != "ata"; } - if(cgd.protocol == CamProto.ProtoAtapi) goto case CamProto.ProtoScsi; + if(cgd.protocol == CamProto.ProtoAtapi) + goto case CamProto.ProtoScsi; + break; } case CamProto.ProtoScsi: { - Inquiry.SCSIInquiry? inq = Inquiry.Decode(cgd.inq_data); + Inquiry? inq = Inquiry.Decode(cgd.inq_data); + if(inq.HasValue) { deviceInfo.Vendor = StringHandlers.CToString(inq.Value.VendorIdentification).Trim(); @@ -142,11 +147,13 @@ namespace DiscImageChef.Devices.FreeBSD case CamProto.ProtoNvme: deviceInfo.Bus = "NVMe"; deviceInfo.Supported = false; + break; case CamProto.ProtoMmcsd: deviceInfo.Model = "Unknown card"; deviceInfo.Bus = "MMC/SD"; deviceInfo.Supported = false; + break; } diff --git a/DiscImageChef.DiscImages/BlindWrite5/Read.cs b/DiscImageChef.DiscImages/BlindWrite5/Read.cs index e9944843f..b152b1aa9 100644 --- a/DiscImageChef.DiscImages/BlindWrite5/Read.cs +++ b/DiscImageChef.DiscImages/BlindWrite5/Read.cs @@ -41,6 +41,7 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI.Modes; using DiscImageChef.Console; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.DVD; @@ -58,7 +59,9 @@ namespace DiscImageChef.DiscImages { Stream stream = imageFilter.GetDataForkStream(); stream.Seek(0, SeekOrigin.Begin); - if(stream.Length < 276) return false; + + if(stream.Length < 276) + return false; byte[] hdr = new byte[260]; stream.Read(hdr, 0, 260); @@ -66,71 +69,86 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.signature = {0}", StringHandlers.CToString(header.signature)); + for(int i = 0; i < header.unknown1.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown1[{1}] = 0x{0:X8}", header.unknown1[i], i); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.profile = {0}", header.profile); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.profile = {0}", header.profile); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.sessions = {0}", header.sessions); + for(int i = 0; i < header.unknown2.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown2[{1}] = 0x{0:X8}", header.unknown2[i], i); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.mcnIsValid = {0}", header.mcnIsValid); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.mcn = {0}", - StringHandlers.CToString(header.mcn)); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.mcn = {0}", StringHandlers.CToString(header.mcn)); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown3 = 0x{0:X4}", header.unknown3); + for(int i = 0; i < header.unknown4.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown4[{1}] = 0x{0:X8}", header.unknown4[i], i); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.pmaLen = {0}", header.pmaLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.atipLen = {0}", header.atipLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.cdtLen = {0}", header.cdtLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.pmaLen = {0}", header.pmaLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.atipLen = {0}", header.atipLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.cdtLen = {0}", header.cdtLen); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.cdInfoLen = {0}", header.cdInfoLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.bcaLen = {0}", header.bcaLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.bcaLen = {0}", header.bcaLen); + for(int i = 0; i < header.unknown5.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown5[{1}] = 0x{0:X8}", header.unknown5[i], i); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dvdStrLen = {0}", header.dvdStrLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dvdStrLen = {0}", header.dvdStrLen); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dvdInfoLen = {0}", header.dvdInfoLen); + for(int i = 0; i < header.unknown6.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unknown6[{1}] = 0x{0:X2}", header.unknown6[i], i); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.manufacturer = {0}", StringHandlers.CToString(header.manufacturer)); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.product = {0}", StringHandlers.CToString(header.product)); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.revision = {0}", StringHandlers.CToString(header.revision)); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.vendor = {0}", StringHandlers.CToString(header.vendor)); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.volumeId = {0}", StringHandlers.CToString(header.volumeId)); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.mode2ALen = {0}", header.mode2ALen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unkBlkLen = {0}", header.unkBlkLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dataLen = {0}", header.dataLen); + + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.mode2ALen = {0}", header.mode2ALen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.unkBlkLen = {0}", header.unkBlkLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dataLen = {0}", header.dataLen); DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.sessionsLen = {0}", header.sessionsLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dpmLen = {0}", header.dpmLen); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "header.dpmLen = {0}", header.dpmLen); mode2A = new byte[header.mode2ALen]; + if(mode2A.Length > 0) { stream.Read(mode2A, 0, mode2A.Length); mode2A[1] -= 2; - Modes.ModePage_2A decoded2A = Modes.DecodeModePage_2A(mode2A); + var decoded2A = ModePage_2A.Decode(mode2A); + if(!(decoded2A is null)) DicConsole.DebugWriteLine("BlindWrite5 plugin", "mode page 2A: {0}", Modes.PrettifyModePage_2A(decoded2A)); - else mode2A = null; + else + mode2A = null; } unkBlock = new byte[header.unkBlkLen]; - if(unkBlock.Length > 0) stream.Read(unkBlock, 0, unkBlock.Length); + + if(unkBlock.Length > 0) + stream.Read(unkBlock, 0, unkBlock.Length); byte[] temp = new byte[header.pmaLen]; + if(temp.Length > 0) { byte[] tushort = BitConverter.GetBytes((ushort)(temp.Length + 2)); @@ -141,12 +159,15 @@ namespace DiscImageChef.DiscImages Array.Copy(temp, 0, pma, 4, temp.Length); PMA.CDPMA? decodedPma = PMA.Decode(pma); + if(decodedPma.HasValue) DicConsole.DebugWriteLine("BlindWrite5 plugin", "PMA: {0}", PMA.Prettify(decodedPma)); - else pma = null; + else + pma = null; } temp = new byte[header.atipLen]; + if(temp.Length > 0) { byte[] tushort = BitConverter.GetBytes((ushort)(temp.Length + 2)); @@ -157,12 +178,15 @@ namespace DiscImageChef.DiscImages Array.Copy(temp, 0, atip, 4, temp.Length); ATIP.CDATIP? decodedAtip = ATIP.Decode(atip); + if(decodedAtip.HasValue) DicConsole.DebugWriteLine("BlindWrite5 plugin", "ATIP: {0}", ATIP.Prettify(decodedAtip)); - else atip = null; + else + atip = null; } temp = new byte[header.cdtLen]; + if(temp.Length > 0) { byte[] tushort = BitConverter.GetBytes((ushort)(temp.Length + 2)); @@ -173,24 +197,30 @@ namespace DiscImageChef.DiscImages Array.Copy(temp, 0, cdtext, 4, temp.Length); CDTextOnLeadIn.CDText? decodedCdText = CDTextOnLeadIn.Decode(cdtext); + if(decodedCdText.HasValue) DicConsole.DebugWriteLine("BlindWrite5 plugin", "CD-Text: {0}", CDTextOnLeadIn.Prettify(decodedCdText)); - else cdtext = null; + else + cdtext = null; } bca = new byte[header.bcaLen]; - if(bca.Length > 0) stream.Read(bca, 0, bca.Length); - else bca = null; + + if(bca.Length > 0) + stream.Read(bca, 0, bca.Length); + else + bca = null; temp = new byte[header.dvdStrLen]; + if(temp.Length > 0) { stream.Read(temp, 0, temp.Length); dmi = new byte[2052]; pfi = new byte[2052]; - Array.Copy(temp, 0, dmi, 0, 2050); + Array.Copy(temp, 0, dmi, 0, 2050); Array.Copy(temp, 0x802, pfi, 4, 2048); pfi[0] = 0x08; @@ -199,6 +229,7 @@ namespace DiscImageChef.DiscImages dmi[1] = 0x02; PFI.PhysicalFormatInformation? decodedPfi = PFI.Decode(pfi); + if(decodedPfi.HasValue) DicConsole.DebugWriteLine("BlindWrite5 plugin", "PFI: {0}", PFI.Prettify(decodedPfi)); else @@ -220,19 +251,23 @@ namespace DiscImageChef.DiscImages case ProfileNumber.HDBURNR: case ProfileNumber.HDBURNRW: discInformation = new byte[header.cdInfoLen]; + break; default: discInformation = new byte[header.dvdInfoLen]; + break; } if(discInformation.Length > 0) { stream.Read(discInformation, 0, discInformation.Length); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "Disc information: {0}", PrintHex.ByteArrayToHexArrayString(discInformation, 40)); } - else discInformation = null; + else + discInformation = null; // How many data blocks byte[] tmpArray = new byte[4]; @@ -247,10 +282,15 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "Data path: {0}", dataPath); dataFiles = new List(); + for(int cD = 0; cD < dataBlockCount; cD++) { tmpArray = new byte[52]; - Bw5DataFile dataFile = new Bw5DataFile {Unknown1 = new uint[4], Unknown2 = new uint[3]}; + + var dataFile = new Bw5DataFile + { + Unknown1 = new uint[4], Unknown2 = new uint[3] + }; stream.Read(tmpArray, 0, tmpArray.Length); dataFile.Type = BitConverter.ToUInt32(tmpArray, 0); @@ -279,27 +319,30 @@ namespace DiscImageChef.DiscImages dataFiles.Add(dataFile); DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.type = 0x{0:X8}", dataFile.Type); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.length = {0}", dataFile.Length); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.length = {0}", dataFile.Length); + for(int i = 0; i < dataFile.Unknown1.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.unknown1[{1}] = {0}", dataFile.Unknown1[i], i); DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.offset = {0}", dataFile.Offset); + for(int i = 0; i < dataFile.Unknown2.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.unknown2[{1}] = {0}", dataFile.Unknown2[i], i); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.startLba = {0}", dataFile.StartLba); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.sectors = {0}", dataFile.Sectors); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.startLba = {0}", dataFile.StartLba); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.sectors = {0}", dataFile.Sectors); DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.filenameLen = {0}", dataFile.FilenameLen); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.filename = {0}", dataFile.Filename); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.unknown3 = {0}", dataFile.Unknown3); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.filename = {0}", dataFile.Filename); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "dataFile.unknown3 = {0}", dataFile.Unknown3); } bwSessions = new List(); + for(int ses = 0; ses < header.sessions; ses++) { - Bw5SessionDescriptor session = new Bw5SessionDescriptor(); + var session = new Bw5SessionDescriptor(); tmpArray = new byte[16]; stream.Read(tmpArray, 0, tmpArray.Length); session.Sequence = BitConverter.ToUInt16(tmpArray, 0); @@ -312,12 +355,14 @@ namespace DiscImageChef.DiscImages session.Tracks = new Bw5TrackDescriptor[session.Entries]; DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].filename = {1}", ses, session.Sequence); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].entries = {1}", ses, session.Entries); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].unknown = {1}", ses, session.Unknown); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].start = {1}", ses, session.Start); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].end = {1}", ses, session.End); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].entries = {1}", ses, session.Entries); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].unknown = {1}", ses, session.Unknown); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].start = {1}", ses, session.Start); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].end = {1}", ses, session.End); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].firstTrack = {1}", ses, session.FirstTrack); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].lastTrack = {1}", ses, session.LastTrack); for(int tSeq = 0; tSeq < session.Entries; tSeq++) @@ -336,6 +381,7 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].type = {2}", ses, tSeq, session.Tracks[tSeq].type); + for(int i = 0; i < session.Tracks[tSeq].unknown1.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown1[{2}] = 0x{3:X2}", ses, tSeq, i, @@ -343,36 +389,52 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown2 = 0x{2:X8}", ses, tSeq, session.Tracks[tSeq].unknown2); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].subchannel = {2}", ses, tSeq, session.Tracks[tSeq].subchannel); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown3 = 0x{2:X2}", ses, tSeq, session.Tracks[tSeq].unknown3); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].ctl = {2}", ses, tSeq, session.Tracks[tSeq].ctl); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].adr = {2}", ses, tSeq, session.Tracks[tSeq].adr); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].point = {2}", ses, tSeq, session.Tracks[tSeq].point); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown4 = 0x{2:X2}", ses, tSeq, session.Tracks[tSeq].tno); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].min = {2}", ses, tSeq, session.Tracks[tSeq].min); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].sec = {2}", ses, tSeq, session.Tracks[tSeq].sec); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].frame = {2}", ses, tSeq, session.Tracks[tSeq].frame); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].zero = {2}", ses, tSeq, session.Tracks[tSeq].zero); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].pmin = {2}", ses, tSeq, session.Tracks[tSeq].pmin); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].psec = {2}", ses, tSeq, session.Tracks[tSeq].psec); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].pframe = {2}", ses, tSeq, session.Tracks[tSeq].pframe); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown5 = 0x{2:X2}", ses, tSeq, session.Tracks[tSeq].unknown5); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].pregap = {2}", ses, tSeq, session.Tracks[tSeq].pregap); + for(int i = 0; i < session.Tracks[tSeq].unknown6.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown6[{2}] = 0x{3:X8}", ses, tSeq, i, @@ -380,8 +442,10 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].startLba = {2}", ses, tSeq, session.Tracks[tSeq].startLba); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].sectors = {2}", ses, tSeq, session.Tracks[tSeq].sectors); + for(int i = 0; i < session.Tracks[tSeq].unknown7.Length; i++) DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown7[{2}] = 0x{3:X8}", ses, tSeq, i, @@ -389,10 +453,13 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].session = {2}", ses, tSeq, session.Tracks[tSeq].session); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "session[{0}].track[{1}].unknown8 = 0x{2:X4}", ses, tSeq, session.Tracks[tSeq].unknown8); + if(session.Tracks[tSeq].type == Bw5TrackType.Dvd || - session.Tracks[tSeq].type == Bw5TrackType.NotData) continue; + session.Tracks[tSeq].type == Bw5TrackType.NotData) + continue; { for(int i = 0; i < session.Tracks[tSeq].unknown9.Length; i++) @@ -418,15 +485,16 @@ namespace DiscImageChef.DiscImages if(bw5Footer.SequenceEqual(footer)) DicConsole.DebugWriteLine("BlindWrite5 plugin", "Correctly arrived end of image"); else - DicConsole - .ErrorWriteLine("BlindWrite5 image ends after expected position. Probably new version with different data. Errors may occur."); + DicConsole. + ErrorWriteLine("BlindWrite5 image ends after expected position. Probably new version with different data. Errors may occur."); filePaths = new List(); + foreach(Bw5DataFile dataFile in dataFiles) { - DataFileCharacteristics chars = new DataFileCharacteristics(); - string path = Path.Combine(dataPath, dataFile.Filename); - FiltersList filtersList = new FiltersList(); + var chars = new DataFileCharacteristics(); + string path = Path.Combine(dataPath, dataFile.Filename); + var filtersList = new FiltersList(); if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)) != null) { @@ -436,6 +504,7 @@ namespace DiscImageChef.DiscImages else { path = Path.Combine(dataPath, dataFile.Filename.ToLower(CultureInfo.CurrentCulture)); + if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)) != null) { chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)); @@ -444,6 +513,7 @@ namespace DiscImageChef.DiscImages else { path = Path.Combine(dataPath, dataFile.Filename.ToUpper(CultureInfo.CurrentCulture)); + if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)) != null) { chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)); @@ -452,71 +522,81 @@ namespace DiscImageChef.DiscImages else { path = Path.Combine(dataPath.ToLower(CultureInfo.CurrentCulture), dataFile.Filename); + if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)) != null) { chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)); + chars.FilePath = path; } else { path = Path.Combine(dataPath.ToUpper(CultureInfo.CurrentCulture), dataFile.Filename); + if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)) != null) { chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path)); + chars.FilePath = path; } else { path = Path.Combine(dataPath, dataFile.Filename); + if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), path.ToLower(CultureInfo.CurrentCulture))) != null) { chars.FilePath = path.ToLower(CultureInfo.CurrentCulture); + chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - path.ToLower(CultureInfo - .CurrentCulture))); + path.ToLower(CultureInfo. + CurrentCulture))); } else if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - path.ToUpper(CultureInfo - .CurrentCulture))) != + path.ToUpper(CultureInfo. + CurrentCulture))) != null) { chars.FilePath = path.ToUpper(CultureInfo.CurrentCulture); + chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - path.ToUpper(CultureInfo - .CurrentCulture))); + path.ToUpper(CultureInfo. + CurrentCulture))); } else if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - dataFile.Filename.ToLower(CultureInfo - .CurrentCulture))) != + dataFile.Filename.ToLower(CultureInfo. + CurrentCulture))) != null) { chars.FilePath = dataFile.Filename.ToLower(CultureInfo.CurrentCulture); + chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - dataFile.Filename.ToLower(CultureInfo - .CurrentCulture))); + dataFile.Filename.ToLower(CultureInfo. + CurrentCulture))); } else if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - dataFile.Filename.ToUpper(CultureInfo - .CurrentCulture))) != + dataFile.Filename.ToUpper(CultureInfo. + CurrentCulture))) != null) { chars.FilePath = dataFile.Filename.ToUpper(CultureInfo.CurrentCulture); + chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), - dataFile.Filename.ToUpper(CultureInfo - .CurrentCulture))); + dataFile.Filename.ToUpper(CultureInfo. + CurrentCulture))); } else if(filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), dataFile.Filename)) != null) { chars.FilePath = dataFile.Filename; + chars.FileFilter = filtersList.GetFilter(Path.Combine(imageFilter.GetParentFolder(), dataFile.Filename)); @@ -524,6 +604,7 @@ namespace DiscImageChef.DiscImages else { DicConsole.ErrorWriteLine("Cannot find data file {0}", dataFile.Filename); + return false; } } @@ -533,21 +614,26 @@ namespace DiscImageChef.DiscImages } long sectorSize = dataFile.Length / dataFile.Sectors; + if(sectorSize > 2352) switch(sectorSize - 2352) { case 16: chars.Subchannel = TrackSubchannelType.Q16Interleaved; + break; case 96: chars.Subchannel = TrackSubchannelType.PackedInterleaved; + break; default: DicConsole.ErrorWriteLine("BlindWrite5 found unknown subchannel size: {0}", sectorSize - 2352); + return false; } - else chars.Subchannel = TrackSubchannelType.None; + else + chars.Subchannel = TrackSubchannelType.None; chars.SectorSize = sectorSize; chars.StartLba = dataFile.StartLba; @@ -559,8 +645,13 @@ namespace DiscImageChef.DiscImages Sessions = new List(); Tracks = new List(); Partitions = new List(); - MemoryStream fullTocStream = new MemoryStream(); - fullTocStream.Write(new byte[] {0, 0, 0, 0}, 0, 4); + var fullTocStream = new MemoryStream(); + + fullTocStream.Write(new byte[] + { + 0, 0, 0, 0 + }, 0, 4); + ulong offsetBytes = 0; offsetmap = new Dictionary(); bool isDvd = false; @@ -570,6 +661,7 @@ namespace DiscImageChef.DiscImages imageInfo.Sectors = 0; DicConsole.DebugWriteLine("BlindWrite5 plugin", "Building maps"); + foreach(Bw5SessionDescriptor ses in bwSessions) { // TODO: This does nothing, should it? @@ -582,8 +674,11 @@ namespace DiscImageChef.DiscImages session.EndTrack = ses.LastTrack; */ - if(ses.Sequence < firstSession) firstSession = (byte)ses.Sequence; - if(ses.Sequence > lastSession) lastSession = (byte)ses.Sequence; + if(ses.Sequence < firstSession) + firstSession = (byte)ses.Sequence; + + if(ses.Sequence > lastSession) + lastSession = (byte)ses.Sequence; foreach(Bw5TrackDescriptor trk in ses.Tracks) { @@ -600,10 +695,11 @@ namespace DiscImageChef.DiscImages fullTocStream.WriteByte(trk.psec); fullTocStream.WriteByte(trk.pframe); - if(trk.point >= 0xA0) continue; + if(trk.point >= 0xA0) + continue; - Track track = new Track(); - Partition partition = new Partition(); + var track = new Track(); + var partition = new Partition(); trackFlags.Add(trk.point, trk.ctl); @@ -612,55 +708,84 @@ namespace DiscImageChef.DiscImages case Bw5TrackType.Audio: track.TrackBytesPerSector = 2352; track.TrackRawBytesPerSector = 2352; - if(imageInfo.SectorSize < 2352) imageInfo.SectorSize = 2352; + + if(imageInfo.SectorSize < 2352) + imageInfo.SectorSize = 2352; + break; case Bw5TrackType.Mode1: case Bw5TrackType.Mode2F1: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2352; - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; + break; case Bw5TrackType.Mode2: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + track.TrackBytesPerSector = 2336; track.TrackRawBytesPerSector = 2352; - if(imageInfo.SectorSize < 2336) imageInfo.SectorSize = 2336; + + if(imageInfo.SectorSize < 2336) + imageInfo.SectorSize = 2336; + break; case Bw5TrackType.Mode2F2: if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); + track.TrackBytesPerSector = 2336; track.TrackRawBytesPerSector = 2352; - if(imageInfo.SectorSize < 2324) imageInfo.SectorSize = 2324; + + if(imageInfo.SectorSize < 2324) + imageInfo.SectorSize = 2324; + break; case Bw5TrackType.Dvd: track.TrackBytesPerSector = 2048; track.TrackRawBytesPerSector = 2048; - if(imageInfo.SectorSize < 2048) imageInfo.SectorSize = 2048; + + if(imageInfo.SectorSize < 2048) + imageInfo.SectorSize = 2048; + isDvd = true; + break; } @@ -674,10 +799,14 @@ namespace DiscImageChef.DiscImages { track.TrackFilter = chars.FileFilter; track.TrackFile = chars.FileFilter.GetFilename(); + if(trk.startLba >= 0) - track.TrackFileOffset = (ulong)((trk.startLba - chars.StartLba) * chars.SectorSize); - else track.TrackFileOffset = (ulong)(trk.startLba * -1 * chars.SectorSize); + track.TrackFileOffset = (ulong)((trk.startLba - chars.StartLba) * chars.SectorSize); + else + track.TrackFileOffset = (ulong)(trk.startLba * -1 * chars.SectorSize); + track.TrackFileType = "BINARY"; + if(chars.Subchannel != TrackSubchannelType.None) { track.TrackSubchannelFilter = track.TrackFilter; @@ -696,11 +825,19 @@ namespace DiscImageChef.DiscImages track.TrackPregap = trk.pregap; track.TrackSequence = trk.point; track.TrackType = BlindWriteTrackTypeToTrackType(trk.type); - track.Indexes = new Dictionary {{1, track.TrackStartSector}}; + + track.Indexes = new Dictionary + { + { + 1, track.TrackStartSector + } + }; partition.Description = track.TrackDescription; + partition.Size = (track.TrackEndSector - track.TrackStartSector) * (ulong)track.TrackRawBytesPerSector; + partition.Length = track.TrackEndSector - track.TrackStartSector; partition.Sequence = track.TrackSequence; partition.Offset = offsetBytes; @@ -717,28 +854,31 @@ namespace DiscImageChef.DiscImages } DicConsole.DebugWriteLine("BlindWrite5 plugin", "printing track map"); + foreach(Track track in Tracks) { - DicConsole.DebugWriteLine("BlindWrite5 plugin", "Partition sequence: {0}", track.TrackSequence); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "Partition sequence: {0}", track.TrackSequence); DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition description: {0}", track.TrackDescription); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition type: {0}", track.TrackType); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition type: {0}", track.TrackType); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition starting sector: {0}", track.TrackStartSector); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition ending sector: {0}", track.TrackEndSector); } DicConsole.DebugWriteLine("BlindWrite5 plugin", "printing partition map"); + foreach(Partition partition in Partitions) { DicConsole.DebugWriteLine("BlindWrite5 plugin", "Partition sequence: {0}", partition.Sequence); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition name: {0}", partition.Name); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition description: {0}", - partition.Description); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition type: {0}", partition.Type); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition name: {0}", partition.Name); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition description: {0}", partition.Description); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition type: {0}", partition.Type); DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition starting sector: {0}", partition.Start); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition sectors: {0}", partition.Length); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition sectors: {0}", partition.Length); DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition starting offset: {0}", partition.Offset); - DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition size in bytes: {0}", partition.Size); + DicConsole.DebugWriteLine("BlindWrite5 plugin", "\tPartition size in bytes: {0}", partition.Size); } if(!isDvd) @@ -761,14 +901,16 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("BlindWrite5 plugin", "TOC not correctly rebuilt"); fullToc = null; } - else DicConsole.DebugWriteLine("BlindWrite5 plugin", "TOC correctly rebuilt"); + else + DicConsole.DebugWriteLine("BlindWrite5 plugin", "TOC correctly rebuilt"); imageInfo.ReadableSectorTags.Add(SectorTagType.CdTrackFlags); } imageInfo.MediaType = BlindWriteProfileToMediaType(header.profile); - if(dmi != null && pfi != null) + if(dmi != null && + pfi != null) { PFI.PhysicalFormatInformation? pfi0 = PFI.Decode(pfi); @@ -780,53 +922,70 @@ namespace DiscImageChef.DiscImages { case DiskCategory.DVDPR: imageInfo.MediaType = MediaType.DVDPR; + break; case DiskCategory.DVDPRDL: imageInfo.MediaType = MediaType.DVDPRDL; + break; case DiskCategory.DVDPRW: imageInfo.MediaType = MediaType.DVDPRW; + break; case DiskCategory.DVDPRWDL: imageInfo.MediaType = MediaType.DVDPRWDL; + break; case DiskCategory.DVDR: imageInfo.MediaType = pfi0.Value.PartVersion == 6 ? MediaType.DVDRDL : MediaType.DVDR; + break; case DiskCategory.DVDRAM: imageInfo.MediaType = MediaType.DVDRAM; + break; default: imageInfo.MediaType = MediaType.DVDROM; + break; case DiskCategory.DVDRW: imageInfo.MediaType = pfi0.Value.PartVersion == 3 ? MediaType.DVDRWDL : MediaType.DVDRW; + break; case DiskCategory.HDDVDR: imageInfo.MediaType = MediaType.HDDVDR; + break; case DiskCategory.HDDVDRAM: imageInfo.MediaType = MediaType.HDDVDRAM; + break; case DiskCategory.HDDVDROM: imageInfo.MediaType = MediaType.HDDVDROM; + break; case DiskCategory.HDDVDRW: imageInfo.MediaType = MediaType.HDDVDRW; + break; case DiskCategory.Nintendo: imageInfo.MediaType = pfi0.Value.DiscSize == DVDSize.Eighty ? MediaType.GOD : MediaType.WOD; + break; case DiskCategory.UMD: imageInfo.MediaType = MediaType.UMD; + break; } - if(DMI.IsXbox(dmi)) imageInfo.MediaType = MediaType.XGD; - else if(DMI.IsXbox360(dmi)) imageInfo.MediaType = MediaType.XGD2; + if(DMI.IsXbox(dmi)) + imageInfo.MediaType = MediaType.XGD; + else if(DMI.IsXbox360(dmi)) + imageInfo.MediaType = MediaType.XGD2; } } - else if(imageInfo.MediaType == MediaType.CD || imageInfo.MediaType == MediaType.CDROM) + else if(imageInfo.MediaType == MediaType.CD || + imageInfo.MediaType == MediaType.CDROM) { bool data = false; bool mode2 = false; @@ -854,25 +1013,39 @@ namespace DiscImageChef.DiscImages case TrackType.CdMode2Form1: case TrackType.CdMode2Form2: mode2 = true; + break; } } - if(!data && !firstdata) imageInfo.MediaType = MediaType.CDDA; - else if(firstaudio && data && Sessions.Count > 1 && mode2) imageInfo.MediaType = MediaType.CDPLUS; - else if(firstdata && audio || mode2) imageInfo.MediaType = MediaType.CDROMXA; - else if(!audio) imageInfo.MediaType = MediaType.CDROM; - else imageInfo.MediaType = MediaType.CD; + if(!data && + !firstdata) + imageInfo.MediaType = MediaType.CDDA; + else if(firstaudio && + data && + Sessions.Count > 1 && + mode2) + imageInfo.MediaType = MediaType.CDPLUS; + else if((firstdata && audio) || mode2) + imageInfo.MediaType = MediaType.CDROMXA; + else if(!audio) + imageInfo.MediaType = MediaType.CDROM; + else + imageInfo.MediaType = MediaType.CD; } imageInfo.DriveManufacturer = StringHandlers.CToString(header.manufacturer); imageInfo.DriveModel = StringHandlers.CToString(header.product); imageInfo.DriveFirmwareRevision = StringHandlers.CToString(header.revision); imageInfo.Application = "BlindWrite"; + if(string.Compare(Path.GetExtension(imageFilter.GetFilename()), "B5T", - StringComparison.OrdinalIgnoreCase) == 0) imageInfo.ApplicationVersion = "5"; + StringComparison.OrdinalIgnoreCase) == 0) + imageInfo.ApplicationVersion = "5"; else if(string.Compare(Path.GetExtension(imageFilter.GetFilename()), "B6T", - StringComparison.OrdinalIgnoreCase) == 0) imageInfo.ApplicationVersion = "6"; + StringComparison.OrdinalIgnoreCase) == 0) + imageInfo.ApplicationVersion = "6"; + imageInfo.Version = "5"; imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength(); @@ -884,8 +1057,7 @@ namespace DiscImageChef.DiscImages { PMA.CDPMA pma0 = PMA.Decode(pma).Value; - foreach(uint id in from descriptor in pma0.PMADescriptors - where descriptor.ADR == 2 + foreach(uint id in from descriptor in pma0.PMADescriptors where descriptor.ADR == 2 select (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame)) imageInfo.MediaSerialNumber = $"{id & 0x00FFFFFF:X6}"; } @@ -905,7 +1077,9 @@ namespace DiscImageChef.DiscImages } bool isBd = false; - if(imageInfo.MediaType == MediaType.BDR || imageInfo.MediaType == MediaType.BDRE || + + if(imageInfo.MediaType == MediaType.BDR || + imageInfo.MediaType == MediaType.BDRE || imageInfo.MediaType == MediaType.BDROM) { isDvd = false; @@ -917,25 +1091,42 @@ namespace DiscImageChef.DiscImages { case MediaType.BDR: imageInfo.MediaType = MediaType.BDRXL; + break; case MediaType.BDRE: imageInfo.MediaType = MediaType.BDREXL; + break; } DicConsole.DebugWriteLine("BlindWrite5 plugin", "ImageInfo.mediaType = {0}", imageInfo.MediaType); - if(mode2A != null) imageInfo.ReadableMediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A); - if(pma != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_PMA); - if(atip != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_ATIP); - if(cdtext != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT); + if(mode2A != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.SCSI_MODEPAGE_2A); + + if(pma != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_PMA); + + if(atip != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_ATIP); + + if(cdtext != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_TEXT); + if(bca != null) if(isDvd) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_BCA); - else if(isBd) imageInfo.ReadableMediaTags.Add(MediaTagType.BD_BCA); - if(dmi != null) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); - if(pfi != null) imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); - if(fullToc != null) imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); + else if(isBd) + imageInfo.ReadableMediaTags.Add(MediaTagType.BD_BCA); + + if(dmi != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_DMI); + + if(pfi != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.DVD_PFI); + + if(fullToc != null) + imageInfo.ReadableMediaTags.Add(MediaTagType.CD_FullTOC); if(imageInfo.MediaType == MediaType.XGD2) if(imageInfo.Sectors == 25063 || // Locked (or non compatible drive) @@ -954,50 +1145,58 @@ namespace DiscImageChef.DiscImages { case MediaTagType.SCSI_MODEPAGE_2A: { - if(mode2A != null) return (byte[])mode2A.Clone(); + if(mode2A != null) + return(byte[])mode2A.Clone(); throw new FeatureNotPresentImageException("Image does not contain SCSI MODE PAGE 2Ah."); } case MediaTagType.CD_PMA: { - if(pma != null) return (byte[])pma.Clone(); + if(pma != null) + return(byte[])pma.Clone(); throw new FeatureNotPresentImageException("Image does not contain PMA information."); } case MediaTagType.CD_ATIP: { - if(atip != null) return (byte[])atip.Clone(); + if(atip != null) + return(byte[])atip.Clone(); throw new FeatureNotPresentImageException("Image does not contain ATIP information."); } case MediaTagType.CD_TEXT: { - if(cdtext != null) return (byte[])cdtext.Clone(); + if(cdtext != null) + return(byte[])cdtext.Clone(); throw new FeatureNotPresentImageException("Image does not contain CD-Text information."); } case MediaTagType.DVD_BCA: case MediaTagType.BD_BCA: { - if(bca != null) return (byte[])bca.Clone(); + if(bca != null) + return(byte[])bca.Clone(); throw new FeatureNotPresentImageException("Image does not contain BCA information."); } case MediaTagType.DVD_PFI: { - if(pfi != null) return (byte[])pfi.Clone(); + if(pfi != null) + return(byte[])pfi.Clone(); throw new FeatureNotPresentImageException("Image does not contain PFI."); } case MediaTagType.DVD_DMI: { - if(dmi != null) return (byte[])dmi.Clone(); + if(dmi != null) + return(byte[])dmi.Clone(); throw new FeatureNotPresentImageException("Image does not contain DMI."); } case MediaTagType.CD_FullTOC: { - if(fullToc != null) return (byte[])fullToc.Clone(); + if(fullToc != null) + return(byte[])fullToc.Clone(); throw new FeatureNotPresentImageException("Image does not contain TOC information."); } @@ -1017,13 +1216,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectors(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); @@ -1031,13 +1227,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectorsTag(sectorAddress - kvp.Value, length, kvp.Key, tag); throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); @@ -1046,14 +1239,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectors(ulong sectorAddress, uint length, uint track) { // TODO: Cross data files - Track dicTrack = new Track(); - DataFileCharacteristics chars = new DataFileCharacteristics(); + var dicTrack = new Track(); + var chars = new DataFileCharacteristics(); dicTrack.TrackSequence = 0; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } @@ -1067,14 +1261,16 @@ namespace DiscImageChef.DiscImages foreach(DataFileCharacteristics characteristics in filePaths.Where(characteristics => (long)sectorAddress >= characteristics.StartLba && - length < (ulong)characteristics - .Sectors - sectorAddress)) + length < (ulong)characteristics. + Sectors - sectorAddress)) { chars = characteristics; + break; } - if(string.IsNullOrEmpty(chars.FilePath) || chars.FileFilter == null) + if(string.IsNullOrEmpty(chars.FilePath) || + chars.FileFilter == null) throw new ArgumentOutOfRangeException(nameof(chars.FileFilter), "Track does not exist in disc image"); uint sectorOffset; @@ -1088,6 +1284,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2048; sectorSkip = 288; + break; } case TrackType.CdMode2Formless: @@ -1095,6 +1292,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 2336; sectorSkip = 0; + break; } case TrackType.CdMode2Form1: @@ -1102,6 +1300,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 24; sectorSize = 2048; sectorSkip = 280; + break; } case TrackType.CdMode2Form2: @@ -1109,6 +1308,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 24; sectorSize = 2324; sectorSkip = 4; + break; } case TrackType.Audio: @@ -1116,6 +1316,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.Data: @@ -1123,6 +1324,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); @@ -1132,12 +1334,15 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } @@ -1145,12 +1350,15 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = chars.FileFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1166,14 +1374,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag) { // TODO: Cross data files - Track dicTrack = new Track(); - DataFileCharacteristics chars = new DataFileCharacteristics(); + var dicTrack = new Track(); + var chars = new DataFileCharacteristics(); dicTrack.TrackSequence = 0; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } @@ -1187,14 +1396,16 @@ namespace DiscImageChef.DiscImages foreach(DataFileCharacteristics characteristics in filePaths.Where(characteristics => (long)sectorAddress >= characteristics.StartLba && - length < (ulong)characteristics - .Sectors - sectorAddress)) + length < (ulong)characteristics. + Sectors - sectorAddress)) { chars = characteristics; + break; } - if(string.IsNullOrEmpty(chars.FilePath) || chars.FileFilter == null) + if(string.IsNullOrEmpty(chars.FilePath) || + chars.FileFilter == null) throw new ArgumentOutOfRangeException(nameof(chars.FileFilter), "Track does not exist in disc image"); if(dicTrack.TrackType == TrackType.Data) @@ -1211,7 +1422,11 @@ namespace DiscImageChef.DiscImages case SectorTagType.CdSectorSubHeader: case SectorTagType.CdSectorSync: break; case SectorTagType.CdTrackFlags: - if(trackFlags.TryGetValue(track, out byte flag)) return new[] {flag}; + if(trackFlags.TryGetValue(track, out byte flag)) + return new[] + { + flag + }; throw new ArgumentException("Unsupported tag requested", nameof(tag)); default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); @@ -1231,6 +1446,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -1238,6 +1454,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -1247,6 +1464,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -1254,6 +1472,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -1261,6 +1480,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -1268,6 +1488,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2064; sectorSize = 4; sectorSkip = 284; + break; } case SectorTagType.CdSectorSubchannel: @@ -1291,6 +1512,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -1298,6 +1520,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2332; sectorSize = 4; sectorSkip = 0; + break; } case SectorTagType.CdSectorSubchannel: @@ -1315,6 +1538,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -1322,6 +1546,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -1329,6 +1554,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEcc: @@ -1336,6 +1562,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 276; sectorSkip = 0; + break; } case SectorTagType.CdSectorEccP: @@ -1343,6 +1570,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2076; sectorSize = 172; sectorSkip = 104; + break; } case SectorTagType.CdSectorEccQ: @@ -1350,6 +1578,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2248; sectorSize = 104; sectorSkip = 0; + break; } case SectorTagType.CdSectorEdc: @@ -1357,6 +1586,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2072; sectorSize = 4; sectorSkip = 276; + break; } case SectorTagType.CdSectorSubchannel: @@ -1373,6 +1603,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 12; sectorSkip = 2340; + break; } case SectorTagType.CdSectorHeader: @@ -1380,6 +1611,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 12; sectorSize = 4; sectorSkip = 2336; + break; } case SectorTagType.CdSectorSubHeader: @@ -1387,6 +1619,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 16; sectorSize = 8; sectorSkip = 2328; + break; } case SectorTagType.CdSectorEdc: @@ -1394,6 +1627,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 2348; sectorSize = 4; sectorSkip = 0; + break; } case SectorTagType.CdSectorSubchannel: @@ -1418,12 +1652,15 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } @@ -1431,11 +1668,15 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = dicTrack.TrackFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1454,13 +1695,10 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length) { - foreach(KeyValuePair kvp in from kvp in offsetmap - where sectorAddress >= kvp.Value - from track in Tracks - where track.TrackSequence == kvp.Key + foreach(KeyValuePair kvp in from kvp in offsetmap where sectorAddress >= kvp.Value + from track in Tracks where track.TrackSequence == kvp.Key where sectorAddress - kvp.Value < - track.TrackEndSector - track.TrackStartSector - select kvp) + track.TrackEndSector - track.TrackStartSector select kvp) return ReadSectorsLong(sectorAddress - kvp.Value, length, kvp.Key); throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found"); @@ -1469,14 +1707,15 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track) { // TODO: Cross data files - Track dicTrack = new Track(); - DataFileCharacteristics chars = new DataFileCharacteristics(); + var dicTrack = new Track(); + var chars = new DataFileCharacteristics(); dicTrack.TrackSequence = 0; foreach(Track bwTrack in Tracks.Where(bwTrack => bwTrack.TrackSequence == track)) { dicTrack = bwTrack; + break; } @@ -1490,14 +1729,16 @@ namespace DiscImageChef.DiscImages foreach(DataFileCharacteristics characteristics in filePaths.Where(characteristics => (long)sectorAddress >= characteristics.StartLba && - length < (ulong)characteristics - .Sectors - sectorAddress)) + length < (ulong)characteristics. + Sectors - sectorAddress)) { chars = characteristics; + break; } - if(string.IsNullOrEmpty(chars.FilePath) || chars.FileFilter == null) + if(string.IsNullOrEmpty(chars.FilePath) || + chars.FileFilter == null) throw new ArgumentOutOfRangeException(nameof(chars.FileFilter), "Track does not exist in disc image"); uint sectorOffset; @@ -1515,6 +1756,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2352; sectorSkip = 0; + break; } case TrackType.Data: @@ -1522,6 +1764,7 @@ namespace DiscImageChef.DiscImages sectorOffset = 0; sectorSize = 2048; sectorSkip = 0; + break; } default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); @@ -1531,12 +1774,15 @@ namespace DiscImageChef.DiscImages { case TrackSubchannelType.None: sectorSkip += 0; + break; case TrackSubchannelType.Q16Interleaved: sectorSkip += 16; + break; case TrackSubchannelType.PackedInterleaved: sectorSkip += 96; + break; default: throw new FeatureSupportedButNotImplementedImageException("Unsupported subchannel type"); } @@ -1544,11 +1790,15 @@ namespace DiscImageChef.DiscImages byte[] buffer = new byte[sectorSize * length]; imageStream = dicTrack.TrackFilter.GetDataForkStream(); - BinaryReader br = new BinaryReader(imageStream); - br.BaseStream - .Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), + var br = new BinaryReader(imageStream); + + br.BaseStream. + Seek((long)dicTrack.TrackFileOffset + (long)(sectorAddress * (sectorOffset + sectorSize + sectorSkip)), SeekOrigin.Begin); - if(sectorOffset == 0 && sectorSkip == 0) buffer = br.ReadBytes((int)(sectorSize * length)); + + if(sectorOffset == 0 && + sectorSkip == 0) + buffer = br.ReadBytes((int)(sectorSize * length)); else for(int i = 0; i < length; i++) { @@ -1563,14 +1813,13 @@ namespace DiscImageChef.DiscImages public List GetSessionTracks(Session session) { - if(Sessions.Contains(session)) return GetSessionTracks(session.SessionSequence); + if(Sessions.Contains(session)) + return GetSessionTracks(session.SessionSequence); throw new ImageNotSupportedException("Session does not exist in disc image"); } - public List GetSessionTracks(ushort session) - { - return Tracks.Where(dicTrack => dicTrack.TrackSession == session).ToList(); - } + public List GetSessionTracks(ushort session) => + Tracks.Where(dicTrack => dicTrack.TrackSession == session).ToList(); } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/CHD/Read.cs b/DiscImageChef.DiscImages/CHD/Read.cs index 205176c0a..0937fd3be 100644 --- a/DiscImageChef.DiscImages/CHD/Read.cs +++ b/DiscImageChef.DiscImages/CHD/Read.cs @@ -41,8 +41,8 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Console; -using DiscImageChef.Decoders.ATA; using DiscImageChef.Helpers; namespace DiscImageChef.DiscImages @@ -55,7 +55,9 @@ namespace DiscImageChef.DiscImages stream.Seek(0, SeekOrigin.Begin); byte[] magic = new byte[8]; stream.Read(magic, 0, 8); - if(!chdTag.SequenceEqual(magic)) return false; + + if(!chdTag.SequenceEqual(magic)) + return false; // Read length byte[] buffer = new byte[4]; @@ -77,23 +79,23 @@ namespace DiscImageChef.DiscImages { ChdHeaderV1 hdrV1 = Marshal.ByteArrayToStructureBigEndian(buffer); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.tag = \"{0}\"", - Encoding.ASCII.GetString(hdrV1.tag)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.tag = \"{0}\"", Encoding.ASCII.GetString(hdrV1.tag)); DicConsole.DebugWriteLine("CHD plugin", "hdrV1.length = {0} bytes", hdrV1.length); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.version = {0}", hdrV1.version); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.flags = {0}", (ChdFlags)hdrV1.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.version = {0}", hdrV1.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.flags = {0}", (ChdFlags)hdrV1.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.compression = {0}", (ChdCompression)hdrV1.compression); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.hunksize = {0}", hdrV1.hunksize); + + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.hunksize = {0}", hdrV1.hunksize); DicConsole.DebugWriteLine("CHD plugin", "hdrV1.totalhunks = {0}", hdrV1.totalhunks); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.cylinders = {0}", hdrV1.cylinders); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.heads = {0}", hdrV1.heads); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.sectors = {0}", hdrV1.sectors); - DicConsole.DebugWriteLine("CHD plugin", "hdrV1.md5 = {0}", - ArrayHelpers.ByteArrayToHex(hdrV1.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.cylinders = {0}", hdrV1.cylinders); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.heads = {0}", hdrV1.heads); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.sectors = {0}", hdrV1.sectors); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.md5 = {0}", ArrayHelpers.ByteArrayToHex(hdrV1.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV1.parentmd5 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV1.parentmd5) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV1.parentmd5) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV1.parentmd5)); DicConsole.DebugWriteLine("CHD plugin", "Reading Hunk map."); @@ -101,22 +103,26 @@ namespace DiscImageChef.DiscImages hunkTable = new ulong[hdrV1.totalhunks]; - uint hunkSectorCount = (uint)Math.Ceiling((double)hdrV1.totalhunks * 8 / 512); + uint hunkSectorCount = (uint)Math.Ceiling(((double)hdrV1.totalhunks * 8) / 512); byte[] hunkSectorBytes = new byte[512]; for(int i = 0; i < hunkSectorCount; i++) { stream.Read(hunkSectorBytes, 0, 512); + // This does the big-endian trick but reverses the order of elements also Array.Reverse(hunkSectorBytes); HunkSector hunkSector = Marshal.ByteArrayToStructureLittleEndian(hunkSectorBytes); + // This restores the order of elements Array.Reverse(hunkSector.hunkEntry); - if(hunkTable.Length >= i * 512 / 8 + 512 / 8) - Array.Copy(hunkSector.hunkEntry, 0, hunkTable, i * 512 / 8, 512 / 8); + + if(hunkTable.Length >= ((i * 512) / 8) + (512 / 8)) + Array.Copy(hunkSector.hunkEntry, 0, hunkTable, (i * 512) / 8, 512 / 8); else - Array.Copy(hunkSector.hunkEntry, 0, hunkTable, i * 512 / 8, hunkTable.Length - i * 512 / 8); + Array.Copy(hunkSector.hunkEntry, 0, hunkTable, (i * 512) / 8, + hunkTable.Length - ((i * 512) / 8)); } DateTime end = DateTime.UtcNow; @@ -146,24 +152,25 @@ namespace DiscImageChef.DiscImages { ChdHeaderV2 hdrV2 = Marshal.ByteArrayToStructureBigEndian(buffer); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.tag = \"{0}\"", - Encoding.ASCII.GetString(hdrV2.tag)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.tag = \"{0}\"", Encoding.ASCII.GetString(hdrV2.tag)); DicConsole.DebugWriteLine("CHD plugin", "hdrV2.length = {0} bytes", hdrV2.length); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.version = {0}", hdrV2.version); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.flags = {0}", (ChdFlags)hdrV2.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.version = {0}", hdrV2.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.flags = {0}", (ChdFlags)hdrV2.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.compression = {0}", (ChdCompression)hdrV2.compression); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.hunksize = {0}", hdrV2.hunksize); + + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.hunksize = {0}", hdrV2.hunksize); DicConsole.DebugWriteLine("CHD plugin", "hdrV2.totalhunks = {0}", hdrV2.totalhunks); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.cylinders = {0}", hdrV2.cylinders); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.heads = {0}", hdrV2.heads); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.sectors = {0}", hdrV2.sectors); - DicConsole.DebugWriteLine("CHD plugin", "hdrV2.md5 = {0}", - ArrayHelpers.ByteArrayToHex(hdrV2.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.cylinders = {0}", hdrV2.cylinders); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.heads = {0}", hdrV2.heads); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.sectors = {0}", hdrV2.sectors); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.md5 = {0}", ArrayHelpers.ByteArrayToHex(hdrV2.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.parentmd5 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV2.parentmd5) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV2.parentmd5) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV2.parentmd5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV2.seclen = {0}", hdrV2.seclen); DicConsole.DebugWriteLine("CHD plugin", "Reading Hunk map."); @@ -172,22 +179,26 @@ namespace DiscImageChef.DiscImages hunkTable = new ulong[hdrV2.totalhunks]; // How many sectors uses the BAT - uint hunkSectorCount = (uint)Math.Ceiling((double)hdrV2.totalhunks * 8 / 512); + uint hunkSectorCount = (uint)Math.Ceiling(((double)hdrV2.totalhunks * 8) / 512); byte[] hunkSectorBytes = new byte[512]; for(int i = 0; i < hunkSectorCount; i++) { stream.Read(hunkSectorBytes, 0, 512); + // This does the big-endian trick but reverses the order of elements also Array.Reverse(hunkSectorBytes); HunkSector hunkSector = Marshal.ByteArrayToStructureLittleEndian(hunkSectorBytes); + // This restores the order of elements Array.Reverse(hunkSector.hunkEntry); - if(hunkTable.Length >= i * 512 / 8 + 512 / 8) - Array.Copy(hunkSector.hunkEntry, 0, hunkTable, i * 512 / 8, 512 / 8); + + if(hunkTable.Length >= ((i * 512) / 8) + (512 / 8)) + Array.Copy(hunkSector.hunkEntry, 0, hunkTable, (i * 512) / 8, 512 / 8); else - Array.Copy(hunkSector.hunkEntry, 0, hunkTable, i * 512 / 8, hunkTable.Length - i * 512 / 8); + Array.Copy(hunkSector.hunkEntry, 0, hunkTable, (i * 512) / 8, + hunkTable.Length - ((i * 512) / 8)); } DateTime end = DateTime.UtcNow; @@ -217,28 +228,30 @@ namespace DiscImageChef.DiscImages { ChdHeaderV3 hdrV3 = Marshal.ByteArrayToStructureBigEndian(buffer); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.tag = \"{0}\"", - Encoding.ASCII.GetString(hdrV3.tag)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.tag = \"{0}\"", Encoding.ASCII.GetString(hdrV3.tag)); DicConsole.DebugWriteLine("CHD plugin", "hdrV3.length = {0} bytes", hdrV3.length); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.version = {0}", hdrV3.version); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.flags = {0}", (ChdFlags)hdrV3.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.version = {0}", hdrV3.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.flags = {0}", (ChdFlags)hdrV3.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.compression = {0}", (ChdCompression)hdrV3.compression); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.totalhunks = {0}", hdrV3.totalhunks); + + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.totalhunks = {0}", hdrV3.totalhunks); DicConsole.DebugWriteLine("CHD plugin", "hdrV3.logicalbytes = {0}", hdrV3.logicalbytes); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.metaoffset = {0}", hdrV3.metaoffset); - DicConsole.DebugWriteLine("CHD plugin", "hdrV3.md5 = {0}", - ArrayHelpers.ByteArrayToHex(hdrV3.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.metaoffset = {0}", hdrV3.metaoffset); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.md5 = {0}", ArrayHelpers.ByteArrayToHex(hdrV3.md5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.parentmd5 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV3.parentmd5) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV3.parentmd5) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV3.parentmd5)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.hunkbytes = {0}", hdrV3.hunkbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.sha1 = {0}", ArrayHelpers.ByteArrayToHex(hdrV3.sha1)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV3.parentsha1 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV3.parentsha1) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV3.parentsha1) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV3.parentsha1)); DicConsole.DebugWriteLine("CHD plugin", "Reading Hunk map."); @@ -267,23 +280,26 @@ namespace DiscImageChef.DiscImages { ChdHeaderV4 hdrV4 = Marshal.ByteArrayToStructureBigEndian(buffer); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.tag = \"{0}\"", - Encoding.ASCII.GetString(hdrV4.tag)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.tag = \"{0}\"", Encoding.ASCII.GetString(hdrV4.tag)); DicConsole.DebugWriteLine("CHD plugin", "hdrV4.length = {0} bytes", hdrV4.length); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.version = {0}", hdrV4.version); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.flags = {0}", (ChdFlags)hdrV4.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.version = {0}", hdrV4.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.flags = {0}", (ChdFlags)hdrV4.flags); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.compression = {0}", (ChdCompression)hdrV4.compression); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.totalhunks = {0}", hdrV4.totalhunks); + + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.totalhunks = {0}", hdrV4.totalhunks); DicConsole.DebugWriteLine("CHD plugin", "hdrV4.logicalbytes = {0}", hdrV4.logicalbytes); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.metaoffset = {0}", hdrV4.metaoffset); - DicConsole.DebugWriteLine("CHD plugin", "hdrV4.hunkbytes = {0}", hdrV4.hunkbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.metaoffset = {0}", hdrV4.metaoffset); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.hunkbytes = {0}", hdrV4.hunkbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.sha1 = {0}", ArrayHelpers.ByteArrayToHex(hdrV4.sha1)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.parentsha1 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV4.parentsha1) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV4.parentsha1) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV4.parentsha1)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV4.rawsha1 = {0}", ArrayHelpers.ByteArrayToHex(hdrV4.rawsha1)); @@ -313,33 +329,39 @@ namespace DiscImageChef.DiscImages { ChdHeaderV5 hdrV5 = Marshal.ByteArrayToStructureBigEndian(buffer); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.tag = \"{0}\"", - Encoding.ASCII.GetString(hdrV5.tag)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.tag = \"{0}\"", Encoding.ASCII.GetString(hdrV5.tag)); DicConsole.DebugWriteLine("CHD plugin", "hdrV5.length = {0} bytes", hdrV5.length); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.version = {0}", hdrV5.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.version = {0}", hdrV5.version); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.compressor0 = \"{0}\"", - Encoding.ASCII.GetString(BigEndianBitConverter - .GetBytes(hdrV5.compressor0))); + Encoding.ASCII.GetString(BigEndianBitConverter. + GetBytes(hdrV5.compressor0))); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.compressor1 = \"{0}\"", - Encoding.ASCII.GetString(BigEndianBitConverter - .GetBytes(hdrV5.compressor1))); + Encoding.ASCII.GetString(BigEndianBitConverter. + GetBytes(hdrV5.compressor1))); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.compressor2 = \"{0}\"", - Encoding.ASCII.GetString(BigEndianBitConverter - .GetBytes(hdrV5.compressor2))); + Encoding.ASCII.GetString(BigEndianBitConverter. + GetBytes(hdrV5.compressor2))); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.compressor3 = \"{0}\"", - Encoding.ASCII.GetString(BigEndianBitConverter - .GetBytes(hdrV5.compressor3))); + Encoding.ASCII.GetString(BigEndianBitConverter. + GetBytes(hdrV5.compressor3))); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.logicalbytes = {0}", hdrV5.logicalbytes); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.mapoffset = {0}", hdrV5.mapoffset); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.metaoffset = {0}", hdrV5.metaoffset); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.hunkbytes = {0}", hdrV5.hunkbytes); - DicConsole.DebugWriteLine("CHD plugin", "hdrV5.unitbytes = {0}", hdrV5.unitbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.mapoffset = {0}", hdrV5.mapoffset); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.metaoffset = {0}", hdrV5.metaoffset); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.hunkbytes = {0}", hdrV5.hunkbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.unitbytes = {0}", hdrV5.unitbytes); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.sha1 = {0}", ArrayHelpers.ByteArrayToHex(hdrV5.sha1)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.parentsha1 = {0}", - ArrayHelpers.ArrayIsNullOrEmpty(hdrV5.parentsha1) - ? "null" + ArrayHelpers.ArrayIsNullOrEmpty(hdrV5.parentsha1) ? "null" : ArrayHelpers.ByteArrayToHex(hdrV5.parentsha1)); + DicConsole.DebugWriteLine("CHD plugin", "hdrV5.rawsha1 = {0}", ArrayHelpers.ByteArrayToHex(hdrV5.rawsha1)); @@ -351,7 +373,7 @@ namespace DiscImageChef.DiscImages hunkTableSmall = new uint[hdrV5.logicalbytes / hdrV5.hunkbytes]; - uint hunkSectorCount = (uint)Math.Ceiling((double)hunkTableSmall.Length * 4 / 512); + uint hunkSectorCount = (uint)Math.Ceiling(((double)hunkTableSmall.Length * 4) / 512); byte[] hunkSectorBytes = new byte[512]; @@ -360,23 +382,28 @@ namespace DiscImageChef.DiscImages for(int i = 0; i < hunkSectorCount; i++) { stream.Read(hunkSectorBytes, 0, 512); + // This does the big-endian trick but reverses the order of elements also Array.Reverse(hunkSectorBytes); + HunkSectorSmall hunkSector = Marshal.ByteArrayToStructureLittleEndian(hunkSectorBytes); + // This restores the order of elements Array.Reverse(hunkSector.hunkEntry); - if(hunkTableSmall.Length >= i * 512 / 4 + 512 / 4) - Array.Copy(hunkSector.hunkEntry, 0, hunkTableSmall, i * 512 / 4, 512 / 4); + + if(hunkTableSmall.Length >= ((i * 512) / 4) + (512 / 4)) + Array.Copy(hunkSector.hunkEntry, 0, hunkTableSmall, (i * 512) / 4, 512 / 4); else - Array.Copy(hunkSector.hunkEntry, 0, hunkTableSmall, i * 512 / 4, - hunkTableSmall.Length - i * 512 / 4); + Array.Copy(hunkSector.hunkEntry, 0, hunkTableSmall, (i * 512) / 4, + hunkTableSmall.Length - ((i * 512) / 4)); } DateTime end = DateTime.UtcNow; DicConsole.DebugWriteLine("CHD plugin", "Took {0} seconds", (end - start).TotalSeconds); } - else throw new ImageNotSupportedException("Cannot read compressed CHD version 5"); + else + throw new ImageNotSupportedException("Cannot read compressed CHD version 5"); nextMetaOff = hdrV5.metaoffset; @@ -418,6 +445,7 @@ namespace DiscImageChef.DiscImages ChdMetadataHeader header = Marshal.ByteArrayToStructureBigEndian(hdrBytes); byte[] meta = new byte[header.flagsAndLength & 0xFFFFFF]; stream.Read(meta, 0, meta.Length); + DicConsole.DebugWriteLine("CHD plugin", "Found metadata \"{0}\"", Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(header.tag))); @@ -430,8 +458,9 @@ namespace DiscImageChef.DiscImages ImageNotSupportedException("Image cannot be a hard disk and a C/GD-ROM at the same time, aborting."); string gddd = StringHandlers.CToString(meta); - Regex gdddRegEx = new Regex(REGEX_METADATA_HDD); + var gdddRegEx = new Regex(REGEX_METADATA_HDD); Match gdddMatch = gdddRegEx.Match(gddd); + if(gdddMatch.Success) { isHdd = true; @@ -442,6 +471,7 @@ namespace DiscImageChef.DiscImages } break; + // "CHCD" case CDROM_OLD_METADATA: if(isHdd) @@ -455,60 +485,69 @@ namespace DiscImageChef.DiscImages uint chdTracksNumber = BigEndianBitConverter.ToUInt32(meta, 0); // Byteswapped - if(chdTracksNumber > 99) chdTracksNumber = BigEndianBitConverter.ToUInt32(meta, 0); + if(chdTracksNumber > 99) + chdTracksNumber = BigEndianBitConverter.ToUInt32(meta, 0); currentSector = 0; for(uint i = 0; i < chdTracksNumber; i++) { - ChdTrackOld chdTrack = new ChdTrackOld + var chdTrack = new ChdTrackOld { - type = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 0)), - subType = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 4)), - dataSize = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 8)), - subSize = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 12)), - frames = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 16)), - extraFrames = BigEndianBitConverter.ToUInt32(meta, (int)(4 + i * 24 + 20)) + type = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 0)), + subType = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 4)), + dataSize = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 8)), + subSize = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 12)), + frames = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 16)), + extraFrames = BigEndianBitConverter.ToUInt32(meta, (int)(4 + (i * 24) + 20)) }; - Track dicTrack = new Track(); + var dicTrack = new Track(); + switch((ChdOldTrackType)chdTrack.type) { case ChdOldTrackType.Audio: dicTrack.TrackBytesPerSector = 2352; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.Audio; + break; case ChdOldTrackType.Mode1: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode1; + break; case ChdOldTrackType.Mode1Raw: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode1; + break; case ChdOldTrackType.Mode2: case ChdOldTrackType.Mode2FormMix: dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2336; dicTrack.TrackType = TrackType.CdMode2Formless; + break; case ChdOldTrackType.Mode2Form1: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode2Form1; + break; case ChdOldTrackType.Mode2Form2: dicTrack.TrackBytesPerSector = 2324; dicTrack.TrackRawBytesPerSector = 2324; dicTrack.TrackType = TrackType.CdMode2Form2; + break; case ChdOldTrackType.Mode2Raw: dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode2Formless; + break; default: throw new ImageNotSupportedException($"Unsupported track type {chdTrack.type}"); @@ -520,14 +559,17 @@ namespace DiscImageChef.DiscImages dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.PackedInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; case ChdOldSubType.None: dicTrack.TrackSubchannelType = TrackSubchannelType.None; + break; case ChdOldSubType.Raw: dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.RawInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; default: throw new @@ -535,8 +577,8 @@ namespace DiscImageChef.DiscImages } dicTrack.Indexes = new Dictionary(); - dicTrack.TrackDescription = $"Track {i + 1}"; - dicTrack.TrackEndSector = currentSector + chdTrack.frames - 1; + dicTrack.TrackDescription = $"Track {i + 1}"; + dicTrack.TrackEndSector = (currentSector + chdTrack.frames) - 1; dicTrack.TrackFile = imageFilter.GetFilename(); dicTrack.TrackFileType = "BINARY"; dicTrack.TrackFilter = imageFilter; @@ -550,6 +592,7 @@ namespace DiscImageChef.DiscImages isCdrom = true; break; + // "CHTR" case CDROM_TRACK_METADATA: if(isHdd) @@ -561,8 +604,9 @@ namespace DiscImageChef.DiscImages ImageNotSupportedException("Image cannot be a GD-ROM and a CD-ROM at the same time, aborting."); string chtr = StringHandlers.CToString(meta); - Regex chtrRegEx = new Regex(REGEX_METADATA_CDROM); + var chtrRegEx = new Regex(REGEX_METADATA_CDROM); Match chtrMatch = chtrRegEx.Match(chtr); + if(chtrMatch.Success) { isCdrom = true; @@ -575,25 +619,29 @@ namespace DiscImageChef.DiscImages if(trackNo != currentTrack) throw new ImageNotSupportedException("Unsorted tracks, cannot proceed."); - Track dicTrack = new Track(); + var dicTrack = new Track(); + switch(tracktype) { case TRACK_TYPE_AUDIO: dicTrack.TrackBytesPerSector = 2352; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.Audio; + break; case TRACK_TYPE_MODE1: case TRACK_TYPE_MODE1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE1_RAW: case TRACK_TYPE_MODE1_RAW_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE2: case TRACK_TYPE_MODE2_2K: @@ -601,24 +649,28 @@ namespace DiscImageChef.DiscImages dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2336; dicTrack.TrackType = TrackType.CdMode2Formless; + break; case TRACK_TYPE_MODE2_F1: case TRACK_TYPE_MODE2_F1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode2Form1; + break; case TRACK_TYPE_MODE2_F2: case TRACK_TYPE_MODE2_F2_2K: dicTrack.TrackBytesPerSector = 2324; dicTrack.TrackRawBytesPerSector = 2324; dicTrack.TrackType = TrackType.CdMode2Form2; + break; case TRACK_TYPE_MODE2_RAW: case TRACK_TYPE_MODE2_RAW_2K: dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode2Formless; + break; default: throw new ImageNotSupportedException($"Unsupported track type {tracktype}"); @@ -630,14 +682,17 @@ namespace DiscImageChef.DiscImages dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.PackedInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; case SUB_TYPE_NONE: dicTrack.TrackSubchannelType = TrackSubchannelType.None; + break; case SUB_TYPE_RAW: dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.RawInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; default: throw new ImageNotSupportedException($"Unsupported subchannel type {subtype}"); @@ -645,7 +700,7 @@ namespace DiscImageChef.DiscImages dicTrack.Indexes = new Dictionary(); dicTrack.TrackDescription = $"Track {trackNo}"; - dicTrack.TrackEndSector = currentSector + frames - 1; + dicTrack.TrackEndSector = (currentSector + frames) - 1; dicTrack.TrackFile = imageFilter.GetFilename(); dicTrack.TrackFileType = "BINARY"; dicTrack.TrackFilter = imageFilter; @@ -658,6 +713,7 @@ namespace DiscImageChef.DiscImages } break; + // "CHT2" case CDROM_TRACK_METADATA2: if(isHdd) @@ -669,8 +725,9 @@ namespace DiscImageChef.DiscImages ImageNotSupportedException("Image cannot be a GD-ROM and a CD-ROM at the same time, aborting."); string cht2 = StringHandlers.CToString(meta); - Regex cht2RegEx = new Regex(REGEX_METADATA_CDROM2); + var cht2RegEx = new Regex(REGEX_METADATA_CDROM2); Match cht2Match = cht2RegEx.Match(cht2); + if(cht2Match.Success) { isCdrom = true; @@ -679,6 +736,7 @@ namespace DiscImageChef.DiscImages uint frames = uint.Parse(cht2Match.Groups["frames"].Value); string subtype = cht2Match.Groups["sub_type"].Value; string tracktype = cht2Match.Groups["track_type"].Value; + // TODO: Check pregap and postgap behaviour uint pregap = uint.Parse(cht2Match.Groups["pregap"].Value); string pregapType = cht2Match.Groups["pgtype"].Value; @@ -688,25 +746,29 @@ namespace DiscImageChef.DiscImages if(trackNo != currentTrack) throw new ImageNotSupportedException("Unsorted tracks, cannot proceed."); - Track dicTrack = new Track(); + var dicTrack = new Track(); + switch(tracktype) { case TRACK_TYPE_AUDIO: dicTrack.TrackBytesPerSector = 2352; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.Audio; + break; case TRACK_TYPE_MODE1: case TRACK_TYPE_MODE1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE1_RAW: case TRACK_TYPE_MODE1_RAW_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE2: case TRACK_TYPE_MODE2_2K: @@ -714,24 +776,28 @@ namespace DiscImageChef.DiscImages dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2336; dicTrack.TrackType = TrackType.CdMode2Formless; + break; case TRACK_TYPE_MODE2_F1: case TRACK_TYPE_MODE2_F1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode2Form1; + break; case TRACK_TYPE_MODE2_F2: case TRACK_TYPE_MODE2_F2_2K: dicTrack.TrackBytesPerSector = 2324; dicTrack.TrackRawBytesPerSector = 2324; dicTrack.TrackType = TrackType.CdMode2Form2; + break; case TRACK_TYPE_MODE2_RAW: case TRACK_TYPE_MODE2_RAW_2K: dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode2Formless; + break; default: throw new ImageNotSupportedException($"Unsupported track type {tracktype}"); @@ -743,14 +809,17 @@ namespace DiscImageChef.DiscImages dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.PackedInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; case SUB_TYPE_NONE: dicTrack.TrackSubchannelType = TrackSubchannelType.None; + break; case SUB_TYPE_RAW: dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.RawInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; default: throw new ImageNotSupportedException($"Unsupported subchannel type {subtype}"); @@ -758,7 +827,7 @@ namespace DiscImageChef.DiscImages dicTrack.Indexes = new Dictionary(); dicTrack.TrackDescription = $"Track {trackNo}"; - dicTrack.TrackEndSector = currentSector + frames - 1; + dicTrack.TrackEndSector = (currentSector + frames) - 1; dicTrack.TrackFile = imageFilter.GetFilename(); dicTrack.TrackFileType = "BINARY"; dicTrack.TrackFilter = imageFilter; @@ -771,10 +840,12 @@ namespace DiscImageChef.DiscImages } break; + // "CHGT" case GDROM_OLD_METADATA: swapAudio = true; goto case GDROM_METADATA; + // "CHGD" case GDROM_METADATA: if(isHdd) @@ -786,8 +857,9 @@ namespace DiscImageChef.DiscImages ImageNotSupportedException("Image cannot be a CD-ROM and a GD-ROM at the same time, aborting."); string chgd = StringHandlers.CToString(meta); - Regex chgdRegEx = new Regex(REGEX_METADATA_GDROM); + var chgdRegEx = new Regex(REGEX_METADATA_GDROM); Match chgdMatch = chgdRegEx.Match(chgd); + if(chgdMatch.Success) { isGdrom = true; @@ -796,6 +868,7 @@ namespace DiscImageChef.DiscImages uint frames = uint.Parse(chgdMatch.Groups["frames"].Value); string subtype = chgdMatch.Groups["sub_type"].Value; string tracktype = chgdMatch.Groups["track_type"].Value; + // TODO: Check pregap, postgap and pad behaviour uint pregap = uint.Parse(chgdMatch.Groups["pregap"].Value); string pregapType = chgdMatch.Groups["pgtype"].Value; @@ -806,25 +879,29 @@ namespace DiscImageChef.DiscImages if(trackNo != currentTrack) throw new ImageNotSupportedException("Unsorted tracks, cannot proceed."); - Track dicTrack = new Track(); + var dicTrack = new Track(); + switch(tracktype) { case TRACK_TYPE_AUDIO: dicTrack.TrackBytesPerSector = 2352; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.Audio; + break; case TRACK_TYPE_MODE1: case TRACK_TYPE_MODE1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE1_RAW: case TRACK_TYPE_MODE1_RAW_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode1; + break; case TRACK_TYPE_MODE2: case TRACK_TYPE_MODE2_2K: @@ -832,24 +909,28 @@ namespace DiscImageChef.DiscImages dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2336; dicTrack.TrackType = TrackType.CdMode2Formless; + break; case TRACK_TYPE_MODE2_F1: case TRACK_TYPE_MODE2_F1_2K: dicTrack.TrackBytesPerSector = 2048; dicTrack.TrackRawBytesPerSector = 2048; dicTrack.TrackType = TrackType.CdMode2Form1; + break; case TRACK_TYPE_MODE2_F2: case TRACK_TYPE_MODE2_F2_2K: dicTrack.TrackBytesPerSector = 2324; dicTrack.TrackRawBytesPerSector = 2324; dicTrack.TrackType = TrackType.CdMode2Form2; + break; case TRACK_TYPE_MODE2_RAW: case TRACK_TYPE_MODE2_RAW_2K: dicTrack.TrackBytesPerSector = 2336; dicTrack.TrackRawBytesPerSector = 2352; dicTrack.TrackType = TrackType.CdMode2Formless; + break; default: throw new ImageNotSupportedException($"Unsupported track type {tracktype}"); @@ -861,14 +942,17 @@ namespace DiscImageChef.DiscImages dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.PackedInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; case SUB_TYPE_NONE: dicTrack.TrackSubchannelType = TrackSubchannelType.None; + break; case SUB_TYPE_RAW: dicTrack.TrackSubchannelFile = imageFilter.GetFilename(); dicTrack.TrackSubchannelType = TrackSubchannelType.RawInterleaved; dicTrack.TrackSubchannelFilter = imageFilter; + break; default: throw new ImageNotSupportedException($"Unsupported subchannel type {subtype}"); @@ -876,7 +960,7 @@ namespace DiscImageChef.DiscImages dicTrack.Indexes = new Dictionary(); dicTrack.TrackDescription = $"Track {trackNo}"; - dicTrack.TrackEndSector = currentSector + frames - 1; + dicTrack.TrackEndSector = (currentSector + frames) - 1; dicTrack.TrackFile = imageFilter.GetFilename(); dicTrack.TrackFileType = "BINARY"; dicTrack.TrackFilter = imageFilter; @@ -889,9 +973,11 @@ namespace DiscImageChef.DiscImages } break; + // "IDNT" case HARD_DISK_IDENT_METADATA: - Identify.IdentifyDevice? idnt = Decoders.ATA.Identify.Decode(meta); + Identify.IdentifyDevice? idnt = CommonTypes.Structs.Devices.ATA.Identify.Decode(meta); + if(idnt.HasValue) { imageInfo.MediaManufacturer = idnt.Value.MediaManufacturer; @@ -899,7 +985,9 @@ namespace DiscImageChef.DiscImages imageInfo.DriveModel = idnt.Value.Model; imageInfo.DriveSerialNumber = idnt.Value.SerialNumber; imageInfo.DriveFirmwareRevision = idnt.Value.FirmwareRevision; - if(idnt.Value.CurrentCylinders > 0 && idnt.Value.CurrentHeads > 0 && + + if(idnt.Value.CurrentCylinders > 0 && + idnt.Value.CurrentHeads > 0 && idnt.Value.CurrentSectorsPerTrack > 0) { imageInfo.Cylinders = idnt.Value.CurrentCylinders; @@ -915,13 +1003,17 @@ namespace DiscImageChef.DiscImages } identify = meta; + if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) imageInfo.ReadableMediaTags.Add(MediaTagType.ATA_IDENTIFY); + break; case PCMCIA_CIS_METADATA: cis = meta; + if(!imageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) imageInfo.ReadableMediaTags.Add(MediaTagType.PCMCIA_CIS); + break; } @@ -943,7 +1035,7 @@ namespace DiscImageChef.DiscImages imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; foreach(Track dicTrack in tracks.Values) - imageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1; + imageInfo.Sectors += (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1; } else if(isGdrom) { @@ -953,9 +1045,10 @@ namespace DiscImageChef.DiscImages imageInfo.XmlMediaType = XmlMediaType.OpticalDisc; foreach(Track dicTrack in tracks.Values) - imageInfo.Sectors += dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1; + imageInfo.Sectors += (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1; } - else throw new ImageNotSupportedException("Image does not represent a known media, aborting"); + else + throw new ImageNotSupportedException("Image does not represent a known media, aborting"); } if(isCdrom || isGdrom) @@ -963,20 +1056,19 @@ namespace DiscImageChef.DiscImages offsetmap = new Dictionary(); partitions = new List(); ulong partPos = 0; + foreach(Track dicTrack in tracks.Values) { - Partition partition = new Partition + var partition = new Partition { Description = dicTrack.TrackDescription, - Size = - (dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1) * - (ulong)dicTrack.TrackRawBytesPerSector, - Length = dicTrack.TrackEndSector - dicTrack.TrackStartSector + 1, - Sequence = dicTrack.TrackSequence, - Offset = partPos, - Start = dicTrack.TrackStartSector, + Size = ((dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1) * + (ulong)dicTrack.TrackRawBytesPerSector, + Length = (dicTrack.TrackEndSector - dicTrack.TrackStartSector) + 1, + Sequence = dicTrack.TrackSequence, Offset = partPos, Start = dicTrack.TrackStartSector, Type = dicTrack.TrackType.ToString() }; + partPos += partition.Length; offsetmap.Add(dicTrack.TrackStartSector, dicTrack.TrackSequence); @@ -992,16 +1084,22 @@ namespace DiscImageChef.DiscImages { if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEcc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEcc); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccP)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccP); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEccQ)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEccQ); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); } @@ -1012,10 +1110,13 @@ namespace DiscImageChef.DiscImages { if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSubHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubHeader); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorEdc)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorEdc); } @@ -1026,6 +1127,7 @@ namespace DiscImageChef.DiscImages { if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorSync)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSync); + if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.CdSectorHeader)) imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorHeader); } @@ -1053,7 +1155,8 @@ namespace DiscImageChef.DiscImages // TODO: Detect CompactFlash // TODO: Get manufacturer and drive name from CIS if applicable - if(cis != null) imageInfo.MediaType = MediaType.PCCardTypeI; + if(cis != null) + imageInfo.MediaType = MediaType.PCCardTypeI; return true; } @@ -1064,32 +1167,35 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - Track track = new Track(); - uint sectorSize; + var track = new Track(); + uint sectorSize; if(!sectorCache.TryGetValue(sectorAddress, out byte[] sector)) { - if(isHdd) sectorSize = imageInfo.SectorSize; + if(isHdd) + sectorSize = imageInfo.SectorSize; else { track = GetTrack(sectorAddress); sectorSize = (uint)track.TrackRawBytesPerSector; } - ulong hunkNo = sectorAddress / sectorsPerHunk; - ulong secOff = sectorAddress * sectorSize % (sectorsPerHunk * sectorSize); + ulong hunkNo = sectorAddress / sectorsPerHunk; + ulong secOff = (sectorAddress * sectorSize) % (sectorsPerHunk * sectorSize); byte[] hunk = GetHunk(hunkNo); sector = new byte[imageInfo.SectorSize]; Array.Copy(hunk, (int)secOff, sector, 0, sector.Length); - if(sectorCache.Count >= maxSectorCache) sectorCache.Clear(); + if(sectorCache.Count >= maxSectorCache) + sectorCache.Clear(); sectorCache.Add(sectorAddress, sector); } - if(isHdd) return sector; + if(isHdd) + return sector; uint sectorOffset; @@ -1148,6 +1254,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 0; sectorSize = 2352; + break; } @@ -1162,20 +1269,22 @@ namespace DiscImageChef.DiscImages buffer[i + 1] = sector[i]; buffer[i] = sector[i + 1]; } - else Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); + else + Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); return buffer; } public byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag) { - if(isHdd) throw new FeatureNotPresentImageException("Hard disk images do not have sector tags"); + if(isHdd) + throw new FeatureNotPresentImageException("Hard disk images do not have sector tags"); if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - Track track = new Track(); + var track = new Track(); uint sectorSize; @@ -1184,20 +1293,22 @@ namespace DiscImageChef.DiscImages track = GetTrack(sectorAddress); sectorSize = (uint)track.TrackRawBytesPerSector; - ulong hunkNo = sectorAddress / sectorsPerHunk; - ulong secOff = sectorAddress * sectorSize % (sectorsPerHunk * sectorSize); + ulong hunkNo = sectorAddress / sectorsPerHunk; + ulong secOff = (sectorAddress * sectorSize) % (sectorsPerHunk * sectorSize); byte[] hunk = GetHunk(hunkNo); sector = new byte[imageInfo.SectorSize]; Array.Copy(hunk, (int)secOff, sector, 0, sector.Length); - if(sectorCache.Count >= maxSectorCache) sectorCache.Clear(); + if(sectorCache.Count >= maxSectorCache) + sectorCache.Clear(); sectorCache.Add(sectorAddress, sector); } - if(isHdd) return sector; + if(isHdd) + return sector; uint sectorOffset; @@ -1209,6 +1320,7 @@ namespace DiscImageChef.DiscImages case TrackSubchannelType.RawInterleaved: sectorOffset = (uint)track.TrackRawBytesPerSector; sectorSize = 96; + break; default: throw new @@ -1227,6 +1339,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 0; sectorSize = 12; + break; } @@ -1234,6 +1347,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 12; sectorSize = 4; + break; } @@ -1244,6 +1358,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2076; sectorSize = 276; + break; } @@ -1251,6 +1366,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2076; sectorSize = 172; + break; } @@ -1258,6 +1374,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2248; sectorSize = 104; + break; } @@ -1265,12 +1382,14 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2064; sectorSize = 4; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } - else throw new FeatureNotPresentImageException("Requested sector does not contain tags"); + else + throw new FeatureNotPresentImageException("Requested sector does not contain tags"); break; } @@ -1284,6 +1403,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 0; sectorSize = 12; + break; } @@ -1291,6 +1411,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 12; sectorSize = 4; + break; } @@ -1298,6 +1419,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 16; sectorSize = 8; + break; } @@ -1305,6 +1427,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2348; sectorSize = 4; + break; } @@ -1325,6 +1448,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 0; sectorSize = 8; + break; } @@ -1332,6 +1456,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2332; sectorSize = 4; + break; } @@ -1357,6 +1482,7 @@ namespace DiscImageChef.DiscImages { sectorOffset = 0; sectorSize = 8; + break; } @@ -1364,12 +1490,14 @@ namespace DiscImageChef.DiscImages { sectorOffset = 2332; sectorSize = 4; + break; } default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } - else throw new FeatureNotPresentImageException("Requested sector does not contain tags"); + else + throw new FeatureNotPresentImageException("Requested sector does not contain tags"); break; } @@ -1387,7 +1515,8 @@ namespace DiscImageChef.DiscImages buffer[i + 1] = sector[i]; buffer[i] = sector[i + 1]; } - else Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); + else + Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); if(track.TrackType == TrackType.Audio && swapAudio) for(int i = 0; i < 2352; i += 2) @@ -1395,7 +1524,8 @@ namespace DiscImageChef.DiscImages buffer[i + 1] = sector[i]; buffer[i] = sector[i + 1]; } - else Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); + else + Array.Copy(sector, sectorOffset, buffer, 0, sectorSize); return buffer; } @@ -1410,7 +1540,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(length), $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})"); - MemoryStream ms = new MemoryStream(); + var ms = new MemoryStream(); for(uint i = 0; i < length; i++) { @@ -1431,7 +1561,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(length), $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})"); - MemoryStream ms = new MemoryStream(); + var ms = new MemoryStream(); for(uint i = 0; i < length; i++) { @@ -1444,28 +1574,30 @@ namespace DiscImageChef.DiscImages public byte[] ReadSectorLong(ulong sectorAddress) { - if(isHdd) return ReadSector(sectorAddress); + if(isHdd) + return ReadSector(sectorAddress); if(sectorAddress > imageInfo.Sectors - 1) throw new ArgumentOutOfRangeException(nameof(sectorAddress), $"Sector address {sectorAddress} not found"); - Track track = new Track(); + var track = new Track(); if(!sectorCache.TryGetValue(sectorAddress, out byte[] sector)) { track = GetTrack(sectorAddress); uint sectorSize = (uint)track.TrackRawBytesPerSector; - ulong hunkNo = sectorAddress / sectorsPerHunk; - ulong secOff = sectorAddress * sectorSize % (sectorsPerHunk * sectorSize); + ulong hunkNo = sectorAddress / sectorsPerHunk; + ulong secOff = (sectorAddress * sectorSize) % (sectorsPerHunk * sectorSize); byte[] hunk = GetHunk(hunkNo); sector = new byte[imageInfo.SectorSize]; Array.Copy(hunk, (int)secOff, sector, 0, sector.Length); - if(sectorCache.Count >= maxSectorCache) sectorCache.Clear(); + if(sectorCache.Count >= maxSectorCache) + sectorCache.Clear(); sectorCache.Add(sectorAddress, sector); } @@ -1478,7 +1610,8 @@ namespace DiscImageChef.DiscImages buffer[i + 1] = sector[i]; buffer[i] = sector[i + 1]; } - else Array.Copy(sector, 0, buffer, 0, track.TrackRawBytesPerSector); + else + Array.Copy(sector, 0, buffer, 0, track.TrackRawBytesPerSector); return buffer; } @@ -1493,7 +1626,7 @@ namespace DiscImageChef.DiscImages throw new ArgumentOutOfRangeException(nameof(length), $"Requested more sectors ({sectorAddress + length}) than available ({imageInfo.Sectors})"); - MemoryStream ms = new MemoryStream(); + var ms = new MemoryStream(); for(uint i = 0; i < length; i++) { @@ -1506,9 +1639,11 @@ namespace DiscImageChef.DiscImages public byte[] ReadDiskTag(MediaTagType tag) { - if(imageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) return identify; + if(imageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY)) + return identify; - if(imageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) return cis; + if(imageInfo.ReadableMediaTags.Contains(MediaTagType.PCMCIA_CIS)) + return cis; throw new FeatureUnsupportedImageException("Feature not supported by image format"); } diff --git a/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs b/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs index b4e24c997..f1a7e61ff 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs @@ -33,31 +33,33 @@ using System; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; -using DiscImageChef.Decoders.ATA; -using DiscImageChef.Decoders.SCSI; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.SecureDigital; using DiscImageChef.Helpers; -using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString; namespace DiscImageChef.DiscImages { public partial class DiscImageChef { - /// - /// Checks for media tags that may contain metadata and sets it up if not already set - /// + /// Checks for media tags that may contain metadata and sets it up if not already set void SetMetadataFromTags() { // Search for SecureDigital CID if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid)) { CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid); + if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = VendorString.Prettify(decoded.Manufacturer); - if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName; + + if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) + imageInfo.DriveModel = decoded.ProductName; + if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; + if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; } @@ -66,12 +68,17 @@ namespace DiscImageChef.DiscImages if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid)) { Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid); + if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer); - if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = decoded.ProductName; + + if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) + imageInfo.DriveModel = decoded.ProductName; + if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; + if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}"; } @@ -79,15 +86,18 @@ namespace DiscImageChef.DiscImages // Search for SCSI INQUIRY if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry)) { - Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry); + Inquiry? nullableInquiry = Inquiry.Decode(scsiInquiry); if(nullableInquiry.HasValue) { - Inquiry.SCSIInquiry inquiry = nullableInquiry.Value; + Inquiry inquiry = nullableInquiry.Value; + if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = StringHandlers.CToString(inquiry.VendorIdentification)?.Trim(); + if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = StringHandlers.CToString(inquiry.ProductIdentification)?.Trim(); + if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = StringHandlers.CToString(inquiry.ProductRevisionLevel)?.Trim(); @@ -95,29 +105,34 @@ namespace DiscImageChef.DiscImages } // Search for ATA or ATAPI IDENTIFY - if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) && - !mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return; + if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) && + !mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) + return; - Identify.IdentifyDevice? nullableIdentify = Decoders.ATA.Identify.Decode(ataIdentify); + Identify.IdentifyDevice? nullableIdentify = CommonTypes.Structs.Devices.ATA.Identify.Decode(ataIdentify); - if(!nullableIdentify.HasValue) return; + if(!nullableIdentify.HasValue) + return; Identify.IdentifyDevice identify = nullableIdentify.Value; string[] separated = identify.Model.Split(' '); if(separated.Length == 1) - if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[0]; + if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) + imageInfo.DriveModel = separated[0]; else { if(string.IsNullOrWhiteSpace(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = separated[0]; + if(string.IsNullOrWhiteSpace(imageInfo.DriveModel)) imageInfo.DriveModel = separated[separated.Length - 1]; } if(string.IsNullOrWhiteSpace(imageInfo.DriveFirmwareRevision)) imageInfo.DriveFirmwareRevision = identify.FirmwareRevision; + if(string.IsNullOrWhiteSpace(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = identify.SerialNumber; } @@ -225,9 +240,11 @@ namespace DiscImageChef.DiscImages // Gets a DDT entry ulong GetDdtEntry(ulong sectorAddress) { - if(inMemoryDdt) return userDataDdt[sectorAddress]; + if(inMemoryDdt) + return userDataDdt[sectorAddress]; - if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) return entry; + if(ddtEntryCache.TryGetValue(sectorAddress, out ulong entry)) + return entry; long oldPosition = imageStream.Position; imageStream.Position = outMemoryDdtPosition + Marshal.SizeOf(); @@ -237,9 +254,11 @@ namespace DiscImageChef.DiscImages imageStream.Position = oldPosition; entry = BitConverter.ToUInt64(temp, 0); - if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) ddtEntryCache.Clear(); + if(ddtEntryCache.Count >= MAX_DDT_ENTRY_CACHE) + ddtEntryCache.Clear(); ddtEntryCache.Add(sectorAddress, entry); + return entry; } @@ -248,8 +267,11 @@ namespace DiscImageChef.DiscImages { if(inMemoryDdt) { - if(IsTape) tapeDdt[sectorAddress] = pointer; - else userDataDdt[sectorAddress] = pointer; + if(IsTape) + tapeDdt[sectorAddress] = pointer; + else + userDataDdt[sectorAddress] = pointer; + return; } diff --git a/DiscImageChef.DiscImages/RsIde/Read.cs b/DiscImageChef.DiscImages/RsIde/Read.cs index 1405ec68e..ad7fd7407 100644 --- a/DiscImageChef.DiscImages/RsIde/Read.cs +++ b/DiscImageChef.DiscImages/RsIde/Read.cs @@ -37,7 +37,7 @@ using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; -using DiscImageChef.Decoders.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Helpers; namespace DiscImageChef.DiscImages @@ -54,7 +54,8 @@ namespace DiscImageChef.DiscImages RsIdeHeader hdr = Marshal.ByteArrayToStructureLittleEndian(hdrB); - if(!hdr.magic.SequenceEqual(signature)) return false; + if(!hdr.magic.SequenceEqual(signature)) + return false; dataOff = hdr.dataOff; @@ -72,7 +73,7 @@ namespace DiscImageChef.DiscImages { identify = new byte[512]; Array.Copy(hdr.identify, 0, identify, 0, hdr.identify.Length); - Identify.IdentifyDevice? ataId = Decoders.ATA.Identify.Decode(identify); + Identify.IdentifyDevice? ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identify); if(ataId.HasValue) { @@ -88,7 +89,9 @@ namespace DiscImageChef.DiscImages } } - if(imageInfo.Cylinders == 0 || imageInfo.Heads == 0 || imageInfo.SectorsPerTrack == 0) + if(imageInfo.Cylinders == 0 || + imageInfo.Heads == 0 || + imageInfo.SectorsPerTrack == 0) { imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63); imageInfo.Heads = 16; @@ -114,7 +117,7 @@ namespace DiscImageChef.DiscImages Stream stream = rsIdeImageFilter.GetDataForkStream(); - stream.Seek((long)(dataOff + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin); + stream.Seek((long)(dataOff + (sectorAddress * imageInfo.SectorSize)), SeekOrigin.Begin); stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize)); @@ -123,11 +126,13 @@ namespace DiscImageChef.DiscImages public byte[] ReadDiskTag(MediaTagType tag) { - if(!imageInfo.ReadableMediaTags.Contains(tag) || tag != MediaTagType.ATA_IDENTIFY) + if(!imageInfo.ReadableMediaTags.Contains(tag) || + tag != MediaTagType.ATA_IDENTIFY) throw new FeatureUnsupportedImageException("Feature not supported by image format"); byte[] buffer = new byte[512]; Array.Copy(identify, 0, buffer, 0, 512); + return buffer; } } diff --git a/DiscImageChef.DiscImages/RsIde/Write.cs b/DiscImageChef.DiscImages/RsIde/Write.cs index 546219851..15fafe687 100644 --- a/DiscImageChef.DiscImages/RsIde/Write.cs +++ b/DiscImageChef.DiscImages/RsIde/Write.cs @@ -37,7 +37,7 @@ using System.Linq; using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Structs; -using DiscImageChef.Decoders.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; using DiscImageChef.Helpers; using Schemas; using Version = DiscImageChef.CommonTypes.Interop.Version; @@ -47,37 +47,49 @@ namespace DiscImageChef.DiscImages public partial class RsIde { public bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors, - uint sectorSize) + uint sectorSize) { - if(sectorSize != 256 && sectorSize != 512) + if(sectorSize != 256 && + sectorSize != 512) { ErrorMessage = "Unsupported sector size"; + return false; } if(sectors > 63 * 16 * 1024) { ErrorMessage = "Too many sectors"; + return false; } if(!SupportedMediaTypes.Contains(mediaType)) { ErrorMessage = $"Unsupport media format {mediaType}"; + return false; } - imageInfo = new ImageInfo {MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors}; + imageInfo = new ImageInfo + { + MediaType = mediaType, SectorSize = sectorSize, Sectors = sectors + }; - try { writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } + try + { + writingStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); + } catch(IOException e) { ErrorMessage = $"Could not create new image file, exception {e.Message}"; + return false; } IsWriting = true; ErrorMessage = null; + return true; } @@ -86,17 +98,20 @@ namespace DiscImageChef.DiscImages if(tag != MediaTagType.ATA_IDENTIFY) { ErrorMessage = $"Unsupported media tag {tag}."; + return false; } if(!IsWriting) { ErrorMessage = "Tried to write on a non-writable image"; + return false; } identify = new byte[106]; Array.Copy(data, 0, identify, 0, 106); + return true; } @@ -105,26 +120,31 @@ namespace DiscImageChef.DiscImages if(!IsWriting) { ErrorMessage = "Tried to write on a non-writable image"; + return false; } if(data.Length != imageInfo.SectorSize) { ErrorMessage = "Incorrect data size"; + return false; } if(sectorAddress >= imageInfo.Sectors) { ErrorMessage = "Tried to write past image size"; + return false; } - writingStream.Seek((long)((ulong)Marshal.SizeOf() + sectorAddress * imageInfo.SectorSize), + writingStream.Seek((long)((ulong)Marshal.SizeOf() + (sectorAddress * imageInfo.SectorSize)), SeekOrigin.Begin); + writingStream.Write(data, 0, data.Length); ErrorMessage = ""; + return true; } @@ -133,38 +153,45 @@ namespace DiscImageChef.DiscImages if(!IsWriting) { ErrorMessage = "Tried to write on a non-writable image"; + return false; } if(data.Length % imageInfo.SectorSize != 0) { ErrorMessage = "Incorrect data size"; + return false; } if(sectorAddress + length > imageInfo.Sectors) { ErrorMessage = "Tried to write past image size"; + return false; } - writingStream.Seek((long)((ulong)Marshal.SizeOf() + sectorAddress * imageInfo.SectorSize), + writingStream.Seek((long)((ulong)Marshal.SizeOf() + (sectorAddress * imageInfo.SectorSize)), SeekOrigin.Begin); + writingStream.Write(data, 0, data.Length); ErrorMessage = ""; + return true; } public bool WriteSectorLong(byte[] data, ulong sectorAddress) { ErrorMessage = "Writing sectors with tags is not supported."; + return false; } public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) { ErrorMessage = "Writing sectors with tags is not supported."; + return false; } @@ -173,6 +200,7 @@ namespace DiscImageChef.DiscImages if(!IsWriting) { ErrorMessage = "Image is not opened for writing"; + return false; } @@ -194,52 +222,53 @@ namespace DiscImageChef.DiscImages imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack); - if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break; + if(imageInfo.Cylinders == 0 && + imageInfo.Heads == 0 && + imageInfo.SectorsPerTrack == 0) + break; } } - RsIdeHeader header = new RsIdeHeader + var header = new RsIdeHeader { - magic = signature, - identify = new byte[106], - dataOff = (ushort)Marshal.SizeOf(), - revision = 1, - reserved = new byte[11] + magic = signature, identify = new byte[106], dataOff = (ushort)Marshal.SizeOf(), + revision = 1, reserved = new byte[11] }; - if(imageInfo.SectorSize == 256) header.flags = RsIdeFlags.HalfSectors; + + if(imageInfo.SectorSize == 256) + header.flags = RsIdeFlags.HalfSectors; if(identify == null) { - Identify.IdentifyDevice ataId = new Identify.IdentifyDevice + var ataId = new Identify.IdentifyDevice { GeneralConfiguration = - Decoders.ATA.Identify.GeneralConfigurationBit.UltraFastIDE | - Decoders.ATA.Identify.GeneralConfigurationBit.Fixed | - Decoders.ATA.Identify.GeneralConfigurationBit.NotMFM | - Decoders.ATA.Identify.GeneralConfigurationBit.SoftSector, - Cylinders = (ushort)imageInfo.Cylinders, - Heads = (ushort)imageInfo.Heads, - SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, - VendorWord47 = 0x80, - Capabilities = - Decoders.ATA.Identify.CapabilitiesBit.DMASupport | - Decoders.ATA.Identify.CapabilitiesBit.IORDY | - Decoders.ATA.Identify.CapabilitiesBit.LBASupport, - ExtendedIdentify = Decoders.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid, - CurrentCylinders = (ushort)imageInfo.Cylinders, - CurrentHeads = (ushort)imageInfo.Heads, + CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.UltraFastIDE | + CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.Fixed | + CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.NotMFM | + CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit.SoftSector, + Cylinders = (ushort)imageInfo.Cylinders, Heads = (ushort)imageInfo.Heads, + SectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, VendorWord47 = 0x80, + Capabilities = CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.DMASupport | + CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.IORDY | + CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport, + ExtendedIdentify = + CommonTypes.Structs.Devices.ATA.Identify.ExtendedIdentifyBit.Words54to58Valid, + CurrentCylinders = (ushort)imageInfo.Cylinders, CurrentHeads = (ushort)imageInfo.Heads, CurrentSectorsPerTrack = (ushort)imageInfo.SectorsPerTrack, - CurrentSectors = (uint)imageInfo.Sectors, - LBASectors = (uint)imageInfo.Sectors, - DMASupported = Decoders.ATA.Identify.TransferMode.Mode0, - DMAActive = Decoders.ATA.Identify.TransferMode.Mode0 + CurrentSectors = (uint)imageInfo.Sectors, LBASectors = (uint)imageInfo.Sectors, + DMASupported = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0, + DMAActive = CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0 }; - if(string.IsNullOrEmpty(imageInfo.DriveManufacturer)) imageInfo.DriveManufacturer = "DiscImageChef"; + if(string.IsNullOrEmpty(imageInfo.DriveManufacturer)) + imageInfo.DriveManufacturer = "DiscImageChef"; - if(string.IsNullOrEmpty(imageInfo.DriveModel)) imageInfo.DriveModel = ""; + if(string.IsNullOrEmpty(imageInfo.DriveModel)) + imageInfo.DriveModel = ""; - if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision)) Version.GetVersion(); + if(string.IsNullOrEmpty(imageInfo.DriveFirmwareRevision)) + Version.GetVersion(); if(string.IsNullOrEmpty(imageInfo.DriveSerialNumber)) imageInfo.DriveSerialNumber = $"{new Random().NextDouble():16X}"; @@ -247,17 +276,21 @@ namespace DiscImageChef.DiscImages byte[] ataIdBytes = new byte[Marshal.SizeOf()]; IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512); System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, true); + System.Runtime.InteropServices.Marshal.Copy(ptr, ataIdBytes, 0, Marshal.SizeOf()); + System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr); Array.Copy(ScrambleAtaString(imageInfo.DriveManufacturer + " " + imageInfo.DriveModel, 40), 0, ataIdBytes, 27 * 2, 40); - Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8); - Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20); - Array.Copy(ataIdBytes, 0, header.identify, 0, 106); + + Array.Copy(ScrambleAtaString(imageInfo.DriveFirmwareRevision, 8), 0, ataIdBytes, 23 * 2, 8); + Array.Copy(ScrambleAtaString(imageInfo.DriveSerialNumber, 20), 0, ataIdBytes, 10 * 2, 20); + Array.Copy(ataIdBytes, 0, header.identify, 0, 106); } - else Array.Copy(identify, 0, header.identify, 0, 106); + else + Array.Copy(identify, 0, header.identify, 0, 106); byte[] hdr = new byte[Marshal.SizeOf()]; IntPtr hdrPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.SizeOf()); @@ -273,6 +306,7 @@ namespace DiscImageChef.DiscImages IsWriting = false; ErrorMessage = ""; + return true; } @@ -291,18 +325,21 @@ namespace DiscImageChef.DiscImages if(cylinders > ushort.MaxValue) { ErrorMessage = "Too many cylinders."; + return false; } if(heads > ushort.MaxValue) { ErrorMessage = "Too many heads."; + return false; } if(sectorsPerTrack > ushort.MaxValue) { ErrorMessage = "Too many sectors per track."; + return false; } @@ -316,12 +353,14 @@ namespace DiscImageChef.DiscImages public bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag) { ErrorMessage = "Unsupported feature"; + return false; } public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag) { ErrorMessage = "Unsupported feature"; + return false; } diff --git a/DiscImageChef.DiscImages/ZZZRawImage/Read.cs b/DiscImageChef.DiscImages/ZZZRawImage/Read.cs index 171020b18..1acca74c5 100644 --- a/DiscImageChef.DiscImages/ZZZRawImage/Read.cs +++ b/DiscImageChef.DiscImages/ZZZRawImage/Read.cs @@ -40,12 +40,14 @@ using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Exceptions; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.DVD; using DiscImageChef.Decoders.SCSI; using Schemas; using DMI = DiscImageChef.Decoders.Xbox.DMI; +using Inquiry = DiscImageChef.CommonTypes.Structs.Devices.SCSI.Inquiry; using Session = DiscImageChef.CommonTypes.Structs.Session; using TrackType = DiscImageChef.CommonTypes.Enums.TrackType; @@ -781,7 +783,7 @@ namespace DiscImageChef.DiscImages if (mediaTags.ContainsKey(MediaTagType.SCSI_INQUIRY)) { var devType = PeripheralDeviceTypes.DirectAccess; - Inquiry.SCSIInquiry? scsiInq = null; + Inquiry? scsiInq = null; if (mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out var inq)) { scsiInq = Inquiry.Decode(inq); @@ -858,7 +860,7 @@ namespace DiscImageChef.DiscImages // It's ATA, check tags if (mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out var identifyBuf)) { - var ataId = Decoders.ATA.Identify.Decode(identifyBuf); + var ataId = CommonTypes.Structs.Devices.ATA.Identify.Decode(identifyBuf); if (ataId.HasValue) { imageInfo.MediaType = (ushort) ataId.Value.GeneralConfiguration == 0x848A diff --git a/DiscImageChef.Gui/Forms/frmDecodeMediaTags.xeto.cs b/DiscImageChef.Gui/Forms/frmDecodeMediaTags.xeto.cs index 40b382bd5..9b5540f18 100644 --- a/DiscImageChef.Gui/Forms/frmDecodeMediaTags.xeto.cs +++ b/DiscImageChef.Gui/Forms/frmDecodeMediaTags.xeto.cs @@ -35,6 +35,7 @@ using System.Collections.ObjectModel; using System.Text; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.Bluray; using DiscImageChef.Decoders.CD; @@ -48,6 +49,7 @@ using BCA = DiscImageChef.Decoders.Bluray.BCA; using Cartridge = DiscImageChef.Decoders.Bluray.Cartridge; using DDS = DiscImageChef.Decoders.DVD.DDS; using DMI = DiscImageChef.Decoders.Xbox.DMI; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; using Spare = DiscImageChef.Decoders.DVD.Spare; namespace DiscImageChef.Gui.Forms diff --git a/DiscImageChef.Gui/Forms/frmMain.xeto.cs b/DiscImageChef.Gui/Forms/frmMain.xeto.cs index b2a63f30b..22e43957c 100644 --- a/DiscImageChef.Gui/Forms/frmMain.xeto.cs +++ b/DiscImageChef.Gui/Forms/frmMain.xeto.cs @@ -39,6 +39,7 @@ using DiscImageChef.CommonTypes; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Core.Media.Info; diff --git a/DiscImageChef.Gui/Panels/pnlImageInfo.xeto.cs b/DiscImageChef.Gui/Panels/pnlImageInfo.xeto.cs index 5efcefacc..eba4aca8a 100644 --- a/DiscImageChef.Gui/Panels/pnlImageInfo.xeto.cs +++ b/DiscImageChef.Gui/Panels/pnlImageInfo.xeto.cs @@ -37,6 +37,7 @@ using System.Text; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interfaces; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.DVD; using DiscImageChef.Decoders.SCSI; @@ -48,6 +49,7 @@ using Eto.Drawing; using Eto.Forms; using Eto.Serialization.Xaml; using Schemas; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; using Session = DiscImageChef.CommonTypes.Structs.Session; namespace DiscImageChef.Gui.Panels @@ -258,7 +260,7 @@ namespace DiscImageChef.Gui.Panels PeripheralDeviceTypes scsiDeviceType = PeripheralDeviceTypes.DirectAccess; byte[] scsiInquiryData = null; - Inquiry.SCSIInquiry? scsiInquiry = null; + CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry = null; Modes.DecodedMode? scsiMode = null; byte[] scsiModeSense6 = null; byte[] scsiModeSense10 = null; @@ -270,7 +272,7 @@ namespace DiscImageChef.Gui.Panels scsiDeviceType = (PeripheralDeviceTypes)(scsiInquiryData[0] & 0x1F); - scsiInquiry = Inquiry.Decode(scsiInquiryData); + scsiInquiry = CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(scsiInquiryData); } if(imageFormat.Info.ReadableMediaTags != null && diff --git a/DiscImageChef.Gui/Tabs/tabScsiInfo.xeto.cs b/DiscImageChef.Gui/Tabs/tabScsiInfo.xeto.cs index b22c7f794..af3c8a75d 100644 --- a/DiscImageChef.Gui/Tabs/tabScsiInfo.xeto.cs +++ b/DiscImageChef.Gui/Tabs/tabScsiInfo.xeto.cs @@ -34,11 +34,13 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using Eto.Forms; using Eto.Serialization.Xaml; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; namespace DiscImageChef.Gui.Tabs { @@ -46,7 +48,7 @@ namespace DiscImageChef.Gui.Tabs { private byte[] configuration; private Dictionary evpdPages; - private Inquiry.SCSIInquiry? inquiry; + private CommonTypes.Structs.Devices.SCSI.Inquiry? inquiry; private byte[] inquiryData; private Modes.DecodedMode? mode; private byte[] modeSense10; @@ -58,7 +60,7 @@ namespace DiscImageChef.Gui.Tabs XamlReader.Load(this); } - internal void LoadData(byte[] scsiInquiryData, Inquiry.SCSIInquiry? scsiInquiry, + internal void LoadData(byte[] scsiInquiryData, CommonTypes.Structs.Devices.SCSI.Inquiry? scsiInquiry, Dictionary scsiEvpdPages, Modes.DecodedMode? scsiMode, PeripheralDeviceTypes scsiType, byte[] scsiModeSense6, byte[] scsiModeSense10, diff --git a/DiscImageChef.sln.DotSettings b/DiscImageChef.sln.DotSettings index c538e0ffd..fc721bd9e 100644 --- a/DiscImageChef.sln.DotSettings +++ b/DiscImageChef.sln.DotSettings @@ -251,6 +251,7 @@ True True True + True True True True @@ -287,6 +288,7 @@ True True True + True True True True diff --git a/DiscImageChef/Commands/Device/DeviceReport.cs b/DiscImageChef/Commands/Device/DeviceReport.cs index 70f4e1f63..4944a5b4b 100644 --- a/DiscImageChef/Commands/Device/DeviceReport.cs +++ b/DiscImageChef/Commands/Device/DeviceReport.cs @@ -39,11 +39,12 @@ using System.Threading; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Interop; using DiscImageChef.CommonTypes.Metadata; +using DiscImageChef.CommonTypes.Structs.Devices.ATA; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Database; using DiscImageChef.Database.Models; -using DiscImageChef.Decoders.ATA; using DiscImageChef.Decoders.SCSI; using DiscImageChef.Devices; using Newtonsoft.Json; diff --git a/DiscImageChef/Commands/Device/Info.cs b/DiscImageChef/Commands/Device/Info.cs index dcb30c047..1c944aa43 100644 --- a/DiscImageChef/Commands/Device/Info.cs +++ b/DiscImageChef/Commands/Device/Info.cs @@ -35,6 +35,7 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Database; @@ -47,6 +48,7 @@ using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Devices; using Command = System.CommandLine.Command; using DeviceInfo = DiscImageChef.Core.Devices.Info.DeviceInfo; +using Inquiry = DiscImageChef.Decoders.SCSI.Inquiry; namespace DiscImageChef.Commands.Device { diff --git a/DiscImageChef/Commands/Media/Info.cs b/DiscImageChef/Commands/Media/Info.cs index 19e9f0854..39b4d795d 100644 --- a/DiscImageChef/Commands/Media/Info.cs +++ b/DiscImageChef/Commands/Media/Info.cs @@ -37,6 +37,7 @@ using System.CommandLine.Invocation; using System.Linq; using DiscImageChef.CommonTypes.Enums; using DiscImageChef.CommonTypes.Structs; +using DiscImageChef.CommonTypes.Structs.Devices.SCSI; using DiscImageChef.Console; using DiscImageChef.Core; using DiscImageChef.Core.Devices.Dumping; @@ -46,7 +47,6 @@ using DiscImageChef.Database.Models; using DiscImageChef.Decoders.Bluray; using DiscImageChef.Decoders.CD; using DiscImageChef.Decoders.DVD; -using DiscImageChef.Decoders.SCSI; using DiscImageChef.Decoders.SCSI.MMC; using DiscImageChef.Decoders.SCSI.SSC; using DiscImageChef.Decoders.Xbox;