mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Save Compact Disc track indexes in aaruformat.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 &&
|
||||
|
||||
Reference in New Issue
Block a user