Add reader for DiscImageCreator DVD Raw dumps (#817)

This commit is contained in:
Rebecca Wallander
2023-08-22 16:27:52 +02:00
committed by GitHub
parent d1d9e0833e
commit ebf893e278
19 changed files with 798 additions and 95 deletions

View File

@@ -136,7 +136,7 @@ partial class Dump
outputFormat.WriteSectorTag(new[]
{
titleKey.Value.CMI
}, i + j, SectorTagType.DvdCmi);
}, i + j, SectorTagType.DvdSectorCmi);
else
continue;
@@ -147,7 +147,7 @@ partial class Dump
outputFormat.WriteSectorTag(new byte[]
{
0, 0, 0, 0, 0
}, i + j, SectorTagType.DvdTitleKey);
}, i + j, SectorTagType.DvdSectorTitleKey);
outputFormat.WriteSectorTag(new byte[]
{
@@ -166,7 +166,7 @@ partial class Dump
outputFormat.WriteSectorTag(new byte[]
{
0, 0, 0, 0, 0
}, i + j, SectorTagType.DvdTitleKey);
}, i + j, SectorTagType.DvdSectorTitleKey);
outputFormat.WriteSectorTag(new byte[]
{
@@ -178,7 +178,7 @@ partial class Dump
continue;
}
outputFormat.WriteSectorTag(titleKey.Value.Key, i + j, SectorTagType.DvdTitleKey);
outputFormat.WriteSectorTag(titleKey.Value.Key, i + j, SectorTagType.DvdSectorTitleKey);
_resume.MissingTitleKeys.Remove(i + j);
CSS.DecryptTitleKey(discKey, titleKey.Value.Key, out tmpBuf);
@@ -190,7 +190,7 @@ partial class Dump
// Todo: Flag in the outputFormat that a sector has been decrypted
{
ErrorNumber errno =
outputFormat.ReadSectorsTag(i, blocksToRead, SectorTagType.DvdCmi, out byte[] cmi);
outputFormat.ReadSectorsTag(i, blocksToRead, SectorTagType.DvdSectorCmi, out byte[] cmi);
if(errno != ErrorNumber.NoError)
ErrorMessage?.Invoke(string.Format(Localization.Core.Error_retrieving_CMI_for_sector_0, i));

View File

@@ -378,7 +378,7 @@ partial class Dump
outputFormat.WriteSectorTag(new[]
{
titleKey.Value.CMI
}, missingKey, SectorTagType.DvdCmi);
}, missingKey, SectorTagType.DvdSectorCmi);
// If the CMI bit is 1, the sector is using copy protection, else it is not
// If the decoded title key is zeroed, there should be no copy protection
@@ -388,7 +388,7 @@ partial class Dump
outputFormat.WriteSectorTag(new byte[]
{
0, 0, 0, 0, 0
}, missingKey, SectorTagType.DvdTitleKey);
}, missingKey, SectorTagType.DvdSectorTitleKey);
outputFormat.WriteSectorTag(new byte[]
{
@@ -404,7 +404,7 @@ partial class Dump
}
else
{
outputFormat.WriteSectorTag(titleKey.Value.Key, missingKey, SectorTagType.DvdTitleKey);
outputFormat.WriteSectorTag(titleKey.Value.Key, missingKey, SectorTagType.DvdSectorTitleKey);
_resume.MissingTitleKeys.Remove(missingKey);
if(discKey != null)

View File

@@ -48,6 +48,7 @@ using Aaru.Decoders.Sega;
using Aaru.Devices;
using Aaru.Helpers;
using DMI = Aaru.Decoders.Xbox.DMI;
using Sector = Aaru.Decoders.CD.Sector;
namespace Aaru.Core.Media.Detection;

View File

@@ -93,7 +93,7 @@ public partial class Device
/// If set to <c>true</c> requested blocks shall be assigned the lowest retention priority on cache
/// fetch/retain.
/// </param>
/// <param name="fua">If set to <c>true</c> requested blocks MUST bu read from medium and not the cache.</param>
/// <param name="fua">If set to <c>true</c> requested blocks MUST be read from medium and not the cache.</param>
/// <param name="fuaNv">
/// If set to <c>true</c> requested blocks will be returned from non-volatile cache. If they're not
/// present they shall be stored there.

View File

@@ -128,7 +128,10 @@ public sealed partial class AaruFormat : IWritableOpticalImage, IVerifiableImage
/// <summary>If DDT is on-disk, this is the image stream offset at which it starts.</summary>
long _outMemoryDdtPosition;
bool _rewinded;
byte[] _sectorCpiMai;
byte[] _sectorCprMai;
byte[] _sectorIed;
byte[] _sectorId;
byte[] _sectorEdc;
byte[] _sectorDecryptedTitleKey;
/// <summary>Cache for data that prefixes the user data on a sector (e.g. sync).</summary>
byte[] _sectorPrefix;

View File

@@ -214,10 +214,16 @@ public sealed partial class AaruFormat
CompactDiscLeadIn = 79,
/// <summary>Decrypted DVD Disc Key</summary>
DvdDiscKeyDecrypted = 80,
/// <summary>DVD CPI_MAI</summary>
DvdSectorCpiMai = 81,
/// <summary>DVD Copyright Management Information (CPR_MAI)</summary>
DvdSectorCprMai = 81,
/// <summary>Decrypted DVD Title Key</summary>
DvdSectorTitleKeyDecrypted = 82
DvdSectorTitleKeyDecrypted = 82,
/// <summary>DVD Identification Data (ID)</summary>
DvdSectorId = 83,
/// <summary>DVD ID Error Detection Code (IED)</summary>
DvdSectorIed = 84,
/// <summary>DVD Error Detection Code (EDC)</summary>
DvdSectorEdc = 85
}
/// <summary>List of known blocks types</summary>

View File

@@ -382,14 +382,47 @@ public sealed partial class AaruFormat
GC.GetTotalMemory(false));
break;
case DataType.DvdSectorCpiMai:
_sectorCpiMai = data;
case DataType.DvdSectorCprMai:
_sectorCprMai = data;
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdCmi))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdCmi);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorCmi))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorCmi);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKey))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKey);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorTitleKey))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorTitleKey);
AaruConsole.DebugWriteLine("Aaru Format plugin", Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
break;
case DataType.DvdSectorId:
_sectorId = data;
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorInformation))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorInformation);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorNumber))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorNumber);
AaruConsole.DebugWriteLine("Aaru Format plugin", Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
break;
case DataType.DvdSectorIed:
_sectorDecryptedTitleKey = data;
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorIed))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorIed);
AaruConsole.DebugWriteLine("Aaru Format plugin", Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
break;
case DataType.DvdSectorEdc:
_sectorDecryptedTitleKey = data;
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorEdc))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorEdc);
AaruConsole.DebugWriteLine("Aaru Format plugin", Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
@@ -1769,8 +1802,12 @@ public sealed partial class AaruFormat
case SectorTagType.CdSectorSubchannel:
case SectorTagType.CdSectorSubHeader:
case SectorTagType.CdSectorSync:
case SectorTagType.DvdCmi:
case SectorTagType.DvdTitleKey:
case SectorTagType.DvdSectorCmi:
case SectorTagType.DvdSectorTitleKey:
case SectorTagType.DvdSectorInformation:
case SectorTagType.DvdSectorNumber:
case SectorTagType.DvdSectorIed:
case SectorTagType.DvdSectorEdc:
case SectorTagType.DvdTitleKeyDecrypted: break;
case SectorTagType.CdTrackFlags:
if(!_trackFlags.TryGetValue((byte)sectorAddress, out byte flags))
@@ -1954,21 +1991,57 @@ public sealed partial class AaruFormat
if(_imageInfo.MediaType == MediaType.DVDROM)
switch(tag)
{
case SectorTagType.DvdCmi:
case SectorTagType.DvdSectorCmi:
{
sectorOffset = 0;
sectorSize = 1;
sectorSkip = 5;
dataSource = _sectorCpiMai;
dataSource = _sectorCprMai;
break;
}
case SectorTagType.DvdTitleKey:
case SectorTagType.DvdSectorTitleKey:
{
sectorOffset = 1;
sectorSize = 5;
sectorSkip = 0;
dataSource = _sectorCpiMai;
dataSource = _sectorCprMai;
break;
}
case SectorTagType.DvdSectorInformation:
{
sectorOffset = 0;
sectorSize = 1;
sectorSkip = 3;
dataSource = _sectorId;
break;
}
case SectorTagType.DvdSectorNumber:
{
sectorOffset = 1;
sectorSize = 3;
sectorSkip = 0;
dataSource = _sectorId;
break;
}
case SectorTagType.DvdSectorIed:
{
sectorOffset = 0;
sectorSize = 2;
sectorSkip = 0;
dataSource = _sectorIed;
break;
}
case SectorTagType.DvdSectorEdc:
{
sectorOffset = 0;
sectorSize = 4;
sectorSkip = 0;
dataSource = _sectorEdc;
break;
}

View File

@@ -554,14 +554,14 @@ public sealed partial class AaruFormat
GC.GetTotalMemory(false));
break;
case DataType.DvdSectorCpiMai:
_sectorCpiMai = data;
case DataType.DvdSectorCprMai:
_sectorCprMai = data;
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdCmi))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdCmi);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorCmi))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorCmi);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdTitleKey))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdTitleKey);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorTitleKey))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorTitleKey);
AaruConsole.DebugWriteLine("Aaru Format plugin", Localization.Memory_snapshot_0_bytes,
GC.GetTotalMemory(false));
@@ -2030,6 +2030,24 @@ public sealed partial class AaruFormat
track.EndSector == 0)
track.Type = TrackType.Data;
if(data.Length == 2064 &&
_imageInfo.MediaType == MediaType.DVDROM)
{
sector = new byte[2048];
_sectorId ??= new byte[_imageInfo.Sectors * 4];
_sectorIed ??= new byte[_imageInfo.Sectors * 2];
_sectorCprMai ??= new byte[_imageInfo.Sectors * 6];
_sectorEdc ??= new byte[_imageInfo.Sectors * 4];
Array.Copy(data, 0, _sectorId, (int)sectorAddress * 4, 4);
Array.Copy(data, 4, _sectorIed, (int)sectorAddress * 2, 2);
Array.Copy(data, 6, _sectorCprMai, (int)sectorAddress * 6, 6);
Array.Copy(data, 12, sector, 0, 2048);
Array.Copy(data, 2060, _sectorEdc, (int)sectorAddress * 4, 4);
return WriteSector(sector, sectorAddress);
}
if(data.Length != 2352)
{
ErrorMessage = Localization.Incorrect_data_size;
@@ -2426,6 +2444,31 @@ public sealed partial class AaruFormat
switch(_imageInfo.MetadataMediaType)
{
case MetadataMediaType.OpticalDisc:
switch(_imageInfo.MediaType)
{
case MediaType.DVDROM:
if(data.Length % 2064 != 0)
{
ErrorMessage = Localization.Incorrect_data_size;
return false;
}
sector = new byte[2064];
for(uint i = 0; i < length; i++)
{
Array.Copy(data, 2064 * i, sector, 0, 2064);
if(!WriteSectorLong(sector, sectorAddress + i))
return false;
}
ErrorMessage = "";
return true;
default:
if(data.Length % 2352 != 0)
{
ErrorMessage = Localization.Incorrect_data_size;
@@ -2446,6 +2489,8 @@ public sealed partial class AaruFormat
ErrorMessage = "";
return true;
}
case MetadataMediaType.BlockMedia:
switch(_imageInfo.MediaType)
{
@@ -4037,25 +4082,25 @@ public sealed partial class AaruFormat
blockStream.Close();
}
if(_sectorCpiMai != null)
if(_sectorCprMai != null)
{
idxEntry = new IndexEntry
{
blockType = BlockType.DataBlock,
dataType = DataType.DvdSectorCpiMai,
dataType = DataType.DvdSectorCprMai,
offset = (ulong)_imageStream.Position
};
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Writing_DVD_CPI_MAI_block_to_position_0, idxEntry.offset);
Localization.Writing_DVD_CPR_MAI_block_to_position_0, idxEntry.offset);
Crc64Context.Data(_sectorCpiMai, out byte[] blockCrc);
Crc64Context.Data(_sectorCprMai, out byte[] blockCrc);
var cpiMaiBlock = new BlockHeader
var cprMaiBlock = new BlockHeader
{
identifier = BlockType.DataBlock,
type = DataType.DvdSectorCpiMai,
length = (uint)_sectorCpiMai.Length,
type = DataType.DvdSectorCprMai,
length = (uint)_sectorCprMai.Length,
crc64 = BitConverter.ToUInt64(blockCrc, 0),
sectorSize = 6
};
@@ -4064,28 +4109,28 @@ public sealed partial class AaruFormat
if(!_compress)
{
cpiMaiBlock.compression = CompressionType.None;
cpiMaiBlock.cmpCrc64 = cpiMaiBlock.crc64;
cpiMaiBlock.cmpLength = cpiMaiBlock.length;
blockStream = new MemoryStream(_sectorCpiMai);
cprMaiBlock.compression = CompressionType.None;
cprMaiBlock.cmpCrc64 = cprMaiBlock.crc64;
cprMaiBlock.cmpLength = cprMaiBlock.length;
blockStream = new MemoryStream(_sectorCprMai);
}
else
{
startCompress = DateTime.Now;
byte[] cmpBuffer = new byte[_sectorCpiMai.Length + 262144];
byte[] cmpBuffer = new byte[_sectorCprMai.Length + 262144];
int cmpLen;
switch(_compressionAlgorithm)
{
case CompressionType.Lzma:
cmpLen = LZMA.EncodeBuffer(_sectorCpiMai, cmpBuffer, out lzmaProperties, 9,
cmpLen = LZMA.EncodeBuffer(_sectorCprMai, cmpBuffer, out lzmaProperties, 9,
_dictionarySize, 4, 0, 2, 273);
break;
case CompressionType.None:
cmpBuffer = _sectorCpiMai;
cmpBuffer = _sectorCprMai;
cmpLen = cmpBuffer.Length;
break;
@@ -4101,32 +4146,317 @@ public sealed partial class AaruFormat
cmpCrc.Update(blockStream.ToArray());
blockCrc = cmpCrc.Final();
cpiMaiBlock.cmpLength = (uint)blockStream.Length;
cprMaiBlock.cmpLength = (uint)blockStream.Length;
if(_compressionAlgorithm == CompressionType.Lzma)
cpiMaiBlock.cmpLength += LZMA_PROPERTIES_LENGTH;
cprMaiBlock.cmpLength += LZMA_PROPERTIES_LENGTH;
cpiMaiBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
cpiMaiBlock.compression = _compressionAlgorithm;
cprMaiBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
cprMaiBlock.compression = _compressionAlgorithm;
endCompress = DateTime.Now;
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Took_0_seconds_to_compress_CPI_MAI,
Localization.Took_0_seconds_to_compress_CPR_MAI,
(endCompress - startCompress).TotalSeconds);
}
_structureBytes = new byte[Marshal.SizeOf<BlockHeader>()];
MemoryMarshal.Write(_structureBytes, ref cpiMaiBlock);
MemoryMarshal.Write(_structureBytes, ref cprMaiBlock);
_imageStream.Write(_structureBytes, 0, _structureBytes.Length);
if(cpiMaiBlock.compression is CompressionType.Lzma
if(cprMaiBlock.compression is CompressionType.Lzma
or CompressionType.LzmaClauniaSubchannelTransform)
_imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
_imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
_index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorCpiMai });
_index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorCprMai });
_index.Add(idxEntry);
blockStream.Close();
}
if(_sectorId != null)
{
idxEntry = new IndexEntry
{
blockType = BlockType.DataBlock,
dataType = DataType.DvdSectorId,
offset = (ulong)_imageStream.Position
};
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Writing_DVD_ID_block_to_position_0, idxEntry.offset);
Crc64Context.Data(_sectorId, out byte[] blockCrc);
var idBlock = new BlockHeader
{
identifier = BlockType.DataBlock,
type = DataType.DvdSectorId,
length = (uint)_sectorId.Length,
crc64 = BitConverter.ToUInt64(blockCrc, 0),
sectorSize = 4
};
byte[] lzmaProperties = null;
if(!_compress)
{
idBlock.compression = CompressionType.None;
idBlock.cmpCrc64 = idBlock.crc64;
idBlock.cmpLength = idBlock.length;
blockStream = new MemoryStream(_sectorId);
}
else
{
startCompress = DateTime.Now;
byte[] cmpBuffer = new byte[_sectorId.Length + 262144];
int cmpLen;
switch(_compressionAlgorithm)
{
case CompressionType.Lzma:
cmpLen = LZMA.EncodeBuffer(_sectorId, cmpBuffer, out lzmaProperties, 9,
_dictionarySize, 4, 0, 2, 273);
break;
case CompressionType.None:
cmpBuffer = _sectorId;
cmpLen = cmpBuffer.Length;
break;
default: throw new ArgumentOutOfRangeException();
}
blockStream = new MemoryStream(cmpBuffer, 0, cmpLen);
var cmpCrc = new Crc64Context();
if(_compressionAlgorithm == CompressionType.Lzma)
cmpCrc.Update(lzmaProperties);
cmpCrc.Update(blockStream.ToArray());
blockCrc = cmpCrc.Final();
idBlock.cmpLength = (uint)blockStream.Length;
if(_compressionAlgorithm == CompressionType.Lzma)
idBlock.cmpLength += LZMA_PROPERTIES_LENGTH;
idBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
idBlock.compression = _compressionAlgorithm;
endCompress = DateTime.Now;
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Took_0_seconds_to_compress_ID,
(endCompress - startCompress).TotalSeconds);
}
_structureBytes = new byte[Marshal.SizeOf<BlockHeader>()];
MemoryMarshal.Write(_structureBytes, ref idBlock);
_imageStream.Write(_structureBytes, 0, _structureBytes.Length);
if(idBlock.compression is CompressionType.Lzma
or CompressionType.LzmaClauniaSubchannelTransform)
_imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
_imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
_index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorId });
_index.Add(idxEntry);
blockStream.Close();
}
if(_sectorIed != null)
{
idxEntry = new IndexEntry
{
blockType = BlockType.DataBlock,
dataType = DataType.DvdSectorIed,
offset = (ulong)_imageStream.Position
};
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Writing_DVD_IED_block_to_position_0, idxEntry.offset);
Crc64Context.Data(_sectorIed, out byte[] blockCrc);
var iedBlock = new BlockHeader
{
identifier = BlockType.DataBlock,
type = DataType.DvdSectorIed,
length = (uint)_sectorIed.Length,
crc64 = BitConverter.ToUInt64(blockCrc, 0),
sectorSize = 2
};
byte[] lzmaProperties = null;
if(!_compress)
{
iedBlock.compression = CompressionType.None;
iedBlock.cmpCrc64 = iedBlock.crc64;
iedBlock.cmpLength = iedBlock.length;
blockStream = new MemoryStream(_sectorIed);
}
else
{
startCompress = DateTime.Now;
byte[] cmpBuffer = new byte[_sectorIed.Length + 262144];
int cmpLen;
switch(_compressionAlgorithm)
{
case CompressionType.Lzma:
cmpLen = LZMA.EncodeBuffer(_sectorIed, cmpBuffer, out lzmaProperties, 9,
_dictionarySize, 4, 0, 2, 273);
break;
case CompressionType.None:
cmpBuffer = _sectorIed;
cmpLen = cmpBuffer.Length;
break;
default: throw new ArgumentOutOfRangeException();
}
blockStream = new MemoryStream(cmpBuffer, 0, cmpLen);
var cmpCrc = new Crc64Context();
if(_compressionAlgorithm == CompressionType.Lzma)
cmpCrc.Update(lzmaProperties);
cmpCrc.Update(blockStream.ToArray());
blockCrc = cmpCrc.Final();
iedBlock.cmpLength = (uint)blockStream.Length;
if(_compressionAlgorithm == CompressionType.Lzma)
iedBlock.cmpLength += LZMA_PROPERTIES_LENGTH;
iedBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
iedBlock.compression = _compressionAlgorithm;
endCompress = DateTime.Now;
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Took_0_seconds_to_compress_IED,
(endCompress - startCompress).TotalSeconds);
}
_structureBytes = new byte[Marshal.SizeOf<BlockHeader>()];
MemoryMarshal.Write(_structureBytes, ref iedBlock);
_imageStream.Write(_structureBytes, 0, _structureBytes.Length);
if(iedBlock.compression is CompressionType.Lzma
or CompressionType.LzmaClauniaSubchannelTransform)
_imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
_imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
_index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorIed });
_index.Add(idxEntry);
blockStream.Close();
}
if(_sectorEdc != null)
{
idxEntry = new IndexEntry
{
blockType = BlockType.DataBlock,
dataType = DataType.DvdSectorEdc,
offset = (ulong)_imageStream.Position
};
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Writing_DVD_EDC_block_to_position_0, idxEntry.offset);
Crc64Context.Data(_sectorEdc, out byte[] blockCrc);
var edcBlock = new BlockHeader
{
identifier = BlockType.DataBlock,
type = DataType.DvdSectorEdc,
length = (uint)_sectorEdc.Length,
crc64 = BitConverter.ToUInt64(blockCrc, 0),
sectorSize = 4
};
byte[] lzmaProperties = null;
if(!_compress)
{
edcBlock.compression = CompressionType.None;
edcBlock.cmpCrc64 = edcBlock.crc64;
edcBlock.cmpLength = edcBlock.length;
blockStream = new MemoryStream(_sectorEdc);
}
else
{
startCompress = DateTime.Now;
byte[] cmpBuffer = new byte[_sectorEdc.Length + 262144];
int cmpLen;
switch(_compressionAlgorithm)
{
case CompressionType.Lzma:
cmpLen = LZMA.EncodeBuffer(_sectorEdc, cmpBuffer, out lzmaProperties, 9,
_dictionarySize, 4, 0, 2, 273);
break;
case CompressionType.None:
cmpBuffer = _sectorEdc;
cmpLen = cmpBuffer.Length;
break;
default: throw new ArgumentOutOfRangeException();
}
blockStream = new MemoryStream(cmpBuffer, 0, cmpLen);
var cmpCrc = new Crc64Context();
if(_compressionAlgorithm == CompressionType.Lzma)
cmpCrc.Update(lzmaProperties);
cmpCrc.Update(blockStream.ToArray());
blockCrc = cmpCrc.Final();
edcBlock.cmpLength = (uint)blockStream.Length;
if(_compressionAlgorithm == CompressionType.Lzma)
edcBlock.cmpLength += LZMA_PROPERTIES_LENGTH;
edcBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
edcBlock.compression = _compressionAlgorithm;
endCompress = DateTime.Now;
AaruConsole.DebugWriteLine("Aaru Format plugin",
Localization.Took_0_seconds_to_compress_EDC,
(endCompress - startCompress).TotalSeconds);
}
_structureBytes = new byte[Marshal.SizeOf<BlockHeader>()];
MemoryMarshal.Write(_structureBytes, ref edcBlock);
_imageStream.Write(_structureBytes, 0, _structureBytes.Length);
if(edcBlock.compression is CompressionType.Lzma
or CompressionType.LzmaClauniaSubchannelTransform)
_imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
_imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
_index.RemoveAll(t => t is { blockType: BlockType.DataBlock, dataType: DataType.DvdSectorEdc });
_index.Add(idxEntry);
blockStream.Close();
@@ -4929,7 +5259,7 @@ public sealed partial class AaruFormat
return true;
}
case SectorTagType.DvdCmi:
case SectorTagType.DvdSectorCmi:
{
if(data.Length != 1)
{
@@ -4938,13 +5268,14 @@ public sealed partial class AaruFormat
return false;
}
_sectorCpiMai ??= new byte[_imageInfo.Sectors * 6];
_sectorCprMai ??= new byte[_imageInfo.Sectors * 6];
Array.Copy(data, 0, _sectorCpiMai, (int)(6 * sectorAddress), 1);
Array.Copy(data, 0, _sectorCprMai, (int)(6 * sectorAddress), 1);
return true;
}
case SectorTagType.DvdTitleKey:
case SectorTagType.DvdSectorTitleKey:
{
if(data.Length != 5)
{
@@ -4953,12 +5284,77 @@ public sealed partial class AaruFormat
return false;
}
_sectorCpiMai ??= new byte[_imageInfo.Sectors * 6];
_sectorCprMai ??= new byte[_imageInfo.Sectors * 6];
Array.Copy(data, 0, _sectorCpiMai, (int)(1 + (6 * sectorAddress)), 5);
Array.Copy(data, 0, _sectorCprMai, (int)(1 + (6 * sectorAddress)), 5);
return true;
}
case SectorTagType.DvdSectorInformation:
{
if(data.Length != 1)
{
ErrorMessage = Localization.Incorrect_data_size_for_dvd_id_information;
return false;
}
_sectorId ??= new byte[_imageInfo.Sectors * 4];
Array.Copy(data, 0, _sectorId, (int)(4 * sectorAddress), 1);
return true;
}
case SectorTagType.DvdSectorNumber:
{
if(data.Length != 3)
{
ErrorMessage = Localization.Incorrect_data_size_for_dvd_id_number;
return false;
}
_sectorId ??= new byte[_imageInfo.Sectors * 4];
Array.Copy(data, 0, _sectorId, (int)(1 + (4 * sectorAddress)), 3);
return true;
}
case SectorTagType.DvdSectorIed:
{
if(data.Length != 2)
{
ErrorMessage = Localization.Incorrect_data_size_for_ied;
return false;
}
_sectorIed ??= new byte[_imageInfo.Sectors * 2];
Array.Copy(data, 0, _sectorIed, (int)(2 * sectorAddress), 2);
return true;
}
case SectorTagType.DvdSectorEdc:
{
if(data.Length != 4)
{
ErrorMessage = Localization.Incorrect_data_size_for_edc;
return false;
}
_sectorEdc ??= new byte[_imageInfo.Sectors * 4];
Array.Copy(data, 0, _sectorEdc, (int)(4 * sectorAddress), 4);
return true;
}
case SectorTagType.DvdTitleKeyDecrypted:
{
if(data.Length != 5)

View File

@@ -43,6 +43,7 @@ using Aaru.Decoders.CD;
using Aaru.Decoders.DVD;
using Aaru.Helpers;
using DMI = Aaru.Decoders.Xbox.DMI;
using Sector = Aaru.Decoders.CD.Sector;
namespace Aaru.DiscImages;

View File

@@ -49,6 +49,7 @@ using Aaru.Decoders.SCSI.MMC;
using Aaru.Filters;
using Aaru.Helpers;
using DMI = Aaru.Decoders.Xbox.DMI;
using Sector = Aaru.Decoders.CD.Sector;
using Session = Aaru.CommonTypes.Structs.Session;
namespace Aaru.DiscImages;

View File

@@ -789,15 +789,51 @@ namespace Aaru.DiscImages {
}
}
internal static string Writing_DVD_CPI_MAI_block_to_position_0 {
internal static string Writing_DVD_CPR_MAI_block_to_position_0 {
get {
return ResourceManager.GetString("Writing_DVD_CPI_MAI_block_to_position_0", resourceCulture);
return ResourceManager.GetString("Writing_DVD_CPR_MAI_block_to_position_0", resourceCulture);
}
}
internal static string Took_0_seconds_to_compress_CPI_MAI {
internal static string Took_0_seconds_to_compress_CPR_MAI {
get {
return ResourceManager.GetString("Took_0_seconds_to_compress_CPI_MAI", resourceCulture);
return ResourceManager.GetString("Took_0_seconds_to_compress_CPR_MAI", resourceCulture);
}
}
internal static string Writing_DVD_ID_block_to_position_0 {
get {
return ResourceManager.GetString("Writing_DVD_ID_block_to_position_0", resourceCulture);
}
}
internal static string Took_0_seconds_to_compress_ID {
get {
return ResourceManager.GetString("Took_0_seconds_to_compress_ID", resourceCulture);
}
}
internal static string Writing_DVD_IED_block_to_position_0 {
get {
return ResourceManager.GetString("Writing_DVD_IED_block_to_position_0", resourceCulture);
}
}
internal static string Took_0_seconds_to_compress_IED {
get {
return ResourceManager.GetString("Took_0_seconds_to_compress_IED", resourceCulture);
}
}
internal static string Writing_DVD_EDC_block_to_position_0 {
get {
return ResourceManager.GetString("Writing_DVD_EDC_block_to_position_0", resourceCulture);
}
}
internal static string Took_0_seconds_to_compress_EDC {
get {
return ResourceManager.GetString("Took_0_seconds_to_compress_EDC", resourceCulture);
}
}
@@ -891,6 +927,30 @@ namespace Aaru.DiscImages {
}
}
internal static string Incorrect_data_size_for_dvd_id_information {
get {
return ResourceManager.GetString("Incorrect_data_size_for_dvd_id_information", resourceCulture);
}
}
internal static string Incorrect_data_size_for_dvd_id_number {
get {
return ResourceManager.GetString("Incorrect_data_size_for_dvd_id_number", resourceCulture);
}
}
internal static string Incorrect_data_size_for_ied {
get {
return ResourceManager.GetString("Incorrect_data_size_for_ied", resourceCulture);
}
}
internal static string Incorrect_data_size_for_edc {
get {
return ResourceManager.GetString("Incorrect_data_size_for_edc", resourceCulture);
}
}
internal static string Incorrect_data_size_for_decrypted_title_key {
get {
return ResourceManager.GetString("Incorrect_data_size_for_decrypted_title_key", resourceCulture);

View File

@@ -397,11 +397,29 @@
<data name="Took_0_seconds_to_compress_subchannel" xml:space="preserve">
<value>Took {0} seconds to compress subchannel</value>
</data>
<data name="Writing_DVD_CPI_MAI_block_to_position_0" xml:space="preserve">
<value>Writing DVD CPI_MAI block to position {0}</value>
<data name="Writing_DVD_CPR_MAI_block_to_position_0" xml:space="preserve">
<value>Writing DVD CPR_MAI block to position {0}</value>
</data>
<data name="Took_0_seconds_to_compress_CPI_MAI" xml:space="preserve">
<value>Took {0} seconds to compress CPI_MAI</value>
<data name="Took_0_seconds_to_compress_CPR_MAI" xml:space="preserve">
<value>Took {0} seconds to compress CPR_MAI</value>
</data>
<data name="Writing_DVD_ID_block_to_position_0" xml:space="preserve">
<value>Writing DVD ID block to position {0}</value>
</data>
<data name="Took_0_seconds_to_compress_ID" xml:space="preserve">
<value>Took {0} seconds to compress ID</value>
</data>
<data name="Writing_DVD_IED_block_to_position_0" xml:space="preserve">
<value>Writing DVD IED block to position {0}</value>
</data>
<data name="Took_0_seconds_to_compress_IED" xml:space="preserve">
<value>Took {0} seconds to compress IED</value>
</data>
<data name="Writing_DVD_EDC_block_to_position_0" xml:space="preserve">
<value>Writing DVD EDC block to position {0}</value>
</data>
<data name="Took_0_seconds_to_compress_EDC" xml:space="preserve">
<value>Took {0} seconds to compress EDC</value>
</data>
<data name="Writing_decrypted_DVD_title_key_block_to_position_0" xml:space="preserve">
<value>Writing decrypted DVD title key block to position {0}</value>
@@ -448,6 +466,18 @@
<data name="Incorrect_data_size_for_title_key" xml:space="preserve">
<value>Incorrect data size for title key</value>
</data>
<data name="Incorrect_data_size_for_dvd_id_information" xml:space="preserve">
<value>Incorrect data size for DVD ID information</value>
</data>
<data name="Incorrect_data_size_for_dvd_id_number" xml:space="preserve">
<value>Incorrect data size for DVD ID number</value>
</data>
<data name="Incorrect_data_size_for_ied" xml:space="preserve">
<value>Incorrect data size for IED</value>
</data>
<data name="Incorrect_data_size_for_edc" xml:space="preserve">
<value>Incorrect data size for EDC</value>
</data>
<data name="Incorrect_data_size_for_decrypted_title_key" xml:space="preserve">
<value>Incorrect data size for decrypted title key</value>
</data>

View File

@@ -38,6 +38,12 @@ public sealed partial class ZZZRawImage
{
MediaType CalculateDiskType()
{
if(_rawDvd)
{
// TODO: Add all types
return MediaType.DVDROM;
}
if(_imageInfo.SectorSize == 2048)
return _imageInfo.Sectors switch
{

View File

@@ -59,6 +59,7 @@ public sealed partial class ZZZRawImage
case ".256": return imageFilter.DataForkLength % 256 == 0;
case ".toast" when imageFilter.DataForkLength % 2048 == 0: return true;
case ".toast" when imageFilter.DataForkLength % 2056 == 0: return true;
case ".raw" when imageFilter.DataForkLength % 2064 == 0: return true;
// Handle this properly on Open()
//case ".toast" when imageFilter.DataForkLength % 2336 == 0: return true;

View File

@@ -51,6 +51,7 @@ using Schemas;
using DMI = Aaru.Decoders.Xbox.DMI;
using File = System.IO.File;
using Inquiry = Aaru.CommonTypes.Structs.Devices.SCSI.Inquiry;
using Sector = Aaru.Decoders.CD.Sector;
using Session = Aaru.CommonTypes.Structs.Session;
using Track = Aaru.CommonTypes.Structs.Track;
using TrackType = Aaru.CommonTypes.Enums.TrackType;
@@ -143,6 +144,11 @@ public sealed partial class ZZZRawImage
case ".d81" when imageFilter.DataForkLength == 819200:
_imageInfo.SectorSize = 256;
break;
case ".raw" when imageFilter.DataForkLength % 2064 == 0:
_imageInfo.SectorSize = 2048;
_rawDvd = true;
break;
default:
switch(_extension)
@@ -377,6 +383,9 @@ public sealed partial class ZZZRawImage
if(_toastXa)
_imageInfo.MediaType = MediaType.CD;
if(_rawDvd)
_imageInfo.Sectors = _imageInfo.ImageSize / 2064;
// Sharp X68000 SASI hard disks
if(_extension == ".hdf")
if(_imageInfo.ImageSize % 256 == 0)
@@ -1164,6 +1173,27 @@ public sealed partial class ZZZRawImage
_imageInfo.ReadableMediaTags = new List<MediaTagType>(_mediaTags.Keys);
if(_rawDvd)
{
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorInformation))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorInformation);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorNumber))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorNumber);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorIed))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorIed);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorCmi))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorCmi);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorTitleKey))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorTitleKey);
if(!_imageInfo.ReadableSectorTags.Contains(SectorTagType.DvdSectorEdc))
_imageInfo.ReadableSectorTags.Add(SectorTagType.DvdSectorEdc);
}
if(!_rawCompactDisc &&
!_toastXa)
return ErrorNumber.NoError;
@@ -1254,6 +1284,13 @@ public sealed partial class ZZZRawImage
if(_hasSubchannel)
sectorSkip += 96;
if(_rawDvd)
{
sectorOffset = 12;
sectorSize = 2048;
sectorSkip = 4;
}
buffer = new byte[sectorSize * length];
var br = new BinaryReader(stream);
@@ -1280,12 +1317,21 @@ public sealed partial class ZZZRawImage
buffer = br.ReadBytes((int)(sectorSize * length));
else
for(int i = 0; i < length; i++)
{
if(_rawDvd)
{
byte[] sector = br.ReadBytes((int)(sectorSize + sectorSkip + sectorOffset));
sector = _decoding.Scramble(sector);
Array.Copy(sector, sectorOffset, buffer, i * sectorSize, sectorSize);
}
else
{
br.BaseStream.Seek(sectorOffset, SeekOrigin.Current);
byte[] sector = br.ReadBytes((int)sectorSize);
br.BaseStream.Seek(sectorSkip, SeekOrigin.Current);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
return ErrorNumber.NoError;
}
@@ -1418,7 +1464,7 @@ public sealed partial class ZZZRawImage
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc ||
(!_rawCompactDisc && !_toastXa && tag != SectorTagType.CdTrackFlags))
(!_rawCompactDisc && !_toastXa && !_rawDvd && tag != SectorTagType.CdTrackFlags))
return ErrorNumber.NotSupported;
if(tag == SectorTagType.CdTrackFlags)
@@ -1534,6 +1580,60 @@ public sealed partial class ZZZRawImage
break;
}
case SectorTagType.DvdSectorNumber:
{
sectorOffset = 1;
sectorSize = 3;
sectorSkip = 2060;
break;
}
case SectorTagType.DvdSectorInformation:
{
sectorOffset = 0;
sectorSize = 1;
sectorSkip = 2063;
break;
}
case SectorTagType.DvdSectorIed:
{
sectorOffset = 4;
sectorSize = 2;
sectorSkip = 2058;
break;
}
case SectorTagType.DvdSectorCmi:
{
sectorOffset = 6;
sectorSize = 1;
sectorSkip = 2057;
break;
}
case SectorTagType.DvdSectorTitleKey:
{
sectorOffset = 7;
sectorSize = 5;
sectorSkip = 2052;
break;
}
case SectorTagType.DvdSectorEdc:
{
sectorOffset = 2060;
sectorSize = 4;
sectorSkip = 0;
break;
}
default: return ErrorNumber.NotSupported;
}
@@ -1568,7 +1668,7 @@ public sealed partial class ZZZRawImage
buffer = null;
if(_imageInfo.MetadataMediaType != MetadataMediaType.OpticalDisc ||
(!_rawCompactDisc && !_toastXa))
(!_rawCompactDisc && !_toastXa && !_rawDvd))
return ErrorNumber.NotSupported;
if(sectorAddress > _imageInfo.Sectors - 1)
@@ -1577,7 +1677,14 @@ public sealed partial class ZZZRawImage
if(sectorAddress + length > _imageInfo.Sectors)
return ErrorNumber.OutOfRange;
uint sectorSize = _toastXa ? 2056u : 2352u;
uint sectorSize = 2352u;
if(_toastXa)
sectorSize = 2056u;
if(_rawDvd)
sectorSize = 2064u;
uint sectorSkip = 0;
if(_hasSubchannel)
@@ -1604,6 +1711,15 @@ public sealed partial class ZZZRawImage
Array.Copy(fullSector, 0, buffer, i * 2352, 2352);
}
}
else if(_rawDvd)
{
for(int i = 0; i < length; i++)
{
byte[] sector = br.ReadBytes((int)(sectorSize));
sector = _decoding.Scramble(sector);
Array.Copy(sector, 0, buffer, i * sectorSize, sectorSize);
}
}
else if(sectorSkip == 0)
buffer = br.ReadBytes((int)(sectorSize * length));
else

View File

@@ -36,6 +36,7 @@ using System.IO;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs;
using Aaru.Decoders.DVD;
namespace Aaru.DiscImages;
@@ -53,8 +54,10 @@ public sealed partial class ZZZRawImage : IWritableOpticalImage
bool _mode2;
bool _toastXa;
bool _rawCompactDisc;
bool _rawDvd;
IFilter _rawImageFilter;
FileStream _writingStream;
Sector _decoding = new Sector();
/// <summary>Implements reading and writing raw (sector by sector) images</summary>
public ZZZRawImage() => _imageInfo = new ImageInfo

View File

@@ -885,7 +885,7 @@ sealed class ConvertImageCommand : Command
if(sectorsToDo == 1)
{
if(inputOptical.ReadSectorTag(doneSectors + track.StartSector,
SectorTagType.DvdCmi, out cmi) == ErrorNumber.NoError &&
SectorTagType.DvdSectorCmi, out cmi) == ErrorNumber.NoError &&
inputOptical.ReadSectorTag(doneSectors + track.StartSector,
SectorTagType.DvdTitleKeyDecrypted, out titleKey) ==
ErrorNumber.NoError)
@@ -927,7 +927,7 @@ sealed class ConvertImageCommand : Command
else
{
if(inputOptical.ReadSectorsTag(doneSectors + track.StartSector,
sectorsToDo, SectorTagType.DvdCmi, out cmi) ==
sectorsToDo, SectorTagType.DvdSectorCmi, out cmi) ==
ErrorNumber.NoError &&
inputOptical.ReadSectorsTag(doneSectors + track.StartSector,
sectorsToDo, SectorTagType.DvdTitleKeyDecrypted,
@@ -1100,6 +1100,12 @@ sealed class ConvertImageCommand : Command
case SectorTagType.CdSectorEccP:
case SectorTagType.CdSectorEccQ:
case SectorTagType.CdSectorEcc:
case SectorTagType.DvdSectorCmi:
case SectorTagType.DvdSectorTitleKey:
case SectorTagType.DvdSectorEdc:
case SectorTagType.DvdSectorIed:
case SectorTagType.DvdSectorInformation:
case SectorTagType.DvdSectorNumber:
// This tags are inline in long sector
continue;
}