diff --git a/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs b/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs
index eeeb92eaf..12fa22957 100644
--- a/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs
+++ b/DiscImageChef.DiscImages/DiscImageChef/DiscImageChef.cs
@@ -161,6 +161,7 @@ namespace DiscImageChef.DiscImages
ulong[] userDataDdt;
bool writingLong;
ulong writtenSectors;
+ byte[] mode2Subheaders;
public DiscImageChef()
{
diff --git a/DiscImageChef.DiscImages/DiscImageChef/Enums.cs b/DiscImageChef.DiscImages/DiscImageChef/Enums.cs
index 5608dcc46..db769c339 100644
--- a/DiscImageChef.DiscImages/DiscImageChef/Enums.cs
+++ b/DiscImageChef.DiscImages/DiscImageChef/Enums.cs
@@ -205,7 +205,9 @@ namespace DiscImageChef.DiscImages
/// CompactDisc sector prefix (sync, header), only incorrect stored
CdSectorPrefixCorrected = 76,
/// CompactDisc sector suffix (edc, ecc p, ecc q), only incorrect stored
- CdSectorSuffixCorrected = 77
+ CdSectorSuffixCorrected = 77,
+ /// CompactDisc MODE 2 subheader
+ CompactDiscMode2Subheader = 78
}
/// List of known blocks types
diff --git a/DiscImageChef.DiscImages/DiscImageChef/Read.cs b/DiscImageChef.DiscImages/DiscImageChef/Read.cs
index badf43f21..bc9cad9b4 100644
--- a/DiscImageChef.DiscImages/DiscImageChef/Read.cs
+++ b/DiscImageChef.DiscImages/DiscImageChef/Read.cs
@@ -269,6 +269,9 @@ namespace DiscImageChef.DiscImages
if(!imageInfo.ReadableSectorTags.Contains(SectorTagType.AppleSectorTag))
imageInfo.ReadableSectorTags.Add(SectorTagType.AppleSectorTag);
break;
+ case DataType.CompactDiscMode2Subheader:
+ mode2Subheaders = data;
+ break;
default:
MediaTagType mediaTagType = GetMediaTagTypeForDataType(blockHeader.type);
@@ -1362,7 +1365,14 @@ namespace DiscImageChef.DiscImages
case TrackType.CdMode2Formless:
case TrackType.CdMode2Form1:
case TrackType.CdMode2Form2:
- Array.Copy(data, 0, sector, 16, 2336);
+ if(mode2Subheaders != null)
+ {
+ Array.Copy(mode2Subheaders, (int)sectorAddress * 8, sector, 16, 8);
+ Array.Copy(data, 0, sector, 24, 2328);
+ }
+ else
+ Array.Copy(data, 0, sector, 16, 2336);
+
if(sectorPrefix != null)
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
else if(sectorPrefixMs != null)
diff --git a/DiscImageChef.DiscImages/DiscImageChef/Write.cs b/DiscImageChef.DiscImages/DiscImageChef/Write.cs
index e88a44c86..e77c4b33c 100644
--- a/DiscImageChef.DiscImages/DiscImageChef/Write.cs
+++ b/DiscImageChef.DiscImages/DiscImageChef/Write.cs
@@ -1211,7 +1211,7 @@ namespace DiscImageChef.DiscImages
if(sectorPrefixDdt == null) sectorPrefixDdt = new uint[imageInfo.Sectors];
- sector = new byte[2336];
+ sector = new byte[2328];
if(ArrayHelpers.ArrayIsNullOrEmpty(data))
{
sectorPrefixDdt[sectorAddress] = (uint)CdFixFlags.NotDumped;
@@ -1223,9 +1223,7 @@ namespace DiscImageChef.DiscImages
if(data[0x00] != 0x00 || data[0x01] != 0xFF || data[0x02] != 0xFF || data[0x03] != 0xFF ||
data[0x04] != 0xFF || data[0x05] != 0xFF || data[0x06] != 0xFF || data[0x07] != 0xFF ||
data[0x08] != 0xFF || data[0x09] != 0xFF || data[0x0A] != 0xFF || data[0x0B] != 0x00 ||
- data[0x0F] != 0x02 || data[0x10] != 0x00 || data[0x11] != 0x00 || data[0x12] != 0x00 ||
- data[0x13] != 0x00 || data[0x14] != 0x00 || data[0x15] != 0x00 || data[0x16] != 0x00 ||
- data[0x17] != 0x00) prefixCorrect = false;
+ data[0x0F] != 0x02) prefixCorrect = false;
if(prefixCorrect)
{
@@ -1249,7 +1247,10 @@ namespace DiscImageChef.DiscImages
sectorPrefixMs.Write(data, 0, 16);
}
- Array.Copy(data, 16, sector, 0, 2336);
+ if(mode2Subheaders == null) mode2Subheaders = new byte[imageInfo.Sectors * 8];
+
+ Array.Copy(data, 16, mode2Subheaders, (int)sectorAddress * 8, 8);
+ Array.Copy(data, 24, sector, 0, 2328);
return WriteSector(sector, sectorAddress);
}
@@ -2380,6 +2381,80 @@ namespace DiscImageChef.DiscImages
index.Add(idxEntry);
}
+ if(mode2Subheaders != null)
+ {
+ idxEntry = new IndexEntry
+ {
+ blockType = BlockType.DataBlock,
+ dataType = DataType.CompactDiscMode2Subheader,
+ offset = (ulong)imageStream.Position
+ };
+
+ DicConsole.DebugWriteLine("DiscImageChef format plugin",
+ "Writing CD MODE2 subheaders block to position {0}", idxEntry.offset);
+
+ Crc64Context.Data(mode2Subheaders, out byte[] blockCrc);
+
+ BlockHeader subheaderBlock = new BlockHeader
+ {
+ identifier = BlockType.DataBlock,
+ type = DataType.CompactDiscMode2Subheader,
+ length = (uint)mode2Subheaders.Length,
+ crc64 = BitConverter.ToUInt64(blockCrc, 0),
+ sectorSize = 8
+ };
+
+ byte[] lzmaProperties = null;
+
+ if(nocompress)
+ {
+ subheaderBlock.compression = CompressionType.None;
+ subheaderBlock.cmpCrc64 = subheaderBlock.crc64;
+ subheaderBlock.cmpLength = subheaderBlock.length;
+ blockStream = new MemoryStream(mode2Subheaders);
+ }
+ else
+ {
+ startCompress = DateTime.Now;
+ blockStream = new MemoryStream();
+ lzmaBlockStream = new LzmaStream(lzmaEncoderProperties, false, blockStream);
+ lzmaBlockStream.Write(mode2Subheaders, 0, mode2Subheaders.Length);
+ lzmaProperties = lzmaBlockStream.Properties;
+ lzmaBlockStream.Close();
+
+ Crc64Context cmpCrc = new Crc64Context();
+ cmpCrc.Update(lzmaProperties);
+ cmpCrc.Update(blockStream.ToArray());
+ blockCrc = cmpCrc.Final();
+ subheaderBlock.cmpLength = (uint)blockStream.Length + LZMA_PROPERTIES_LENGTH;
+ subheaderBlock.cmpCrc64 = BitConverter.ToUInt64(blockCrc, 0);
+ subheaderBlock.compression = CompressionType.Lzma;
+
+ lzmaBlockStream = null;
+ endCompress = DateTime.Now;
+ DicConsole.DebugWriteLine("DiscImageChef format plugin",
+ "Took {0} seconds to compress MODE2 subheaders",
+ (endCompress - startCompress).TotalSeconds);
+ }
+
+ structurePointer = Marshal.AllocHGlobal(Marshal.SizeOf(subheaderBlock));
+ structureBytes = new byte[Marshal.SizeOf(subheaderBlock)];
+ Marshal.StructureToPtr(subheaderBlock, structurePointer, true);
+ Marshal.Copy(structurePointer, structureBytes, 0, structureBytes.Length);
+ Marshal.FreeHGlobal(structurePointer);
+ imageStream.Write(structureBytes, 0, structureBytes.Length);
+ if(subheaderBlock.compression == CompressionType.Lzma)
+ imageStream.Write(lzmaProperties, 0, lzmaProperties.Length);
+ imageStream.Write(blockStream.ToArray(), 0, (int)blockStream.Length);
+
+ index.RemoveAll(t => t.blockType == BlockType.DataBlock &&
+ t.dataType == DataType.CompactDiscMode2Subheader);
+
+ index.Add(idxEntry);
+ blockStream = null;
+ }
+
+
if(sectorSubchannel != null)
{
idxEntry = new IndexEntry
diff --git a/templates/dicformat.bt b/templates/dicformat.bt
index de65e558a..c34b1f759 100644
--- a/templates/dicformat.bt
+++ b/templates/dicformat.bt
@@ -624,7 +624,8 @@ enum DataType
PriamDataTowerTag = 74,
CompactDiscMediaCatalogueNumber = 75,
CdSectorPrefixCorrected = 76,
- CdSectorSuffixCorrected = 77
+ CdSectorSuffixCorrected = 77,
+ CompactDiscMode2Subheader = 78
};
enum BlockType