diff --git a/DiscImageChef.DiscImages/ImagePlugin.cs b/DiscImageChef.DiscImages/ImagePlugin.cs
index 26e8ce81..a18e4bf8 100644
--- a/DiscImageChef.DiscImages/ImagePlugin.cs
+++ b/DiscImageChef.DiscImages/ImagePlugin.cs
@@ -693,7 +693,9 @@ namespace DiscImageChef.ImagePlugins
/// MultiMediaCard Extended CSD
MMC_ExtendedCSD,
/// Xbox Security Sector
- Xbox_SecuritySector
+ Xbox_SecuritySector,
+ /// On floppy disks, data in last cylinder usually in a different format that contains duplication or manufacturing information
+ Floppy_LeadOut,
};
///
diff --git a/DiscImageChef.DiscImages/TeleDisk.cs b/DiscImageChef.DiscImages/TeleDisk.cs
index 006cebe5..3469e87f 100644
--- a/DiscImageChef.DiscImages/TeleDisk.cs
+++ b/DiscImageChef.DiscImages/TeleDisk.cs
@@ -202,6 +202,7 @@ namespace DiscImageChef.ImagePlugins
// Cylinder by head, sector data matrix
byte[][][][] sectorsData;
Stream inStream;
+ byte[] leadOut;
#endregion
@@ -479,16 +480,12 @@ namespace DiscImageChef.ImagePlugins
if(TDTrack.sectors == 0xFF) // End of disk image
break;
- if(TDTrack.sectors < ImageInfo.sectorsPerTrack)
- ImageInfo.sectorsPerTrack = TDTrack.sectors;
-
for(byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++)
{
TDSectorHeader TDSector = new TDSectorHeader();
TDDataHeader TDData = new TDDataHeader();
byte[] dataSizeBytes = new byte[2];
byte[] data;
- byte[] decodedData;
TDSector.cylinder = (byte)stream.ReadByte();
TDSector.head = (byte)stream.ReadByte();
@@ -505,7 +502,6 @@ namespace DiscImageChef.ImagePlugins
stream.Read(dataSizeBytes, 0, 2);
TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it
- ImageInfo.imageSize += TDData.dataSize;
TDData.dataEncoding = (byte)stream.ReadByte();
data = new byte[TDData.dataSize];
stream.Read(data, 0, TDData.dataSize);
@@ -524,13 +520,67 @@ namespace DiscImageChef.ImagePlugins
if(totalCylinders <= 0 || totalHeads <= 0)
throw new ImageNotSupportedException("No cylinders or heads found");
+ bool hasLeadOutOnHead0 = false;
+ bool hasLeadOutOnHead1 = false;
+ ImageInfo.cylinders = (ushort)totalCylinders;
+ ImageInfo.heads = (byte)totalHeads;
+
+ // Count sectors per track
+ stream.Seek(currentPos, SeekOrigin.Begin);
+ while(true)
+ {
+ TDTrackHeader TDTrack = new TDTrackHeader();
+
+ TDTrack.sectors = (byte)stream.ReadByte();
+ TDTrack.cylinder = (byte)stream.ReadByte();
+ TDTrack.head = (byte)stream.ReadByte();
+ TDTrack.crc = (byte)stream.ReadByte();
+
+ if(TDTrack.sectors == 0xFF) // End of disk image
+ break;
+
+ if(TDTrack.sectors < ImageInfo.sectorsPerTrack)
+ {
+ if(TDTrack.cylinder + 1 == totalCylinders)
+ {
+ hasLeadOutOnHead0 |= TDTrack.head == 0;
+ hasLeadOutOnHead1 |= TDTrack.head == 1;
+ if(ImageInfo.cylinders == totalCylinders)
+ ImageInfo.cylinders--;
+ }
+ else
+ ImageInfo.sectorsPerTrack = TDTrack.sectors;
+ }
+ for(byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++)
+ {
+ TDSectorHeader TDSector = new TDSectorHeader();
+ TDDataHeader TDData = new TDDataHeader();
+ byte[] dataSizeBytes = new byte[2];
+ byte[] data;
+
+ TDSector.cylinder = (byte)stream.ReadByte();
+ TDSector.head = (byte)stream.ReadByte();
+ TDSector.sectorNumber = (byte)stream.ReadByte();
+ TDSector.sectorSize = (byte)stream.ReadByte();
+ TDSector.flags = (byte)stream.ReadByte();
+ TDSector.crc = (byte)stream.ReadByte();
+
+ if((TDSector.flags & FlagsSectorDataless) != FlagsSectorDataless && (TDSector.flags & FlagsSectorSkipped) != FlagsSectorSkipped)
+ {
+ stream.Read(dataSizeBytes, 0, 2);
+ TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
+ TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it
+ TDData.dataEncoding = (byte)stream.ReadByte();
+ data = new byte[TDData.dataSize];
+ stream.Read(data, 0, TDData.dataSize);
+ }
+ }
+ }
+
sectorsData = new byte[totalCylinders][][][];
// Total sectors per track
uint[][] spts = new uint[totalCylinders][];
- ImageInfo.cylinders = (ushort)totalCylinders;
- ImageInfo.heads = (byte)totalHeads;
-
DicConsole.DebugWriteLine("TeleDisk plugin", "Found {0} cylinders and {1} heads with a maximum sector number of {2}", totalCylinders, totalHeads, maxSector);
// Create heads
@@ -654,6 +704,29 @@ namespace DiscImageChef.ImagePlugins
}
}
+ MemoryStream leadOutMs = new MemoryStream();
+ if(hasLeadOutOnHead0)
+ {
+ for(int i = 0; i < sectorsData[totalCylinders - 1][0].Length; i++)
+ {
+ if(sectorsData[totalCylinders - 1][0][i] != null)
+ leadOutMs.Write(sectorsData[totalCylinders - 1][0][i], 0, sectorsData[totalCylinders - 1][0][i].Length);
+ }
+ }
+ if(hasLeadOutOnHead1)
+ {
+ for(int i = 0; i < sectorsData[totalCylinders - 1][1].Length; i++)
+ {
+ if(sectorsData[totalCylinders - 1][1][i] != null)
+ leadOutMs.Write(sectorsData[totalCylinders - 1][1][i], 0, sectorsData[totalCylinders - 1][1][i].Length);
+ }
+ }
+ if(leadOutMs.Length != 0)
+ {
+ leadOut = leadOutMs.ToArray();
+ ImageInfo.readableMediaTags.Add(MediaTagType.Floppy_LeadOut);
+ }
+
ImageInfo.sectors = ImageInfo.cylinders * ImageInfo.heads * ImageInfo.sectorsPerTrack;
ImageInfo.mediaType = DecodeTeleDiskDiskType();
@@ -666,6 +739,13 @@ namespace DiscImageChef.ImagePlugins
inStream.Dispose();
stream.Dispose();
+ /*
+ FileStream debugFs = new FileStream("debug.img", FileMode.CreateNew, FileAccess.Write);
+ for(ulong i = 0; i < ImageInfo.sectors; i++)
+ debugFs.Write(ReadSector(i), 0, (int)ImageInfo.sectorSize);
+ debugFs.Dispose();
+ */
+
return true;
}
@@ -717,6 +797,8 @@ namespace DiscImageChef.ImagePlugins
for(uint i = 0; i < length; i++)
{
byte[] sector = ReadSector(sectorAddress + i);
+ if(sector == null)
+ sector = new byte[ImageInfo.sectorSize];
buffer.Write(sector, 0, sector.Length);
}
@@ -1128,6 +1210,18 @@ namespace DiscImageChef.ImagePlugins
}
}
+ public override byte[] ReadDiskTag(MediaTagType tag)
+ {
+ if(tag == MediaTagType.Floppy_LeadOut)
+ {
+ if(leadOut != null)
+ return leadOut;
+ throw new FeatureNotPresentImageException("Lead-out not present in disk image");
+ }
+ else
+ throw new FeatureUnsupportedImageException("Feature not supported by image format");
+ }
+
#endregion
#region Unsupported features
@@ -1142,11 +1236,6 @@ namespace DiscImageChef.ImagePlugins
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
- public override byte[] ReadDiskTag(MediaTagType tag)
- {
- throw new FeatureUnsupportedImageException("Feature not supported by image format");
- }
-
public override string GetImageCreator()
{
return ImageInfo.imageCreator;