diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml index 484e03fbd..20ad456dc 100644 --- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml +++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml @@ -235,6 +235,7 @@ + diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs index 5bd21a5f6..d6faa5977 100644 --- a/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/Dump.cs @@ -1645,111 +1645,9 @@ namespace DiscImageChef.Core.Devices.Dumping EndProgress?.Invoke(); // TODO: Enable when underlying images support lead-outs - /* - if(persistent) - { - UpdateStatus?.Invoke("Reading lead-outs"); - dumpLog.WriteLine("Reading lead-outs"); - - InitProgress?.Invoke(); - foreach(Tuple leadout in leadOutExtents.ToArray()) - for(ulong i = leadout.Item1; i <= leadout.Item2; i++) - { - if(aborted) - { - currentTry.Extents = ExtentsConverter.ToMetadata(extents); - dumpLog.WriteLine("Aborted!"); - break; - } - - double cmdDuration = 0; - - #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator - if(currentSpeed > maxSpeed && currentSpeed != 0) maxSpeed = currentSpeed; - if(currentSpeed < minSpeed && currentSpeed != 0) minSpeed = currentSpeed; - #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator - - PulseProgress?.Invoke(string.Format("Reading sector {0} at lead-out ({1:F3} MiB/sec.)", i, blocks, - currentSpeed)); - - if(readcd) - { - sense = dev.ReadCd(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, - MmcSectorTypes.AllTypes, false, false, true, MmcHeaderCodes.AllHeaders, - true, true, MmcErrorField.None, supportedSubchannel, dev.Timeout, - out cmdDuration); - totalDuration += cmdDuration; - } - else if(read16) - sense = dev.Read16(out cmdBuf, out senseBuf, 0, false, true, false, i, blockSize, 0, 1, - false, dev.Timeout, out cmdDuration); - else if(read12) - sense = dev.Read12(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, - blockSize, 0, 1, false, dev.Timeout, out cmdDuration); - else if(read10) - sense = dev.Read10(out cmdBuf, out senseBuf, 0, false, true, false, false, (uint)i, - blockSize, 0, 1, dev.Timeout, out cmdDuration); - else if(read6) - sense = dev.Read6(out cmdBuf, out senseBuf, (uint)i, blockSize, 1, dev.Timeout, - out cmdDuration); - - if(!sense && !dev.Error) - { - mhddLog.Write(i, cmdDuration); - ibgLog.Write(i, currentSpeed * 1024); - extents.Add(i, blocksToRead, true); - leadOutExtents.Remove(i); - DateTime writeStart = DateTime.Now; - if(supportedSubchannel != MmcSubchannel.None) - { - byte[] data = new byte[SECTOR_SIZE * blocksToRead]; - byte[] sub = new byte[subSize * blocksToRead]; - - for(int b = 0; b < blocksToRead; b++) - { - Array.Copy(cmdBuf, (int)(0 + b * blockSize), data, SECTOR_SIZE * b, - SECTOR_SIZE); - Array.Copy(cmdBuf, (int)(SECTOR_SIZE + b * blockSize), sub, subSize * b, - subSize); - } - - outputPlugin.WriteSectorsLong(data, i, blocksToRead); - outputPlugin.WriteSectorsTag(sub, i, blocksToRead, SectorTagType.CdSectorSubchannel); - } - else outputPlugin.WriteSectors(cmdBuf, i, blocksToRead); - - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - } - else - { - // TODO: Reset device after X errors - if(stopOnError) return; // TODO: Return more cleanly - - // Write empty data - DateTime writeStart = DateTime.Now; - if(supportedSubchannel != MmcSubchannel.None) - { - outputPlugin.WriteSectorsLong(new byte[SECTOR_SIZE * skip], i, 1); - outputPlugin.WriteSectorsTag(new byte[subSize * skip], i, 1, - SectorTagType.CdSectorSubchannel); - } - else outputPlugin.WriteSectors(new byte[blockSize * skip], i, 1); - - imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; - - mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); - - ibgLog.Write(i, 0); - } - - double newSpeed = - (double)blockSize * blocksToRead / 1048576 / (cmdDuration / 1000); - if(!double.IsInfinity(newSpeed)) currentSpeed = newSpeed; - resume.NextBlock = i + 1; - } - - EndProgress?.Invoke(); - }*/ + DumpCdLeadOuts(blocks, blockSize, ref currentSpeed, currentTry, extents, ibgLog, ref imageWriteDuration, + leadOutExtents, ref maxSpeed, mhddLog, ref minSpeed, read6, read10, read12, read16, readcd, + supportedSubchannel, subSize, ref totalDuration); end = DateTime.UtcNow; mhddLog.Close(); diff --git a/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs b/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs new file mode 100644 index 000000000..6b7f18878 --- /dev/null +++ b/DiscImageChef.Core/Devices/Dumping/CompactDisc/LeadOuts.cs @@ -0,0 +1,198 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : CompactDisc.cs +// Author(s) : Natalia Portillo +// +// Component : Core algorithms. +// +// --[ Description ] ---------------------------------------------------------- +// +// Dumps CDs and DDCDs. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2019 Natalia Portillo +// ****************************************************************************/ + +using System; +using DiscImageChef.CommonTypes.Enums; +using DiscImageChef.CommonTypes.Extents; +using DiscImageChef.Core.Logging; +using DiscImageChef.Devices; +using Schemas; + +// ReSharper disable JoinDeclarationAndInitializer +// ReSharper disable InlineOutVariableDeclaration +// ReSharper disable TooWideLocalVariableScope + +namespace DiscImageChef.Core.Devices.Dumping +{ + partial class Dump + { + /// + /// Total number of positive sectors + /// Size of the read sector in bytes + /// Current read speed + /// Current dump hardware try + /// Extents + /// IMGBurn log + /// Duration of image write + /// Lead-out extents + /// Maximum speed + /// MHDD log + /// Minimum speed + /// Device supports READ(6) + /// Device supports READ(10) + /// Device supports READ(12) + /// Device supports READ(16) + /// Device supports READ CD + /// Drive's maximum supported subchannel + /// Subchannel size in bytes + /// Total commands duration + void DumpCdLeadOuts(ulong blocks, uint blockSize, ref double currentSpeed, DumpHardwareType currentTry, + ExtentsULong extents, IbgLog ibgLog, ref double imageWriteDuration, + ExtentsULong leadOutExtents, ref double maxSpeed, MhddLog mhddLog, ref double minSpeed, + bool read6, bool read10, bool read12, bool read16, bool readcd, + MmcSubchannel supportedSubchannel, uint subSize, ref double totalDuration) + { + byte[] cmdBuf = null; // Data buffer + const uint sectorSize = 2352; // Full sector size + bool sense = true; // Sense indicator + + UpdateStatus?.Invoke("Reading lead-outs"); + _dumpLog.WriteLine("Reading lead-outs"); + + InitProgress?.Invoke(); + + foreach((ulong item1, ulong item2) in leadOutExtents.ToArray()) + for(ulong i = item1; i <= item2; i++) + { + if(_aborted) + { + currentTry.Extents = ExtentsConverter.ToMetadata(extents); + _dumpLog.WriteLine("Aborted!"); + + break; + } + + double cmdDuration = 0; + + #pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator + + // ReSharper disable CompareOfFloatsByEqualityOperator + if(currentSpeed > maxSpeed && + currentSpeed != 0) + maxSpeed = currentSpeed; + + if(currentSpeed < minSpeed && + currentSpeed != 0) + minSpeed = currentSpeed; + + // ReSharper restore CompareOfFloatsByEqualityOperator + #pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator + + PulseProgress?.Invoke($"Reading sector {i} at lead-out ({currentSpeed:F3} MiB/sec.)"); + + if(readcd) + { + sense = _dev.ReadCd(out cmdBuf, out _, (uint)i, blockSize, 1, MmcSectorTypes.AllTypes, false, + false, true, MmcHeaderCodes.AllHeaders, true, true, MmcErrorField.None, + supportedSubchannel, _dev.Timeout, out cmdDuration); + + totalDuration += cmdDuration; + } + else if(read16) + sense = _dev.Read16(out cmdBuf, out _, 0, false, true, false, i, blockSize, 0, 1, false, + _dev.Timeout, out cmdDuration); + else if(read12) + sense = _dev.Read12(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1, + false, _dev.Timeout, out cmdDuration); + else if(read10) + sense = _dev.Read10(out cmdBuf, out _, 0, false, true, false, false, (uint)i, blockSize, 0, 1, + _dev.Timeout, out cmdDuration); + else if(read6) + sense = _dev.Read6(out cmdBuf, out _, (uint)i, blockSize, 1, _dev.Timeout, out cmdDuration); + + if(!sense && + !_dev.Error) + { + mhddLog.Write(i, cmdDuration); + ibgLog.Write(i, currentSpeed * 1024); + extents.Add(i, _maximumReadable, true); + leadOutExtents.Remove(i); + DateTime writeStart = DateTime.Now; + + if(supportedSubchannel != MmcSubchannel.None) + { + byte[] data = new byte[sectorSize * _maximumReadable]; + byte[] sub = new byte[subSize * _maximumReadable]; + + for(int b = 0; b < _maximumReadable; b++) + { + Array.Copy(cmdBuf, (int)(0 + (b * blockSize)), data, sectorSize * b, sectorSize); + + Array.Copy(cmdBuf, (int)(sectorSize + (b * blockSize)), sub, subSize * b, subSize); + } + + _outputPlugin.WriteSectorsLong(data, i, _maximumReadable); + _outputPlugin.WriteSectorsTag(sub, i, _maximumReadable, SectorTagType.CdSectorSubchannel); + } + else + _outputPlugin.WriteSectors(cmdBuf, i, _maximumReadable); + + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + } + else + { + // TODO: Reset device after X errors + if(_stopOnError) + return; // TODO: Return more cleanly + + // Write empty data + DateTime writeStart = DateTime.Now; + + if(supportedSubchannel != MmcSubchannel.None) + { + _outputPlugin.WriteSectorsLong(new byte[sectorSize * _skip], i, 1); + + _outputPlugin.WriteSectorsTag(new byte[subSize * _skip], i, 1, + SectorTagType.CdSectorSubchannel); + } + else + _outputPlugin.WriteSectors(new byte[blockSize * _skip], i, 1); + + imageWriteDuration += (DateTime.Now - writeStart).TotalSeconds; + + mhddLog.Write(i, cmdDuration < 500 ? 65535 : cmdDuration); + + ibgLog.Write(i, 0); + } + + double newSpeed = ((double)blockSize * _maximumReadable) / 1048576 / (cmdDuration / 1000); + + if(!double.IsInfinity(newSpeed)) + currentSpeed = newSpeed; + + _resume.NextBlock = i + 1; + } + + EndProgress?.Invoke(); + } + } +} \ No newline at end of file diff --git a/DiscImageChef.Core/DiscImageChef.Core.csproj b/DiscImageChef.Core/DiscImageChef.Core.csproj index faa12d05d..0b65444b4 100644 --- a/DiscImageChef.Core/DiscImageChef.Core.csproj +++ b/DiscImageChef.Core/DiscImageChef.Core.csproj @@ -48,6 +48,7 @@ +