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.Linq;
|
||||
using System.Reactive;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
using Aaru.CommonTypes;
|
||||
@@ -45,6 +46,8 @@ using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Core.Media;
|
||||
using Aaru.Devices;
|
||||
using Aaru.Gui.Models;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
@@ -67,11 +70,9 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
string _commentsText;
|
||||
bool _commentsVisible;
|
||||
string _creatorText;
|
||||
|
||||
bool _creatorVisible;
|
||||
bool _destinationEnabled;
|
||||
string _destinationText;
|
||||
|
||||
bool _destinationVisible;
|
||||
string _driveFirmwareRevisionText;
|
||||
bool _driveFirmwareRevisionVisible;
|
||||
@@ -82,7 +83,6 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
string _driveSerialNumberText;
|
||||
bool _driveSerialNumberVisible;
|
||||
bool _forceChecked;
|
||||
|
||||
bool _formatReadOnly;
|
||||
double _lastMediaSequenceValue;
|
||||
bool _lastMediaSequenceVisible;
|
||||
@@ -152,7 +152,6 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
|
||||
CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
|
||||
StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
|
||||
|
||||
SourceText = imageSource;
|
||||
CreatorVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.Creator);
|
||||
MediaTitleVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaTitle);
|
||||
@@ -162,11 +161,8 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
MediaSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaSerialNumber);
|
||||
MediaBarcodeVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaBarcode);
|
||||
MediaPartNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.MediaPartNumber);
|
||||
|
||||
MediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
||||
|
||||
LastMediaSequenceVisible = inputFormat.Info.MediaSequence != 0 && inputFormat.Info.LastMediaSequence != 0;
|
||||
|
||||
DriveManufacturerVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveManufacturer);
|
||||
DriveModelVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveModel);
|
||||
DriveSerialNumberVisible = !string.IsNullOrWhiteSpace(inputFormat.Info.DriveSerialNumber);
|
||||
@@ -1014,6 +1010,47 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
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)
|
||||
{
|
||||
if(!useLong || cancel)
|
||||
@@ -1076,11 +1113,44 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
if(sectorsToDo == 1)
|
||||
{
|
||||
sector = inputFormat.ReadSectorTag(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
|
||||
{
|
||||
sector = inputFormat.ReadSectorsTag(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);
|
||||
}
|
||||
|
||||
@@ -1118,6 +1188,21 @@ namespace Aaru.Gui.ViewModels.Windows
|
||||
|
||||
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
|
||||
|
||||
@@ -36,6 +36,7 @@ using System.CommandLine;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using Aaru.CommonTypes;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
@@ -44,6 +45,8 @@ using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.CommonTypes.Structs;
|
||||
using Aaru.Console;
|
||||
using Aaru.Core;
|
||||
using Aaru.Core.Media;
|
||||
using Aaru.Devices;
|
||||
using Schemas;
|
||||
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
|
||||
using MediaType = Aaru.CommonTypes.MediaType;
|
||||
@@ -186,6 +189,30 @@ namespace Aaru.Commands.Image
|
||||
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>
|
||||
{
|
||||
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 mediaBarcode, string mediaManufacturer, string mediaModel,
|
||||
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();
|
||||
|
||||
@@ -214,6 +242,12 @@ namespace Aaru.Commands.Image
|
||||
if(verbose)
|
||||
AaruConsole.VerboseWriteLineEvent += System.Console.WriteLine;
|
||||
|
||||
if(fixSubchannelCrc)
|
||||
fixSubchannel = true;
|
||||
|
||||
if(fixSubchannel)
|
||||
fixSubchannelPosition = true;
|
||||
|
||||
Statistics.AddCommand("convert-image");
|
||||
|
||||
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", "--resume-file={0}", resumeFile);
|
||||
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);
|
||||
AaruConsole.DebugWriteLine("Analyze command", "Parsed options:");
|
||||
@@ -690,6 +727,48 @@ namespace Aaru.Commands.Image
|
||||
|
||||
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))
|
||||
{
|
||||
if(!useLong)
|
||||
@@ -763,13 +842,43 @@ namespace Aaru.Commands.Image
|
||||
if(sectorsToDo == 1)
|
||||
{
|
||||
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
|
||||
{
|
||||
sector = inputFormat.ReadSectorsTag(doneSectors + track.TrackStartSector, sectorsToDo,
|
||||
tag);
|
||||
|
||||
if(tag == SectorTagType.CdSectorSubchannel)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -810,6 +919,21 @@ namespace Aaru.Commands.Image
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user