Added support for floppy leadout.

This commit is contained in:
2017-10-02 14:25:04 +01:00
parent e7cec5e561
commit a174b9e2f2
2 changed files with 105 additions and 14 deletions

View File

@@ -693,7 +693,9 @@ namespace DiscImageChef.ImagePlugins
/// <summary>MultiMediaCard Extended CSD</summary>
MMC_ExtendedCSD,
/// <summary>Xbox Security Sector</summary>
Xbox_SecuritySector
Xbox_SecuritySector,
/// <summary>On floppy disks, data in last cylinder usually in a different format that contains duplication or manufacturing information</summary>
Floppy_LeadOut,
};
/// <summary>

View File

@@ -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;