mirror of
https://github.com/aaru-dps/Aaru.git
synced 2026-07-08 18:16:24 +00:00
Add error recovery support and related logging
This commit is contained in:
@@ -45,6 +45,7 @@ using Aaru.Core.Graphics;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Decoders.ATA;
|
||||
using Aaru.Decoders.PCMCIA;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Identify = Aaru.CommonTypes.Structs.Devices.ATA.Identify;
|
||||
@@ -250,6 +251,8 @@ public partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
// Setting geometry
|
||||
outputFormat.SetGeometry(cylinders, heads, sectors);
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ using Aaru.Core.Media.Detection;
|
||||
using Aaru.Database.Models;
|
||||
using Aaru.Decoders.CD;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Spectre.Console;
|
||||
@@ -971,6 +972,8 @@ sealed partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputOptical is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
ErrorNumber errno = outputOptical.ReadMediaTag(MediaTagType.CD_MCN, out byte[] mcnBytes);
|
||||
|
||||
if(errno == ErrorNumber.NoError) mcn = Encoding.ASCII.GetString(mcnBytes);
|
||||
@@ -1083,9 +1086,8 @@ sealed partial class Dump
|
||||
foreach(int sub in _resume.BadSubchannels) subchannelExtents.Add(sub);
|
||||
|
||||
if(_resume.NextBlock < blocks)
|
||||
{
|
||||
for(ulong i = _resume.NextBlock; i < blocks; i++) subchannelExtents.Add((int)i);
|
||||
}
|
||||
for(ulong i = _resume.NextBlock; i < blocks; i++)
|
||||
subchannelExtents.Add((int)i);
|
||||
}
|
||||
|
||||
if(_resume.NextBlock > 0)
|
||||
@@ -1511,9 +1513,8 @@ sealed partial class Dump
|
||||
supportsLongSectors);
|
||||
|
||||
foreach(Tuple<ulong, ulong> leadoutExtent in leadOutExtents.ToArray())
|
||||
{
|
||||
for(ulong e = leadoutExtent.Item1; e <= leadoutExtent.Item2; e++) subchannelExtents.Remove((int)e);
|
||||
}
|
||||
for(ulong e = leadoutExtent.Item1; e <= leadoutExtent.Item2; e++)
|
||||
subchannelExtents.Remove((int)e);
|
||||
|
||||
if(subchannelExtents.Count > 0 && _retryPasses > 0 && _retrySubchannel)
|
||||
{
|
||||
|
||||
@@ -83,6 +83,7 @@ public partial class Dump
|
||||
readonly Stopwatch _dumpStopwatch;
|
||||
readonly Encoding _encoding;
|
||||
readonly ErrorLog _errorLog;
|
||||
readonly int _errorRecovery;
|
||||
readonly bool _fixSubchannel;
|
||||
readonly bool _fixSubchannelCrc;
|
||||
readonly bool _fixSubchannelPosition;
|
||||
@@ -103,6 +104,7 @@ public partial class Dump
|
||||
readonly bool _retrySubchannel;
|
||||
readonly Stopwatch _sidecarStopwatch;
|
||||
readonly Stopwatch _speedStopwatch;
|
||||
readonly bool _startReverse;
|
||||
readonly bool _stopOnError;
|
||||
readonly bool _storeEncrypted;
|
||||
readonly DumpSubchannel _subchannel;
|
||||
@@ -125,7 +127,6 @@ public partial class Dump
|
||||
bool _skipCdireadyHole;
|
||||
int _speed;
|
||||
int _speedMultiplier;
|
||||
readonly bool _startReverse;
|
||||
bool _supportsPlextorD8;
|
||||
bool _useBufferedReads;
|
||||
|
||||
@@ -183,7 +184,7 @@ public partial class Dump
|
||||
bool fixSubchannel, bool fixSubchannelCrc, bool skipCdireadyHole, ErrorLog errorLog,
|
||||
bool generateSubchannels, uint maximumReadable, bool useBufferedReads, bool storeEncrypted,
|
||||
bool titleKeys, uint ignoreCdrRunOuts, bool createGraph, uint dimensions, bool paranoia,
|
||||
bool cureParanoia, bool bypassWiiDecryption, bool startReverse)
|
||||
bool cureParanoia, bool bypassWiiDecryption, bool startReverse, int errorRecovery)
|
||||
{
|
||||
_doResume = doResume;
|
||||
_dev = dev;
|
||||
@@ -229,6 +230,7 @@ public partial class Dump
|
||||
_cureParanoia = cureParanoia;
|
||||
_bypassWiiDecryption = bypassWiiDecryption;
|
||||
_startReverse = startReverse;
|
||||
_errorRecovery = errorRecovery;
|
||||
_dumpStopwatch = new Stopwatch();
|
||||
_sidecarStopwatch = new Stopwatch();
|
||||
_speedStopwatch = new Stopwatch();
|
||||
|
||||
@@ -46,6 +46,7 @@ using Aaru.Core.Graphics;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Version = Aaru.CommonTypes.Interop.Version;
|
||||
@@ -223,6 +224,8 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
_dumpStopwatch.Restart();
|
||||
double imageWriteDuration = 0;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ using Aaru.Core.Graphics;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Version = Aaru.CommonTypes.Interop.Version;
|
||||
@@ -142,6 +143,8 @@ public partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
_dumpStopwatch.Restart();
|
||||
double imageWriteDuration = 0;
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ using Aaru.Core.Graphics;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Track = Aaru.CommonTypes.Structs.Track;
|
||||
@@ -169,6 +170,8 @@ public partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputOptical is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
_dumpStopwatch.Restart();
|
||||
double imageWriteDuration = 0;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ using Aaru.Decoders.SCSI;
|
||||
using Aaru.Decoders.SCSI.SSC;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Helpers;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using TapeFile = Aaru.CommonTypes.Structs.TapeFile;
|
||||
@@ -283,8 +284,9 @@ partial class Dump
|
||||
Modes.DecodedMode? decMode = null;
|
||||
|
||||
if(!sense && !_dev.Error)
|
||||
if(Modes.DecodeMode10(cmdBuf, _dev.ScsiType).HasValue)
|
||||
decMode = Modes.DecodeMode10(cmdBuf, _dev.ScsiType);
|
||||
{
|
||||
if(Modes.DecodeMode10(cmdBuf, _dev.ScsiType).HasValue) decMode = Modes.DecodeMode10(cmdBuf, _dev.ScsiType);
|
||||
}
|
||||
|
||||
UpdateStatus?.Invoke(Localization.Core.Requesting_MODE_SENSE_6);
|
||||
|
||||
@@ -312,8 +314,9 @@ partial class Dump
|
||||
if(sense || _dev.Error) sense = _dev.ModeSense(out cmdBuf, out senseBuf, 5, out duration);
|
||||
|
||||
if(!sense && !_dev.Error)
|
||||
if(Modes.DecodeMode6(cmdBuf, _dev.ScsiType).HasValue)
|
||||
decMode = Modes.DecodeMode6(cmdBuf, _dev.ScsiType);
|
||||
{
|
||||
if(Modes.DecodeMode6(cmdBuf, _dev.ScsiType).HasValue) decMode = Modes.DecodeMode6(cmdBuf, _dev.ScsiType);
|
||||
}
|
||||
|
||||
// TODO: Check partitions page
|
||||
if(decMode.HasValue)
|
||||
@@ -834,6 +837,8 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputTape is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
_dumpStopwatch.Restart();
|
||||
var mhddLog = new MhddLog(_outputPrefix + ".mhddlog.bin", _dev, blocks, blockSize, 1, _private);
|
||||
var ibgLog = new IbgLog(_outputPrefix + ".ibg", 0x0008);
|
||||
|
||||
@@ -35,7 +35,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.AaruMetadata;
|
||||
@@ -76,16 +75,16 @@ partial class Dump
|
||||
DVDDecryption dvdDecrypt = null)
|
||||
{
|
||||
bool sense;
|
||||
byte scsiMediumType = 0;
|
||||
byte scsiDensityCode = 0;
|
||||
byte scsiMediumType = 0;
|
||||
byte scsiDensityCode = 0;
|
||||
var containsFloppyPage = false;
|
||||
const ushort sbcProfile = 0x0001;
|
||||
const uint DvdLeadinSectors = 4096; // Usable Lead-in before LBA 0 per DVD spec (PSN 0x02F000–0x02FFFF)
|
||||
double totalDuration = 0;
|
||||
double currentSpeed = 0;
|
||||
double maxSpeed = double.MinValue;
|
||||
double minSpeed = double.MaxValue;
|
||||
Modes.DecodedMode? decMode = null;
|
||||
const ushort sbcProfile = 0x0001;
|
||||
const uint DvdLeadinSectors = 4096; // Usable Lead-in before LBA 0 per DVD spec (PSN 0x02F000–0x02FFFF)
|
||||
double totalDuration = 0;
|
||||
double currentSpeed = 0;
|
||||
double maxSpeed = double.MinValue;
|
||||
double minSpeed = double.MaxValue;
|
||||
Modes.DecodedMode? decMode = null;
|
||||
bool ret;
|
||||
ExtentsULong blankExtents = null;
|
||||
var outputFormat = _outputPlugin as IWritableImage;
|
||||
@@ -325,9 +324,9 @@ partial class Dump
|
||||
|
||||
scsiReader.layerbreak = decodedPfi?.Layer0EndPSN ?? 0;
|
||||
if(scsiReader.layerbreak == 0) scsiReader.layerbreak = decodedPfi?.DataAreaEndPSN ?? 0;
|
||||
scsiReader.otp = decodedPfi?.TrackPath ?? false;
|
||||
scsiReader.otp = decodedPfi?.TrackPath ?? false;
|
||||
|
||||
if(scsiReader.HldtstReadRaw) blocksToRead = 1;
|
||||
if(scsiReader.HldtstReadRaw) blocksToRead = 1;
|
||||
if(scsiReader.OmniDriveReadRaw) blocksToRead = 31;
|
||||
|
||||
UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_raw_bytes_1_cooked_bytes_per_sector,
|
||||
@@ -345,7 +344,8 @@ partial class Dump
|
||||
{
|
||||
if(!scsiReader.OmniDriveReadRaw)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke(Localization.Core.Dumping_Nintendo_GameCube_or_Wii_discs_is_not_yet_implemented);
|
||||
StoppingErrorMessage?.Invoke(Localization.Core
|
||||
.Dumping_Nintendo_GameCube_or_Wii_discs_is_not_yet_implemented);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -410,6 +410,8 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
imageCreated = true;
|
||||
}
|
||||
|
||||
@@ -428,13 +430,13 @@ partial class Dump
|
||||
if(decodedPfi.HasValue) nominalNegativeSectors = decodedPfi.Value.DataAreaStartPSN;
|
||||
|
||||
if(scsiReader.OmniDriveReadRaw &&
|
||||
decodedPfi.HasValue &&
|
||||
((dskType >= MediaType.DVDROM && dskType <= MediaType.DVDDownload)
|
||||
|| dskType == MediaType.PS2DVD
|
||||
|| dskType == MediaType.PS3DVD
|
||||
|| dskType == MediaType.Nuon
|
||||
|| dskType == MediaType.GOD
|
||||
|| dskType == MediaType.WOD))
|
||||
decodedPfi.HasValue &&
|
||||
(dskType >= MediaType.DVDROM && dskType <= MediaType.DVDDownload ||
|
||||
dskType == MediaType.PS2DVD ||
|
||||
dskType == MediaType.PS3DVD ||
|
||||
dskType == MediaType.Nuon ||
|
||||
dskType == MediaType.GOD ||
|
||||
dskType == MediaType.WOD))
|
||||
nominalNegativeSectors = Math.Min(nominalNegativeSectors, DvdLeadinSectors);
|
||||
|
||||
mediaTags.TryGetValue(MediaTagType.BD_DI, out byte[] di);
|
||||
@@ -587,6 +589,9 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0)
|
||||
aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
imageCreated = true;
|
||||
|
||||
#if DEBUG
|
||||
@@ -722,6 +727,8 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
if(writeSingleOpticalTrack)
|
||||
{
|
||||
UpdateStatus?.Invoke(Localization.Core
|
||||
@@ -811,8 +818,7 @@ partial class Dump
|
||||
|
||||
var newTrim = false;
|
||||
|
||||
if(ngcwMode && !InitializeNgcwContext(dskType, scsiReader, outputFormat))
|
||||
return;
|
||||
if(ngcwMode && !InitializeNgcwContext(dskType, scsiReader, outputFormat)) return;
|
||||
|
||||
if(mediaTags.TryGetValue(MediaTagType.DVD_CMI, out byte[] cmi) &&
|
||||
Settings.Settings.Current.EnableDecryption &&
|
||||
@@ -849,33 +855,35 @@ partial class Dump
|
||||
|
||||
if(scsiReader.HldtstReadRaw || scsiReader.ReadBuffer3CReadRaw || scsiReader.OmniDriveReadRaw)
|
||||
{
|
||||
uint nominalForRawDvd = 0;
|
||||
uint nominalForRawDvd = 0;
|
||||
uint overflowForRawDvd = 0;
|
||||
|
||||
if(scsiReader.OmniDriveReadRaw && outputFormat is IWritableOpticalImage optImg)
|
||||
{
|
||||
if(optImg.OpticalCapabilities.HasFlag(OpticalImageCapabilities.CanStoreNegativeSectors))
|
||||
nominalForRawDvd = nominalNegativeSectors;
|
||||
|
||||
if(optImg.OpticalCapabilities.HasFlag(OpticalImageCapabilities.CanStoreOverflowSectors))
|
||||
overflowForRawDvd = 100u;
|
||||
}
|
||||
|
||||
ReadRawDvdData(blocks,
|
||||
blocksToRead,
|
||||
blockSize,
|
||||
currentTry,
|
||||
extents,
|
||||
ref currentSpeed,
|
||||
ref minSpeed,
|
||||
ref maxSpeed,
|
||||
ref totalDuration,
|
||||
scsiReader,
|
||||
mhddLog,
|
||||
ibgLog,
|
||||
ref imageWriteDuration,
|
||||
ref newTrim,
|
||||
discKey ?? null,
|
||||
nominalForRawDvd,
|
||||
overflowForRawDvd);
|
||||
blocksToRead,
|
||||
blockSize,
|
||||
currentTry,
|
||||
extents,
|
||||
ref currentSpeed,
|
||||
ref minSpeed,
|
||||
ref maxSpeed,
|
||||
ref totalDuration,
|
||||
scsiReader,
|
||||
mhddLog,
|
||||
ibgLog,
|
||||
ref imageWriteDuration,
|
||||
ref newTrim,
|
||||
discKey ?? null,
|
||||
nominalForRawDvd,
|
||||
overflowForRawDvd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -962,8 +970,8 @@ partial class Dump
|
||||
|
||||
// Unnecessary since keys are already in raw data
|
||||
!scsiReader.ReadBuffer3CReadRaw &&
|
||||
!scsiReader.OmniDriveReadRaw &&
|
||||
!scsiReader.HldtstReadRaw &&
|
||||
!scsiReader.OmniDriveReadRaw &&
|
||||
!scsiReader.HldtstReadRaw &&
|
||||
mediaTag is not null)
|
||||
RetryTitleKeys(dvdDecrypt, mediaTag, ref totalDuration);
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ using Aaru.Core.Graphics;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Decoders.MMC;
|
||||
using Aaru.Decoders.SecureDigital;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using CSD = Aaru.Decoders.MMC.CSD;
|
||||
@@ -457,6 +458,8 @@ public partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
if(cid != null)
|
||||
{
|
||||
switch(_dev.Type)
|
||||
|
||||
@@ -48,6 +48,7 @@ using Aaru.Decoders.DVD;
|
||||
using Aaru.Decoders.SCSI;
|
||||
using Aaru.Decoders.Xbox;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Images;
|
||||
using Aaru.Logging;
|
||||
using Humanizer;
|
||||
using Device = Aaru.Devices.Remote.Device;
|
||||
@@ -515,6 +516,8 @@ partial class Dump
|
||||
return;
|
||||
}
|
||||
|
||||
if(outputFormat is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
_dumpStopwatch.Restart();
|
||||
double imageWriteDuration = 0;
|
||||
|
||||
@@ -1088,9 +1091,8 @@ partial class Dump
|
||||
List<ulong> tmpList = [];
|
||||
|
||||
foreach(ulong ur in _resume.BadBlocks)
|
||||
{
|
||||
for(ulong i = ur; i < ur + blocksToRead; i++) tmpList.Add(i);
|
||||
}
|
||||
for(ulong i = ur; i < ur + blocksToRead; i++)
|
||||
tmpList.Add(i);
|
||||
|
||||
tmpList.Sort();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ public partial class Convert
|
||||
readonly string _driveManufacturer;
|
||||
readonly string _driveModel;
|
||||
readonly string _driveSerialNumber;
|
||||
readonly int _errorRecovery;
|
||||
readonly bool _fixSubchannel;
|
||||
readonly bool _fixSubchannelCrc;
|
||||
readonly bool _fixSubchannelPosition;
|
||||
@@ -64,7 +65,7 @@ public partial class Convert
|
||||
PluginRegister plugins, bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc,
|
||||
bool generateSubchannels, (uint cylinders, uint heads, uint sectors)? geometryValues, Resume resume,
|
||||
Metadata sidecar, bool bypassPs3Decryption, bool bypassWiiuDecryption, bool bypassWiiDecryption,
|
||||
string inputPath = null)
|
||||
string inputPath, int errorRecovery)
|
||||
{
|
||||
_inputImage = inputImage;
|
||||
_outputImage = outputImage;
|
||||
@@ -102,6 +103,7 @@ public partial class Convert
|
||||
_bypassWiiuDecryption = bypassWiiuDecryption;
|
||||
_bypassWiiDecryption = bypassWiiDecryption;
|
||||
_inputPath = inputPath;
|
||||
_errorRecovery = errorRecovery;
|
||||
}
|
||||
|
||||
public ErrorNumber Start()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.Images;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Core.Image;
|
||||
@@ -26,6 +27,8 @@ public partial class Convert
|
||||
_overflowSectors,
|
||||
_inputImage.Info.SectorSize);
|
||||
|
||||
if(_outputImage is AaruFormat aif && _errorRecovery > 0) aif.SetErasureCodingAuto((byte)_errorRecovery);
|
||||
|
||||
EndProgress?.Invoke();
|
||||
|
||||
if(created) return ErrorNumber.NoError;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Images;
|
||||
using Aaru.Localization;
|
||||
|
||||
namespace Aaru.Core.Image;
|
||||
@@ -23,6 +24,8 @@ public sealed partial class Merger
|
||||
overflowSectors,
|
||||
primaryImage.Info.SectorSize);
|
||||
|
||||
if(outputImage is AaruFormat aif && errorRecovery > 0) aif.SetErasureCodingAuto((byte)errorRecovery);
|
||||
|
||||
EndProgress?.Invoke();
|
||||
|
||||
if(created) return ErrorNumber.NoError;
|
||||
|
||||
@@ -6,6 +6,7 @@ using Aaru.CommonTypes.AaruMetadata;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Images;
|
||||
using Aaru.Localization;
|
||||
using File = System.IO.File;
|
||||
using MediaType = Aaru.CommonTypes.MediaType;
|
||||
@@ -49,7 +50,8 @@ public sealed partial class Merger
|
||||
bool generateSubchannels,
|
||||
bool decrypt,
|
||||
bool ignoreNegativeSectors,
|
||||
bool ignoreOverflowSectors
|
||||
bool ignoreOverflowSectors,
|
||||
int errorRecovery
|
||||
)
|
||||
{
|
||||
const string MODULE_NAME = "Image merger";
|
||||
@@ -144,6 +146,23 @@ public sealed partial class Merger
|
||||
|
||||
UpdateStatus?.Invoke(string.Format(UI.Output_image_format_0, outputFormat.Name));
|
||||
|
||||
if(errorRecovery > 0)
|
||||
{
|
||||
if(outputFormat is not AaruFormat)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke(UI.Error_recovery_is_only_supported_in_AaruFormat);
|
||||
|
||||
return ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
if(errorRecovery > 100)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke(UI.Maximum_error_recovery_is_100);
|
||||
|
||||
return ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
if(primaryImage.Info.Sectors != secondaryImage.Info.Sectors)
|
||||
{
|
||||
StoppingErrorMessage?.Invoke(UI.Images_have_different_number_of_sectors_cannot_merge);
|
||||
@@ -220,13 +239,13 @@ public sealed partial class Merger
|
||||
InitProgress?.Invoke();
|
||||
PulseProgress?.Invoke(UI.Calculating_sectors_to_merge);
|
||||
|
||||
List<ulong> sectorsToCopyFromSecondImage =
|
||||
CalculateSectorsToCopy(primaryImage, secondaryImage, primaryResume, secondaryResume, overrideSectorsList);
|
||||
List<ulong> sectorsToCopyFromSecondImage =
|
||||
CalculateSectorsToCopy(primaryImage, secondaryImage, primaryResume, secondaryResume, overrideSectorsList);
|
||||
|
||||
EndProgress?.Invoke();
|
||||
|
||||
// Flux images might contain no decoded data, which results in a sector count of 0. We allow this if the image contains flux.
|
||||
var containsFlux = primaryImage is IFluxImage || secondaryImage is IFluxImage;
|
||||
bool containsFlux = primaryImage is IFluxImage || secondaryImage is IFluxImage;
|
||||
|
||||
if(sectorsToCopyFromSecondImage.Count == 0 && !containsFlux)
|
||||
{
|
||||
@@ -349,7 +368,7 @@ public sealed partial class Merger
|
||||
|
||||
if(primaryImage is IFluxImage primaryFlux && outputFormat is IWritableFluxImage outputFlux)
|
||||
{
|
||||
IFluxImage secondaryFlux = secondaryImage as IFluxImage;
|
||||
var secondaryFlux = secondaryImage as IFluxImage;
|
||||
|
||||
UpdateStatus?.Invoke(secondaryFlux != null
|
||||
? UI.Flux_merge_primary_then_secondary_appended
|
||||
|
||||
@@ -352,7 +352,8 @@ public sealed partial class ImageConvertViewModel : ViewModelBase
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
SourceText);
|
||||
SourceText,
|
||||
0);
|
||||
|
||||
// Prepare UI
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
|
||||
@@ -762,7 +762,8 @@ public sealed partial class MediaDumpViewModel : ViewModelBase
|
||||
Paranoia,
|
||||
CureParanoia,
|
||||
BypassWiiDecryption,
|
||||
false);
|
||||
false,
|
||||
0);
|
||||
|
||||
new Thread(DoWork).Start();
|
||||
}
|
||||
|
||||
18
Aaru.Localization/UI.Designer.cs
generated
18
Aaru.Localization/UI.Designer.cs
generated
@@ -11231,5 +11231,23 @@ namespace Aaru.Localization {
|
||||
return ResourceManager.GetString("Start_reverse_error_retry", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Add_error_recovery {
|
||||
get {
|
||||
return ResourceManager.GetString("Add_error_recovery", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Error_recovery_is_only_supported_in_AaruFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_recovery_is_only_supported_in_AaruFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Maximum_error_recovery_is_100 {
|
||||
get {
|
||||
return ResourceManager.GetString("Maximum_error_recovery_is_100", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5611,4 +5611,13 @@ Probadores:
|
||||
<data name="Start_reverse_error_retry" xml:space="preserve">
|
||||
<value>Comenzar reintentos de errores al revés.</value>
|
||||
</data>
|
||||
<data name="Add_error_recovery" xml:space="preserve">
|
||||
<value>Añade el porcentaje especificado de recuperación de errores (sólo AaruFormat).</value>
|
||||
</data>
|
||||
<data name="Error_recovery_is_only_supported_in_AaruFormat" xml:space="preserve">
|
||||
<value>La recuperación de errores solo está soportada en AaruFormat</value>
|
||||
</data>
|
||||
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
||||
<value>La recuperación de errores máxima es 100%</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -5695,4 +5695,13 @@ Do you want to continue?</value>
|
||||
<data name="Start_reverse_error_retry" xml:space="preserve">
|
||||
<value>Start error retrying in reverse.</value>
|
||||
</data>
|
||||
<data name="Add_error_recovery" xml:space="preserve">
|
||||
<value>Add the specified percentage of error recovery (only AaruFormat).</value>
|
||||
</data>
|
||||
<data name="Error_recovery_is_only_supported_in_AaruFormat" xml:space="preserve">
|
||||
<value>Error recovery is only supported in AaruFormat</value>
|
||||
</data>
|
||||
<data name="Maximum_error_recovery_is_100" xml:space="preserve">
|
||||
<value>Maximum error recovery is 100%</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -44,6 +44,7 @@ using Aaru.CommonTypes.Enums;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Core;
|
||||
using Aaru.Images;
|
||||
using Aaru.Localization;
|
||||
using Aaru.Logging;
|
||||
using Schemas;
|
||||
@@ -234,6 +235,23 @@ sealed class ConvertImageCommand : Command<ConvertImageCommand.Settings>
|
||||
|
||||
if(outputFormat == null) return (int)ErrorNumber.FormatNotFound;
|
||||
|
||||
if(settings.ErrorRecovery > 0)
|
||||
{
|
||||
if(outputFormat is not AaruFormat)
|
||||
{
|
||||
AaruLogging.Error(UI.Error_recovery_is_only_supported_in_AaruFormat);
|
||||
|
||||
return (int)ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
if(settings.ErrorRecovery > 100)
|
||||
{
|
||||
AaruLogging.Error(UI.Maximum_error_recovery_is_100);
|
||||
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
if(settings.Verbose)
|
||||
AaruLogging.Verbose(UI.Output_image_format_0_1, outputFormat.Name, outputFormat.Id);
|
||||
else
|
||||
@@ -274,7 +292,8 @@ sealed class ConvertImageCommand : Command<ConvertImageCommand.Settings>
|
||||
settings.BypassPs3Decryption,
|
||||
settings.BypassWiiuDecryption,
|
||||
settings.BypassWiiDecryption,
|
||||
settings.InputPath);
|
||||
settings.InputPath,
|
||||
settings.ErrorRecovery);
|
||||
|
||||
ErrorNumber errno = ErrorNumber.NoError;
|
||||
|
||||
@@ -560,6 +579,7 @@ sealed class ConvertImageCommand : Command<ConvertImageCommand.Settings>
|
||||
AaruLogging.Debug(MODULE_NAME, "--aaru-metadata={0}", Markup.Escape(settings.AaruMetadata ?? ""));
|
||||
AaruLogging.Debug(MODULE_NAME, "--ignore-negative-sectors={0}", settings.IgnoreNegativeSectors);
|
||||
AaruLogging.Debug(MODULE_NAME, "--ignore-overflow-sectors={0}", settings.IgnoreOverflowSectors);
|
||||
AaruLogging.Debug(MODULE_NAME, "--error-recovery={0}", settings.ErrorRecovery);
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
@@ -758,5 +778,9 @@ sealed class ConvertImageCommand : Command<ConvertImageCommand.Settings>
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--ignore-overflow-sectors")]
|
||||
public bool IgnoreOverflowSectors { get; init; }
|
||||
[LocalizedDescription(nameof(UI.Add_error_recovery))]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("--error-recovery")]
|
||||
public int ErrorRecovery { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,8 @@ class MergeCommand : AsyncCommand<MergeCommand.Settings>
|
||||
settings.GenerateSubchannels,
|
||||
settings.Decrypt,
|
||||
settings.IgnoreNegativeSectors,
|
||||
settings.IgnoreOverflowSectors);
|
||||
settings.IgnoreOverflowSectors,
|
||||
settings.ErrorRecovery);
|
||||
|
||||
ErrorNumber errno = ErrorNumber.NoError;
|
||||
|
||||
@@ -188,6 +189,7 @@ class MergeCommand : AsyncCommand<MergeCommand.Settings>
|
||||
AaruLogging.Debug(MODULE_NAME, "--sectors-file={0}", Markup.Escape(settings.SectorsFile ?? ""));
|
||||
AaruLogging.Debug(MODULE_NAME, "--ignore-negative-sectors={0}", settings.IgnoreNegativeSectors);
|
||||
AaruLogging.Debug(MODULE_NAME, "--ignore-overflow-sectors={0}", settings.IgnoreOverflowSectors);
|
||||
AaruLogging.Debug(MODULE_NAME, "--error-recovery={0}", settings.ErrorRecovery);
|
||||
|
||||
AaruLogging.Debug(MODULE_NAME, UI.Parsed_options);
|
||||
|
||||
@@ -326,5 +328,9 @@ class MergeCommand : AsyncCommand<MergeCommand.Settings>
|
||||
[DefaultValue(false)]
|
||||
[CommandOption("--ignore-overflow-sectors")]
|
||||
public bool IgnoreOverflowSectors { get; init; }
|
||||
[LocalizedDescription(nameof(UI.Add_error_recovery))]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("--error-recovery")]
|
||||
public int ErrorRecovery { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ using Aaru.CommonTypes.Structs.Devices.SCSI;
|
||||
using Aaru.Core;
|
||||
using Aaru.Core.Devices.Dumping;
|
||||
using Aaru.Core.Logging;
|
||||
using Aaru.Images;
|
||||
using Aaru.Localization;
|
||||
using Aaru.Logging;
|
||||
using Schemas;
|
||||
@@ -126,6 +127,7 @@ sealed class DumpMediaCommand : Command<DumpMediaCommand.Settings>
|
||||
AaruLogging.Debug(MODULE_NAME, "--cure-paranoia={0}", settings.CureParanoia);
|
||||
AaruLogging.Debug(MODULE_NAME, "--raw={0}", settings.Raw);
|
||||
AaruLogging.Debug(MODULE_NAME, "--start-reverse={0}", settings.StartReverse);
|
||||
AaruLogging.Debug(MODULE_NAME, "--error-recovery={0}", settings.ErrorRecovery);
|
||||
|
||||
Dictionary<string, string> parsedOptions = Options.Parse(settings.Options);
|
||||
AaruLogging.Debug(MODULE_NAME, UI.Parsed_options);
|
||||
@@ -480,6 +482,23 @@ sealed class DumpMediaCommand : Command<DumpMediaCommand.Settings>
|
||||
|
||||
IBaseWritableImage outputFormat = candidates[0];
|
||||
|
||||
if(settings.ErrorRecovery > 0)
|
||||
{
|
||||
if(outputFormat is not AaruFormat)
|
||||
{
|
||||
AaruLogging.Error(UI.Error_recovery_is_only_supported_in_AaruFormat);
|
||||
|
||||
return (int)ErrorNumber.NotSupported;
|
||||
}
|
||||
|
||||
if(settings.ErrorRecovery > 100)
|
||||
{
|
||||
AaruLogging.Error(UI.Maximum_error_recovery_is_100);
|
||||
|
||||
return (int)ErrorNumber.InvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceLog.StartLog(dev, settings.Private);
|
||||
|
||||
if(settings.Verbose)
|
||||
@@ -530,7 +549,8 @@ sealed class DumpMediaCommand : Command<DumpMediaCommand.Settings>
|
||||
settings.Paranoia,
|
||||
settings.CureParanoia,
|
||||
settings.BypassWiiDecryption,
|
||||
settings.StartReverse);
|
||||
settings.StartReverse,
|
||||
settings.ErrorRecovery);
|
||||
|
||||
AnsiConsole.Progress()
|
||||
.AutoClear(true)
|
||||
@@ -806,6 +826,10 @@ sealed class DumpMediaCommand : Command<DumpMediaCommand.Settings>
|
||||
[LocalizedDescription(nameof(UI.Start_reverse_error_retry))]
|
||||
[CommandOption("--start-reverse")]
|
||||
public bool StartReverse { get; init; }
|
||||
[LocalizedDescription(nameof(UI.Add_error_recovery))]
|
||||
[DefaultValue(0)]
|
||||
[CommandOption("--error-recovery")]
|
||||
public int ErrorRecovery { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user