diff --git a/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs b/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs index a54236834..31797a224 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs @@ -122,7 +122,6 @@ namespace DiscImageChef.DiscImages List index; /// If set to true, the DDT entries are in-memory. bool inMemoryDdt; - bool isTape; ulong lastWrittenBlock; /// LZMA stream. LzmaStream lzmaBlockStream; diff --git a/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs b/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs index 4ff49e040..b46e0160c 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/Helpers.cs @@ -248,7 +248,7 @@ namespace DiscImageChef.DiscImages { if(inMemoryDdt) { - if(isTape) tapeDdt[sectorAddress] = pointer; + if(IsTape) tapeDdt[sectorAddress] = pointer; else userDataDdt[sectorAddress] = pointer; return; } diff --git a/DiscImageChef.DiscImages/DiscImageChef/Read.cs b/DiscImageChef.DiscImages/DiscImageChef/Read.cs index 4648891c7..78d5569f9 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/Read.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/Read.cs @@ -811,6 +811,59 @@ namespace DiscImageChef.DiscImages DicConsole.DebugWriteLine("DiscImageChef format plugin", "Memory snapshot: {0} bytes", GC.GetTotalMemory(false)); break; + // Tape partition block + case BlockType.TapePartitionBlock: + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + TapePartitionHeader partitionHeader = + Marshal.SpanToStructureLittleEndian(structureBytes); + if(partitionHeader.identifier != BlockType.TapePartitionBlock) break; + + DicConsole.DebugWriteLine("DiscImageChef format plugin", + "Found tape partition block at position {0}", entry.offset); + + byte[] tapePartitionBytes = new byte[partitionHeader.length]; + imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length); + Span tapePartitions = + MemoryMarshal.Cast(tapePartitionBytes); + TapePartitions = new List(); + + foreach(TapePartitionEntry tapePartition in tapePartitions) + TapePartitions.Add(new TapePartition + { + FirstBlock = tapePartition.FirstBlock, + LastBlock = tapePartition.LastBlock, + Number = tapePartition.Number + }); + + IsTape = true; + break; + // Tape file block + case BlockType.TapeFileBlock: + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + TapeFileHeader fileHeader = Marshal.SpanToStructureLittleEndian(structureBytes); + if(fileHeader.identifier != BlockType.TapeFileBlock) break; + + DicConsole.DebugWriteLine("DiscImageChef format plugin", + "Found tape file block at position {0}", entry.offset); + + byte[] tapeFileBytes = new byte[fileHeader.length]; + imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length); + Span tapeFiles = MemoryMarshal.Cast(tapeFileBytes); + Files = new List(); + + foreach(TapeFileEntry file in tapeFiles) + Files.Add(new TapeFile + { + FirstBlock = file.FirstBlock, + LastBlock = file.LastBlock, + Partition = file.Partition, + File = file.File + }); + + IsTape = true; + break; } } @@ -1150,6 +1203,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorPrefix; break; } + case SectorTagType.CdSectorHeader: { sectorOffset = 12; @@ -1158,6 +1212,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorPrefix; break; } + case SectorTagType.CdSectorSubHeader: throw new ArgumentException("Unsupported tag requested for this track", nameof(tag)); case SectorTagType.CdSectorEcc: @@ -1168,6 +1223,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorSuffix; break; } + case SectorTagType.CdSectorEccP: { sectorOffset = 12; @@ -1176,6 +1232,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorSuffix; break; } + case SectorTagType.CdSectorEccQ: { sectorOffset = 184; @@ -1184,6 +1241,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorSuffix; break; } + case SectorTagType.CdSectorEdc: { sectorOffset = 0; @@ -1192,6 +1250,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorSuffix; break; } + case SectorTagType.CdSectorSubchannel: { sectorOffset = 0; @@ -1200,6 +1259,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorSubchannel; break; } + default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } @@ -1218,6 +1278,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorPrefix; break; } + case SectorTagType.CdSectorHeader: { sectorOffset = 12; @@ -1226,6 +1287,7 @@ namespace DiscImageChef.DiscImages dataSource = sectorPrefix; break; } + // These could be implemented case SectorTagType.CdSectorEcc: case SectorTagType.CdSectorEccP: @@ -1241,11 +1303,13 @@ namespace DiscImageChef.DiscImages dataSource = sectorSubchannel; break; } + default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } break; } + case TrackType.Audio: { switch(tag) @@ -1258,11 +1322,13 @@ namespace DiscImageChef.DiscImages dataSource = sectorSubchannel; break; } + default: throw new ArgumentException("Unsupported tag requested", nameof(tag)); } break; } + default: throw new FeatureSupportedButNotImplementedImageException("Unsupported track type"); } } diff --git a/DiscImageChef.DiscImages/DiscImageChef/Tape.cs b/DiscImageChef.DiscImages/DiscImageChef/Tape.cs index fef684841..dbdd28bab 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/Tape.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/Tape.cs @@ -40,6 +40,7 @@ namespace DiscImageChef.DiscImages { public List Files { get; private set; } public List TapePartitions { get; private set; } + public bool IsTape { get; private set; } public bool AddFile(TapeFile file) { @@ -69,7 +70,7 @@ namespace DiscImageChef.DiscImages { Files = new List(); TapePartitions = new List(); - return isTape = true; + return IsTape = true; } } } \ No newline at end of file diff --git a/DiscImageChef.DiscImages/DiscImageChef/Write.cs b/DiscImageChef.DiscImages/DiscImageChef/Write.cs index 5bfc644d3..44e69b6f1 100644 --- a/DiscImageChef.DiscImages/DiscImageChef/Write.cs +++ b/DiscImageChef.DiscImages/DiscImageChef/Write.cs @@ -407,7 +407,7 @@ namespace DiscImageChef.DiscImages if(ddtHeader.identifier != BlockType.DeDuplicationTable) break; - if(ddtHeader.entries != imageInfo.Sectors && !isTape) + if(ddtHeader.entries != imageInfo.Sectors && !IsTape) { ErrorMessage = $"Trying to write a media with {imageInfo.Sectors} sectors to an image with {ddtHeader.entries} sectors, not continuing..."; @@ -449,7 +449,7 @@ namespace DiscImageChef.DiscImages ImageNotSupportedException($"Found unsupported compression algorithm {(ushort)ddtHeader.compression}"); } - if(isTape) + if(IsTape) { tapeDdt = new Dictionary(); for(long i = 0; i < userDataDdt.LongLength; i++) @@ -672,6 +672,60 @@ namespace DiscImageChef.DiscImages if(DumpHardware.Count == 0) DumpHardware = null; break; + // Tape partition block + case BlockType.TapePartitionBlock: + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + TapePartitionHeader partitionHeader = + Marshal.SpanToStructureLittleEndian(structureBytes); + if(partitionHeader.identifier != BlockType.TapePartitionBlock) break; + + DicConsole.DebugWriteLine("DiscImageChef format plugin", + "Found tape partition block at position {0}", entry.offset); + + byte[] tapePartitionBytes = new byte[partitionHeader.length]; + imageStream.Read(tapePartitionBytes, 0, tapePartitionBytes.Length); + Span tapePartitions = + MemoryMarshal.Cast(tapePartitionBytes); + TapePartitions = new List(); + + foreach(TapePartitionEntry tapePartition in tapePartitions) + TapePartitions.Add(new TapePartition + { + FirstBlock = tapePartition.FirstBlock, + LastBlock = tapePartition.LastBlock, + Number = tapePartition.Number + }); + + IsTape = true; + break; + // Tape file block + case BlockType.TapeFileBlock: + structureBytes = new byte[Marshal.SizeOf()]; + imageStream.Read(structureBytes, 0, structureBytes.Length); + TapeFileHeader fileHeader = + Marshal.SpanToStructureLittleEndian(structureBytes); + if(fileHeader.identifier != BlockType.TapeFileBlock) break; + + DicConsole.DebugWriteLine("DiscImageChef format plugin", + "Found tape file block at position {0}", entry.offset); + + byte[] tapeFileBytes = new byte[fileHeader.length]; + imageStream.Read(tapeFileBytes, 0, tapeFileBytes.Length); + Span tapeFiles = MemoryMarshal.Cast(tapeFileBytes); + Files = new List(); + + foreach(TapeFileEntry file in tapeFiles) + Files.Add(new TapeFile + { + FirstBlock = file.FirstBlock, + LastBlock = file.LastBlock, + Partition = file.Partition, + File = file.File + }); + + IsTape = true; + break; } } @@ -699,7 +753,7 @@ namespace DiscImageChef.DiscImages // If in memory, easy if(inMemoryDdt) { - if(isTape) tapeDdt = new Dictionary(); + if(IsTape) tapeDdt = new Dictionary(); else userDataDdt = new ulong[sectors]; } // If not, create the block, add to index, and enlarge the file to allow the DDT to exist on-disk @@ -811,7 +865,7 @@ namespace DiscImageChef.DiscImages return false; } - if(sectorAddress >= Info.Sectors && !isTape) + if(sectorAddress >= Info.Sectors && !IsTape) { ErrorMessage = "Tried to write past image size"; return false; @@ -1867,7 +1921,7 @@ namespace DiscImageChef.DiscImages } } - if(isTape) + if(IsTape) { ulong latestBlock = tapeDdt.Max(b => b.Key);