mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add DiscImageChef format version 1.
This commit is contained in:
@@ -50,13 +50,13 @@
|
|||||||
Apple GCR sector tags).
|
Apple GCR sector tags).
|
||||||
|
|
||||||
Optical disks contain a track block that describes the tracks.
|
Optical disks contain a track block that describes the tracks.
|
||||||
Streaming tapes contain a file block that describes the files and an optional partition block that describes the tape
|
TODO: Streaming tapes contain a file block that describes the files and an optional partition block that describes the tape
|
||||||
partitions.
|
partitions.
|
||||||
|
|
||||||
There are also blocks for image metadata, contents metadata and dump hardware information.
|
TODO: There are also blocks for image metadata, contents metadata and dump hardware information.
|
||||||
|
|
||||||
A differencing image will have all the metadata and deduplication tables, but the entries in these ones will be set to
|
A differencing image will have all the metadata and deduplication tables, but the entries in these ones will be set to
|
||||||
0 if the block is stored in the parent image. This is not yet implemented.
|
0 if the block is stored in the parent image. TODO: This is not yet implemented.
|
||||||
|
|
||||||
Also because the file becomes useless without the index and deduplication table, each can be stored twice. In case of
|
Also because the file becomes useless without the index and deduplication table, each can be stored twice. In case of
|
||||||
the index it should just be searched for. In case of deduplication tables, both copies should be indexed.
|
the index it should just be searched for. In case of deduplication tables, both copies should be indexed.
|
||||||
@@ -90,50 +90,92 @@ using VendorString = DiscImageChef.Decoders.SecureDigital.VendorString;
|
|||||||
|
|
||||||
namespace DiscImageChef.DiscImages
|
namespace DiscImageChef.DiscImages
|
||||||
{
|
{
|
||||||
// TODO: Work in progress
|
|
||||||
public class DiscImageChef : IWritableImage
|
public class DiscImageChef : IWritableImage
|
||||||
{
|
{
|
||||||
const ulong DIC_MAGIC = 0x544D464444434944;
|
/// <summary>Magic identidier = "DICMFMT".</summary>
|
||||||
const byte DICF_VERSION = 0;
|
const ulong DIC_MAGIC = 0x544D52464D434944;
|
||||||
|
/// <summary>
|
||||||
|
/// Image format version. A change in this number indicates an incompatible change to the format that
|
||||||
|
/// prevents older implementations from reading it correctly, if at all.
|
||||||
|
/// </summary>
|
||||||
|
const byte DICF_VERSION = 1;
|
||||||
|
/// <summary>Maximum read cache size, 256MiB.</summary>
|
||||||
const uint MAX_CACHE_SIZE = 256 * 1024 * 1024;
|
const uint MAX_CACHE_SIZE = 256 * 1024 * 1024;
|
||||||
|
/// <summary>Size in bytes of LZMA properties.</summary>
|
||||||
const int LZMA_PROPERTIES_LENGTH = 5;
|
const int LZMA_PROPERTIES_LENGTH = 5;
|
||||||
|
/// <summary>Maximum number of entries for the DDT cache.</summary>
|
||||||
const int MAX_DDT_ENTRY_CACHE = 16000000;
|
const int MAX_DDT_ENTRY_CACHE = 16000000;
|
||||||
|
/// <summary>How many samples are contained in a RedBook sector.</summary>
|
||||||
const int SAMPLES_PER_SECTOR = 588;
|
const int SAMPLES_PER_SECTOR = 588;
|
||||||
|
/// <summary>Maximum number of samples for a FLAC block. Bigger than 4608 gives no benefit.</summary>
|
||||||
const int MAX_FLAKE_BLOCK = 4608;
|
const int MAX_FLAKE_BLOCK = 4608;
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum number of samples for a FLAC block. <see cref="CUETools.Codecs.FLAKE" /> does not support it to be
|
||||||
|
/// smaller than 256.
|
||||||
|
/// </summary>
|
||||||
const int MIN_FLAKE_BLOCK = 256;
|
const int MIN_FLAKE_BLOCK = 256;
|
||||||
|
|
||||||
|
/// <summary>Cache of uncompressed blocks.</summary>
|
||||||
Dictionary<ulong, byte[]> blockCache;
|
Dictionary<ulong, byte[]> blockCache;
|
||||||
|
/// <summary>Cache of block headers.</summary>
|
||||||
Dictionary<ulong, BlockHeader> blockHeaderCache;
|
Dictionary<ulong, BlockHeader> blockHeaderCache;
|
||||||
|
/// <summary>Stream used for writing blocks.</summary>
|
||||||
MemoryStream blockStream;
|
MemoryStream blockStream;
|
||||||
|
/// <summary>Provides checksum for deduplication of sectors.</summary>
|
||||||
SHA256 checksumProvider;
|
SHA256 checksumProvider;
|
||||||
LzmaStream compressedBlockStream;
|
/// <summary>Provides CRC64.</summary>
|
||||||
Crc64Context crc64;
|
Crc64Context crc64;
|
||||||
|
/// <summary>Header of the currently writing block.</summary>
|
||||||
BlockHeader currentBlockHeader;
|
BlockHeader currentBlockHeader;
|
||||||
|
/// <summary>Sector offset of writing position in currently writing block.</summary>
|
||||||
uint currentBlockOffset;
|
uint currentBlockOffset;
|
||||||
|
/// <summary>Current size in bytes of the block cache</summary>
|
||||||
uint currentCacheSize;
|
uint currentCacheSize;
|
||||||
|
/// <summary>Cache of DDT entries.</summary>
|
||||||
Dictionary<ulong, ulong> ddtEntryCache;
|
Dictionary<ulong, ulong> ddtEntryCache;
|
||||||
|
/// <summary>On-memory deduplication table indexed by checksum.</summary>
|
||||||
Dictionary<byte[], ulong> deduplicationTable;
|
Dictionary<byte[], ulong> deduplicationTable;
|
||||||
|
/// <summary><see cref="CUETools.Codecs.FLAKE" /> writer.</summary>
|
||||||
FlakeWriter flakeWriter;
|
FlakeWriter flakeWriter;
|
||||||
|
/// <summary><see cref="CUETools.Codecs.FLAKE" /> settings.</summary>
|
||||||
FlakeWriterSettings flakeWriterSettings;
|
FlakeWriterSettings flakeWriterSettings;
|
||||||
|
/// <summary>Block with logical geometry.</summary>
|
||||||
GeometryBlock geometryBlock;
|
GeometryBlock geometryBlock;
|
||||||
|
/// <summary>Image header.</summary>
|
||||||
DicHeader header;
|
DicHeader header;
|
||||||
|
/// <summary>Image information.</summary>
|
||||||
ImageInfo imageInfo;
|
ImageInfo imageInfo;
|
||||||
|
/// <summary>Image data stream.</summary>
|
||||||
Stream imageStream;
|
Stream imageStream;
|
||||||
|
/// <summary>Index.</summary>
|
||||||
List<IndexEntry> index;
|
List<IndexEntry> index;
|
||||||
|
/// <summary>If set to <c>true</c>, the DDT entries are in-memory.</summary>
|
||||||
bool inMemoryDdt;
|
bool inMemoryDdt;
|
||||||
|
/// <summary>LZMA stream.</summary>
|
||||||
|
LzmaStream lzmaBlockStream;
|
||||||
|
/// <summary>LZMA properties.</summary>
|
||||||
LzmaEncoderProperties lzmaEncoderProperties;
|
LzmaEncoderProperties lzmaEncoderProperties;
|
||||||
|
/// <summary>Cache of media tags.</summary>
|
||||||
Dictionary<MediaTagType, byte[]> mediaTags;
|
Dictionary<MediaTagType, byte[]> mediaTags;
|
||||||
|
/// <summary>If DDT is on-disk, this is the image stream offset at which it starts.</summary>
|
||||||
long outMemoryDdtPosition;
|
long outMemoryDdtPosition;
|
||||||
|
/// <summary>Cache for data that prefixes the user data on a sector (e.g. sync).</summary>
|
||||||
byte[] sectorPrefix;
|
byte[] sectorPrefix;
|
||||||
|
/// <summary>Cache for data that goes side by side with user data (e.g. CompactDisc subchannel).</summary>
|
||||||
byte[] sectorSubchannel;
|
byte[] sectorSubchannel;
|
||||||
|
/// <summary>Cache for data that suffixes the user data on a sector (e.g. edc, ecc).</summary>
|
||||||
byte[] sectorSuffix;
|
byte[] sectorSuffix;
|
||||||
|
/// <summary>Shift for calculating number of sectors in a block.</summary>
|
||||||
byte shift;
|
byte shift;
|
||||||
|
/// <summary>Cache for bytes to write/rad on-disk.</summary>
|
||||||
byte[] structureBytes;
|
byte[] structureBytes;
|
||||||
|
/// <summary>Cache for pointer for marshaling structures.</summary>
|
||||||
IntPtr structurePointer;
|
IntPtr structurePointer;
|
||||||
|
/// <summary>Cache of CompactDisc track's flags</summary>
|
||||||
Dictionary<byte, byte> trackFlags;
|
Dictionary<byte, byte> trackFlags;
|
||||||
|
/// <summary>Cache of CompactDisc track's ISRC</summary>
|
||||||
Dictionary<byte, string> trackIsrcs;
|
Dictionary<byte, string> trackIsrcs;
|
||||||
|
/// <summary>In-memory deduplication table</summary>
|
||||||
ulong[] userDataDdt;
|
ulong[] userDataDdt;
|
||||||
|
|
||||||
public DiscImageChef()
|
public DiscImageChef()
|
||||||
@@ -212,6 +254,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageInfo.Version = $"{header.imageMajorVersion}.{header.imageMinorVersion}";
|
imageInfo.Version = $"{header.imageMajorVersion}.{header.imageMinorVersion}";
|
||||||
imageInfo.MediaType = header.mediaType;
|
imageInfo.MediaType = header.mediaType;
|
||||||
|
|
||||||
|
// Read the index header
|
||||||
imageStream.Position = (long)header.indexOffset;
|
imageStream.Position = (long)header.indexOffset;
|
||||||
IndexHeader idxHeader = new IndexHeader();
|
IndexHeader idxHeader = new IndexHeader();
|
||||||
structureBytes = new byte[Marshal.SizeOf(idxHeader)];
|
structureBytes = new byte[Marshal.SizeOf(idxHeader)];
|
||||||
@@ -226,6 +269,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Index at {0} contains {1} entries",
|
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Index at {0} contains {1} entries",
|
||||||
header.indexOffset, idxHeader.entries);
|
header.indexOffset, idxHeader.entries);
|
||||||
|
|
||||||
|
// Fill in-memory index
|
||||||
index = new List<IndexEntry>();
|
index = new List<IndexEntry>();
|
||||||
for(ushort i = 0; i < idxHeader.entries; i++)
|
for(ushort i = 0; i < idxHeader.entries; i++)
|
||||||
{
|
{
|
||||||
@@ -296,6 +340,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
"Found data block type {0} at position {1}", entry.dataType,
|
"Found data block type {0} at position {1}", entry.dataType,
|
||||||
entry.offset);
|
entry.offset);
|
||||||
|
|
||||||
|
// Decompress media tag
|
||||||
if(blockHeader.compression == CompressionType.Lzma)
|
if(blockHeader.compression == CompressionType.Lzma)
|
||||||
{
|
{
|
||||||
byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
|
byte[] compressedTag = new byte[blockHeader.cmpLength - LZMA_PROPERTIES_LENGTH];
|
||||||
@@ -322,6 +367,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check CRC, if not correct, skip it
|
||||||
Crc64Context.Data(data, out byte[] blockCrc);
|
Crc64Context.Data(data, out byte[] blockCrc);
|
||||||
blockCrc = blockCrc.Reverse().ToArray();
|
blockCrc = blockCrc.Reverse().ToArray();
|
||||||
if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64)
|
if(BitConverter.ToUInt64(blockCrc, 0) != blockHeader.crc64)
|
||||||
@@ -332,6 +378,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if it's not a media tag, but a sector tag, and fill the appropriate table then
|
||||||
switch(entry.dataType)
|
switch(entry.dataType)
|
||||||
{
|
{
|
||||||
case DataType.CdSectorPrefix:
|
case DataType.CdSectorPrefix:
|
||||||
@@ -401,6 +448,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageInfo.Sectors = ddtHeader.entries;
|
imageInfo.Sectors = ddtHeader.entries;
|
||||||
shift = ddtHeader.shift;
|
shift = ddtHeader.shift;
|
||||||
|
|
||||||
|
// Check for DDT compression
|
||||||
switch(ddtHeader.compression)
|
switch(ddtHeader.compression)
|
||||||
{
|
{
|
||||||
case CompressionType.Lzma:
|
case CompressionType.Lzma:
|
||||||
@@ -436,6 +484,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
foundUserDataDdt = true;
|
foundUserDataDdt = true;
|
||||||
break;
|
break;
|
||||||
|
// Logical geometry block. It doesn't have a CRC coz, well, it's not so important
|
||||||
case BlockType.GeometryBlock:
|
case BlockType.GeometryBlock:
|
||||||
geometryBlock = new GeometryBlock();
|
geometryBlock = new GeometryBlock();
|
||||||
structureBytes = new byte[Marshal.SizeOf(geometryBlock)];
|
structureBytes = new byte[Marshal.SizeOf(geometryBlock)];
|
||||||
@@ -456,6 +505,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
// Metadata block
|
||||||
case BlockType.MetadataBlock:
|
case BlockType.MetadataBlock:
|
||||||
MetadataBlock metadataBlock = new MetadataBlock();
|
MetadataBlock metadataBlock = new MetadataBlock();
|
||||||
structureBytes = new byte[Marshal.SizeOf(metadataBlock)];
|
structureBytes = new byte[Marshal.SizeOf(metadataBlock)];
|
||||||
@@ -626,6 +676,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
// Optical disc tracks block
|
||||||
case BlockType.TracksBlock:
|
case BlockType.TracksBlock:
|
||||||
TracksHeader tracksHeader = new TracksHeader();
|
TracksHeader tracksHeader = new TracksHeader();
|
||||||
structureBytes = new byte[Marshal.SizeOf(tracksHeader)];
|
structureBytes = new byte[Marshal.SizeOf(tracksHeader)];
|
||||||
@@ -719,6 +770,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
currentCacheSize = 0;
|
currentCacheSize = 0;
|
||||||
if(!inMemoryDdt) ddtEntryCache = new Dictionary<ulong, ulong>();
|
if(!inMemoryDdt) ddtEntryCache = new Dictionary<ulong, ulong>();
|
||||||
|
|
||||||
|
// Initialize tracks, sessions and partitions
|
||||||
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
||||||
{
|
{
|
||||||
if(Tracks == null || Tracks.Count == 0)
|
if(Tracks == null || Tracks.Count == 0)
|
||||||
@@ -827,6 +879,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
byte[] sector;
|
byte[] sector;
|
||||||
|
|
||||||
|
// Check if block is cached
|
||||||
if(blockCache.TryGetValue(blockOffset, out byte[] block) &&
|
if(blockCache.TryGetValue(blockOffset, out byte[] block) &&
|
||||||
blockHeaderCache.TryGetValue(blockOffset, out BlockHeader blockHeader))
|
blockHeaderCache.TryGetValue(blockOffset, out BlockHeader blockHeader))
|
||||||
{
|
{
|
||||||
@@ -835,6 +888,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read block header
|
||||||
imageStream.Position = (long)blockOffset;
|
imageStream.Position = (long)blockOffset;
|
||||||
blockHeader = new BlockHeader();
|
blockHeader = new BlockHeader();
|
||||||
structureBytes = new byte[Marshal.SizeOf(blockHeader)];
|
structureBytes = new byte[Marshal.SizeOf(blockHeader)];
|
||||||
@@ -844,6 +898,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
blockHeader = (BlockHeader)Marshal.PtrToStructure(structurePointer, typeof(BlockHeader));
|
blockHeader = (BlockHeader)Marshal.PtrToStructure(structurePointer, typeof(BlockHeader));
|
||||||
Marshal.FreeHGlobal(structurePointer);
|
Marshal.FreeHGlobal(structurePointer);
|
||||||
|
|
||||||
|
// Decompress block
|
||||||
switch(blockHeader.compression)
|
switch(blockHeader.compression)
|
||||||
{
|
{
|
||||||
case CompressionType.None:
|
case CompressionType.None:
|
||||||
@@ -879,6 +934,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
ImageNotSupportedException($"Found unsupported compression algorithm {(ushort)blockHeader.compression}");
|
ImageNotSupportedException($"Found unsupported compression algorithm {(ushort)blockHeader.compression}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if cache needs to be emptied
|
||||||
if(currentCacheSize + blockHeader.length >= MAX_CACHE_SIZE)
|
if(currentCacheSize + blockHeader.length >= MAX_CACHE_SIZE)
|
||||||
{
|
{
|
||||||
currentCacheSize = 0;
|
currentCacheSize = 0;
|
||||||
@@ -886,6 +942,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
blockCache = new Dictionary<ulong, byte[]>();
|
blockCache = new Dictionary<ulong, byte[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add block to cache
|
||||||
currentCacheSize += blockHeader.length;
|
currentCacheSize += blockHeader.length;
|
||||||
blockHeaderCache.Add(blockOffset, blockHeader);
|
blockHeaderCache.Add(blockOffset, blockHeader);
|
||||||
blockCache.Add(blockOffset, block);
|
blockCache.Add(blockOffset, block);
|
||||||
@@ -1070,6 +1127,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
dataSource = sectorPrefix;
|
dataSource = sectorPrefix;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// These could be implemented
|
||||||
case SectorTagType.CdSectorEcc:
|
case SectorTagType.CdSectorEcc:
|
||||||
case SectorTagType.CdSectorEccP:
|
case SectorTagType.CdSectorEccP:
|
||||||
case SectorTagType.CdSectorEccQ:
|
case SectorTagType.CdSectorEccQ:
|
||||||
@@ -1243,8 +1301,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
switch(trk.TrackType)
|
switch(trk.TrackType)
|
||||||
{
|
{
|
||||||
|
// These types only contain user data
|
||||||
case TrackType.Audio:
|
case TrackType.Audio:
|
||||||
case TrackType.Data: return ReadSectors(sectorAddress, length);
|
case TrackType.Data: return ReadSectors(sectorAddress, length);
|
||||||
|
// Join prefix (sync, header) with user data with suffix (edc, ecc p, ecc q)
|
||||||
case TrackType.CdMode1:
|
case TrackType.CdMode1:
|
||||||
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
||||||
|
|
||||||
@@ -1261,6 +1321,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sectors;
|
return sectors;
|
||||||
|
// Join prefix (sync, header) with user data
|
||||||
case TrackType.CdMode2Formless:
|
case TrackType.CdMode2Formless:
|
||||||
case TrackType.CdMode2Form1:
|
case TrackType.CdMode2Form1:
|
||||||
case TrackType.CdMode2Form2:
|
case TrackType.CdMode2Form2:
|
||||||
@@ -1283,6 +1344,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
case XmlMediaType.BlockMedia:
|
case XmlMediaType.BlockMedia:
|
||||||
switch(imageInfo.MediaType)
|
switch(imageInfo.MediaType)
|
||||||
{
|
{
|
||||||
|
// Join user data with tags
|
||||||
case MediaType.AppleFileWare:
|
case MediaType.AppleFileWare:
|
||||||
case MediaType.AppleProfile:
|
case MediaType.AppleProfile:
|
||||||
case MediaType.AppleSonySS:
|
case MediaType.AppleSonySS:
|
||||||
@@ -1376,6 +1438,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
failingLbas = new List<ulong>();
|
failingLbas = new List<ulong>();
|
||||||
unknownLbas = new List<ulong>();
|
unknownLbas = new List<ulong>();
|
||||||
|
|
||||||
|
// Right now only CompactDisc sectors are verifyable
|
||||||
if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
|
if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
|
||||||
{
|
{
|
||||||
for(ulong i = sectorAddress; i < sectorAddress + length; i++) unknownLbas.Add(i);
|
for(ulong i = sectorAddress; i < sectorAddress + length; i++) unknownLbas.Add(i);
|
||||||
@@ -1413,6 +1476,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
|
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
|
||||||
out List<ulong> unknownLbas)
|
out List<ulong> unknownLbas)
|
||||||
{
|
{
|
||||||
|
// Right now only CompactDisc sectors are verifyable
|
||||||
if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
|
if(imageInfo.XmlMediaType != XmlMediaType.OpticalDisc)
|
||||||
{
|
{
|
||||||
failingLbas = new List<ulong>();
|
failingLbas = new List<ulong>();
|
||||||
@@ -1452,6 +1516,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
public bool? VerifyMediaImage()
|
public bool? VerifyMediaImage()
|
||||||
{
|
{
|
||||||
|
// This will traverse all blocks and check their CRC64 without uncompressing them
|
||||||
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Checking index integrity at {0}",
|
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Checking index integrity at {0}",
|
||||||
header.indexOffset);
|
header.indexOffset);
|
||||||
imageStream.Position = (long)header.indexOffset;
|
imageStream.Position = (long)header.indexOffset;
|
||||||
@@ -1502,6 +1567,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
vrIndex.Add(entry);
|
vrIndex.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read up to 1MiB at a time for verification
|
||||||
const int VERIFY_SIZE = 1024 * 1024;
|
const int VERIFY_SIZE = 1024 * 1024;
|
||||||
|
|
||||||
foreach(IndexEntry entry in vrIndex)
|
foreach(IndexEntry entry in vrIndex)
|
||||||
@@ -1691,12 +1757,14 @@ namespace DiscImageChef.DiscImages
|
|||||||
maxDdtSize = 256;
|
maxDdtSize = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This really, cannot happen
|
||||||
if(!SupportedMediaTypes.Contains(mediaType))
|
if(!SupportedMediaTypes.Contains(mediaType))
|
||||||
{
|
{
|
||||||
ErrorMessage = $"Unsupport media format {mediaType}";
|
ErrorMessage = $"Unsupport media format {mediaType}";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate shift
|
||||||
shift = 0;
|
shift = 0;
|
||||||
uint oldSectorsPerBlock = sectorsPerBlock;
|
uint oldSectorsPerBlock = sectorsPerBlock;
|
||||||
while(sectorsPerBlock > 1)
|
while(sectorsPerBlock > 1)
|
||||||
@@ -1723,6 +1791,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if appending to an existing image
|
||||||
if(imageStream.Length > Marshal.SizeOf(typeof(DicHeader)))
|
if(imageStream.Length > Marshal.SizeOf(typeof(DicHeader)))
|
||||||
{
|
{
|
||||||
header = new DicHeader();
|
header = new DicHeader();
|
||||||
@@ -1772,6 +1841,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
index = new List<IndexEntry>();
|
index = new List<IndexEntry>();
|
||||||
|
|
||||||
|
// If there exists an index, we are appending, so read index
|
||||||
if(header.indexOffset > 0)
|
if(header.indexOffset > 0)
|
||||||
{
|
{
|
||||||
imageStream.Position = (long)header.indexOffset;
|
imageStream.Position = (long)header.indexOffset;
|
||||||
@@ -1977,11 +2047,15 @@ namespace DiscImageChef.DiscImages
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Creating new
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Checking that DDT is smaller than requested size
|
||||||
inMemoryDdt = sectors <= maxDdtSize * 1024 * 1024 / sizeof(ulong);
|
inMemoryDdt = sectors <= maxDdtSize * 1024 * 1024 / sizeof(ulong);
|
||||||
|
|
||||||
|
// If in memory, easy
|
||||||
if(inMemoryDdt) userDataDdt = new ulong[sectors];
|
if(inMemoryDdt) userDataDdt = new ulong[sectors];
|
||||||
|
// If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outMemoryDdtPosition = imageStream.Position;
|
outMemoryDdtPosition = imageStream.Position;
|
||||||
@@ -2019,6 +2093,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
DicConsole.DebugWriteLine("DiscImageChef format plugin", "In memory DDT?: {0}", inMemoryDdt);
|
DicConsole.DebugWriteLine("DiscImageChef format plugin", "In memory DDT?: {0}", inMemoryDdt);
|
||||||
|
|
||||||
|
// Initialize tables
|
||||||
imageStream.Seek(0, SeekOrigin.End);
|
imageStream.Seek(0, SeekOrigin.End);
|
||||||
mediaTags = new Dictionary<MediaTagType, byte[]>();
|
mediaTags = new Dictionary<MediaTagType, byte[]>();
|
||||||
checksumProvider = SHA256.Create();
|
checksumProvider = SHA256.Create();
|
||||||
@@ -2026,6 +2101,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
trackIsrcs = new Dictionary<byte, string>();
|
trackIsrcs = new Dictionary<byte, string>();
|
||||||
trackFlags = new Dictionary<byte, byte>();
|
trackFlags = new Dictionary<byte, byte>();
|
||||||
|
|
||||||
|
// Initialize compressors properties (all maxed)
|
||||||
lzmaEncoderProperties = new LzmaEncoderProperties(true, (int)dictionary, 273);
|
lzmaEncoderProperties = new LzmaEncoderProperties(true, (int)dictionary, 273);
|
||||||
flakeWriterSettings = new FlakeWriterSettings
|
flakeWriterSettings = new FlakeWriterSettings
|
||||||
{
|
{
|
||||||
@@ -2049,6 +2125,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
AllowNonSubset = true
|
AllowNonSubset = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if FLAKE's block size is bigger than what we want
|
||||||
if(flakeWriterSettings.BlockSize > MAX_FLAKE_BLOCK) flakeWriterSettings.BlockSize = MAX_FLAKE_BLOCK;
|
if(flakeWriterSettings.BlockSize > MAX_FLAKE_BLOCK) flakeWriterSettings.BlockSize = MAX_FLAKE_BLOCK;
|
||||||
if(flakeWriterSettings.BlockSize < MIN_FLAKE_BLOCK) flakeWriterSettings.BlockSize = MIN_FLAKE_BLOCK;
|
if(flakeWriterSettings.BlockSize < MIN_FLAKE_BLOCK) flakeWriterSettings.BlockSize = MIN_FLAKE_BLOCK;
|
||||||
FlakeWriter.Vendor = "DiscImageChef";
|
FlakeWriter.Vendor = "DiscImageChef";
|
||||||
@@ -2099,6 +2176,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
Track trk = new Track();
|
Track trk = new Track();
|
||||||
|
|
||||||
|
// If optical disc check track
|
||||||
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
|
||||||
{
|
{
|
||||||
trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
trk = Tracks.FirstOrDefault(t => sectorAddress >= t.TrackStartSector &&
|
||||||
@@ -2110,10 +2188,12 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
// Close current block first
|
// Close current block first
|
||||||
if(blockStream != null &&
|
if(blockStream != null &&
|
||||||
|
// When sector siz changes
|
||||||
(currentBlockHeader.sectorSize != data.Length ||
|
(currentBlockHeader.sectorSize != data.Length ||
|
||||||
|
// When block if filled
|
||||||
currentBlockOffset == 1 << shift ||
|
currentBlockOffset == 1 << shift ||
|
||||||
currentBlockHeader.compression == CompressionType.Flac &&
|
// When we change to/from CompactDisc audio
|
||||||
trk.TrackType != TrackType.Audio))
|
currentBlockHeader.compression == CompressionType.Flac && trk.TrackType != TrackType.Audio))
|
||||||
{
|
{
|
||||||
currentBlockHeader.length = currentBlockOffset * currentBlockHeader.sectorSize;
|
currentBlockHeader.length = currentBlockOffset * currentBlockHeader.sectorSize;
|
||||||
currentBlockHeader.crc64 = BitConverter.ToUInt64(crc64.Final(), 0);
|
currentBlockHeader.crc64 = BitConverter.ToUInt64(crc64.Final(), 0);
|
||||||
@@ -2143,8 +2223,8 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lzmaProperties = compressedBlockStream.Properties;
|
lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
cmpCrc64Context.Update(lzmaProperties);
|
cmpCrc64Context.Update(lzmaProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2191,9 +2271,8 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
if(currentBlockHeader.compression == CompressionType.Flac)
|
if(currentBlockHeader.compression == CompressionType.Flac)
|
||||||
flakeWriter =
|
flakeWriter = new FlakeWriter("", blockStream, flakeWriterSettings) {DoSeekTable = false};
|
||||||
new FlakeWriter("", blockStream, flakeWriterSettings) {DoSeekTable = false};
|
else lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
else compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
|
||||||
crc64 = new Crc64Context();
|
crc64 = new Crc64Context();
|
||||||
crc64.Init();
|
crc64.Init();
|
||||||
}
|
}
|
||||||
@@ -2205,7 +2284,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
AudioBuffer audioBuffer = new AudioBuffer(AudioPCMConfig.RedBook, data, SAMPLES_PER_SECTOR);
|
AudioBuffer audioBuffer = new AudioBuffer(AudioPCMConfig.RedBook, data, SAMPLES_PER_SECTOR);
|
||||||
flakeWriter.Write(audioBuffer);
|
flakeWriter.Write(audioBuffer);
|
||||||
}
|
}
|
||||||
else compressedBlockStream.Write(data, 0, data.Length);
|
else lzmaBlockStream.Write(data, 0, data.Length);
|
||||||
|
|
||||||
SetDdtEntry(sectorAddress, ddtEntry);
|
SetDdtEntry(sectorAddress, ddtEntry);
|
||||||
crc64.Update(data);
|
crc64.Update(data);
|
||||||
@@ -2271,6 +2350,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split raw cd sector data in prefix (sync, header), user data and suffix (edc, ecc p, ecc q)
|
||||||
switch(track.TrackType)
|
switch(track.TrackType)
|
||||||
{
|
{
|
||||||
case TrackType.Audio:
|
case TrackType.Audio:
|
||||||
@@ -2298,6 +2378,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
case XmlMediaType.BlockMedia:
|
case XmlMediaType.BlockMedia:
|
||||||
switch(imageInfo.MediaType)
|
switch(imageInfo.MediaType)
|
||||||
{
|
{
|
||||||
|
// Split user data from Apple tags
|
||||||
case MediaType.AppleFileWare:
|
case MediaType.AppleFileWare:
|
||||||
case MediaType.AppleProfile:
|
case MediaType.AppleProfile:
|
||||||
case MediaType.AppleSonyDS:
|
case MediaType.AppleSonyDS:
|
||||||
@@ -2528,8 +2609,8 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lzmaProperties = compressedBlockStream.Properties;
|
lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
cmpCrc64Context.Update(lzmaProperties);
|
cmpCrc64Context.Update(lzmaProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2560,6 +2641,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
IndexEntry idxEntry;
|
IndexEntry idxEntry;
|
||||||
|
|
||||||
|
// Write media tag blocks
|
||||||
foreach(KeyValuePair<MediaTagType, byte[]> mediaTag in mediaTags)
|
foreach(KeyValuePair<MediaTagType, byte[]> mediaTag in mediaTags)
|
||||||
{
|
{
|
||||||
DataType dataType = GetDataTypeForMediaTag(mediaTag.Key);
|
DataType dataType = GetDataTypeForMediaTag(mediaTag.Key);
|
||||||
@@ -2584,10 +2666,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
compressedBlockStream.Write(mediaTag.Value, 0, mediaTag.Value.Length);
|
lzmaBlockStream.Write(mediaTag.Value, 0, mediaTag.Value.Length);
|
||||||
byte[] lzmaProperties = compressedBlockStream.Properties;
|
byte[] lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
byte[] tagData;
|
byte[] tagData;
|
||||||
|
|
||||||
// Not compressible
|
// Not compressible
|
||||||
@@ -2607,7 +2689,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
tagBlock.compression = CompressionType.Lzma;
|
tagBlock.compression = CompressionType.Lzma;
|
||||||
}
|
}
|
||||||
|
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
blockStream = null;
|
blockStream = null;
|
||||||
|
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(tagBlock));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(tagBlock));
|
||||||
@@ -2625,6 +2707,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
index.Add(idxEntry);
|
index.Add(idxEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have set the geometry block, write it
|
||||||
if(geometryBlock.identifier == BlockType.GeometryBlock)
|
if(geometryBlock.identifier == BlockType.GeometryBlock)
|
||||||
{
|
{
|
||||||
idxEntry = new IndexEntry
|
idxEntry = new IndexEntry
|
||||||
@@ -2649,6 +2732,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
index.Add(idxEntry);
|
index.Add(idxEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the DDT is in-memory, write it to disk
|
||||||
if(inMemoryDdt)
|
if(inMemoryDdt)
|
||||||
{
|
{
|
||||||
idxEntry = new IndexEntry
|
idxEntry = new IndexEntry
|
||||||
@@ -2672,18 +2756,18 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
crc64 = new Crc64Context();
|
crc64 = new Crc64Context();
|
||||||
crc64.Init();
|
crc64.Init();
|
||||||
for(ulong i = 0; i < (ulong)userDataDdt.LongLength; i++)
|
for(ulong i = 0; i < (ulong)userDataDdt.LongLength; i++)
|
||||||
{
|
{
|
||||||
byte[] ddtEntry = BitConverter.GetBytes(userDataDdt[i]);
|
byte[] ddtEntry = BitConverter.GetBytes(userDataDdt[i]);
|
||||||
crc64.Update(ddtEntry);
|
crc64.Update(ddtEntry);
|
||||||
compressedBlockStream.Write(ddtEntry, 0, ddtEntry.Length);
|
lzmaBlockStream.Write(ddtEntry, 0, ddtEntry.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] lzmaProperties = compressedBlockStream.Properties;
|
byte[] lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
ddtHeader.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
ddtHeader.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
Crc64Context cmpCrc64Context = new Crc64Context();
|
Crc64Context cmpCrc64Context = new Crc64Context();
|
||||||
cmpCrc64Context.Init();
|
cmpCrc64Context.Init();
|
||||||
@@ -2701,13 +2785,14 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
|
imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
|
||||||
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
|
imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
|
||||||
blockStream = null;
|
blockStream = null;
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
|
|
||||||
index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && t.dataType == DataType.UserData);
|
index.RemoveAll(t => t.blockType == BlockType.DeDuplicationTable && t.dataType == DataType.UserData);
|
||||||
|
|
||||||
index.Add(idxEntry);
|
index.Add(idxEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write the sector prefix, suffix and subchannels if present
|
||||||
switch(imageInfo.XmlMediaType)
|
switch(imageInfo.XmlMediaType)
|
||||||
{
|
{
|
||||||
case XmlMediaType.OpticalDisc when Tracks != null && Tracks.Count > 0:
|
case XmlMediaType.OpticalDisc when Tracks != null && Tracks.Count > 0:
|
||||||
@@ -2734,17 +2819,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
compressedBlockStream.Write(sectorPrefix, 0, sectorPrefix.Length);
|
lzmaBlockStream.Write(sectorPrefix, 0, sectorPrefix.Length);
|
||||||
byte[] lzmaProperties = compressedBlockStream.Properties;
|
byte[] lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
|
|
||||||
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
||||||
prefixBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
prefixBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
||||||
prefixBlock.compression = CompressionType.Lzma;
|
prefixBlock.compression = CompressionType.Lzma;
|
||||||
|
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
|
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(prefixBlock));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(prefixBlock));
|
||||||
structureBytes = new byte[Marshal.SizeOf(prefixBlock)];
|
structureBytes = new byte[Marshal.SizeOf(prefixBlock)];
|
||||||
@@ -2782,17 +2867,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
compressedBlockStream.Write(sectorSuffix, 0, sectorSuffix.Length);
|
lzmaBlockStream.Write(sectorSuffix, 0, sectorSuffix.Length);
|
||||||
lzmaProperties = compressedBlockStream.Properties;
|
lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
|
|
||||||
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
||||||
prefixBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
prefixBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
prefixBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
||||||
prefixBlock.compression = CompressionType.Lzma;
|
prefixBlock.compression = CompressionType.Lzma;
|
||||||
|
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
|
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(prefixBlock));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(prefixBlock));
|
||||||
structureBytes = new byte[Marshal.SizeOf(prefixBlock)];
|
structureBytes = new byte[Marshal.SizeOf(prefixBlock)];
|
||||||
@@ -2834,17 +2919,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
compressedBlockStream.Write(sectorSubchannel, 0, sectorSubchannel.Length);
|
lzmaBlockStream.Write(sectorSubchannel, 0, sectorSubchannel.Length);
|
||||||
byte[] lzmaProperties = compressedBlockStream.Properties;
|
byte[] lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
|
|
||||||
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
||||||
subchannelBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
subchannelBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
||||||
subchannelBlock.compression = CompressionType.Lzma;
|
subchannelBlock.compression = CompressionType.Lzma;
|
||||||
|
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
|
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subchannelBlock));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subchannelBlock));
|
||||||
structureBytes = new byte[Marshal.SizeOf(subchannelBlock)];
|
structureBytes = new byte[Marshal.SizeOf(subchannelBlock)];
|
||||||
@@ -2885,6 +2970,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are tracks build the tracks block
|
||||||
if(trackEntries.Count > 0)
|
if(trackEntries.Count > 0)
|
||||||
{
|
{
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
@@ -2977,17 +3063,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
compressedBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
|
||||||
compressedBlockStream.Write(sectorSubchannel, 0, sectorSubchannel.Length);
|
lzmaBlockStream.Write(sectorSubchannel, 0, sectorSubchannel.Length);
|
||||||
byte[] lzmaProperties = compressedBlockStream.Properties;
|
byte[] lzmaProperties = lzmaBlockStream.Properties;
|
||||||
compressedBlockStream.Close();
|
lzmaBlockStream.Close();
|
||||||
|
|
||||||
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
Crc64Context.Data(blockStream.ToArray(), out blockCrc);
|
||||||
subchannelBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
subchannelBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
|
||||||
subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
subchannelBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
|
||||||
subchannelBlock.compression = CompressionType.Lzma;
|
subchannelBlock.compression = CompressionType.Lzma;
|
||||||
|
|
||||||
compressedBlockStream = null;
|
lzmaBlockStream = null;
|
||||||
|
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subchannelBlock));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subchannelBlock));
|
||||||
structureBytes = new byte[Marshal.SizeOf(subchannelBlock)];
|
structureBytes = new byte[Marshal.SizeOf(subchannelBlock)];
|
||||||
@@ -3008,6 +3094,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write metadata if present
|
||||||
SetMetadataFromTags();
|
SetMetadataFromTags();
|
||||||
MetadataBlock metadataBlock = new MetadataBlock();
|
MetadataBlock metadataBlock = new MetadataBlock();
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
@@ -3141,6 +3228,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
blockStream.Write(new byte[] {0, 0}, 0, 2);
|
blockStream.Write(new byte[] {0, 0}, 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if we set up any metadata earlier, then write its block
|
||||||
if(metadataBlock.identifier == BlockType.MetadataBlock)
|
if(metadataBlock.identifier == BlockType.MetadataBlock)
|
||||||
{
|
{
|
||||||
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Writing metadata to position {0}",
|
DicConsole.DebugWriteLine("DiscImageChef format plugin", "Writing metadata to position {0}",
|
||||||
@@ -3170,6 +3258,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
blockStream = new MemoryStream();
|
blockStream = new MemoryStream();
|
||||||
|
|
||||||
|
// Write index to memory
|
||||||
foreach(IndexEntry entry in index)
|
foreach(IndexEntry entry in index)
|
||||||
{
|
{
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(entry));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(entry));
|
||||||
@@ -3189,6 +3278,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
crc64 = BitConverter.ToUInt64(idxCrc, 0)
|
crc64 = BitConverter.ToUInt64(idxCrc, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Write index to disk
|
||||||
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(idxHeader));
|
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(idxHeader));
|
||||||
structureBytes = new byte[Marshal.SizeOf(idxHeader)];
|
structureBytes = new byte[Marshal.SizeOf(idxHeader)];
|
||||||
Marshal.StructureToPtr(idxHeader, structurePointer, true);
|
Marshal.StructureToPtr(idxHeader, structurePointer, true);
|
||||||
@@ -3381,8 +3471,12 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks for media tags that may contain metadata and sets it up if not already set
|
||||||
|
/// </summary>
|
||||||
void SetMetadataFromTags()
|
void SetMetadataFromTags()
|
||||||
{
|
{
|
||||||
|
// Search for SecureDigital CID
|
||||||
if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid))
|
if(mediaTags.TryGetValue(MediaTagType.SD_CID, out byte[] sdCid))
|
||||||
{
|
{
|
||||||
CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid);
|
CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(sdCid);
|
||||||
@@ -3397,6 +3491,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for MultiMediaCard CID
|
||||||
if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid))
|
if(mediaTags.TryGetValue(MediaTagType.MMC_CID, out byte[] mmcCid))
|
||||||
{
|
{
|
||||||
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid);
|
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(mmcCid);
|
||||||
@@ -3411,6 +3506,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
imageInfo.DriveSerialNumber = $"{decoded.ProductSerialNumber}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for SCSI INQUIRY
|
||||||
if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry))
|
if(mediaTags.TryGetValue(MediaTagType.SCSI_INQUIRY, out byte[] scsiInquiry))
|
||||||
{
|
{
|
||||||
Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
|
Inquiry.SCSIInquiry? nullableInquiry = Inquiry.Decode(scsiInquiry);
|
||||||
@@ -3428,6 +3524,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search for ATA or ATAPI IDENTIFY
|
||||||
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
|
if(!mediaTags.TryGetValue(MediaTagType.ATA_IDENTIFY, out byte[] ataIdentify) &&
|
||||||
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return;
|
!mediaTags.TryGetValue(MediaTagType.ATAPI_IDENTIFY, out ataIdentify)) return;
|
||||||
|
|
||||||
@@ -3456,6 +3553,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageInfo.DriveSerialNumber = identify.SerialNumber;
|
imageInfo.DriveSerialNumber = identify.SerialNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the CICM XML media type from DIC media type
|
||||||
static XmlMediaType GetXmlMediaType(MediaType type)
|
static XmlMediaType GetXmlMediaType(MediaType type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
@@ -3542,6 +3640,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets a DDT entry
|
||||||
ulong GetDdtEntry(ulong sectorAddress)
|
ulong GetDdtEntry(ulong sectorAddress)
|
||||||
{
|
{
|
||||||
if(inMemoryDdt) return userDataDdt[sectorAddress];
|
if(inMemoryDdt) return userDataDdt[sectorAddress];
|
||||||
@@ -3562,6 +3661,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets a DDT entry
|
||||||
void SetDdtEntry(ulong sectorAddress, ulong pointer)
|
void SetDdtEntry(ulong sectorAddress, ulong pointer)
|
||||||
{
|
{
|
||||||
if(inMemoryDdt)
|
if(inMemoryDdt)
|
||||||
@@ -3577,6 +3677,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
imageStream.Position = oldPosition;
|
imageStream.Position = oldPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts between image data type and dic media tag type
|
||||||
static MediaTagType GetMediaTagTypeForDataType(DataType type)
|
static MediaTagType GetMediaTagTypeForDataType(DataType type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
@@ -3652,6 +3753,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts between dic media tag type and image data type
|
||||||
static DataType GetDataTypeForMediaTag(MediaTagType tag)
|
static DataType GetDataTypeForMediaTag(MediaTagType tag)
|
||||||
{
|
{
|
||||||
switch(tag)
|
switch(tag)
|
||||||
@@ -3728,100 +3830,201 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>List of known compression types</summary>
|
||||||
enum CompressionType : ushort
|
enum CompressionType : ushort
|
||||||
{
|
{
|
||||||
|
/// <summary>Not compressed</summary>
|
||||||
None = 0,
|
None = 0,
|
||||||
|
/// <summary>LZMA</summary>
|
||||||
Lzma = 1,
|
Lzma = 1,
|
||||||
|
/// <summary>FLAC</summary>
|
||||||
Flac = 2
|
Flac = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>List of known data types</summary>
|
||||||
enum DataType : ushort
|
enum DataType : ushort
|
||||||
{
|
{
|
||||||
|
/// <summary>No data</summary>
|
||||||
NoData = 0,
|
NoData = 0,
|
||||||
|
/// <summary>User data</summary>
|
||||||
UserData = 1,
|
UserData = 1,
|
||||||
|
/// <summary>CompactDisc partial Table of Contents</summary>
|
||||||
CompactDiscPartialToc = 2,
|
CompactDiscPartialToc = 2,
|
||||||
|
/// <summary>CompactDisc session information</summary>
|
||||||
CompactDiscSessionInfo = 3,
|
CompactDiscSessionInfo = 3,
|
||||||
|
/// <summary>CompactDisc Table of Contents</summary>
|
||||||
CompactDiscToc = 4,
|
CompactDiscToc = 4,
|
||||||
|
/// <summary>CompactDisc Power Management Area</summary>
|
||||||
CompactDiscPma = 5,
|
CompactDiscPma = 5,
|
||||||
|
/// <summary>CompactDisc Absolute Time In Pregroove</summary>
|
||||||
CompactDiscAtip = 6,
|
CompactDiscAtip = 6,
|
||||||
|
/// <summary>CompactDisc Lead-in's CD-Text</summary>
|
||||||
CompactDiscLeadInCdText = 7,
|
CompactDiscLeadInCdText = 7,
|
||||||
|
/// <summary>DVD Physical Format Information</summary>
|
||||||
DvdPfi = 8,
|
DvdPfi = 8,
|
||||||
|
/// <summary>DVD Lead-in's Copyright Management Information</summary>
|
||||||
DvdLeadInCmi = 9,
|
DvdLeadInCmi = 9,
|
||||||
|
/// <summary>DVD Disc Key</summary>
|
||||||
DvdDiscKey = 10,
|
DvdDiscKey = 10,
|
||||||
|
/// <summary>DVD Burst Cutting Area</summary>
|
||||||
DvdBca = 11,
|
DvdBca = 11,
|
||||||
|
/// <summary>DVD DMI</summary>
|
||||||
DvdDmi = 12,
|
DvdDmi = 12,
|
||||||
|
/// <summary>DVD Media Identifier</summary>
|
||||||
DvdMediaIdentifier = 13,
|
DvdMediaIdentifier = 13,
|
||||||
|
/// <summary>DVD Media Key Block</summary>
|
||||||
DvdMediaKeyBlock = 14,
|
DvdMediaKeyBlock = 14,
|
||||||
|
/// <summary>DVD-RAM Disc Definition Structure</summary>
|
||||||
DvdRamDds = 15,
|
DvdRamDds = 15,
|
||||||
|
/// <summary>DVD-RAM Medium Status</summary>
|
||||||
DvdRamMediumStatus = 16,
|
DvdRamMediumStatus = 16,
|
||||||
|
/// <summary>DVD-RAM Spare Area Information</summary>
|
||||||
DvdRamSpareArea = 17,
|
DvdRamSpareArea = 17,
|
||||||
|
/// <summary>DVD-R RMD</summary>
|
||||||
DvdRRmd = 18,
|
DvdRRmd = 18,
|
||||||
|
/// <summary>DVD-R Pre-recorded Information</summary>
|
||||||
DvdRPrerecordedInfo = 19,
|
DvdRPrerecordedInfo = 19,
|
||||||
|
/// <summary>DVD-R Media Identifier</summary>
|
||||||
DvdRMediaIdentifier = 20,
|
DvdRMediaIdentifier = 20,
|
||||||
|
/// <summary>DVD-R Physical Format Information</summary>
|
||||||
DvdRPfi = 21,
|
DvdRPfi = 21,
|
||||||
|
/// <summary>DVD ADress In Pregroove</summary>
|
||||||
DvdAdip = 22,
|
DvdAdip = 22,
|
||||||
|
/// <summary>HD DVD Copy Protection Information</summary>
|
||||||
HdDvdCpi = 23,
|
HdDvdCpi = 23,
|
||||||
|
/// <summary>HD DVD Medium Status</summary>
|
||||||
HdDvdMediumStatus = 24,
|
HdDvdMediumStatus = 24,
|
||||||
|
/// <summary>DVD DL Layer Capacity</summary>
|
||||||
DvdDlLayerCapacity = 25,
|
DvdDlLayerCapacity = 25,
|
||||||
|
/// <summary>DVD DL Middle Zone Address</summary>
|
||||||
DvdDlMiddleZoneAddress = 26,
|
DvdDlMiddleZoneAddress = 26,
|
||||||
|
/// <summary>DVD DL Jump Interval Size</summary>
|
||||||
DvdDlJumpIntervalSize = 27,
|
DvdDlJumpIntervalSize = 27,
|
||||||
|
/// <summary>DVD DL Manual Layer Jump LBA</summary>
|
||||||
DvdDlManualLayerJumpLba = 28,
|
DvdDlManualLayerJumpLba = 28,
|
||||||
|
/// <summary>Bluray Disc Information</summary>
|
||||||
BlurayDi = 29,
|
BlurayDi = 29,
|
||||||
|
/// <summary>Bluray Burst Cutting Area</summary>
|
||||||
BlurayBca = 30,
|
BlurayBca = 30,
|
||||||
|
/// <summary>Bluray Disc Definition Structure</summary>
|
||||||
BlurayDds = 31,
|
BlurayDds = 31,
|
||||||
|
/// <summary>Bluray Cartridge Status</summary>
|
||||||
BlurayCartridgeStatus = 32,
|
BlurayCartridgeStatus = 32,
|
||||||
|
/// <summary>Bluray Spare Area Information</summary>
|
||||||
BluraySpareArea = 33,
|
BluraySpareArea = 33,
|
||||||
|
/// <summary>AACS Volume Identifier</summary>
|
||||||
AacsVolumeIdentifier = 34,
|
AacsVolumeIdentifier = 34,
|
||||||
|
/// <summary>AACS Serial Number</summary>
|
||||||
AacsSerialNumber = 35,
|
AacsSerialNumber = 35,
|
||||||
|
/// <summary>AACS Media Identifier</summary>
|
||||||
AacsMediaIdentifier = 36,
|
AacsMediaIdentifier = 36,
|
||||||
|
/// <summary>AACS Media Key Block</summary>
|
||||||
AacsMediaKeyBlock = 37,
|
AacsMediaKeyBlock = 37,
|
||||||
|
/// <summary>AACS Data Keys</summary>
|
||||||
AacsDataKeys = 38,
|
AacsDataKeys = 38,
|
||||||
|
/// <summary>AACS LBA Extents</summary>
|
||||||
AacsLbaExtents = 39,
|
AacsLbaExtents = 39,
|
||||||
|
/// <summary>CPRM Media Key Block</summary>
|
||||||
CprmMediaKeyBlock = 40,
|
CprmMediaKeyBlock = 40,
|
||||||
|
/// <summary>Recognized Layers</summary>
|
||||||
HybridRecognizedLayers = 41,
|
HybridRecognizedLayers = 41,
|
||||||
|
/// <summary>MMC Write Protection</summary>
|
||||||
ScsiMmcWriteProtection = 42,
|
ScsiMmcWriteProtection = 42,
|
||||||
|
/// <summary>MMC Disc Information</summary>
|
||||||
ScsiMmcDiscInformation = 43,
|
ScsiMmcDiscInformation = 43,
|
||||||
|
/// <summary>MMC Track Resources Information</summary>
|
||||||
ScsiMmcTrackResourcesInformation = 44,
|
ScsiMmcTrackResourcesInformation = 44,
|
||||||
|
/// <summary>MMC POW Resources Information</summary>
|
||||||
ScsiMmcPowResourcesInformation = 45,
|
ScsiMmcPowResourcesInformation = 45,
|
||||||
|
/// <summary>SCSI INQUIRY RESPONSE</summary>
|
||||||
ScsiInquiry = 46,
|
ScsiInquiry = 46,
|
||||||
|
/// <summary>SCSI MODE PAGE 2Ah</summary>
|
||||||
ScsiModePage2A = 47,
|
ScsiModePage2A = 47,
|
||||||
|
/// <summary>ATA IDENTIFY response</summary>
|
||||||
AtaIdentify = 48,
|
AtaIdentify = 48,
|
||||||
|
/// <summary>ATAPI IDENTIFY response</summary>
|
||||||
AtapiIdentify = 49,
|
AtapiIdentify = 49,
|
||||||
|
/// <summary>PCMCIA CIS</summary>
|
||||||
PcmciaCis = 50,
|
PcmciaCis = 50,
|
||||||
|
/// <summary>SecureDigital CID</summary>
|
||||||
SecureDigitalCid = 51,
|
SecureDigitalCid = 51,
|
||||||
|
/// <summary>SecureDigital CSD</summary>
|
||||||
SecureDigitalCsd = 52,
|
SecureDigitalCsd = 52,
|
||||||
|
/// <summary>SecureDigital SCR</summary>
|
||||||
SecureDigitalScr = 53,
|
SecureDigitalScr = 53,
|
||||||
|
/// <summary>SecureDigital OCR</summary>
|
||||||
SecureDigitalOcr = 54,
|
SecureDigitalOcr = 54,
|
||||||
|
/// <summary>MultiMediaCard CID</summary>
|
||||||
MultiMediaCardCid = 55,
|
MultiMediaCardCid = 55,
|
||||||
|
/// <summary>MultiMediaCard CSD</summary>
|
||||||
MultiMediaCardCsd = 56,
|
MultiMediaCardCsd = 56,
|
||||||
|
/// <summary>MultiMediaCard OCR</summary>
|
||||||
MultiMediaCardOcr = 57,
|
MultiMediaCardOcr = 57,
|
||||||
|
/// <summary>MultiMediaCard Extended CSD</summary>
|
||||||
MultiMediaCardExtendedCsd = 58,
|
MultiMediaCardExtendedCsd = 58,
|
||||||
|
/// <summary>Xbox Security Sector</summary>
|
||||||
XboxSecuritySector = 59,
|
XboxSecuritySector = 59,
|
||||||
|
/// <summary>Floppy Lead-out</summary>
|
||||||
FloppyLeadOut = 60,
|
FloppyLeadOut = 60,
|
||||||
|
/// <summary>Dvd Disc Control Block</summary>
|
||||||
DvdDiscControlBlock = 61,
|
DvdDiscControlBlock = 61,
|
||||||
|
/// <summary>CompactDisc Lead-in</summary>
|
||||||
CompactDiscLeadIn = 62,
|
CompactDiscLeadIn = 62,
|
||||||
|
/// <summary>CompactDisc Lead-out</summary>
|
||||||
CompactDiscLeadOut = 63,
|
CompactDiscLeadOut = 63,
|
||||||
|
/// <summary>SCSI MODE SENSE (6) response</summary>
|
||||||
ScsiModeSense6 = 64,
|
ScsiModeSense6 = 64,
|
||||||
|
/// <summary>SCSI MODE SENSE (10) response</summary>
|
||||||
ScsiModeSense10 = 65,
|
ScsiModeSense10 = 65,
|
||||||
|
/// <summary>USB descriptors</summary>
|
||||||
UsbDescriptors = 66,
|
UsbDescriptors = 66,
|
||||||
|
/// <summary>Xbox DMI</summary>
|
||||||
XboxDmi = 67,
|
XboxDmi = 67,
|
||||||
|
/// <summary>Xbox Physical Format Information</summary>
|
||||||
XboxPfi = 68,
|
XboxPfi = 68,
|
||||||
|
/// <summary>CompactDisc sector prefix (sync, header</summary>
|
||||||
CdSectorPrefix = 69,
|
CdSectorPrefix = 69,
|
||||||
|
/// <summary>CompactDisc sector suffix (edc, ecc p, ecc q)</summary>
|
||||||
CdSectorSuffix = 70,
|
CdSectorSuffix = 70,
|
||||||
|
/// <summary>CompactDisc subchannel</summary>
|
||||||
CdSectorSubchannel = 71,
|
CdSectorSubchannel = 71,
|
||||||
|
/// <summary>Apple Profile (20 byte) tag</summary>
|
||||||
AppleProfileTag = 72,
|
AppleProfileTag = 72,
|
||||||
|
/// <summary>Apple Sony (12 byte) tag</summary>
|
||||||
AppleSonyTag = 73,
|
AppleSonyTag = 73,
|
||||||
|
/// <summary>Priam Data Tower (24 byte) tag</summary>
|
||||||
PriamDataTowerTag = 74
|
PriamDataTowerTag = 74
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>List of known blocks types</summary>
|
||||||
enum BlockType : uint
|
enum BlockType : uint
|
||||||
{
|
{
|
||||||
DataBlock = 0x484B4C42,
|
/// <summary>Block containing data</summary>
|
||||||
DeDuplicationTable = 0x48544444,
|
DataBlock = 0x4B4C4244,
|
||||||
Index = 0x48584449,
|
/// <summary>Block containing a deduplication table</summary>
|
||||||
|
DeDuplicationTable = 0X2A544444,
|
||||||
|
/// <summary>Block containing the index</summary>
|
||||||
|
Index = 0X58444E49,
|
||||||
|
/// <summary>Block containing logical geometry</summary>
|
||||||
GeometryBlock = 0x4D4F4547,
|
GeometryBlock = 0x4D4F4547,
|
||||||
MetadataBlock = 0x5444545D,
|
/// <summary>Block containing metadata</summary>
|
||||||
TracksBlock = 0x534B5254
|
MetadataBlock = 0x4154454D,
|
||||||
|
/// <summary>Block containing optical disc tracks</summary>
|
||||||
|
TracksBlock = 0x534B5254,
|
||||||
|
/// <summary>TODO: Block containing CICM XML metadata</summary>
|
||||||
|
CicmBlock = 0x4D434943,
|
||||||
|
/// <summary>TODO: Block containing contents checksums</summary>
|
||||||
|
ChecksumBlock = 0x4D534B43,
|
||||||
|
/// <summary>TODO: Block containing data position measurements</summary>
|
||||||
|
DataPositionMeasurementBlock = 0x2A4D5044,
|
||||||
|
/// <summary>TODO: Block containing a snapshot index</summary>
|
||||||
|
SnapshotBlock = 0x50414E53,
|
||||||
|
/// <summary>TODO: Block containing how to locate the parent image</summary>
|
||||||
|
ParentBlock = 0x50524E54,
|
||||||
|
/// <summary>TODO: Block containing an array of hardware used to create the image</summary>
|
||||||
|
DumpHardwareBlock = 0x2A504D44,
|
||||||
|
/// <summary>TODO: Block containing list of files for a tape image</summary>
|
||||||
|
TapeFileBlock = 0x454C4654
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Header, at start of file</summary>
|
/// <summary>Header, at start of file</summary>
|
||||||
@@ -3845,13 +4048,9 @@ namespace DiscImageChef.DiscImages
|
|||||||
public MediaType mediaType;
|
public MediaType mediaType;
|
||||||
/// <summary>Offset to index</summary>
|
/// <summary>Offset to index</summary>
|
||||||
public ulong indexOffset;
|
public ulong indexOffset;
|
||||||
/// <summary>
|
/// <summary>Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image creation time</summary>
|
||||||
/// Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image creation time
|
|
||||||
/// </summary>
|
|
||||||
public long creationTime;
|
public long creationTime;
|
||||||
/// <summary>
|
/// <summary>Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image last written time</summary>
|
||||||
/// Windows filetime (100 nanoseconds since 1601/01/01 00:00:00 UTC) of image last written time
|
|
||||||
/// </summary>
|
|
||||||
public long lastWrittenTime;
|
public long lastWrittenTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3998,6 +4197,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
public uint driveFirmwareRevisionLength;
|
public uint driveFirmwareRevisionLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Contains list of optical disc tracks</summary>
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||||
struct TracksHeader
|
struct TracksHeader
|
||||||
{
|
{
|
||||||
@@ -4009,17 +4209,26 @@ namespace DiscImageChef.DiscImages
|
|||||||
public ulong crc64;
|
public ulong crc64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Optical disc track</summary>
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
|
||||||
struct TrackEntry
|
struct TrackEntry
|
||||||
{
|
{
|
||||||
|
/// <summary>Track sequence</summary>
|
||||||
public byte sequence;
|
public byte sequence;
|
||||||
|
/// <summary>Track type</summary>
|
||||||
public TrackType type;
|
public TrackType type;
|
||||||
|
/// <summary>Track starting LBA</summary>
|
||||||
public long start;
|
public long start;
|
||||||
|
/// <summary>Track last LBA</summary>
|
||||||
public long end;
|
public long end;
|
||||||
|
/// <summary>Track pregap in sectors</summary>
|
||||||
public long pregap;
|
public long pregap;
|
||||||
|
/// <summary>Track session</summary>
|
||||||
public byte session;
|
public byte session;
|
||||||
|
/// <summary>Track's ISRC in ASCII</summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
|
||||||
public string isrc;
|
public string isrc;
|
||||||
|
/// <summary>Track flags</summary>
|
||||||
public byte flags;
|
public byte flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
//
|
//
|
||||||
// File: dicformat.bt
|
// File: dicformat.bt
|
||||||
// Authors: Natalia Portillo
|
// Authors: Natalia Portillo
|
||||||
// Version: 0.0
|
// Version: 1.0
|
||||||
// Purpose: DiscImageChef format
|
// Purpose: DiscImageChef format
|
||||||
// Category: Misc
|
// Category: Misc
|
||||||
// File Mask: *.dicf
|
// File Mask: *.dicf
|
||||||
// ID Bytes: 44 49 43 44 44 46 4D 54 // DICDDFMT
|
// ID Bytes: 44 49 43 4D 46 52 4D 54 // DICMFRMT
|
||||||
// History:
|
// History:
|
||||||
// 0.0 2018-01-25 Natalia Portillo: Initial release
|
// 1.0 2018-01-26 Natalia Portillo: Initial release
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
|
||||||
#define DIC_MAGIC 0x544D464444434944
|
#define DIC_MAGIC 0x544D52464D434944
|
||||||
|
|
||||||
enum <uint> MediaType
|
enum <uint> MediaType
|
||||||
{
|
{
|
||||||
@@ -620,12 +620,19 @@ enum <ushort> DataType
|
|||||||
|
|
||||||
enum <uint> BlockType
|
enum <uint> BlockType
|
||||||
{
|
{
|
||||||
DataBlock = 0x484B4C42,
|
DataBlock = 0x4B4C4244,
|
||||||
DeDuplicationTable = 0x48544444,
|
DeDuplicationTable = 0X2A544444,
|
||||||
Index = 0x48584449,
|
Index = 0X58444E49,
|
||||||
GeometryBlock = 0x4D4F4547,
|
GeometryBlock = 0x4D4F4547,
|
||||||
MetadataBlock = 0x5444545D,
|
MetadataBlock = 0x4154454D,
|
||||||
TracksBlock = 0x534B5254
|
TracksBlock = 0x534B5254,
|
||||||
|
CicmBlock = 0x4D434943,
|
||||||
|
ChecksumBlock = 0x4D534B43,
|
||||||
|
DataPositionMeasurementBlock = 0x2A4D5044,
|
||||||
|
SnapshotBlock = 0x50414E53,
|
||||||
|
ParentBlock = 0x50524E54,
|
||||||
|
DumpHardwareBlock = 0x2A504D44,
|
||||||
|
TapeFileBlock = 0x454C4654
|
||||||
};
|
};
|
||||||
|
|
||||||
enum <byte> TrackType
|
enum <byte> TrackType
|
||||||
@@ -767,16 +774,16 @@ for(i = 0; i < index.entries; i++)
|
|||||||
FSeek(index.items[i].offset);
|
FSeek(index.items[i].offset);
|
||||||
switch(index.items[i].blockType)
|
switch(index.items[i].blockType)
|
||||||
{
|
{
|
||||||
case 0x484B4C42:
|
case 0x4B4C4244:
|
||||||
BlockHeader dataBlock;
|
BlockHeader dataBlock;
|
||||||
break;
|
break;
|
||||||
case 0x48544444:
|
case 0x2A544444:
|
||||||
DdtHeader deduplicationTable;
|
DdtHeader deduplicationTable;
|
||||||
break;
|
break;
|
||||||
case 0x4D4F4547:
|
case 0x4D4F4547:
|
||||||
GeometryBlock geometry;
|
GeometryBlock geometry;
|
||||||
break;
|
break;
|
||||||
case 0x5444545D:
|
case 0x4154454D:
|
||||||
MetadataBlock metadata;
|
MetadataBlock metadata;
|
||||||
if(metadata.creatorOffset > 0)
|
if(metadata.creatorOffset > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user