2021-08-03 00:29:09 +01:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Aaru.Checksums;
|
|
|
|
|
using Aaru.CommonTypes;
|
|
|
|
|
using Aaru.CommonTypes.Enums;
|
|
|
|
|
using Aaru.CommonTypes.Interfaces;
|
|
|
|
|
using Aaru.CommonTypes.Structs;
|
|
|
|
|
using Aaru.Core.Media;
|
|
|
|
|
using Aaru.Devices;
|
|
|
|
|
using FluentAssertions;
|
|
|
|
|
using FluentAssertions.Execution;
|
|
|
|
|
using NUnit.Framework;
|
|
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
namespace Aaru.Tests.WritableImages;
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
public abstract class WritableOpticalMediaImageTest : BaseWritableMediaImageTest
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
const uint SECTORS_TO_READ = 256;
|
|
|
|
|
public abstract OpticalImageTestExpected[] Tests { get; }
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void Info()
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
Environment.CurrentDirectory = DataFolder;
|
|
|
|
|
ErrorNumber errno;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.Multiple(() =>
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(OpticalImageTestExpected test in Tests)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
string testFile = test.TestFile;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
bool exists = File.Exists(testFile);
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.True(exists, string.Format(Localization._0_not_found, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
|
|
|
|
// It arrives here...
|
|
|
|
|
if(!exists)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var filtersList = new FiltersList();
|
|
|
|
|
IFilter filter = filtersList.GetFilter(testFile);
|
|
|
|
|
filter.Open(testFile);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var image = Activator.CreateInstance(InputPlugin.GetType()) as IOpticalMediaImage;
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.NotNull(image, string.Format(Localization.Could_not_instantiate_filesystem_for_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
ErrorNumber opened = image.Open(filter);
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, opened, string.Format(Localization.Open_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(opened != ErrorNumber.NoError)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
using(new AssertionScope())
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.Multiple(() =>
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.Sectors, image.Info.Sectors,
|
|
|
|
|
string.Format(Localization.Sectors_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(test.SectorSize > 0)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.SectorSize, image.Info.SectorSize,
|
|
|
|
|
string.Format(Localization.Sector_size_0, testFile));
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.MediaType, image.Info.MediaType,
|
|
|
|
|
string.Format(Localization.Media_type_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-15 22:21:07 +00:00
|
|
|
if(image.Info.MetadataMediaType != MetadataMediaType.OpticalDisc)
|
2022-03-06 13:29:38 +00:00
|
|
|
return;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.Tracks.Length, image.Tracks.Count,
|
|
|
|
|
string.Format(Localization.Tracks_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.Session).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Session),
|
|
|
|
|
string.Format(Localization.Track_session_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.StartSector).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Start),
|
|
|
|
|
string.Format(Localization.Track_start_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.EndSector).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.End),
|
|
|
|
|
string.Format(Localization.Track_end_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.Pregap).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Pregap),
|
|
|
|
|
string.Format(Localization.Track_pregap_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
var trackNo = 0;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
var flags = new byte?[image.Tracks.Count];
|
|
|
|
|
ulong latestEndSector = 0;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(Track currentTrack in image.Tracks)
|
|
|
|
|
{
|
|
|
|
|
if(currentTrack.EndSector > latestEndSector)
|
|
|
|
|
latestEndSector = currentTrack.EndSector;
|
2021-09-20 20:52:18 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(image.Info.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags))
|
|
|
|
|
{
|
|
|
|
|
errno = image.ReadSectorTag(currentTrack.Sequence, SectorTagType.CdTrackFlags,
|
|
|
|
|
out byte[] tmp);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-11 22:17:39 +00:00
|
|
|
if(errno == ErrorNumber.NoError)
|
2022-03-06 13:29:38 +00:00
|
|
|
flags[trackNo] = tmp[0];
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
trackNo++;
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-11 22:20:23 +00:00
|
|
|
flags.Should().BeEquivalentTo(test.Tracks.Select(s => s.Flags),
|
|
|
|
|
string.Format(Localization.Track_flags_0, testFile));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
Assert.AreEqual(latestEndSector, image.Info.Sectors - 1,
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Last_sector_for_tracks_is_0_but_it_is_1_for_image,
|
|
|
|
|
latestEndSector, image.Info.Sectors));
|
2022-03-06 13:29:38 +00:00
|
|
|
});
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
[Test]
|
|
|
|
|
public void Convert()
|
|
|
|
|
{
|
|
|
|
|
Environment.CurrentDirectory = DataFolder;
|
|
|
|
|
ErrorNumber errno;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
|
{
|
|
|
|
|
foreach(OpticalImageTestExpected test in Tests)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
string testFile = test.TestFile;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
bool exists = File.Exists(testFile);
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.True(exists, string.Format(Localization._0_not_found, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
|
|
|
|
// It arrives here...
|
|
|
|
|
if(!exists)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var filtersList = new FiltersList();
|
|
|
|
|
IFilter filter = filtersList.GetFilter(testFile);
|
|
|
|
|
filter.Open(testFile);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var inputFormat = Activator.CreateInstance(InputPlugin.GetType()) as IOpticalMediaImage;
|
2022-12-11 22:20:23 +00:00
|
|
|
|
|
|
|
|
Assert.NotNull(inputFormat,
|
|
|
|
|
string.Format(Localization.Could_not_instantiate_input_plugin_for_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
ErrorNumber opened = inputFormat.Open(filter);
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, opened, string.Format(Localization.Open_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(opened != ErrorNumber.NoError)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-07 07:36:44 +00:00
|
|
|
string outputPath = Path.Combine(Path.GetTempPath(), $"{Path.GetRandomFileName()}.{OutputExtension}");
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var outputFormat = Activator.CreateInstance(OutputPlugin.GetType()) as IWritableOpticalImage;
|
2022-12-11 22:20:23 +00:00
|
|
|
|
|
|
|
|
Assert.NotNull(outputFormat,
|
|
|
|
|
string.Format(Localization.Could_not_instantiate_output_plugin_for_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.IsTrue(outputFormat.SupportedMediaTypes.Contains(inputFormat.Info.MediaType),
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Trying_to_convert_unsupported_media_type_0_for_1,
|
|
|
|
|
inputFormat.Info.MediaType, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
bool useLong = inputFormat.Info.ReadableSectorTags.Except(new[] { SectorTagType.CdTrackFlags }).Any();
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-04 08:43:23 +01:00
|
|
|
// TODO: Can be done with LINQ only
|
|
|
|
|
foreach(SectorTagType _ in inputFormat.Info.ReadableSectorTags.Where(sectorTag =>
|
|
|
|
|
!outputFormat.SupportedSectorTags.Contains(sectorTag)).Where(
|
|
|
|
|
sectorTag => sectorTag != SectorTagType.CdTrackFlags &&
|
|
|
|
|
sectorTag != SectorTagType.CdTrackIsrc &&
|
|
|
|
|
sectorTag != SectorTagType.CdSectorSubchannel))
|
|
|
|
|
useLong = false;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
Assert.IsTrue(
|
|
|
|
|
outputFormat.Create(outputPath, inputFormat.Info.MediaType, new Dictionary<string, string>(),
|
|
|
|
|
inputFormat.Info.Sectors, inputFormat.Info.SectorSize),
|
|
|
|
|
string.Format(Localization.Error_0_creating_output_image, outputFormat.ErrorMessage));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(MediaTagType mediaTag in inputFormat.Info.ReadableMediaTags.Where(mediaTag =>
|
|
|
|
|
outputFormat.SupportedMediaTags.Contains(mediaTag)))
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-17 23:54:41 +00:00
|
|
|
if(inputFormat.ReadMediaTag(mediaTag, out byte[] buffer) == ErrorNumber.NoError)
|
2022-03-06 13:29:38 +00:00
|
|
|
outputFormat.WriteMediaTag(buffer, mediaTag);
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.IsTrue(outputFormat.SetTracks(inputFormat.Tracks),
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Error_0_sending_tracks_list_to_output_image,
|
|
|
|
|
outputFormat.ErrorMessage));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
ulong doneSectors;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(Track track in inputFormat.Tracks)
|
|
|
|
|
{
|
|
|
|
|
doneSectors = 0;
|
|
|
|
|
ulong trackSectors = track.EndSector - track.StartSector + 1;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
while(doneSectors < trackSectors)
|
|
|
|
|
{
|
|
|
|
|
byte[] sector;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
uint sectorsToDo;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(trackSectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
sectorsToDo = SECTORS_TO_READ;
|
|
|
|
|
else
|
|
|
|
|
sectorsToDo = (uint)(trackSectors - doneSectors);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
var useNotLong = false;
|
|
|
|
|
var result = false;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useLong)
|
|
|
|
|
{
|
|
|
|
|
errno = sectorsToDo == 1
|
|
|
|
|
? inputFormat.ReadSectorLong(doneSectors + track.StartSector, out sector)
|
|
|
|
|
: inputFormat.ReadSectorsLong(doneSectors + track.StartSector, sectorsToDo,
|
|
|
|
|
out sector);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(errno == ErrorNumber.NoError)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
result = sectorsToDo == 1
|
|
|
|
|
? outputFormat.WriteSectorLong(sector, doneSectors + track.StartSector)
|
2022-03-07 07:36:44 +00:00
|
|
|
: outputFormat.WriteSectorsLong(sector, doneSectors + track.StartSector,
|
|
|
|
|
sectorsToDo);
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
else
|
|
|
|
|
result = false;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(!result &&
|
|
|
|
|
sector.Length % 2352 != 0)
|
|
|
|
|
useNotLong = true;
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(!useLong || useNotLong)
|
|
|
|
|
{
|
|
|
|
|
errno = sectorsToDo == 1
|
|
|
|
|
? inputFormat.ReadSector(doneSectors + track.StartSector, out sector)
|
|
|
|
|
: inputFormat.ReadSectors(doneSectors + track.StartSector, sectorsToDo,
|
|
|
|
|
out sector);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno);
|
2021-09-19 21:16:47 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
result = sectorsToDo == 1
|
|
|
|
|
? outputFormat.WriteSector(sector, doneSectors + track.StartSector)
|
|
|
|
|
: outputFormat.WriteSectors(sector, doneSectors + track.StartSector,
|
|
|
|
|
sectorsToDo);
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.IsTrue(result,
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Error_0_writing_sector_1, outputFormat.ErrorMessage,
|
|
|
|
|
doneSectors + track.StartSector));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
doneSectors += sectorsToDo;
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Dictionary<byte, string> isrcs = new();
|
|
|
|
|
Dictionary<byte, byte> trackFlags = new();
|
|
|
|
|
string mcn = null;
|
|
|
|
|
HashSet<int> subchannelExtents = new();
|
|
|
|
|
Dictionary<byte, int> smallestPregapLbaPerTrack = new();
|
2023-10-03 23:44:33 +01:00
|
|
|
var tracks = new Track[inputFormat.Tracks.Count];
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
for(var i = 0; i < tracks.Length; i++)
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
tracks[i] = new Track
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
Indexes = new Dictionary<ushort, int>(),
|
|
|
|
|
Description = inputFormat.Tracks[i].Description,
|
|
|
|
|
EndSector = inputFormat.Tracks[i].EndSector,
|
|
|
|
|
StartSector = inputFormat.Tracks[i].StartSector,
|
|
|
|
|
Pregap = inputFormat.Tracks[i].Pregap,
|
|
|
|
|
Sequence = inputFormat.Tracks[i].Sequence,
|
|
|
|
|
Session = inputFormat.Tracks[i].Session,
|
|
|
|
|
BytesPerSector = inputFormat.Tracks[i].BytesPerSector,
|
|
|
|
|
RawBytesPerSector = inputFormat.Tracks[i].RawBytesPerSector,
|
|
|
|
|
Type = inputFormat.Tracks[i].Type,
|
|
|
|
|
SubchannelType = inputFormat.Tracks[i].SubchannelType
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foreach(KeyValuePair<ushort, int> idx in inputFormat.Tracks[i].Indexes)
|
|
|
|
|
tracks[i].Indexes[idx.Key] = idx.Value;
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
|
|
|
|
Where(t => t == SectorTagType.CdTrackIsrc).OrderBy(t => t))
|
|
|
|
|
{
|
|
|
|
|
foreach(Track track in tracks)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
errno = inputFormat.ReadSectorTag(track.Sequence, tag, out byte[] isrc);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(errno != ErrorNumber.NoError)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
isrcs[(byte)track.Sequence] = Encoding.UTF8.GetString(isrc);
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.
|
2022-03-07 07:36:44 +00:00
|
|
|
Where(t => t == SectorTagType.CdTrackFlags).OrderBy(t => t))
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
foreach(Track track in tracks)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
errno = inputFormat.ReadSectorTag(track.Sequence, tag, out byte[] flags);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(errno != ErrorNumber.NoError)
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
trackFlags[(byte)track.Sequence] = flags[0];
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
for(ulong s = 0; s < inputFormat.Info.Sectors; s++)
|
|
|
|
|
{
|
|
|
|
|
if(s > int.MaxValue)
|
|
|
|
|
break;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
subchannelExtents.Add((int)s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach(SectorTagType tag in inputFormat.Info.ReadableSectorTags.OrderBy(t => t).
|
2022-03-16 00:31:33 +00:00
|
|
|
TakeWhile(_ => useLong))
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
switch(tag)
|
|
|
|
|
{
|
|
|
|
|
case SectorTagType.AppleSectorTag:
|
|
|
|
|
case SectorTagType.CdSectorSync:
|
|
|
|
|
case SectorTagType.CdSectorHeader:
|
|
|
|
|
case SectorTagType.CdSectorSubHeader:
|
|
|
|
|
case SectorTagType.CdSectorEdc:
|
|
|
|
|
case SectorTagType.CdSectorEccP:
|
|
|
|
|
case SectorTagType.CdSectorEccQ:
|
|
|
|
|
case SectorTagType.CdSectorEcc:
|
|
|
|
|
// This tags are inline in long sector
|
|
|
|
|
continue;
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(!outputFormat.SupportedSectorTags.Contains(tag))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
foreach(Track track in inputFormat.Tracks)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
doneSectors = 0;
|
|
|
|
|
ulong trackSectors = track.EndSector - track.StartSector + 1;
|
|
|
|
|
byte[] sector;
|
|
|
|
|
bool result;
|
|
|
|
|
|
2021-08-03 00:29:09 +01:00
|
|
|
switch(tag)
|
|
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
case SectorTagType.CdTrackFlags:
|
|
|
|
|
case SectorTagType.CdTrackIsrc:
|
|
|
|
|
errno = inputFormat.ReadSectorTag(track.Sequence, tag, out sector);
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno,
|
2022-11-29 10:33:40 +00:00
|
|
|
string.Format(Localization.Error_0_reading_tag_not_continuing, errno));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
result = outputFormat.WriteSectorTag(sector, track.Sequence, tag);
|
|
|
|
|
|
|
|
|
|
Assert.IsTrue(result,
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Error_0_writing_tag_not_continuing,
|
|
|
|
|
outputFormat.ErrorMessage));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2021-08-03 00:29:09 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
while(doneSectors < trackSectors)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
uint sectorsToDo;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(trackSectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
sectorsToDo = SECTORS_TO_READ;
|
|
|
|
|
else
|
|
|
|
|
sectorsToDo = (uint)(trackSectors - doneSectors);
|
|
|
|
|
|
|
|
|
|
if(sectorsToDo == 1)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
errno = inputFormat.ReadSectorTag(doneSectors + track.StartSector, tag, out sector);
|
2021-09-20 20:52:18 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno,
|
2022-11-29 10:33:40 +00:00
|
|
|
string.Format(Localization.Error_0_reading_tag_not_continuing, errno));
|
2021-09-20 20:52:18 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(tag == SectorTagType.CdSectorSubchannel)
|
|
|
|
|
{
|
|
|
|
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
2022-03-07 07:36:44 +00:00
|
|
|
MmcSubchannel.Raw, sector, doneSectors + track.StartSector, 1, null, isrcs,
|
|
|
|
|
(byte)track.Sequence, ref mcn, tracks, subchannelExtents, true,
|
2022-04-09 20:27:05 +01:00
|
|
|
outputFormat, true, true, null, null, smallestPregapLbaPerTrack, false,
|
|
|
|
|
out _);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(indexesChanged)
|
|
|
|
|
outputFormat.SetTracks(tracks.ToList());
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-03-07 07:36:44 +00:00
|
|
|
result = outputFormat.WriteSectorTag(sector, doneSectors + track.StartSector, tag);
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
else
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-07 07:36:44 +00:00
|
|
|
errno = inputFormat.ReadSectorsTag(doneSectors + track.StartSector, sectorsToDo, tag,
|
|
|
|
|
out sector);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno,
|
2022-11-29 10:33:40 +00:00
|
|
|
string.Format(Localization.Error_0_reading_tag_not_continuing, errno));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(tag == SectorTagType.CdSectorSubchannel)
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
bool indexesChanged = CompactDisc.WriteSubchannelToImage(MmcSubchannel.Raw,
|
2022-03-07 07:36:44 +00:00
|
|
|
MmcSubchannel.Raw, sector, doneSectors + track.StartSector, sectorsToDo,
|
|
|
|
|
null, isrcs, (byte)track.Sequence, ref mcn, tracks, subchannelExtents,
|
|
|
|
|
true, outputFormat, true, true, null, null, smallestPregapLbaPerTrack,
|
2022-04-09 20:27:05 +01:00
|
|
|
false, out _);
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
if(indexesChanged)
|
|
|
|
|
outputFormat.SetTracks(tracks.ToList());
|
|
|
|
|
|
|
|
|
|
result = true;
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
else
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
result = outputFormat.WriteSectorsTag(sector, doneSectors + track.StartSector,
|
|
|
|
|
sectorsToDo, tag);
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.IsTrue(result,
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Error_0_writing_tag_for_sector_1_not_continuing,
|
|
|
|
|
outputFormat.ErrorMessage, doneSectors + track.StartSector));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
doneSectors += sectorsToDo;
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(isrcs.Count > 0)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(KeyValuePair<byte, string> isrc in isrcs)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
outputFormat.WriteSectorTag(Encoding.UTF8.GetBytes(isrc.Value), isrc.Key,
|
|
|
|
|
SectorTagType.CdTrackIsrc);
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(trackFlags.Count > 0)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach((byte track, byte flags) in trackFlags)
|
2023-10-03 23:44:33 +01:00
|
|
|
outputFormat.WriteSectorTag(new[] { flags }, track, SectorTagType.CdTrackFlags);
|
|
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
if(mcn != null)
|
|
|
|
|
outputFormat.WriteMediaTag(Encoding.UTF8.GetBytes(mcn), MediaTagType.CD_MCN);
|
|
|
|
|
|
|
|
|
|
// TODO: Progress
|
2022-03-16 11:47:00 +00:00
|
|
|
if(inputFormat.Info.MediaType is MediaType.CD or MediaType.CDDA or MediaType.CDG or MediaType.CDEG
|
2023-10-03 23:44:33 +01:00
|
|
|
or MediaType.CDI or MediaType.CDROM or MediaType.CDROMXA
|
|
|
|
|
or MediaType.CDPLUS or MediaType.CDMO
|
|
|
|
|
or MediaType.CDR or MediaType.CDRW or MediaType.CDMRW or MediaType.VCD
|
|
|
|
|
or MediaType.SVCD
|
|
|
|
|
or MediaType.PCD or MediaType.DTSCD or MediaType.CDMIDI or MediaType.CDV
|
|
|
|
|
or MediaType.CDIREADY
|
|
|
|
|
or MediaType.FMTOWNS or MediaType.PS1CD or MediaType.PS2CD
|
|
|
|
|
or MediaType.MEGACD or MediaType.SATURNCD
|
|
|
|
|
or MediaType.GDROM or MediaType.GDR or MediaType.MilCD
|
|
|
|
|
or MediaType.SuperCDROM2 or MediaType.JaguarCD
|
|
|
|
|
or MediaType.ThreeDO or MediaType.PCFX or MediaType.NeoGeoCD
|
|
|
|
|
or MediaType.CDTV or MediaType.CD32
|
|
|
|
|
or MediaType.Playdia or MediaType.Pippin or MediaType.VideoNow
|
|
|
|
|
or MediaType.VideoNowColor
|
|
|
|
|
or MediaType.VideoNowXp or MediaType.CVD)
|
|
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
CompactDisc.GenerateSubchannels(subchannelExtents, tracks, trackFlags, inputFormat.Info.Sectors,
|
|
|
|
|
null, null, null, null, null, outputFormat);
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
Assert.IsTrue(outputFormat.Close(),
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format(Localization.Error_0_closing_output_image_Contents_are_not_correct,
|
|
|
|
|
outputFormat.ErrorMessage));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
filtersList = new FiltersList();
|
|
|
|
|
filter = filtersList.GetFilter(outputPath);
|
|
|
|
|
filter.Open(outputPath);
|
|
|
|
|
|
|
|
|
|
string tmpFolder = Path.GetDirectoryName(outputPath);
|
|
|
|
|
Environment.CurrentDirectory = tmpFolder;
|
|
|
|
|
|
|
|
|
|
var image = Activator.CreateInstance(OutputPlugin.GetType()) as IOpticalMediaImage;
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.NotNull(image, string.Format(Localization.Could_not_instantiate_output_plugin_for_0, testFile));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
opened = image.Open(filter);
|
2022-11-29 10:33:40 +00:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, opened, string.Format(Localization.Open_created_0, testFile));
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
if(opened != ErrorNumber.NoError)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
using(new AssertionScope())
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.Multiple(() =>
|
|
|
|
|
{
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.Sectors, image.Info.Sectors,
|
|
|
|
|
string.Format(Localization.Sectors_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(test.SectorSize > 0)
|
2023-10-03 23:44:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.AreEqual(test.SectorSize, image.Info.SectorSize,
|
2022-11-29 10:33:40 +00:00
|
|
|
string.Format(Localization.Sector_size_output_0, testFile));
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.Tracks.Length, image.Tracks.Count,
|
|
|
|
|
string.Format(Localization.Tracks_output_0, testFile));
|
2021-09-20 20:52:18 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.Session).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Session),
|
|
|
|
|
string.Format(Localization.Track_session_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.StartSector).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Start),
|
|
|
|
|
string.Format(Localization.Track_start_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.EndSector).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.End),
|
|
|
|
|
string.Format(Localization.Track_end_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
image.Tracks.Select(t => t.Pregap).Should().
|
2022-12-11 22:20:23 +00:00
|
|
|
BeEquivalentTo(test.Tracks.Select(s => s.Pregap),
|
|
|
|
|
string.Format(Localization.Track_pregap_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
var trackNo = 0;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2023-10-03 23:44:33 +01:00
|
|
|
var flags = new byte?[image.Tracks.Count];
|
|
|
|
|
ulong latestEndSector = 0;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
|
|
|
|
foreach(Track currentTrack in image.Tracks)
|
|
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(currentTrack.EndSector > latestEndSector)
|
|
|
|
|
latestEndSector = currentTrack.EndSector;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(image.Info.ReadableSectorTags.Contains(SectorTagType.CdTrackFlags))
|
2021-08-03 00:29:09 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
errno = image.ReadSectorTag(currentTrack.Sequence, SectorTagType.CdTrackFlags,
|
|
|
|
|
out byte[] tmp);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(errno == ErrorNumber.NoError)
|
|
|
|
|
flags[trackNo] = tmp[0];
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
trackNo++;
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
flags.Should().BeEquivalentTo(test.Tracks.Select(s => s.Flags),
|
2022-11-29 10:33:40 +00:00
|
|
|
string.Format(Localization.Track_flags_output_0, testFile));
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
Assert.AreEqual(latestEndSector, image.Info.Sectors - 1,
|
2022-12-11 22:20:23 +00:00
|
|
|
string.
|
2023-10-03 23:44:33 +01:00
|
|
|
Format(
|
|
|
|
|
Localization.Last_sector_for_tracks_is_0_but_it_is_1_for_image_output,
|
|
|
|
|
latestEndSector, image.Info.Sectors));
|
2022-03-06 13:29:38 +00:00
|
|
|
});
|
2023-10-03 23:44:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
Md5Context ctx;
|
2021-08-03 00:29:09 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
foreach(bool @long in new[]
|
|
|
|
|
{
|
|
|
|
|
/*false,*/ true
|
|
|
|
|
})
|
|
|
|
|
{
|
2021-08-03 00:29:09 +01:00
|
|
|
ctx = new Md5Context();
|
|
|
|
|
|
|
|
|
|
foreach(Track currentTrack in image.Tracks)
|
|
|
|
|
{
|
2021-09-14 21:18:28 +01:00
|
|
|
ulong sectors = currentTrack.EndSector - currentTrack.StartSector + 1;
|
2021-08-03 00:29:09 +01:00
|
|
|
doneSectors = 0;
|
|
|
|
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
{
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
|
|
|
if(sectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
{
|
2023-10-03 23:44:33 +01:00
|
|
|
errno = @long
|
|
|
|
|
? image.ReadSectorsLong(doneSectors, SECTORS_TO_READ,
|
|
|
|
|
currentTrack.Sequence, out sector)
|
2022-03-06 13:29:38 +00:00
|
|
|
: image.ReadSectors(doneSectors, SECTORS_TO_READ, currentTrack.Sequence,
|
|
|
|
|
out sector);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
|
|
|
|
doneSectors += SECTORS_TO_READ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-03 23:44:33 +01:00
|
|
|
errno = @long
|
|
|
|
|
? image.ReadSectorsLong(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
currentTrack.Sequence, out sector)
|
2022-03-06 13:29:38 +00:00
|
|
|
: image.ReadSectors(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
currentTrack.Sequence, out sector);
|
2021-08-03 00:29:09 +01:00
|
|
|
|
|
|
|
|
doneSectors += sectors - doneSectors;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-21 03:42:15 +01:00
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno);
|
|
|
|
|
|
2021-08-03 00:29:09 +01:00
|
|
|
ctx.Update(sector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 01:37:37 +00:00
|
|
|
Assert.AreEqual(@long ? test.LongMd5 : test.Md5, ctx.End(),
|
2022-12-11 22:20:23 +00:00
|
|
|
string.Format("{0}: {1}",
|
|
|
|
|
@long ? Localization.Long_hash_output : Localization.Hash_output,
|
|
|
|
|
testFile));
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!image.Info.ReadableSectorTags.Contains(SectorTagType.CdSectorSubchannel))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ctx = new Md5Context();
|
|
|
|
|
|
|
|
|
|
foreach(Track currentTrack in image.Tracks)
|
|
|
|
|
{
|
|
|
|
|
ulong sectors = currentTrack.EndSector - currentTrack.StartSector + 1;
|
|
|
|
|
doneSectors = 0;
|
|
|
|
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
{
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
|
|
|
if(sectors - doneSectors >= SECTORS_TO_READ)
|
|
|
|
|
{
|
|
|
|
|
errno = image.ReadSectorsTag(doneSectors, SECTORS_TO_READ, currentTrack.Sequence,
|
|
|
|
|
SectorTagType.CdSectorSubchannel, out sector);
|
|
|
|
|
|
|
|
|
|
doneSectors += SECTORS_TO_READ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
errno = image.ReadSectorsTag(doneSectors, (uint)(sectors - doneSectors),
|
|
|
|
|
currentTrack.Sequence, SectorTagType.CdSectorSubchannel,
|
|
|
|
|
out sector);
|
|
|
|
|
|
|
|
|
|
doneSectors += sectors - doneSectors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(ErrorNumber.NoError, errno);
|
|
|
|
|
|
|
|
|
|
ctx.Update(sector);
|
|
|
|
|
}
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-12-11 22:20:23 +00:00
|
|
|
Assert.AreEqual(test.SubchannelMd5, ctx.End(),
|
|
|
|
|
string.Format(Localization.Subchannel_hash_output_0, testFile));
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
|
|
|
|
});
|
2021-08-03 00:29:09 +01:00
|
|
|
}
|
|
|
|
|
}
|