diff --git a/DiscImageChef.DiscImages/NDIF.cs b/DiscImageChef.DiscImages/NDIF.cs index 7730fa20e..f40f7ea71 100644 --- a/DiscImageChef.DiscImages/NDIF.cs +++ b/DiscImageChef.DiscImages/NDIF.cs @@ -85,9 +85,9 @@ namespace DiscImageChef.DiscImages /// public uint maxSectorsPerChunk; /// - /// Always 0? + /// Offset to add to every chunk offset /// - public uint zeroOffset; + public uint dataOffset; /// /// CRC28 of whole image /// @@ -135,7 +135,7 @@ namespace DiscImageChef.DiscImages /// public byte type; /// - /// Offset in image to start of chunk + /// Offset in start of chunk /// public uint offset; /// @@ -255,7 +255,7 @@ namespace DiscImageChef.DiscImages ResourceFork rsrcFork; Resource rsrc; - byte[] bcem; + short[] bcems; try { @@ -265,76 +265,84 @@ namespace DiscImageChef.DiscImages rsrc = rsrcFork.GetResource(NDIF_Resource); - if(!rsrc.ContainsId(NDIF_ResourceID)) - return false; + bcems = rsrc.GetIds(); - bcem = rsrc.GetResource(NDIF_ResourceID); + if(bcems == null || bcems.Length == 0) + return false; } catch(InvalidCastException) { return false; } - if(bcem.Length < 128) - return false; - - header = BigEndianMarshal.ByteArrayToStructureBigEndian(bcem); - - DicConsole.DebugWriteLine("NDIF plugin", "footer.type = {0}", header.version); - DicConsole.DebugWriteLine("NDIF plugin", "footer.driver = {0}", header.driver); - DicConsole.DebugWriteLine("NDIF plugin", "footer.name = {0}", StringHandlers.PascalToString(header.name)); - DicConsole.DebugWriteLine("NDIF plugin", "footer.sectors = {0}", header.sectors); - DicConsole.DebugWriteLine("NDIF plugin", "footer.maxSectorsPerChunk = {0}", header.maxSectorsPerChunk); - DicConsole.DebugWriteLine("NDIF plugin", "footer.zeroOffset = {0}", header.zeroOffset); - DicConsole.DebugWriteLine("NDIF plugin", "footer.crc = 0x{0:X7}", header.crc); - DicConsole.DebugWriteLine("NDIF plugin", "footer.segmented = {0}", header.segmented); - DicConsole.DebugWriteLine("NDIF plugin", "footer.p1 = 0x{0:X8}", header.p1); - DicConsole.DebugWriteLine("NDIF plugin", "footer.p2 = 0x{0:X8}", header.p2); - DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[0] = 0x{0:X8}", header.unknown[0]); - DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[1] = 0x{0:X8}", header.unknown[1]); - DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[2] = 0x{0:X8}", header.unknown[2]); - DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[3] = 0x{0:X8}", header.unknown[3]); - DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[4] = 0x{0:X8}", header.unknown[4]); - DicConsole.DebugWriteLine("NDIF plugin", "footer.encrypted = {0}", header.encrypted); - DicConsole.DebugWriteLine("NDIF plugin", "footer.hash = 0x{0:X8}", header.hash); - DicConsole.DebugWriteLine("NDIF plugin", "footer.chunks = {0}", header.chunks); - - // Block chunks and headers - chunks = new Dictionary(); - - BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; - - for(int i = 0; i < header.chunks; i++) + ImageInfo.sectors = 0; + foreach(short id in bcems) { - // Obsolete read-only NDIF only prepended the header and then put the image without any kind of block references. - // So let's falsify a block chunk - BlockChunk bChnk = new BlockChunk(); - byte[] sector = new byte[4]; - Array.Copy(bcem, 128 + 0 + i * 12, sector, 1, 3); - bChnk.sector = BigEndianBitConverter.ToUInt32(sector, 0); - bChnk.type = bcem[128 + 3 + i * 12]; - bChnk.offset = BigEndianBitConverter.ToUInt32(bcem, 128 + 4 + i * 12); - bChnk.length = BigEndianBitConverter.ToUInt32(bcem, 128 + 8 + i * 12); + byte[] bcem = rsrc.GetResource(NDIF_ResourceID); - DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].type = 0x{1:X2}", i, bChnk.type); - DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].sector = {1}", i, bChnk.sector); - DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].offset = {1}", i, bChnk.offset); - DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].length = {1}", i, bChnk.length); + if(bcem.Length < 128) + return false; - if(bChnk.type == ChunkType_End) + header = BigEndianMarshal.ByteArrayToStructureBigEndian(bcem); + + DicConsole.DebugWriteLine("NDIF plugin", "footer.type = {0}", header.version); + DicConsole.DebugWriteLine("NDIF plugin", "footer.driver = {0}", header.driver); + DicConsole.DebugWriteLine("NDIF plugin", "footer.name = {0}", StringHandlers.PascalToString(header.name)); + DicConsole.DebugWriteLine("NDIF plugin", "footer.sectors = {0}", header.sectors); + DicConsole.DebugWriteLine("NDIF plugin", "footer.maxSectorsPerChunk = {0}", header.maxSectorsPerChunk); + DicConsole.DebugWriteLine("NDIF plugin", "footer.dataOffset = {0}", header.dataOffset); + DicConsole.DebugWriteLine("NDIF plugin", "footer.crc = 0x{0:X7}", header.crc); + DicConsole.DebugWriteLine("NDIF plugin", "footer.segmented = {0}", header.segmented); + DicConsole.DebugWriteLine("NDIF plugin", "footer.p1 = 0x{0:X8}", header.p1); + DicConsole.DebugWriteLine("NDIF plugin", "footer.p2 = 0x{0:X8}", header.p2); + DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[0] = 0x{0:X8}", header.unknown[0]); + DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[1] = 0x{0:X8}", header.unknown[1]); + DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[2] = 0x{0:X8}", header.unknown[2]); + DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[3] = 0x{0:X8}", header.unknown[3]); + DicConsole.DebugWriteLine("NDIF plugin", "footer.unknown[4] = 0x{0:X8}", header.unknown[4]); + DicConsole.DebugWriteLine("NDIF plugin", "footer.encrypted = {0}", header.encrypted); + DicConsole.DebugWriteLine("NDIF plugin", "footer.hash = 0x{0:X8}", header.hash); + DicConsole.DebugWriteLine("NDIF plugin", "footer.chunks = {0}", header.chunks); + + // Block chunks and headers + chunks = new Dictionary(); + + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + + ImageInfo.sectors += header.sectors; + + for(int i = 0; i < header.chunks; i++) { - ImageInfo.sectors = bChnk.sector; - break; + // Obsolete read-only NDIF only prepended the header and then put the image without any kind of block references. + // So let's falsify a block chunk + BlockChunk bChnk = new BlockChunk(); + byte[] sector = new byte[4]; + Array.Copy(bcem, 128 + 0 + i * 12, sector, 1, 3); + bChnk.sector = BigEndianBitConverter.ToUInt32(sector, 0); + bChnk.type = bcem[128 + 3 + i * 12]; + bChnk.offset = BigEndianBitConverter.ToUInt32(bcem, 128 + 4 + i * 12); + bChnk.length = BigEndianBitConverter.ToUInt32(bcem, 128 + 8 + i * 12); + + DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].type = 0x{1:X2}", i, bChnk.type); + DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].sector = {1}", i, bChnk.sector); + DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].offset = {1}", i, bChnk.offset); + DicConsole.DebugWriteLine("NDIF plugin", "bHdr.chunk[{0}].length = {1}", i, bChnk.length); + + if(bChnk.type == ChunkType_End) + break; + + bChnk.offset += header.dataOffset; + bChnk.sector += (uint)ImageInfo.sectors; + + // TODO: Handle compressed chunks + if((bChnk.type & ChunkType_CompressedMask) == ChunkType_CompressedMask) + throw new ImageNotSupportedException("Compressed chunks are not yet supported."); + + if(bChnk.type != ChunkType_Copy && bChnk.type != ChunkType_NoCopy) + throw new ImageNotSupportedException(string.Format("Unsupported chunk type 0x{0:X8} found", bChnk.type)); + + chunks.Add(bChnk.sector, bChnk); } - - // TODO: Handle compressed chunks - if((bChnk.type & ChunkType_CompressedMask) == ChunkType_CompressedMask) - throw new ImageNotSupportedException("Compressed chunks are not yet supported."); - - if(bChnk.type != ChunkType_Copy && bChnk.type != ChunkType_NoCopy) - throw new ImageNotSupportedException(string.Format("Unsupported chunk type 0x{0:X8} found", bChnk.type)); - - chunks.Add(bChnk.sector, bChnk); } if(header.segmented > 0) diff --git a/DiscImageChef.DiscImages/UDIF.cs b/DiscImageChef.DiscImages/UDIF.cs index fd4ab0e24..5a1d5c8d2 100644 --- a/DiscImageChef.DiscImages/UDIF.cs +++ b/DiscImageChef.DiscImages/UDIF.cs @@ -405,6 +405,7 @@ namespace DiscImageChef.DiscImages ImageInfo.imageApplication = "DiskCopy"; DicConsole.DebugWriteLine("UDIF plugin", "Image application = {0} version {1}", ImageInfo.imageApplication, ImageInfo.imageApplicationVersion); + ImageInfo.sectors = 0; if(!fakeBlockChunks) { if(blkxList.Count == 0) @@ -452,10 +453,13 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("UDIF plugin", "bHdr.chunk[{0}].length = {1}", i, bChnk.length); if(bChnk.type == ChunkType_End) - { - ImageInfo.sectors = bChnk.sector; break; - } + + ImageInfo.sectors += bChnk.sectors; + + // Chunk offset is relative + bChnk.sector += bHdr.sectorStart; + bChnk.offset += bHdr.dataOffset; // TODO: Handle comments if(bChnk.type == ChunkType_Commnt)