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> /// <summary>MultiMediaCard Extended CSD</summary>
MMC_ExtendedCSD, MMC_ExtendedCSD,
/// <summary>Xbox Security Sector</summary> /// <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> /// <summary>

View File

@@ -202,6 +202,7 @@ namespace DiscImageChef.ImagePlugins
// Cylinder by head, sector data matrix // Cylinder by head, sector data matrix
byte[][][][] sectorsData; byte[][][][] sectorsData;
Stream inStream; Stream inStream;
byte[] leadOut;
#endregion #endregion
@@ -479,16 +480,12 @@ namespace DiscImageChef.ImagePlugins
if(TDTrack.sectors == 0xFF) // End of disk image if(TDTrack.sectors == 0xFF) // End of disk image
break; break;
if(TDTrack.sectors < ImageInfo.sectorsPerTrack)
ImageInfo.sectorsPerTrack = TDTrack.sectors;
for(byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++) for(byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++)
{ {
TDSectorHeader TDSector = new TDSectorHeader(); TDSectorHeader TDSector = new TDSectorHeader();
TDDataHeader TDData = new TDDataHeader(); TDDataHeader TDData = new TDDataHeader();
byte[] dataSizeBytes = new byte[2]; byte[] dataSizeBytes = new byte[2];
byte[] data; byte[] data;
byte[] decodedData;
TDSector.cylinder = (byte)stream.ReadByte(); TDSector.cylinder = (byte)stream.ReadByte();
TDSector.head = (byte)stream.ReadByte(); TDSector.head = (byte)stream.ReadByte();
@@ -505,7 +502,6 @@ namespace DiscImageChef.ImagePlugins
stream.Read(dataSizeBytes, 0, 2); stream.Read(dataSizeBytes, 0, 2);
TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0); TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it
ImageInfo.imageSize += TDData.dataSize;
TDData.dataEncoding = (byte)stream.ReadByte(); TDData.dataEncoding = (byte)stream.ReadByte();
data = new byte[TDData.dataSize]; data = new byte[TDData.dataSize];
stream.Read(data, 0, TDData.dataSize); stream.Read(data, 0, TDData.dataSize);
@@ -524,13 +520,67 @@ namespace DiscImageChef.ImagePlugins
if(totalCylinders <= 0 || totalHeads <= 0) if(totalCylinders <= 0 || totalHeads <= 0)
throw new ImageNotSupportedException("No cylinders or heads found"); 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][][][]; sectorsData = new byte[totalCylinders][][][];
// Total sectors per track // Total sectors per track
uint[][] spts = new uint[totalCylinders][]; 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); DicConsole.DebugWriteLine("TeleDisk plugin", "Found {0} cylinders and {1} heads with a maximum sector number of {2}", totalCylinders, totalHeads, maxSector);
// Create heads // 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.sectors = ImageInfo.cylinders * ImageInfo.heads * ImageInfo.sectorsPerTrack;
ImageInfo.mediaType = DecodeTeleDiskDiskType(); ImageInfo.mediaType = DecodeTeleDiskDiskType();
@@ -666,6 +739,13 @@ namespace DiscImageChef.ImagePlugins
inStream.Dispose(); inStream.Dispose();
stream.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; return true;
} }
@@ -717,6 +797,8 @@ namespace DiscImageChef.ImagePlugins
for(uint i = 0; i < length; i++) for(uint i = 0; i < length; i++)
{ {
byte[] sector = ReadSector(sectorAddress + i); byte[] sector = ReadSector(sectorAddress + i);
if(sector == null)
sector = new byte[ImageInfo.sectorSize];
buffer.Write(sector, 0, sector.Length); 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 #endregion
#region Unsupported features #region Unsupported features
@@ -1142,11 +1236,6 @@ namespace DiscImageChef.ImagePlugins
throw new FeatureUnsupportedImageException("Feature not supported by image format"); 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() public override string GetImageCreator()
{ {
return ImageInfo.imageCreator; return ImageInfo.imageCreator;