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

@@ -1,3 +1,8 @@
2016-09-30 Natalia Portillo <claunia@claunia.com>
* NDIF.cs:
* UDIF.cs: Add support for ADC compressed images.
2016-09-30 Natalia Portillo <claunia@claunia.com> 2016-09-30 Natalia Portillo <claunia@claunia.com>
* NDIF.cs: Fail on StuffIt compressed images. * NDIF.cs: Fail on StuffIt compressed images.

View File

@@ -39,6 +39,8 @@ using DiscImageChef.CommonTypes;
using DiscImageChef.Console; using DiscImageChef.Console;
using DiscImageChef.Filters; using DiscImageChef.Filters;
using DiscImageChef.ImagePlugins; using DiscImageChef.ImagePlugins;
using SharpCompress.Compressors;
using SharpCompress.Compressors.ADC;
namespace DiscImageChef.DiscImages namespace DiscImageChef.DiscImages
{ {
@@ -189,9 +191,12 @@ namespace DiscImageChef.DiscImages
const short Driver_DOS = 18771; const short Driver_DOS = 18771;
Dictionary<ulong, byte[]> sectorCache; Dictionary<ulong, byte[]> sectorCache;
Dictionary<ulong, byte[]> chunkCache;
const uint MaxCacheSize = 16777216; const uint MaxCacheSize = 16777216;
const uint sectorSize = 512; const uint sectorSize = 512;
uint maxCachedSectors = MaxCacheSize / sectorSize; uint maxCachedSectors = MaxCacheSize / sectorSize;
uint currentChunkCacheSize;
uint buffersize;
Stream imageStream; Stream imageStream;
@@ -339,8 +344,6 @@ namespace DiscImageChef.DiscImages
throw new ImageNotSupportedException("Chunks compressed with RLE are not yet supported."); throw new ImageNotSupportedException("Chunks compressed with RLE are not yet supported.");
if((bChnk.type == ChunkType_LZH)) if((bChnk.type == ChunkType_LZH))
throw new ImageNotSupportedException("Chunks compressed with LZH are not yet supported."); 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)) if((bChnk.type == ChunkType_StuffIt))
throw new ImageNotSupportedException("Chunks compressed with StuffIt! are not yet supported."); 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); DicConsole.DebugWriteLine("NDIF plugin", "Image application = {0} version {1}", ImageInfo.imageApplication, ImageInfo.imageApplicationVersion);
sectorCache = new Dictionary<ulong, byte[]>(); sectorCache = new Dictionary<ulong, byte[]>();
chunkCache = new Dictionary<ulong, byte[]>();
currentChunkCacheSize = 0;
imageStream = imageFilter.GetDataForkStream(); imageStream = imageFilter.GetDataForkStream();
buffersize = header.maxSectorsPerChunk * sectorSize;
ImageInfo.imageCreationTime = imageFilter.GetCreationTime(); ImageInfo.imageCreationTime = imageFilter.GetCreationTime();
ImageInfo.imageLastModificationTime = imageFilter.GetLastWriteTime(); ImageInfo.imageLastModificationTime = imageFilter.GetLastWriteTime();
@@ -478,6 +484,49 @@ namespace DiscImageChef.DiscImages
if(!chunkFound) if(!chunkFound)
throw new ArgumentOutOfRangeException(nameof(sectorAddress), string.Format("Sector address {0} not found", sectorAddress)); 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) if(currentChunk.type == ChunkType_NoCopy)
{ {

View File

@@ -43,6 +43,7 @@ using DiscImageChef.Filters;
using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.Deflate;
using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors; using SharpCompress.Compressors;
using SharpCompress.Compressors.ADC;
namespace DiscImageChef.DiscImages namespace DiscImageChef.DiscImages
{ {
@@ -484,8 +485,6 @@ namespace DiscImageChef.DiscImages
throw new ImageNotSupportedException("Chunks compressed with RLE are not yet supported."); throw new ImageNotSupportedException("Chunks compressed with RLE are not yet supported.");
if((bChnk.type == ChunkType_LZH)) if((bChnk.type == ChunkType_LZH))
throw new ImageNotSupportedException("Chunks compressed with LZH are not yet supported."); 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_LZFSE)) if((bChnk.type == ChunkType_LZFSE))
throw new ImageNotSupportedException("Chunks compressed with lzfse are not yet supported."); throw new ImageNotSupportedException("Chunks compressed with lzfse are not yet supported.");
@@ -559,7 +558,9 @@ namespace DiscImageChef.DiscImages
MemoryStream cmpMs = new MemoryStream(cmpBuffer); MemoryStream cmpMs = new MemoryStream(cmpBuffer);
Stream decStream; Stream decStream;
if(currentChunk.type == ChunkType_Zlib) if(currentChunk.type == ChunkType_ADC)
decStream = new ADCStream(cmpMs, CompressionMode.Decompress);
else if(currentChunk.type == ChunkType_Zlib)
decStream = new ZlibStream(cmpMs, CompressionMode.Decompress); decStream = new ZlibStream(cmpMs, CompressionMode.Decompress);
else if(currentChunk.type == ChunkType_Bzip) else if(currentChunk.type == ChunkType_Bzip)
decStream = new BZip2Stream(cmpMs, CompressionMode.Decompress); decStream = new BZip2Stream(cmpMs, CompressionMode.Decompress);