Add support for ADC compressed images.

This commit is contained in:
2016-09-30 04:57:35 +01:00
parent 256304bfa2
commit c2ec29a681
3 changed files with 60 additions and 5 deletions

View File

@@ -39,6 +39,8 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.Console;
using DiscImageChef.Filters;
using DiscImageChef.ImagePlugins;
using SharpCompress.Compressors;
using SharpCompress.Compressors.ADC;
namespace DiscImageChef.DiscImages
{
@@ -189,9 +191,12 @@ namespace DiscImageChef.DiscImages
const short Driver_DOS = 18771;
Dictionary<ulong, byte[]> sectorCache;
Dictionary<ulong, byte[]> chunkCache;
const uint MaxCacheSize = 16777216;
const uint sectorSize = 512;
uint maxCachedSectors = MaxCacheSize / sectorSize;
uint currentChunkCacheSize;
uint buffersize;
Stream imageStream;
@@ -339,8 +344,6 @@ namespace DiscImageChef.DiscImages
throw new ImageNotSupportedException("Chunks compressed with RLE are not yet supported.");
if((bChnk.type == ChunkType_LZH))
throw new ImageNotSupportedException("Chunks compressed with LZH are not yet supported.");
if((bChnk.type == ChunkType_ADC))
throw new ImageNotSupportedException("Chunks compressed with ADC are not yet supported.");
if((bChnk.type == ChunkType_StuffIt))
throw new ImageNotSupportedException("Chunks compressed with StuffIt! are not yet supported.");
@@ -433,7 +436,10 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("NDIF plugin", "Image application = {0} version {1}", ImageInfo.imageApplication, ImageInfo.imageApplicationVersion);
sectorCache = new Dictionary<ulong, byte[]>();
chunkCache = new Dictionary<ulong, byte[]>();
currentChunkCacheSize = 0;
imageStream = imageFilter.GetDataForkStream();
buffersize = header.maxSectorsPerChunk * sectorSize;
ImageInfo.imageCreationTime = imageFilter.GetCreationTime();
ImageInfo.imageLastModificationTime = imageFilter.GetLastWriteTime();
@@ -478,6 +484,49 @@ namespace DiscImageChef.DiscImages
if(!chunkFound)
throw new ArgumentOutOfRangeException(nameof(sectorAddress), string.Format("Sector address {0} not found", sectorAddress));
if((currentChunk.type & ChunkType_CompressedMask) == ChunkType_CompressedMask)
{
byte[] buffer;
if(!chunkCache.TryGetValue(chunkStartSector, out buffer))
{
byte[] cmpBuffer = new byte[currentChunk.length];
imageStream.Seek(currentChunk.offset, SeekOrigin.Begin);
imageStream.Read(cmpBuffer, 0, cmpBuffer.Length);
MemoryStream cmpMs = new MemoryStream(cmpBuffer);
Stream decStream;
if(currentChunk.type == ChunkType_ADC)
decStream = new ADCStream(cmpMs, CompressionMode.Decompress);
else
throw new ImageNotSupportedException(string.Format("Unsupported chunk type 0x{0:X8} found", currentChunk.type));
byte[] tmpBuffer = new byte[buffersize];
int realSize = decStream.Read(tmpBuffer, 0, (int)buffersize);
buffer = new byte[realSize];
Array.Copy(tmpBuffer, 0, buffer, 0, realSize);
tmpBuffer = null;
if(currentChunkCacheSize + realSize > MaxCacheSize)
{
chunkCache.Clear();
currentChunkCacheSize = 0;
}
chunkCache.Add(chunkStartSector, buffer);
currentChunkCacheSize += (uint)realSize;
}
sector = new byte[sectorSize];
Array.Copy(buffer, relOff, sector, 0, sectorSize);
if(sectorCache.Count >= maxCachedSectors)
sectorCache.Clear();
sectorCache.Add(sectorAddress, sector);
return sector;
}
if(currentChunk.type == ChunkType_NoCopy)
{