diff --git a/DiscImageChef.DiscImages/ChangeLog b/DiscImageChef.DiscImages/ChangeLog index cd552d503..2adc2a257 100644 --- a/DiscImageChef.DiscImages/ChangeLog +++ b/DiscImageChef.DiscImages/ChangeLog @@ -1,3 +1,8 @@ +2016-09-30 Natalia Portillo + + * NDIF.cs: + * UDIF.cs: Add support for ADC compressed images. + 2016-09-30 Natalia Portillo * NDIF.cs: Fail on StuffIt compressed images. diff --git a/DiscImageChef.DiscImages/NDIF.cs b/DiscImageChef.DiscImages/NDIF.cs index 8434a47d5..c7456a6b6 100644 --- a/DiscImageChef.DiscImages/NDIF.cs +++ b/DiscImageChef.DiscImages/NDIF.cs @@ -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 sectorCache; + Dictionary 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(); + chunkCache = new Dictionary(); + 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) { diff --git a/DiscImageChef.DiscImages/UDIF.cs b/DiscImageChef.DiscImages/UDIF.cs index 0c1abbdf4..6d183db91 100644 --- a/DiscImageChef.DiscImages/UDIF.cs +++ b/DiscImageChef.DiscImages/UDIF.cs @@ -43,6 +43,7 @@ using DiscImageChef.Filters; using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors; +using SharpCompress.Compressors.ADC; namespace DiscImageChef.DiscImages { @@ -484,8 +485,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_LZFSE)) throw new ImageNotSupportedException("Chunks compressed with lzfse are not yet supported."); @@ -559,7 +558,9 @@ namespace DiscImageChef.DiscImages MemoryStream cmpMs = new MemoryStream(cmpBuffer); 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); else if(currentChunk.type == ChunkType_Bzip) decStream = new BZip2Stream(cmpMs, CompressionMode.Decompress);