🐛Fix offset calculation when building long blocks on reads in DiscImageChef format

This commit is contained in:
2018-02-01 01:20:15 +00:00
parent d732d72342
commit 43938e60e7

View File

@@ -137,6 +137,8 @@ namespace DiscImageChef.DiscImages
uint currentCacheSize; uint currentCacheSize;
/// <summary>Cache of DDT entries.</summary> /// <summary>Cache of DDT entries.</summary>
Dictionary<ulong, ulong> ddtEntryCache; Dictionary<ulong, ulong> ddtEntryCache;
MemoryStream decompressedStream;
bool deduplicate;
/// <summary>On-memory deduplication table indexed by checksum.</summary> /// <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> /// <summary><see cref="CUETools.Codecs.FLAKE" /> writer.</summary>
@@ -188,8 +190,6 @@ namespace DiscImageChef.DiscImages
/// <summary>In-memory deduplication table</summary> /// <summary>In-memory deduplication table</summary>
ulong[] userDataDdt; ulong[] userDataDdt;
bool writingLong; bool writingLong;
bool deduplicate;
MemoryStream decompressedStream;
public DiscImageChef() public DiscImageChef()
{ {
@@ -762,7 +762,8 @@ namespace DiscImageChef.DiscImages
imageStream.Read(structureBytes, 0, structureBytes.Length); imageStream.Read(structureBytes, 0, structureBytes.Length);
structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(cicmBlock)); structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(cicmBlock));
Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(cicmBlock)); Marshal.Copy(structureBytes, 0, structurePointer, Marshal.SizeOf(cicmBlock));
cicmBlock = (CicmMetadataBlock)Marshal.PtrToStructure(structurePointer, typeof(CicmMetadataBlock)); cicmBlock = (CicmMetadataBlock)Marshal.PtrToStructure(structurePointer,
typeof(CicmMetadataBlock));
Marshal.FreeHGlobal(structurePointer); Marshal.FreeHGlobal(structurePointer);
if(cicmBlock.identifier != BlockType.CicmBlock) break; if(cicmBlock.identifier != BlockType.CicmBlock) break;
@@ -841,7 +842,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.manufacturerLength - 1]; tmp = new byte[dumpEntry.manufacturerLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Manufacturer = Encoding.UTF8.GetString(tmp); dump.Manufacturer = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.modelLength > 0) if(dumpEntry.modelLength > 0)
@@ -849,7 +850,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.modelLength - 1]; tmp = new byte[dumpEntry.modelLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Model = Encoding.UTF8.GetString(tmp); dump.Model = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.revisionLength > 0) if(dumpEntry.revisionLength > 0)
@@ -857,7 +858,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.revisionLength - 1]; tmp = new byte[dumpEntry.revisionLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Revision = Encoding.UTF8.GetString(tmp); dump.Revision = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.firmwareLength > 0) if(dumpEntry.firmwareLength > 0)
@@ -865,7 +866,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.firmwareLength - 1]; tmp = new byte[dumpEntry.firmwareLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Firmware = Encoding.UTF8.GetString(tmp); dump.Firmware = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.serialLength > 0) if(dumpEntry.serialLength > 0)
@@ -873,7 +874,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.serialLength - 1]; tmp = new byte[dumpEntry.serialLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Serial = Encoding.UTF8.GetString(tmp); dump.Serial = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareNameLength > 0) if(dumpEntry.softwareNameLength > 0)
@@ -881,23 +882,23 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.softwareNameLength - 1]; tmp = new byte[dumpEntry.softwareNameLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Software.Name = Encoding.UTF8.GetString(tmp); dump.Software.Name = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareVersionLength > 0) if(dumpEntry.softwareVersionLength > 0)
{ {
tmp = new byte[dumpEntry.softwareVersionLength - 1]; tmp = new byte[dumpEntry.softwareVersionLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Software.Version = Encoding.UTF8.GetString(tmp); dump.Software.Version = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareOperatingSystemLength > 0) if(dumpEntry.softwareOperatingSystemLength > 0)
{ {
tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp);
} }
tmp = new byte[16]; tmp = new byte[16];
@@ -1469,7 +1470,7 @@ namespace DiscImageChef.DiscImages
throw new ArgumentOutOfRangeException(nameof(sectorAddress), throw new ArgumentOutOfRangeException(nameof(sectorAddress),
"Can't found track containing requested sector"); "Can't found track containing requested sector");
if(trk.TrackStartSector + sectorAddress + length > trk.TrackEndSector + 1) if(sectorAddress + length > trk.TrackEndSector + 1)
throw new ArgumentOutOfRangeException(nameof(length), throw new ArgumentOutOfRangeException(nameof(length),
$"Requested more sectors ({length + sectorAddress}) than present in track ({trk.TrackEndSector - trk.TrackStartSector + 1}), won't cross tracks"); $"Requested more sectors ({length + sectorAddress}) than present in track ({trk.TrackEndSector - trk.TrackStartSector + 1}), won't cross tracks");
@@ -1486,12 +1487,16 @@ namespace DiscImageChef.DiscImages
data = ReadSectors(sectorAddress, length); data = ReadSectors(sectorAddress, length);
for(uint i = 0; i < length; i++) for(uint i = 0; i < length; i++)
{ {
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
(int)((sectorAddress + i) * 2352), 16); 16);
Array.Copy(data, (int)((sectorAddress + i) * 2048), sectors, Array.Copy(data, (int)(i * 2048), sectors,
(int)((sectorAddress + i) * 2352) + 16, 2048); (int)(i * 2352) + 16, 2048);
Array.Copy(sectorSuffix, (int)((sectorAddress + i) * 288), sectors, Array.Copy(sectorSuffix,
(int)((sectorAddress + i) * 2352) + 2064, 288); (int)((sectorAddress + i) * 288),
sectors,
(int)
(i *
2352) + 2064, 288);
} }
return sectors; return sectors;
@@ -1505,10 +1510,10 @@ namespace DiscImageChef.DiscImages
data = ReadSectors(sectorAddress, length); data = ReadSectors(sectorAddress, length);
for(uint i = 0; i < length; i++) for(uint i = 0; i < length; i++)
{ {
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
(int)((sectorAddress + i) * 2352), 16); 16);
Array.Copy(data, (int)((sectorAddress + i) * 2336), sectors, Array.Copy(data, (int)(i * 2336), sectors,
(int)((sectorAddress + i) * 2352) + 16, 2336); (int)(i * 2352) + 16, 2336);
} }
return sectors; return sectors;
@@ -1550,9 +1555,9 @@ namespace DiscImageChef.DiscImages
for(uint i = 0; i < length; i++) for(uint i = 0; i < length; i++)
{ {
Array.Copy(sectorSubchannel, (int)((sectorAddress + i) * tagSize), sectors, Array.Copy(sectorSubchannel, (int)((sectorAddress + i) * tagSize), sectors,
(int)((sectorAddress + i) * sectorSize + 512), tagSize); (int)(i * sectorSize + 512), tagSize);
Array.Copy(data, (int)((sectorAddress + i) * 512), sectors, Array.Copy(data, (int)((sectorAddress + i) * 512),
(int)((sectorAddress + i) * 512), 512); sectors, (int)(i * 512), 512);
} }
return sectors; return sectors;
@@ -1887,7 +1892,8 @@ namespace DiscImageChef.DiscImages
("sha1", typeof(bool), "Calculate and store SHA1 of image's user data"), ("sha1", typeof(bool), "Calculate and store SHA1 of image's user data"),
("sha256", typeof(bool), "Calculate and store SHA256 of image's user data"), ("sha256", typeof(bool), "Calculate and store SHA256 of image's user data"),
("spamsum", typeof(bool), "Calculate and store SpamSum of image's user data"), ("spamsum", typeof(bool), "Calculate and store SpamSum of image's user data"),
("deduplicate", typeof(bool), "Store only unique sectors. This consumes more memory and is slower, but it's enabled by default") ("deduplicate", typeof(bool),
"Store only unique sectors. This consumes more memory and is slower, but it's enabled by default")
}; };
public IEnumerable<string> KnownExtensions => new[] {".dicf"}; public IEnumerable<string> KnownExtensions => new[] {".dicf"};
public bool IsWriting { get; private set; } public bool IsWriting { get; private set; }
@@ -2376,7 +2382,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.manufacturerLength - 1]; tmp = new byte[dumpEntry.manufacturerLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Manufacturer = Encoding.UTF8.GetString(tmp); dump.Manufacturer = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.modelLength > 0) if(dumpEntry.modelLength > 0)
@@ -2384,7 +2390,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.modelLength - 1]; tmp = new byte[dumpEntry.modelLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Model = Encoding.UTF8.GetString(tmp); dump.Model = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.revisionLength > 0) if(dumpEntry.revisionLength > 0)
@@ -2392,7 +2398,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.revisionLength - 1]; tmp = new byte[dumpEntry.revisionLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Revision = Encoding.UTF8.GetString(tmp); dump.Revision = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.firmwareLength > 0) if(dumpEntry.firmwareLength > 0)
@@ -2400,7 +2406,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.firmwareLength - 1]; tmp = new byte[dumpEntry.firmwareLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Firmware = Encoding.UTF8.GetString(tmp); dump.Firmware = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.serialLength > 0) if(dumpEntry.serialLength > 0)
@@ -2408,7 +2414,7 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.serialLength - 1]; tmp = new byte[dumpEntry.serialLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Serial = Encoding.UTF8.GetString(tmp); dump.Serial = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareNameLength > 0) if(dumpEntry.softwareNameLength > 0)
@@ -2416,20 +2422,20 @@ namespace DiscImageChef.DiscImages
tmp = new byte[dumpEntry.softwareNameLength - 1]; tmp = new byte[dumpEntry.softwareNameLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Software.Name = Encoding.UTF8.GetString(tmp); dump.Software.Name = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareVersionLength > 0) if(dumpEntry.softwareVersionLength > 0)
{ {
tmp = new byte[dumpEntry.softwareVersionLength - 1]; tmp = new byte[dumpEntry.softwareVersionLength - 1];
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
imageStream.Position += 1; imageStream.Position += 1;
dump.Software.Version = Encoding.UTF8.GetString(tmp); dump.Software.Version = Encoding.UTF8.GetString(tmp);
} }
if(dumpEntry.softwareOperatingSystemLength > 0) if(dumpEntry.softwareOperatingSystemLength > 0)
{ {
tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1]; tmp = new byte[dumpEntry.softwareOperatingSystemLength - 1];
imageStream.Position += 1; imageStream.Position += 1;
imageStream.Read(tmp, 0, tmp.Length); imageStream.Read(tmp, 0, tmp.Length);
dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp); dump.Software.OperatingSystem = Encoding.UTF8.GetString(tmp);
@@ -2624,10 +2630,9 @@ namespace DiscImageChef.DiscImages
if(sectorAddress == 0) alreadyWrittenZero = true; if(sectorAddress == 0) alreadyWrittenZero = true;
byte[] hash = null; byte[] hash = null;
// Compute hash only if asked to deduplicate, or the sector is empty (those will always be deduplicated) // Compute hash only if asked to deduplicate, or the sector is empty (those will always be deduplicated)
if(deduplicate || ArrayHelpers.ArrayIsNullOrEmpty(data)) if(deduplicate || ArrayHelpers.ArrayIsNullOrEmpty(data)) hash = checksumProvider.ComputeHash(data);
hash = checksumProvider.ComputeHash(data);
if(hash != null && deduplicationTable.TryGetValue(hash, out ulong pointer)) if(hash != null && deduplicationTable.TryGetValue(hash, out ulong pointer))
{ {
@@ -2694,7 +2699,7 @@ namespace DiscImageChef.DiscImages
if(currentBlockHeader.compression == CompressionType.None) if(currentBlockHeader.compression == CompressionType.None)
{ {
blockStream = decompressedStream; blockStream = decompressedStream;
currentBlockHeader.cmpCrc64 = currentBlockHeader.crc64; currentBlockHeader.cmpCrc64 = currentBlockHeader.crc64;
} }
else else
@@ -2722,8 +2727,8 @@ namespace DiscImageChef.DiscImages
imageStream.Write(structureBytes, 0, structureBytes.Length); imageStream.Write(structureBytes, 0, structureBytes.Length);
structureBytes = null; structureBytes = null;
if(currentBlockHeader.compression == CompressionType.Lzma) if(currentBlockHeader.compression == CompressionType.Lzma)
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;
currentBlockOffset = 0; currentBlockOffset = 0;
@@ -2743,7 +2748,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc && trk.TrackType == TrackType.Audio) if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc && trk.TrackType == TrackType.Audio)
currentBlockHeader.compression = CompressionType.Flac; currentBlockHeader.compression = CompressionType.Flac;
blockStream = new MemoryStream(); blockStream = new MemoryStream();
decompressedStream = new MemoryStream(); decompressedStream = new MemoryStream();
if(currentBlockHeader.compression == CompressionType.Flac) if(currentBlockHeader.compression == CompressionType.Flac)
flakeWriter = new FlakeWriter("", blockStream, flakeWriterSettings) {DoSeekTable = false}; flakeWriter = new FlakeWriter("", blockStream, flakeWriterSettings) {DoSeekTable = false};
@@ -2753,8 +2758,7 @@ namespace DiscImageChef.DiscImages
} }
ulong ddtEntry = (ulong)((imageStream.Position << shift) + currentBlockOffset); ulong ddtEntry = (ulong)((imageStream.Position << shift) + currentBlockOffset);
if(hash != null) if(hash != null) deduplicationTable.Add(hash, ddtEntry);
deduplicationTable.Add(hash, ddtEntry);
if(currentBlockHeader.compression == CompressionType.Flac) if(currentBlockHeader.compression == CompressionType.Flac)
{ {
AudioBuffer audioBuffer = new AudioBuffer(AudioPCMConfig.RedBook, data, SAMPLES_PER_SECTOR); AudioBuffer audioBuffer = new AudioBuffer(AudioPCMConfig.RedBook, data, SAMPLES_PER_SECTOR);