Save Compact Disc track indexes in aaruformat.

This commit is contained in:
2020-06-21 02:28:18 +01:00
parent 0efa8e3846
commit 6f66150b1e
4 changed files with 166 additions and 2 deletions

View File

@@ -244,7 +244,9 @@ namespace Aaru.DiscImages
/// <summary>Block containing list of files for a tape image</summary>
TapeFileBlock = 0x454C4654,
/// <summary>Block containing list of partitions for a tape image</summary>
TapePartitionBlock = 0x54425054
TapePartitionBlock = 0x54425054,
/// <summary>Block containing list of indexes for Compact Disc tracks</summary>
CompactDiscIndexesBlock = 0x58494443
}
enum ChecksumAlgorithm : byte

View File

@@ -150,6 +150,7 @@ namespace Aaru.DiscImages
bool foundUserDataDdt = false;
mediaTags = new Dictionary<MediaTagType, byte[]>();
List<CompactDiscIndexEntry> compactDiscIndexes = null;
foreach(IndexEntry entry in index)
{
@@ -994,6 +995,59 @@ namespace Aaru.DiscImages
IsTape = true;
break;
// Optical disc tracks block
case BlockType.CompactDiscIndexesBlock:
structureBytes = new byte[Marshal.SizeOf<CompactDiscIndexesHeader>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
CompactDiscIndexesHeader indexesHeader =
Marshal.SpanToStructureLittleEndian<CompactDiscIndexesHeader>(structureBytes);
if(indexesHeader.identifier != BlockType.CompactDiscIndexesBlock)
{
AaruConsole.DebugWriteLine("Aaru Format plugin",
"Incorrect identifier for compact disc indexes block at position {0}",
entry.offset);
break;
}
structureBytes = new byte[Marshal.SizeOf<CompactDiscIndexEntry>() * indexesHeader.entries];
imageStream.Read(structureBytes, 0, structureBytes.Length);
Crc64Context.Data(structureBytes, out byte[] idsxCrc);
if(BitConverter.ToUInt64(idsxCrc, 0) != indexesHeader.crc64)
{
AaruConsole.DebugWriteLine("Aaru Format plugin",
"Incorrect CRC found: 0x{0:X16} found, expected 0x{1:X16}, continuing...",
BitConverter.ToUInt64(idsxCrc, 0), indexesHeader.crc64);
break;
}
imageStream.Position -= structureBytes.Length;
compactDiscIndexes = new List<CompactDiscIndexEntry>();
AaruConsole.DebugWriteLine("Aaru Format plugin",
"Found {0} compact disc indexes at position {0}",
indexesHeader.entries, entry.offset);
for(ushort i = 0; i < indexesHeader.entries; i++)
{
structureBytes = new byte[Marshal.SizeOf<CompactDiscIndexEntry>()];
imageStream.Read(structureBytes, 0, structureBytes.Length);
compactDiscIndexes.Add(Marshal.
ByteArrayToStructureLittleEndian<CompactDiscIndexEntry
>(structureBytes));
}
AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes",
GC.GetTotalMemory(false));
break;
}
}
@@ -1147,6 +1201,20 @@ namespace Aaru.DiscImages
AaruConsole.DebugWriteLine("Aaru Format plugin", "Memory snapshot: {0} bytes",
GC.GetTotalMemory(false));
if(compactDiscIndexes != null)
{
foreach(CompactDiscIndexEntry compactDiscIndex in compactDiscIndexes.
OrderBy(i => i.Track).ThenBy(i => i.Index))
{
Track track = Tracks.FirstOrDefault(t => t.TrackSequence == compactDiscIndex.Track);
if(track is null)
continue;
track.Indexes[compactDiscIndex.Index] = compactDiscIndex.Lba;
}
}
}
else
{

View File

@@ -380,5 +380,33 @@ namespace Aaru.DiscImages
/// <summary>Last block, inclusive, of the partition</summary>
public ulong LastBlock;
}
/// <summary>
/// Compact Disc track indexes block, contains a cache of all Compact Disc indexes to not need to interpret
/// subchannel
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexesHeader
{
/// <summary>Identifier, <see cref="BlockType.CompactDiscIndexesBlock" /></summary>
public BlockType identifier;
/// <summary>How many entries follow this header</summary>
public ushort entries;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public readonly ulong length;
/// <summary>CRC64-ECMA of the block</summary>
public ulong crc64;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct CompactDiscIndexEntry
{
/// <summary>How many entries follow this header</summary>
public ushort Track;
/// <summary>Size of the whole block, not including this header, in bytes</summary>
public ushort Index;
/// <summary>CRC64-ECMA of the block</summary>
public int Lba;
}
}
}

View File

@@ -2928,7 +2928,8 @@ namespace Aaru.DiscImages
blockStream = null;
}
List<TrackEntry> trackEntries = new List<TrackEntry>();
List<TrackEntry> trackEntries = new List<TrackEntry>();
List<CompactDiscIndexEntry> compactDiscIndexEntries = new List<CompactDiscIndexEntry>();
foreach(Track track in Tracks)
{
@@ -2946,6 +2947,21 @@ namespace Aaru.DiscImages
pregap = (long)track.TrackPregap, session = (byte)track.TrackSession, isrc = isrc,
flags = flags
});
if(!track.Indexes.ContainsKey(0) &&
track.TrackPregap > 0)
{
track.Indexes[0] = (int)track.TrackStartSector;
track.Indexes[1] = (int)(track.TrackStartSector + track.TrackPregap);
}
else if(!track.Indexes.ContainsKey(0) &&
!track.Indexes.ContainsKey(1))
track.Indexes[0] = (int)track.TrackStartSector;
compactDiscIndexEntries.AddRange(track.Indexes.Select(trackIndex => new CompactDiscIndexEntry
{
Index = trackIndex.Key, Lba = trackIndex.Value, Track = (ushort)track.TrackSequence
}));
}
// If there are tracks build the tracks block
@@ -2995,6 +3011,56 @@ namespace Aaru.DiscImages
blockStream = null;
}
// If there are track indexes bigger than 1
if(compactDiscIndexEntries.Any(i => i.Index > 1))
{
blockStream = new NonClosableStream();
foreach(CompactDiscIndexEntry entry in compactDiscIndexEntries)
{
structurePointer =
System.Runtime.InteropServices.Marshal.AllocHGlobal(Marshal.
SizeOf<CompactDiscIndexEntry
>());
structureBytes = new byte[Marshal.SizeOf<CompactDiscIndexEntry>()];
System.Runtime.InteropServices.Marshal.StructureToPtr(entry, structurePointer, true);
System.Runtime.InteropServices.Marshal.Copy(structurePointer, structureBytes, 0,
structureBytes.Length);
System.Runtime.InteropServices.Marshal.FreeHGlobal(structurePointer);
blockStream.Write(structureBytes, 0, structureBytes.Length);
}
Crc64Context.Data(blockStream.ToArray(), out byte[] cdixCrc);
var cdixHeader = new CompactDiscIndexesHeader
{
identifier = BlockType.CompactDiscIndexesBlock,
entries = (ushort)compactDiscIndexEntries.Count, crc64 = BitConverter.ToUInt64(cdixCrc, 0)
};
AaruConsole.DebugWriteLine("Aaru Format plugin", "Writing compact disc indexes to position {0}",
imageStream.Position);
index.RemoveAll(t => t.blockType == BlockType.CompactDiscIndexesBlock &&
t.dataType == DataType.NoData);
index.Add(new IndexEntry
{
blockType = BlockType.CompactDiscIndexesBlock, dataType = DataType.NoData,
offset = (ulong)imageStream.Position
});
structureBytes = new byte[Marshal.SizeOf<CompactDiscIndexesHeader>()];
MemoryMarshal.Write(structureBytes, ref cdixHeader);
imageStream.Write(structureBytes, 0, structureBytes.Length);
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
blockStream.ReallyClose();
blockStream = null;
}
break;
case XmlMediaType.BlockMedia:
if(sectorSubchannel != null &&