Add interface for setting media geometry.

This commit is contained in:
2018-01-01 20:56:33 +00:00
parent df563dd2dd
commit 4756fd8e7c
17 changed files with 376 additions and 112 deletions

View File

@@ -334,18 +334,7 @@ namespace DiscImageChef.DiscImages
return false;
}
(ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding, bool
variableSectorsPerTrack, MediaType type) geometry = Geometry.GetGeometry(mediaType);
fdihdr = new Anex86Header
{
hdrSize = 4096,
dskSize = (int)(sectors * sectorSize),
bps = (int)sectorSize,
spt = geometry.sectorsPerTrack,
heads = geometry.heads,
cylinders = geometry.cylinders
};
fdihdr = new Anex86Header {hdrSize = 4096, dskSize = (int)(sectors * sectorSize), bps = (int)sectorSize};
IsWriting = true;
ErrorMessage = null;
@@ -438,26 +427,26 @@ namespace DiscImageChef.DiscImages
return false;
}
if(imageInfo.MediaType == MediaType.Unknown || imageInfo.MediaType == MediaType.GENERIC_HDD)
if((imageInfo.MediaType == MediaType.Unknown || imageInfo.MediaType == MediaType.GENERIC_HDD) &&
fdihdr.cylinders == 0)
{
// TODO: Interface to set geometry
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 8 / 33);
imageInfo.Heads = 8;
imageInfo.SectorsPerTrack = 33;
fdihdr.cylinders = (int)(imageInfo.Sectors / 8 / 33);
fdihdr.heads = 8;
fdihdr.spt = 33;
while(imageInfo.Cylinders == 0)
while(fdihdr.cylinders == 0)
{
imageInfo.Heads--;
fdihdr.heads--;
if(imageInfo.Heads == 0)
if(fdihdr.heads == 0)
{
imageInfo.SectorsPerTrack--;
imageInfo.Heads = 8;
fdihdr.spt--;
fdihdr.heads = 8;
}
imageInfo.Cylinders = (uint)(imageInfo.Sectors / imageInfo.Heads / imageInfo.SectorsPerTrack);
fdihdr.cylinders = (int)imageInfo.Sectors / fdihdr.heads / fdihdr.spt;
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
if(fdihdr.cylinders == 0 && fdihdr.heads == 0 && fdihdr.spt == 0) break;
}
}
@@ -482,6 +471,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > int.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > int.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > int.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
fdihdr.spt = (int)sectorsPerTrack;
fdihdr.heads = (int)heads;
fdihdr.cylinders = (int)cylinders;
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Anex86Header
{

View File

@@ -2220,6 +2220,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
ErrorMessage = "Unsupported feature";
return false;
}
public bool SetMetadata(ImageInfo metadata)
{
discimage.Barcode = metadata.MediaBarcode;

View File

@@ -640,6 +640,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is not stored in image
return true;
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
enum DiskType : byte
{

View File

@@ -1143,6 +1143,12 @@ namespace DiscImageChef.DiscImages
Close();
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is not stored in image
return true;
}
// DiskCopy 4.2 header, big-endian, data-fork, start of file, 84 bytes
struct Dc42Header
{

View File

@@ -544,6 +544,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is set by media type
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DriFooter
{

View File

@@ -139,8 +139,17 @@ namespace DiscImageChef.DiscImages
/// <summary>
/// Sets image metadata
/// </summary>
/// <param name="metadata"><see cref="ImageInfo"/> containing image metadata</param>
/// <param name="metadata"><see cref="ImageInfo" /> containing image metadata</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetMetadata(ImageInfo metadata);
/// <summary>
/// Sets media geometry
/// </summary>
/// <param name="cylinders">Cylinders</param>
/// <param name="heads">Heads</param>
/// <param name="sectorsPerTrack">Sectors per track</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack);
}
}

View File

@@ -515,6 +515,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > 90)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > 2)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > byte.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct HdkHeader
{

View File

@@ -415,7 +415,8 @@ namespace DiscImageChef.DiscImages
return false;
}
// TODO: Interface to set geometry
if(imageInfo.Cylinders == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 8 / 17);
imageInfo.Heads = 8;
imageInfo.SectorsPerTrack = 17;
@@ -434,6 +435,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
}
}
Nhdr0Header header = new Nhdr0Header
{
@@ -477,6 +479,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > int.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > short.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > short.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Nhdr0Header
{

View File

@@ -458,6 +458,12 @@ namespace DiscImageChef.DiscImages
return false;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is set by media type
return true;
}
public bool Close()
{
if(!IsWriting)

View File

@@ -440,7 +440,8 @@ namespace DiscImageChef.DiscImages
Version thisVersion = GetType().Assembly.GetName().Version;
// TODO: Interface to set geometry
if(imageInfo.Cylinders == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 63;
@@ -459,6 +460,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
}
}
RsIdeHeader header = new RsIdeHeader
{
@@ -538,7 +540,35 @@ namespace DiscImageChef.DiscImages
imageInfo.DriveModel = metadata.DriveModel;
imageInfo.DriveFirmwareRevision = metadata.DriveFirmwareRevision;
imageInfo.DriveSerialNumber = metadata.DriveSerialNumber;
throw new NotImplementedException();
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > ushort.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > ushort.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > ushort.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
static byte[] ScrambleATAString(string text, int length)

View File

@@ -538,6 +538,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is set by media type
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SaveDskFHeader
{

View File

@@ -401,6 +401,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Format uses fixed geometry for heads and sectors per track, cylinders must be calculated on closing.
return true;
}
public bool SetMetadata(ImageInfo metadata)
{
return true;

View File

@@ -1218,7 +1218,8 @@ namespace DiscImageChef.DiscImages
Version thisVersion = GetType().Assembly.GetName().Version;
// TODO: Interface to set geometry
if(imageInfo.Cylinders == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 63;
@@ -1237,6 +1238,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
}
}
HardDiskFooter footer = new HardDiskFooter
{
@@ -1294,6 +1296,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > 0xFFFF)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > 0xFF)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > 0xFF)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
static uint VhdChecksum(IEnumerable<byte> data)
{
uint checksum = data.Aggregate<byte, uint>(0, (current, b) => current + b);

View File

@@ -1066,7 +1066,8 @@ namespace DiscImageChef.DiscImages
writingStream.Flush();
writingStream.Close();
// TODO: Interface to set geometry
if(imageInfo.Cylinders == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 63;
@@ -1085,6 +1086,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
}
}
descriptorStream.WriteLine("# Disk DescriptorFile");
descriptorStream.WriteLine("version=1");
@@ -1116,6 +1118,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > ushort.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > byte.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > byte.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct VMwareExtentHeader
{

View File

@@ -427,7 +427,8 @@ namespace DiscImageChef.DiscImages
return false;
}
// TODO: Interface to set geometry
if(imageInfo.Cylinders == 0)
{
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 63;
@@ -446,6 +447,7 @@ namespace DiscImageChef.DiscImages
if(imageInfo.Cylinders == 0 && imageInfo.Heads == 0 && imageInfo.SectorsPerTrack == 0) break;
}
}
byte[] commentsBytes = null;
if(!string.IsNullOrEmpty(imageInfo.Comments))
@@ -489,6 +491,33 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
if(cylinders > ushort.MaxValue)
{
ErrorMessage = "Too many cylinders.";
return false;
}
if(heads > byte.MaxValue)
{
ErrorMessage = "Too many heads.";
return false;
}
if(sectorsPerTrack > byte.MaxValue)
{
ErrorMessage = "Too many sectors per track.";
return false;
}
imageInfo.SectorsPerTrack = sectorsPerTrack;
imageInfo.Heads = heads;
imageInfo.Cylinders = cylinders;
return true;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Virtual98Header
{

View File

@@ -957,6 +957,7 @@ namespace DiscImageChef.DiscImages
return types;
}
}
public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
new (string name, Type type, string description)[] { };
public IEnumerable<string> KnownExtensions =>
@@ -993,6 +994,12 @@ namespace DiscImageChef.DiscImages
return true;
}
public bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack)
{
// Geometry is not stored in image
return true;
}
public bool WriteMediaTag(byte[] data, MediaTagType tag)
{
// TODO: Implement

View File

@@ -38,6 +38,7 @@ using DiscImageChef.Console;
using DiscImageChef.Core;
using DiscImageChef.DiscImages;
using DiscImageChef.Filters;
using Version = DiscImageChef.Interop.Version;
namespace DiscImageChef.Commands
{
@@ -202,7 +203,7 @@ namespace DiscImageChef.Commands
ImageInfo metadata = new ImageInfo
{
Application = "DiscImageChef",
ApplicationVersion = Interop.Version.GetVersion(),
ApplicationVersion = Version.GetVersion(),
Comments = options.Comments,
Creator = options.Creator,
DriveFirmwareRevision = options.DriveFirmwareRevision,
@@ -316,12 +317,12 @@ namespace DiscImageChef.Commands
doneSectors += sectorsToDo;
}
DicConsole.Write("\rConverting sectors {0} to {1} ({2:P2} done)", inputFormat.Info.Sectors,
inputFormat.Info.Sectors, 1.0);
DicConsole.WriteLine();
}
else
{
foreach(Track track in tracks)
{
doneSectors = 0;
@@ -332,12 +333,14 @@ namespace DiscImageChef.Commands
byte[] sector;
uint sectorsToDo;
if(trackSectors - doneSectors >= (ulong)options.Count)
sectorsToDo = (uint)options.Count;
else sectorsToDo = (uint)(trackSectors - doneSectors);
if(trackSectors - doneSectors >= (ulong)options.Count) sectorsToDo = (uint)options.Count;
else
sectorsToDo =
(uint)(trackSectors - doneSectors);
DicConsole.Write("\rConverting sectors {0} to {1} in track {3} ({2:P2} done)", doneSectors,
doneSectors + sectorsToDo, doneSectors / (double)trackSectors, track.TrackSequence);
doneSectors + sectorsToDo, doneSectors / (double)trackSectors,
track.TrackSequence);
bool result;
if(useLong)
@@ -348,8 +351,10 @@ namespace DiscImageChef.Commands
}
else
{
sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector, sectorsToDo);
result = outputFormat.WriteSectorsLong(sector, doneSectors + track.TrackStartSector, sectorsToDo);
sector = inputFormat.ReadSectorsLong(doneSectors + track.TrackStartSector,
sectorsToDo);
result = outputFormat.WriteSectorsLong(sector, doneSectors + track.TrackStartSector,
sectorsToDo);
}
else
{
@@ -360,8 +365,10 @@ namespace DiscImageChef.Commands
}
else
{
sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector, sectorsToDo);
result = outputFormat.WriteSectors(sector, doneSectors + track.TrackStartSector, sectorsToDo);
sector = inputFormat.ReadSectors(doneSectors + track.TrackStartSector,
sectorsToDo);
result = outputFormat.WriteSectors(sector, doneSectors + track.TrackStartSector,
sectorsToDo);
}
}
@@ -383,6 +390,16 @@ namespace DiscImageChef.Commands
trackSectors, 1.0, track.TrackSequence);
DicConsole.WriteLine();
}
if(tracks == null)
{
DicConsole.WriteLine("Setting geometry to {0} cylinders, {1} heads and {2} sectors per track",
inputFormat.Info.Cylinders, inputFormat.Info.Heads,
inputFormat.Info.SectorsPerTrack);
if(!outputFormat.SetGeometry(inputFormat.Info.Cylinders, inputFormat.Info.Heads,
inputFormat.Info.SectorsPerTrack))
DicConsole.ErrorWriteLine("Error {0} setting geometry, image may be incorrect, continuing...",
outputFormat.ErrorMessage);
}
DicConsole.WriteLine("Closing output image.");