From 6f66150b1e341ab2ffcc1d1c19a0a4737db50077 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 21 Jun 2020 02:28:18 +0100 Subject: [PATCH] Save Compact Disc track indexes in aaruformat. --- Aaru.Images/AaruFormat/Enums.cs | 4 +- Aaru.Images/AaruFormat/Read.cs | 68 +++++++++++++++++++++++++++++++ Aaru.Images/AaruFormat/Structs.cs | 28 +++++++++++++ Aaru.Images/AaruFormat/Write.cs | 68 ++++++++++++++++++++++++++++++- 4 files changed, 166 insertions(+), 2 deletions(-) diff --git a/Aaru.Images/AaruFormat/Enums.cs b/Aaru.Images/AaruFormat/Enums.cs index ec5c23cc3..737edafa9 100644 --- a/Aaru.Images/AaruFormat/Enums.cs +++ b/Aaru.Images/AaruFormat/Enums.cs @@ -244,7 +244,9 @@ namespace Aaru.DiscImages /// Block containing list of files for a tape image TapeFileBlock = 0x454C4654, /// Block containing list of partitions for a tape image - TapePartitionBlock = 0x54425054 + TapePartitionBlock = 0x54425054, + /// Block containing list of indexes for Compact Disc tracks + CompactDiscIndexesBlock = 0x58494443 } enum ChecksumAlgorithm : byte diff --git a/Aaru.Images/AaruFormat/Read.cs b/Aaru.Images/AaruFormat/Read.cs index 83f849b98..9f6e6c3c6 100644 --- a/Aaru.Images/AaruFormat/Read.cs +++ b/Aaru.Images/AaruFormat/Read.cs @@ -150,6 +150,7 @@ namespace Aaru.DiscImages bool foundUserDataDdt = false; mediaTags = new Dictionary(); + List 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()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + + CompactDiscIndexesHeader indexesHeader = + Marshal.SpanToStructureLittleEndian(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() * 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(); + + 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()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + + compactDiscIndexes.Add(Marshal. + ByteArrayToStructureLittleEndian(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 { diff --git a/Aaru.Images/AaruFormat/Structs.cs b/Aaru.Images/AaruFormat/Structs.cs index 59e9487f0..b423a8eb3 100644 --- a/Aaru.Images/AaruFormat/Structs.cs +++ b/Aaru.Images/AaruFormat/Structs.cs @@ -380,5 +380,33 @@ namespace Aaru.DiscImages /// Last block, inclusive, of the partition public ulong LastBlock; } + + /// + /// Compact Disc track indexes block, contains a cache of all Compact Disc indexes to not need to interpret + /// subchannel + /// + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CompactDiscIndexesHeader + { + /// Identifier, + public BlockType identifier; + /// How many entries follow this header + public ushort entries; + /// Size of the whole block, not including this header, in bytes + public readonly ulong length; + /// CRC64-ECMA of the block + public ulong crc64; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct CompactDiscIndexEntry + { + /// How many entries follow this header + public ushort Track; + /// Size of the whole block, not including this header, in bytes + public ushort Index; + /// CRC64-ECMA of the block + public int Lba; + } } } \ No newline at end of file diff --git a/Aaru.Images/AaruFormat/Write.cs b/Aaru.Images/AaruFormat/Write.cs index 18585bbb8..d462d9416 100644 --- a/Aaru.Images/AaruFormat/Write.cs +++ b/Aaru.Images/AaruFormat/Write.cs @@ -2928,7 +2928,8 @@ namespace Aaru.DiscImages blockStream = null; } - List trackEntries = new List(); + List trackEntries = new List(); + List compactDiscIndexEntries = new List(); 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()); + + structureBytes = new byte[Marshal.SizeOf()]; + 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()]; + 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 &&