8000 Read Lite-On raw DVD buffer by FakeShemp · Pull Request #866 · aaru-dps/Aaru · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Read Lite-On raw DVD buffer #866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Aaru.CommonTypes/Metadata/DeviceReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,9 @@ public class TestedMedia
[DisplayName("Can read scrambled DVD sectors using HL-DT-ST cache trick")]
public bool? SupportsHLDTSTReadRawDVD { get; set; }

[DisplayName("Can read scrambled DVD sectors using Lite-On cache trick")]
public bool? SupportsLiteOnReadRawDVD { get; set; }

[DisplayName("Supports NEC READ CD-DA command")]
public bool? SupportsNECReadCDDA { get; set; }

Expand Down Expand Up @@ -1155,6 +1158,9 @@ public class TestedMedia
[DisplayName("Data from HL-DT-ST's scrambled DVD reading trick")]
public byte[] HLDTSTReadRawDVDData { get; set; }

[DisplayName("Data from Lite-On's scrambled DVD reading trick")]
public byte[] LiteOnReadRawDVDData { get; set; }

#endregion
}

Expand Down
2 changes: 1 addition & 1 deletion Aaru.Core/Devices/Dumping/Sbc/Cache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void ReadCacheData(in ulong blocks, in uint maxBlocksToRead, in uint blockSi

// Write empty data
_writeStopwatch.Restart();
outputFormat.WriteSectors(new byte[blockSize * _skip], i, _skip);
outputFormat.WriteSectorsLong(new byte[blockSize * _skip], i, _skip);
imageWriteDuration += _writeStopwatch.Elapsed.TotalSeconds;

for(ulong b = i; b < i + _skip; b++) _resume.BadBlocks.Add(b);
Expand Down
27 changes: 21 additions & 6 deletions Aaru.Core/Devices/Dumping/Sbc/Dump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
using Track = Aaru.CommonTypes.Structs.Track;
using TrackType = Aaru.CommonTypes.Enums.TrackType;
using Version = Aaru.CommonTypes.Interop.Version;
using Aaru.Decoders.DVD;

// ReSharper disable JoinDeclarationAndInitializer

Expand Down Expand Up @@ -332,11 +333,19 @@ void Sbc(Dictionary<MediaTagType, byte[]> mediaTags, MediaType dskType, bool opt
else
{
// Only a block will be read, but it contains 16 sectors and command expect sector number not block number
blocksToRead = (uint)(longBlockSize == 37856 ? 16 : 1);
blocksToRead = 16;

mediaTags.TryGetValue(MediaTagType.DVD_PFI, out byte[] pfi);
PFI.PhysicalFormatInformation? decodedPfi = PFI.Decode(pfi, dskType);

scsiReader.layerbreak = decodedPfi?.Layer0EndPSN ?? 0;
scsiReader.otp = decodedPfi is { Layers: 1, TrackPath: false };

if(scsiReader.HldtstReadRaw) blocksToRead = 1;

UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_raw_bytes_1_cooked_bytes_per_sector,
longBlockSize,
blockSize * blocksToRead));
blockSize));

physicalBlockSize = longBlockSize;
blockSize = longBlockSize;
Expand Down Expand Up @@ -835,7 +844,7 @@ void Sbc(Dictionary<MediaTagType, byte[]> mediaTags, MediaType dskType, bool opt
{
mediaTags.TryGetValue(MediaTagType.DVD_DiscKey_Decrypted, out byte[] discKey);

if(scsiReader.HldtstReadRaw)
if(scsiReader.HldtstReadRaw || scsiReader.LiteOnReadRaw)
{
ReadCacheData(blocks,
blocksToRead,
Expand Down Expand Up @@ -913,6 +922,8 @@ void Sbc(Dictionary<MediaTagType, byte[]> mediaTags, MediaType dskType, bool opt

#region Trimming

mediaTags.TryGetValue(MediaTagType.DVD_DiscKey_Decrypted, out byte[] mediaTag);

if(_resume.BadBlocks.Count > 0 && !_aborted && _trim && newTrim)
{
_trimStopwatch.Restart();
Expand All @@ -921,7 +932,7 @@ void Sbc(Dictionary<MediaTagType, byte[]> mediaTags, MediaType dskType, bool opt

InitProgress?.Invoke();

TrimSbcData(scsiReader, extents, currentTry, blankExtents);
TrimSbcData(scsiReader, extents, currentTry, blankExtents, mediaTag ?? null);

EndProgress?.Invoke();
_trimStopwatch.Stop();
Expand All @@ -940,14 +951,18 @@ void Sbc(Dictionary<MediaTagType, byte[]> mediaTags, MediaType dskType, bool opt
#region Error handling

if(_resume.BadBlocks.Count > 0 && !_aborted && _retryPasses > 0)
RetrySbcData(scsiReader, currentTry, extents, ref totalDuration, blankExtents);
RetrySbcData(scsiReader, currentTry, extents, ref totalDuration, blankExtents, mediaTag ?? null);

if(_resume.MissingTitleKeys?.Count > 0 &&
!_aborted &&
_retryPasses > 0 &&
Settings.Settings.Current.EnableDecryption &&
_titleKeys &&
mediaTags.TryGetValue(MediaTagType.DVD_DiscKey_Decrypted, out byte[] mediaTag))

// Unnecessary since keys are already in raw data
!scsiReader.LiteOnReadRaw &&
!scsiReader.HldtstReadRaw &&
mediaTag is not null)
RetryTitleKeys(dvdDecrypt, mediaTag, ref totalDuration);

#endregion Error handling
Expand Down
48 changes: 46 additions & 2 deletions Aaru.Core/Devices/Dumping/Sbc/Error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ partial class Dump
/// <param name="scsiReader">SCSI reader</param>
/// <param name="blankExtents">Blank extents</param>
void RetrySbcData(Reader scsiReader, DumpHardware currentTry, ExtentsULong extents, ref double totalDuration,
ExtentsULong blankExtents)
ExtentsULong blankExtents, byte[] discKey)
{
var pass = 1;
var forward = true;
Expand Down Expand Up @@ -312,7 +312,51 @@ void RetrySbcData(Reader scsiReader, DumpHardware currentTry, ExtentsULong
{
_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputFormat.WriteSector(buffer, badSector);

if(scsiReader.LiteOnReadRaw || scsiReader.HldtstReadRaw)
{
byte[] cmi = new byte[1];

byte[] key = buffer.Skip(7).Take(5).ToArray();

if(key.All(static k => k == 0))
{
outputFormat.WriteSectorTag([0, 0, 0, 0, 0], badSector, SectorTagType.DvdTitleKeyDecrypted);

_resume.MissingTitleKeys?.Remove(badSector);
}
else
{
CSS.DecryptTitleKey(discKey, key, out byte[] tmpBuf);
outputFormat.WriteSectorTag(tmpBuf, badSector, SectorTagType.DvdTitleKeyDecrypted);
_resume.MissingTitleKeys?.Remove(badSector);

cmi[0] = buffer[6];
}

if(!_storeEncrypted)
{
ErrorNumber errno =
outputFormat.ReadSectorsTag(badSector,
1,
SectorTagType.DvdTitleKeyDecrypted,
out byte[] titleKey);

if(errno != ErrorNumber.NoError)
{
ErrorMessage?.Invoke(string.Format(Localization.Core.Error_retrieving_title_key_for_sector_0,
badSector));
}
else
buffer = CSS.DecryptSectorLong(buffer, titleKey, cmi);
}

_resume.BadBlocks.Remove(badSector);
outputFormat.WriteSectorLong(buffer, badSector);
}
else
outputFormat.WriteSector(buffer, badSector);

_mediaGraph?.PaintSectorGood(badSector);

UpdateStatus?.Invoke(string.Format(Localization.Core.Correctly_retried_block_0_in_pass_1,
Expand Down
59 changes: 57 additions & 2 deletions Aaru.Core/Devices/Dumping/Sbc/Trim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
// ReSharper disable InlineOutVariableDeclaration
// ReSharper disable TooWideLocalVariableScope

using System.Linq;
using Aaru.CommonTypes.AaruMetadata;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Extents;
using Aaru.CommonTypes.Interfaces;
using Aaru.Decryption.DVD;

namespace Aaru.Core.Devices.Dumping;

Expand All @@ -41,7 +44,7 @@ partial class Dump
/// <param name="extents">Correctly dump extents</param>
/// <param name="currentTry">Resume information</param>
/// <param name="blankExtents">Blank extents</param>
void TrimSbcData(Reader scsiReader, ExtentsULong extents, DumpHardware currentTry, ExtentsULong blankExtents)
void TrimSbcData(Reader scsiReader, ExtentsULong extents, DumpHardware currentTry, ExtentsULong blankExtents, byte[] discKey)
{
ulong[] tmpArray = _resume.BadBlocks.ToArray();
bool sense;
Expand Down Expand Up @@ -86,9 +89,61 @@ void TrimSbcData(Reader scsiReader, ExtentsULong extents, DumpHardware currentTr

if((sense || _dev.Error) && !recoveredError) continue;

if(scsiReader.HldtstReadRaw)

// The HL-DT-ST buffer is stored and read in 96-sector chunks. If we start to read at an LBA which is
// not modulo 96, the data will not be correctly fetched. Therefore, we begin every recovery read with
// filling the buffer at a known offset.
// TODO: This is very ugly and there probably exist a more elegant way to solve this issue.
scsiReader.ReadBlock(out _, badSector - badSector % 96 + 1, out _, out _, out _);

_resume.BadBlocks.Remove(badSector);
extents.Add(badSector);
outputFormat.WriteSector(buffer, badSector);

if(scsiReader.LiteOnReadRaw || scsiReader.HldtstReadRaw)
{
byte[] cmi = new byte[1];

byte[] key = buffer.Skip(7).Take(5).ToArray();

if(key.All(static k => k == 0))
{
outputFormat.WriteSectorTag([0, 0, 0, 0, 0], badSector, SectorTagType.DvdTitleKeyDecrypted);

_resume.MissingTitleKeys?.Remove(badSector);
}
else
{
CSS.DecryptTitleKey(discKey, key, out byte[] tmpBuf);
outputFormat.WriteSectorTag(tmpBuf, badSector, SectorTagType.DvdTitleKeyDecrypted);
_resume.MissingTitleKeys?.Remove(badSector);

cmi[0] = buffer[6];
}

if(!_storeEncrypted)
{
ErrorNumber errno =
outputFormat.ReadSectorsTag(badSector,
1,
SectorTagType.DvdTitleKeyDecrypted,
out byte[] titleKey);

if(errno != ErrorNumber.NoError)
{
ErrorMessage?.Invoke(string.Format(Localization.Core.Error_retrieving_title_key_for_sector_0,
badSector));
}
else
buffer = CSS.DecryptSectorLong(buffer, titleKey, cmi);
}

_resume.BadBlocks.Remove(badSector);
outputFormat.WriteSectorLong(buffer, badSector);
}
else
outputFormat.WriteSector(buffer, badSector);

_mediaGraph?.PaintSectorGood(badSector);
}

Expand Down
56 changes: 34 additions & 22 deletions Aaru.Core/Devices/ReaderSCSI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ sealed partial class Reader

// TODO: Raw reading
public bool HldtstReadRaw;
public bool LiteOnReadRaw;
public uint layerbreak;
public bool otp;

ulong ScsiGetBlocks() => ScsiGetBlockSize() ? 0 : Blocks;

Expand Down Expand Up @@ -570,16 +573,22 @@ bool ScsiFindReadCommand()
switch(_dev.Manufacturer)
{
case "HL-DT-ST":
HldtstReadRaw = !_dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _);
HldtstReadRaw =
!_dev.HlDtStReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _, layerbreak, otp);

break;
case "PLEXTOR":
_plextorReadRaw = !_dev.PlextorReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _);

break;
case "LITE-ON":
LiteOnReadRaw =
!_dev.LiteOnReadRawDvd(out _, out senseBuf, 0, 1, _timeout, out _, layerbreak, otp);

break;
}

if(HldtstReadRaw || _plextorReadRaw)
if(HldtstReadRaw || _plextorReadRaw || LiteOnReadRaw)
{
CanReadRaw = true;
LongBlockSize = 2064;
Expand Down Expand Up @@ -612,7 +621,9 @@ bool ScsiFindReadCommand()
AaruConsole.WriteLine(Localization.Core.Using_SyQuest_READ_LONG_6_command);
else if(HldtstReadRaw)
AaruConsole.WriteLine(Localization.Core.Using_HL_DT_ST_raw_DVD_reading);
else if(_plextorReadRaw) AaruConsole.WriteLine(Localization.Core.Using_Plextor_raw_DVD_reading);
else if(_plextorReadRaw)
AaruConsole.WriteLine(Localization.Core.Using_Plextor_raw_DVD_reading);
else if(LiteOnReadRaw) AaruConsole.WriteLine(Localization.Core.Using_Lite_On_raw_DVD_reading);
}
else if(_read6)
AaruConsole.WriteLine(Localization.Core.Using_SCSI_READ_6_command);
Expand Down Expand Up @@ -674,7 +685,7 @@ bool ScsiGetBlocksToRead(uint startWithBlocks)

while(true)
{
if(HldtstReadRaw)
if(HldtstReadRaw || LiteOnReadRaw)
BlocksToRead = 1;
else if(_read6)
{
Expand Down Expand Up @@ -804,24 +815,14 @@ bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double durat
}
else if(HldtstReadRaw)
{
// We need to fill the buffer before reading it with the HL-DT-ST command. We don't care about sense,
// because the data can be wrong anyway, so we need to check the buffer data instead.
_dev.Read12(out buffer,
out senseBuf,
0,
false,
false,
false,
false,
(uint)block,
LogicalBlockSize,
0,
16,
false,
_timeout,
out duration);

sense = _dev.HlDtStReadRawDvd(out buffer, out senseBuf, (uint)block, count, _timeout, out duration);
sense = _dev.HlDtStReadRawDvd(out buffer,
out senseBuf,
(uint)block,
count,
_timeout,
out duration,
layerbreak,
otp);
}
else if(_plextorReadRaw)
{
Expand All @@ -832,6 +833,17 @@ bool ScsiReadBlocks(out byte[] buffer, ulong block, uint count, out double durat
_timeout,
out duration);
}
else if(LiteOnReadRaw)
{
sense = _dev.LiteOnReadRawDvd(out buffer,
out senseBuf,
(uint)block,
count,
_timeout,
out duration,
layerbreak,
otp);
}
else
return true;
}
Expand Down
Loading
Loading
0