mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add options to fix subchannels on image conversion.
This commit is contained in:
@@ -36,6 +36,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using Aaru.CommonTypes;
|
using Aaru.CommonTypes;
|
||||||
@@ -45,6 +46,8 @@ using Aaru.CommonTypes.Metadata;
|
|||||||
using Aaru.CommonTypes.Structs;
|
using Aaru.CommonTypes.Structs;
|
||||||
using Aaru.Console;
|
using Aaru.Console;
|
||||||
using Aaru.Core;
|
using Aaru.Core;
|
||||||
|
using Aaru.Core.Media;
|
||||||
|
using Aaru.Devices;
|
||||||
using Aaru.Gui.Models;
|
using Aaru.Gui.Models;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -59,30 +62,27 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
{
|
{
|
||||||
public class ImageConvertViewModel : ViewModelBase
|
public class ImageConvertViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
readonly Window _view;
|
readonly Window _view;
|
||||||
readonly IMediaImage inputFormat;
|
readonly IMediaImage inputFormat;
|
||||||
bool _cicmXmlFromImageVisible;
|
bool _cicmXmlFromImageVisible;
|
||||||
string _cicmXmlText;
|
string _cicmXmlText;
|
||||||
bool _closeVisible;
|
bool _closeVisible;
|
||||||
string _commentsText;
|
string _commentsText;
|
||||||
bool _commentsVisible;
|
bool _commentsVisible;
|
||||||
string _creatorText;
|
string _creatorText;
|
||||||
|
bool _creatorVisible;
|
||||||
bool _creatorVisible;
|
bool _destinationEnabled;
|
||||||
bool _destinationEnabled;
|
string _destinationText;
|
||||||
string _destinationText;
|
bool _destinationVisible;
|
||||||
|
string _driveFirmwareRevisionText;
|
||||||
bool _destinationVisible;
|
bool _driveFirmwareRevisionVisible;
|
||||||
string _driveFirmwareRevisionText;
|
string _driveManufacturerText;
|
||||||
bool _driveFirmwareRevisionVisible;
|
bool _driveManufacturerVisible;
|
||||||
string _driveManufacturerText;
|
string _driveModelText;
|
||||||
bool _driveManufacturerVisible;
|
bool _driveModelVisible;
|
||||||
string _driveModelText;
|
string _driveSerialNumberText;
|
||||||
bool _driveModelVisible;
|
bool _driveSerialNumberVisible;
|
||||||
string _driveSerialNumberText;
|
bool _forceChecked;
|
||||||
bool _driveSerialNumberVisible;
|
|
||||||
bool _forceChecked;
|
|
||||||
|
|
||||||
bool _formatReadOnly;
|
bool _formatReadOnly;
|
||||||
double _lastMediaSequenceValue;
|
double _lastMediaSequenceValue;
|
||||||
bool _lastMediaSequenceVisible;
|
bool _lastMediaSequenceVisible;
|
||||||
@@ -127,49 +127,45 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
|
|
||||||
public ImageConvertViewModel(IMediaImage inputFormat, string imageSource, Window view)
|
public ImageConvertViewModel(IMediaImage inputFormat, string imageSource, Window view)
|
||||||
{
|
{
|
||||||
_view = view;
|
_view = view;
|
||||||
this.inputFormat = inputFormat;
|
this.inputFormat = inputFormat;
|
||||||
cancel = false;
|
cancel = false;
|
||||||
DestinationCommand = ReactiveCommand.Create(ExecuteDestinationCommand);
|
DestinationCommand = ReactiveCommand.Create(ExecuteDestinationCommand);
|
||||||
CreatorCommand = ReactiveCommand.Create(ExecuteCreatorCommand);
|
CreatorCommand = ReactiveCommand.Create(ExecuteCreatorCommand);
|
||||||
MediaTitleCommand = ReactiveCommand.Create(ExecuteMediaTitleCommand);
|
MediaTitleCommand = ReactiveCommand.Create(ExecuteMediaTitleCommand);
|
||||||
MediaManufacturerCommand = ReactiveCommand.Create(ExecuteMediaManufacturerCommand);
|
MediaManufacturerCommand = ReactiveCommand.Create(ExecuteMediaManufacturerCommand);
|
||||||
MediaModelCommand = ReactiveCommand.Create(ExecuteMediaModelCommand);
|
MediaModelCommand = ReactiveCommand.Create(ExecuteMediaModelCommand);
|
||||||
MediaSerialNumberCommand = ReactiveCommand.Create(ExecuteMediaSerialNumberCommand);
|
MediaSerialNumberCommand = ReactiveCommand.Create(ExecuteMediaSerialNumberCommand);
|
||||||
MediaBarcodeCommand = ReactiveCommand.Create(ExecuteMediaBarcodeCommand);
|
MediaBarcodeCommand = ReactiveCommand.Create(ExecuteMediaBarcodeCommand);
|
||||||
MediaPartNumberCommand = ReactiveCommand.Create(ExecuteMediaPartNumberCommand);
|
MediaPartNumberCommand = ReactiveCommand.Create(ExecuteMediaPartNumberCommand);
|
||||||
MediaSequenceCommand = ReactiveCommand.Create(ExecuteMediaSequenceCommand);
|
MediaSequenceCommand = ReactiveCommand.Create(ExecuteMediaSequenceCommand);
|
||||||
LastMediaSequenceCommand = ReactiveCommand.Create(ExecuteLastMediaSequenceCommand);
|
LastMediaSequenceCommand = ReactiveCommand.Create(ExecuteLastMediaSequenceCommand);
|
||||||
DriveManufacturerCommand = ReactiveCommand.Create(ExecuteDriveManufacturerCommand);
|
DriveManufacturerCommand = ReactiveCommand.Create(ExecuteDriveManufacturerCommand);
|
||||||
DriveModelCommand = ReactiveCommand.Create(ExecuteDriveModelCommand);
|
DriveModelCommand = ReactiveCommand.Create(ExecuteDriveModelCommand);
|
||||||
DriveSerialNumberCommand = ReactiveCommand.Create(ExecuteDriveSerialNumberCommand);
|
DriveSerialNumberCommand = ReactiveCommand.Create(ExecuteDriveSerialNumberCommand);
|
||||||
DriveFirmwareRevisionCommand = ReactiveCommand.Create(ExecuteDriveFirmwareRevisionCommand);
|
DriveFirmwareRevisionCommand = ReactiveCommand.Create(ExecuteDriveFirmwareRevisionCommand);
|
||||||
CommentsCommand = ReactiveCommand.Create(ExecuteCommentsCommand);
|
CommentsCommand = ReactiveCommand.Create(ExecuteCommentsCommand);
|
||||||
CicmXmlFromImageCommand = ReactiveCommand.Create(ExecuteCicmXmlFromImageCommand);
|
CicmXmlFromImageCommand = ReactiveCommand.Create(ExecuteCicmXmlFromImageCommand);
|
||||||
CicmXmlCommand = ReactiveCommand.Create(ExecuteCicmXmlCommand);
|
CicmXmlCommand = ReactiveCommand.Create(ExecuteCicmXmlCommand);
|
||||||
ResumeFileFromImageCommand = ReactiveCommand.Create(ExecuteResumeFileFromImageCommand);
|
ResumeFileFromImageCommand = ReactiveCommand.Create(ExecuteResumeFileFromImageCommand);
|
||||||
ResumeFileCommand = ReactiveCommand.Create(ExecuteResumeFileCommand);
|
ResumeFileCommand = ReactiveCommand.Create(ExecuteResumeFileCommand);
|
||||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||||
StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
|
StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
|
||||||
|
SourceText = imageSource;
|
||||||
SourceText = imageSource;
|
CreatorVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Creator);
|
||||||
CreatorVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Creator);
|
MediaTitleVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaTitle);
|
||||||
MediaTitleVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaTitle);
|
CommentsVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Comments);
|
||||||
CommentsVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Comments);
|
|
||||||
MediaManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaManufacturer);
|
MediaManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaManufacturer);
|
||||||
MediaModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaModel);
|
MediaModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaModel);
|
||||||
MediaSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaSerialNumber);
|
MediaSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaSerialNumber);
|
||||||
MediaBarcodeVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaBarcode);
|
MediaBarcodeVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaBarcode);
|
||||||
MediaPartNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaPartNumber);
|
MediaPartNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaPartNumber);
|
||||||
|
|
||||||
MediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
MediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
||||||
|
|
||||||
LastMediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
LastMediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
||||||
|
DriveManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveManufacturer);
|
||||||
DriveManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveManufacturer);
|
DriveModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveModel);
|
||||||
DriveModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveModel);
|
DriveSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveSerialNumber);
|
||||||
DriveSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveSerialNumber);
|
|
||||||
DriveFirmwareRevisionVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveFirmwareRevision);
|
DriveFirmwareRevisionVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveFirmwareRevision);
|
||||||
|
|
||||||
PluginBase plugins = GetPluginBase.Instance;
|
PluginBase plugins = GetPluginBase.Instance;
|
||||||
@@ -1014,6 +1010,47 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
Progress2Value = Progress2MaxValue;
|
Progress2Value = Progress2MaxValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
|
||||||
|
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>();
|
||||||
|
string mcn = null;
|
||||||
|
HashSet<int> subchannelExtents = new HashSet<int>();
|
||||||
|
|
||||||
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
||||||
|
Where(t => t == SectorTagType.CdTrackIsrc).OrderBy(t => t))
|
||||||
|
{
|
||||||
|
foreach(Track track in inputOptical.Tracks)
|
||||||
|
{
|
||||||
|
byte[] isrc = inputFormat.ReadSectorTag(track.TrackSequence, tag);
|
||||||
|
|
||||||
|
if(isrc is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
isrcs[(byte)track.TrackSequence] = Encoding.UTF8.GetString(isrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
||||||
|
Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
|
||||||
|
{
|
||||||
|
foreach(Track track in inputOptical.Tracks)
|
||||||
|
{
|
||||||
|
byte[] flags = inputFormat.ReadSectorTag(track.TrackSequence, tag);
|
||||||
|
|
||||||
|
if(flags is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
trackFlags[(byte)track.TrackSequence] = flags[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ulong s = 0; s < inputFormat.Info.Sectors; s++)
|
||||||
|
{
|
||||||
|
if(s > int.MaxValue)
|
||||||
|
break;
|
||||||
|
|
||||||
|
subchannelExtents.Add((int)s);
|
||||||
|
}
|
||||||
|
|
||||||
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags)
|
||||||
{
|
{
|
||||||
if(!useLong || cancel)
|
if(!useLong || cancel)
|
||||||
@@ -1076,12 +1113,45 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
if(sectorsToDo == 1)
|
if(sectorsToDo == 1)
|
||||||
{
|
{
|
||||||
sector = inputFormat.ReadSectorTag(doneSectors, tag);
|
sector = inputFormat.ReadSectorTag(doneSectors, tag);
|
||||||
result = outputFormat.WriteSectorTag(sector, doneSectors, tag);
|
Track track = tracks.LastOrDefault(t => t.TrackStartSector >= doneSectors);
|
||||||
|
|
||||||
|
if(tag == SectorTagType.CdSectorSubchannel &&
|
||||||
|
track != null)
|
||||||
|
{
|
||||||
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
||||||
|
MmcSubchannel.Raw, sector, doneSectors, 1, null, isrcs,
|
||||||
|
(byte)track.TrackSequence, ref mcn, tracks.ToArray(), subchannelExtents, false,
|
||||||
|
outputFormat, false, false, null, null);
|
||||||
|
|
||||||
|
if(indexesChanged)
|
||||||
|
outputOptical.SetTracks(tracks.ToList());
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = outputFormat.WriteSectorTag(sector, doneSectors, tag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sector = inputFormat.ReadSectorsTag(doneSectors, sectorsToDo, tag);
|
sector = inputFormat.ReadSectorsTag(doneSectors, sectorsToDo, tag);
|
||||||
result = outputFormat.WriteSectorsTag(sector, doneSectors, sectorsToDo, tag);
|
Track track = tracks.LastOrDefault(t => t.TrackStartSector >= doneSectors);
|
||||||
|
|
||||||
|
if(tag == SectorTagType.CdSectorSubchannel &&
|
||||||
|
track != null)
|
||||||
|
|
||||||
|
{
|
||||||
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
||||||
|
MmcSubchannel.Raw, sector, doneSectors, sectorsToDo, null, isrcs,
|
||||||
|
(byte)track.TrackSequence, ref mcn, tracks.ToArray(), subchannelExtents, false,
|
||||||
|
outputFormat, false, false, null, null);
|
||||||
|
|
||||||
|
if(indexesChanged)
|
||||||
|
outputOptical.SetTracks(tracks.ToList());
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = outputFormat.WriteSectorsTag(sector, doneSectors, sectorsToDo, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
@@ -1118,6 +1188,21 @@ namespace Aaru.Gui.ViewModels.Windows
|
|||||||
|
|
||||||
Progress2Value = Progress2MaxValue;
|
Progress2Value = Progress2MaxValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(isrcs.Count > 0)
|
||||||
|
foreach(KeyValuePair<byte, string> isrc in isrcs)
|
||||||
|
outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
|
||||||
|
SectorTagType.CdTrackIsrc);
|
||||||
|
|
||||||
|
if(trackFlags.Count > 0)
|
||||||
|
foreach(KeyValuePair<byte, byte> flags in trackFlags)
|
||||||
|
outputOptical.WriteSectorTag(new[]
|
||||||
|
{
|
||||||
|
flags.Value
|
||||||
|
}, flags.Key, SectorTagType.CdTrackFlags);
|
||||||
|
|
||||||
|
if(mcn != null)
|
||||||
|
outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ using System.CommandLine;
|
|||||||
using System.CommandLine.Invocation;
|
using System.CommandLine.Invocation;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using Aaru.CommonTypes;
|
using Aaru.CommonTypes;
|
||||||
using Aaru.CommonTypes.Enums;
|
using Aaru.CommonTypes.Enums;
|
||||||
@@ -44,6 +45,8 @@ using Aaru.CommonTypes.Metadata;
|
|||||||
using Aaru.CommonTypes.Structs;
|
using Aaru.CommonTypes.Structs;
|
||||||
using Aaru.Console;
|
using Aaru.Console;
|
||||||
using Aaru.Core;
|
using Aaru.Core;
|
||||||
|
using Aaru.Core.Media;
|
||||||
|
using Aaru.Devices;
|
||||||
using Schemas;
|
using Schemas;
|
||||||
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
||||||
using MediaType = Aaru.CommonTypes.MediaType;
|
using MediaType = Aaru.CommonTypes.MediaType;
|
||||||
@@ -186,6 +189,30 @@ namespace Aaru.Commands.Image
|
|||||||
Argument = new Argument<string>(() => null), Required = false
|
Argument = new Argument<string>(() => null), Required = false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--fix-subchannel-position"
|
||||||
|
}, "Store subchannel according to the sector they describe.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => true), Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--fix-subchannel"
|
||||||
|
}, "Try to fix subchannel. Implies fixing subchannel position.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => false), Required = false
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(new Option(new[]
|
||||||
|
{
|
||||||
|
"--fix-subchannel-crc"
|
||||||
|
}, "If subchannel looks OK but CRC fails, rewrite it. Implies fixing subchannel.")
|
||||||
|
{
|
||||||
|
Argument = new Argument<bool>(() => false), Required = false
|
||||||
|
});
|
||||||
|
|
||||||
AddArgument(new Argument<string>
|
AddArgument(new Argument<string>
|
||||||
{
|
{
|
||||||
Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path"
|
Arity = ArgumentArity.ExactlyOne, Description = "Input image path", Name = "input-path"
|
||||||
@@ -204,7 +231,8 @@ namespace Aaru.Commands.Image
|
|||||||
string driveSerialNumber, bool force, string inputPath, int lastMediaSequence,
|
string driveSerialNumber, bool force, string inputPath, int lastMediaSequence,
|
||||||
string mediaBarcode, string mediaManufacturer, string mediaModel,
|
string mediaBarcode, string mediaManufacturer, string mediaModel,
|
||||||
string mediaPartNumber, int mediaSequence, string mediaSerialNumber, string mediaTitle,
|
string mediaPartNumber, int mediaSequence, string mediaSerialNumber, string mediaTitle,
|
||||||
string outputPath, string options, string resumeFile, string format, string geometry)
|
string outputPath, string options, string resumeFile, string format, string geometry,
|
||||||
|
bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc)
|
||||||
{
|
{
|
||||||
MainClass.PrintCopyright();
|
MainClass.PrintCopyright();
|
||||||
|
|
||||||
@@ -214,6 +242,12 @@ namespace Aaru.Commands.Image
|
|||||||
if(verbose)
|
if(verbose)
|
||||||
AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
|
AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
|
||||||
|
|
||||||
|
if(fixSubchannelCrc)
|
||||||
|
fixSubchannel = true;
|
||||||
|
|
||||||
|
if(fixSubchannel)
|
||||||
|
fixSubchannelPosition = true;
|
||||||
|
|
||||||
Statistics.AddCommand("convert-image");
|
Statistics.AddCommand("convert-image");
|
||||||
|
|
||||||
AaruConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
|
AaruConsole.DebugWriteLine("Analyze command", "--cicm-xml={0}", cicmXml);
|
||||||
@@ -241,6 +275,9 @@ namespace Aaru.Commands.Image
|
|||||||
AaruConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath);
|
AaruConsole.DebugWriteLine("Analyze command", "--output={0}", outputPath);
|
||||||
AaruConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
|
AaruConsole.DebugWriteLine("Analyze command", "--resume-file={0}", resumeFile);
|
||||||
AaruConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
|
AaruConsole.DebugWriteLine("Analyze command", "--verbose={0}", verbose);
|
||||||
|
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel-position={0}", fixSubchannelPosition);
|
||||||
|
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel={0}", fixSubchannel);
|
||||||
|
AaruConsole.DebugWriteLine("Analyze command", "--fix-subchannel-crc={0}", fixSubchannelCrc);
|
||||||
|
|
||||||
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
|
||||||
AaruConsole.DebugWriteLine("Analyze command", "Parsed options:");
|
AaruConsole.DebugWriteLine("Analyze command", "Parsed options:");
|
||||||
@@ -449,8 +486,8 @@ namespace Aaru.Commands.Image
|
|||||||
// Try name
|
// Try name
|
||||||
else
|
else
|
||||||
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format,
|
candidates.AddRange(plugins.WritableImages.Values.Where(t => string.Equals(t.Name, format,
|
||||||
StringComparison.
|
StringComparison.
|
||||||
InvariantCultureIgnoreCase)));
|
InvariantCultureIgnoreCase)));
|
||||||
|
|
||||||
if(candidates.Count == 0)
|
if(candidates.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -613,7 +650,7 @@ namespace Aaru.Commands.Image
|
|||||||
sectorsToDo = (uint)(trackSectors - doneSectors);
|
sectorsToDo = (uint)(trackSectors - doneSectors);
|
||||||
|
|
||||||
AaruConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
|
AaruConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)",
|
||||||
doneSectors + track.TrackStartSector,
|
doneSectors + track.TrackStartSector,
|
||||||
doneSectors + sectorsToDo + track.TrackStartSector,
|
doneSectors + sectorsToDo + track.TrackStartSector,
|
||||||
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
|
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
|
||||||
track.TrackSequence);
|
track.TrackSequence);
|
||||||
@@ -690,6 +727,48 @@ namespace Aaru.Commands.Image
|
|||||||
|
|
||||||
AaruConsole.WriteLine();
|
AaruConsole.WriteLine();
|
||||||
|
|
||||||
|
Dictionary<byte, string> isrcs = new Dictionary<byte, string>();
|
||||||
|
Dictionary<byte, byte> trackFlags = new Dictionary<byte, byte>();
|
||||||
|
string mcn = null;
|
||||||
|
HashSet<int> subchannelExtents = new HashSet<int>();
|
||||||
|
Track[] tracks = inputOptical.Tracks.ToArray();
|
||||||
|
|
||||||
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
||||||
|
Where(t => t == SectorTagType.CdTrackIsrc).OrderBy(t => t))
|
||||||
|
{
|
||||||
|
foreach(Track track in inputOptical.Tracks)
|
||||||
|
{
|
||||||
|
byte[] isrc = inputFormat.ReadSectorTag(track.TrackSequence, tag);
|
||||||
|
|
||||||
|
if(isrc is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
isrcs[(byte)track.TrackSequence] = Encoding.UTF8.GetString(isrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
||||||
|
Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
|
||||||
|
{
|
||||||
|
foreach(Track track in inputOptical.Tracks)
|
||||||
|
{
|
||||||
|
byte[] flags = inputFormat.ReadSectorTag(track.TrackSequence, tag);
|
||||||
|
|
||||||
|
if(flags is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
trackFlags[(byte)track.TrackSequence] = flags[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ulong s = 0; s < inputFormat.Info.Sectors; s++)
|
||||||
|
{
|
||||||
|
if(s > int.MaxValue)
|
||||||
|
break;
|
||||||
|
|
||||||
|
subchannelExtents.Add((int)s);
|
||||||
|
}
|
||||||
|
|
||||||
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t))
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t))
|
||||||
{
|
{
|
||||||
if(!useLong)
|
if(!useLong)
|
||||||
@@ -755,23 +834,53 @@ namespace Aaru.Commands.Image
|
|||||||
sectorsToDo = (uint)(trackSectors - doneSectors);
|
sectorsToDo = (uint)(trackSectors - doneSectors);
|
||||||
|
|
||||||
AaruConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
|
AaruConsole.Write("\rConverting tag {4} for sectors {0} to {1} in track {3} ({2:P2} done)",
|
||||||
doneSectors + track.TrackStartSector,
|
doneSectors + track.TrackStartSector,
|
||||||
doneSectors + sectorsToDo + track.TrackStartSector,
|
doneSectors + sectorsToDo + track.TrackStartSector,
|
||||||
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
|
(doneSectors + track.TrackStartSector) / (double)inputFormat.Info.Sectors,
|
||||||
track.TrackSequence, tag);
|
track.TrackSequence, tag);
|
||||||
|
|
||||||
if(sectorsToDo == 1)
|
if(sectorsToDo == 1)
|
||||||
{
|
{
|
||||||
sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag);
|
sector = inputFormat.ReadSectorTag(doneSectors + track.TrackStartSector, tag);
|
||||||
result = outputFormat.WriteSectorTag(sector, doneSectors + track.TrackStartSector, tag);
|
|
||||||
|
if(tag == SectorTagType.CdSectorSubchannel)
|
||||||
|
{
|
||||||
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
||||||
|
MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector, 1, null,
|
||||||
|
isrcs, (byte)track.TrackSequence, ref mcn, tracks, subchannelExtents,
|
||||||
|
fixSubchannelPosition, outputFormat, fixSubchannel, fixSubchannelCrc, null,
|
||||||
|
null);
|
||||||
|
|
||||||
|
if(indexesChanged)
|
||||||
|
outputOptical.SetTracks(tracks.ToList());
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = outputFormat.WriteSectorTag(sector, doneSectors + track.TrackStartSector,
|
||||||
|
tag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
|
sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
|
||||||
tag);
|
tag);
|
||||||
|
|
||||||
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
|
if(tag == SectorTagType.CdSectorSubchannel)
|
||||||
sectorsToDo, tag);
|
{
|
||||||
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
||||||
|
MmcSubchannel.Raw, sector, doneSectors + track.TrackStartSector,
|
||||||
|
sectorsToDo, null, isrcs, (byte)track.TrackSequence, ref mcn, tracks,
|
||||||
|
subchannelExtents, fixSubchannelPosition, outputFormat, fixSubchannel,
|
||||||
|
fixSubchannelCrc, null, null);
|
||||||
|
|
||||||
|
if(indexesChanged)
|
||||||
|
outputOptical.SetTracks(tracks.ToList());
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.TrackStartSector,
|
||||||
|
sectorsToDo, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
@@ -810,6 +919,21 @@ namespace Aaru.Commands.Image
|
|||||||
|
|
||||||
AaruConsole.WriteLine();
|
AaruConsole.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isrcs.Count > 0)
|
||||||
|
foreach(KeyValuePair<byte, string> isrc in isrcs)
|
||||||
|
outputOptical.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
|
||||||
|
SectorTagType.CdTrackIsrc);
|
||||||
|
|
||||||
|
if(trackFlags.Count > 0)
|
||||||
|
foreach(KeyValuePair<byte, byte> flags in trackFlags)
|
||||||
|
outputOptical.WriteSectorTag(new[]
|
||||||
|
{
|
||||||
|
flags.Value
|
||||||
|
}, flags.Key, SectorTagType.CdTrackFlags);
|
||||||
|
|
||||||
|
if(mcn != null)
|
||||||
|
outputOptical.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user