Files
Aaru/Aaru.Core/Image/Convert/CSS/ConvertCssDvd.cs
2026-04-12 20:22:33 +02:00

204 lines
10 KiB
C#

using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs;
using Aaru.Localization;
namespace Aaru.Core.Image;
public partial class Convert
{
/// <summary>Converts CSS-encrypted DVD optical sectors.</summary>
/// <param name="inputOptical">Input optical media image.</param>
/// <param name="outputOptical">Output optical media image.</param>
/// <param name="useLong">True to use long sector reads.</param>
/// <returns>Error number.</returns>
ErrorNumber ConvertCssDvdOpticalSectors(IOpticalMediaImage inputOptical, IWritableOpticalImage outputOptical,
bool useLong)
{
if(_aborted) return ErrorNumber.NoError;
InitProgress?.Invoke();
InitProgress2?.Invoke();
byte[] generatedTitleKeys = null;
int currentTrack = 0;
foreach(Track track in inputOptical.Tracks)
{
if(_aborted) break;
UpdateProgress?.Invoke(string.Format(UI.Converting_sectors_in_track_0_of_1,
currentTrack + 1,
inputOptical.Tracks.Count),
currentTrack,
inputOptical.Tracks.Count);
ulong doneSectors = 0;
ulong trackSectors = track.EndSector - track.StartSector + 1;
while(doneSectors < trackSectors)
{
if(_aborted) break;
byte[] sector;
uint sectorsToDo = trackSectors - doneSectors >= _count ? _count : (uint)(trackSectors - doneSectors);
UpdateProgress2?.Invoke(string.Format(UI.Converting_sectors_0_to_1_in_track_2,
doneSectors + track.StartSector,
doneSectors + sectorsToDo + track.StartSector,
track.Sequence),
(long)doneSectors,
(long)trackSectors);
bool result = false;
SectorStatus sectorStatus = SectorStatus.NotDumped;
SectorStatus[] sectorStatusArray = new SectorStatus[1];
ErrorNumber errno;
if(useLong)
{
errno = sectorsToDo == 1
? inputOptical.ReadSectorLong(doneSectors + track.StartSector,
false,
out sector,
out sectorStatus)
: inputOptical.ReadSectorsLong(doneSectors + track.StartSector,
false,
sectorsToDo,
out sector,
out sectorStatusArray);
if(errno == ErrorNumber.NoError)
{
CssDvdSectorDecrypt.ApplyCssAfterReadLong(ref sector,
ref sectorStatus,
sectorStatusArray,
sectorsToDo,
sectorsToDo == 1,
inputOptical,
doneSectors + track.StartSector,
_plugins,
ref generatedTitleKeys,
() => _aborted,
MODULE_NAME);
result = sectorsToDo == 1
? outputOptical.WriteSectorLong(sector,
doneSectors + track.StartSector,
false,
sectorStatus)
: outputOptical.WriteSectorsLong(sector,
doneSectors + track.StartSector,
false,
sectorsToDo,
sectorStatusArray);
}
else
{
result = true;
if(_force)
{
ErrorMessage?.Invoke(string.Format(UI.Error_0_reading_sector_1_continuing,
errno,
doneSectors + track.StartSector));
}
else
{
StoppingErrorMessage?.Invoke(string.Format(UI.Error_0_reading_sector_1_not_continuing,
errno,
doneSectors + track.StartSector));
return ErrorNumber.WriteError;
}
}
}
else
{
errno = sectorsToDo == 1
? inputOptical.ReadSector(doneSectors + track.StartSector,
false,
out sector,
out sectorStatus)
: inputOptical.ReadSectors(doneSectors + track.StartSector,
false,
sectorsToDo,
out sector,
out sectorStatusArray);
if(errno == ErrorNumber.NoError)
{
CssDvdSectorDecrypt.ApplyCssAfterRead(ref sector,
ref sectorStatus,
sectorStatusArray,
sectorsToDo,
sectorsToDo == 1,
inputOptical,
doneSectors + track.StartSector,
_plugins,
ref generatedTitleKeys,
() => _aborted,
MODULE_NAME);
result = sectorsToDo == 1
? outputOptical.WriteSector(sector,
doneSectors + track.StartSector,
false,
sectorStatus)
: outputOptical.WriteSectors(sector,
doneSectors + track.StartSector,
false,
sectorsToDo,
sectorStatusArray);
}
else
{
result = true;
if(_force)
{
ErrorMessage?.Invoke(string.Format(UI.Error_0_reading_sector_1_continuing,
errno,
doneSectors + track.StartSector));
}
else
{
StoppingErrorMessage?.Invoke(string.Format(UI.Error_0_reading_sector_1_not_continuing,
errno,
doneSectors + track.StartSector));
return ErrorNumber.WriteError;
}
}
}
if(!result)
{
if(_force)
{
ErrorMessage?.Invoke(string.Format(UI.Error_0_writing_sector_1_continuing,
outputOptical.ErrorMessage,
doneSectors + track.StartSector));
}
else
{
StoppingErrorMessage?.Invoke(string.Format(UI.Error_0_writing_sector_1_not_continuing,
outputOptical.ErrorMessage,
doneSectors + track.StartSector));
return ErrorNumber.WriteError;
}
}
doneSectors += sectorsToDo;
}
currentTrack++;
}
EndProgress2?.Invoke();
EndProgress?.Invoke();
return ErrorNumber.NoError;
}
}