Files
Aaru/DiscImageChef.DiscImages/D88.cs
2017-08-02 23:01:11 +01:00

819 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : D88.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Component
//
// --[ Description ] ----------------------------------------------------------
//
// Description
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2017 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using DiscImageChef.Console;
using DiscImageChef.CommonTypes;
using System.Linq;
using System.Text;
using DiscImageChef.Filters;
using System.Runtime.InteropServices;
using DiscImageChef.Decoders.Floppy;
namespace DiscImageChef.ImagePlugins
{
// Information from Quasi88's FORMAT.TXT file
// Japanese comments copied from there
public class D88 : ImagePlugin
{
#region Internal enumerations
enum DiskType : byte
{
D2 = 0x00,
DD2 = 0x10,
HD2 = 0x20,
}
enum DensityType : byte
{
MFM = 0x00,
FM = 0x40,
}
/// <summary>
/// Status as returned by PC-98 BIOS
/// ステータスは、PC-98x1 のBIOS が返してくるステータスで、
/// </summary>
enum StatusType : byte
{
/// <summary>
/// Normal
/// 正常
/// </summary>
Normal = 0x00,
/// <summary>
/// Deleted
/// 正常(DELETED DATA)
/// </summary>
Deleted = 0x10,
/// <summary>
/// CRC error in address fields
/// ID CRC エラー
/// </summary>
IDError = 0xA0,
/// <summary>
/// CRC error in data block
/// データ CRC エラー
/// </summary>
DataError = 0xB0,
/// <summary>
/// Address mark not found
/// アドレスマークなし
/// </summary>
AddressMarkNotFound = 0xE0,
/// <summary>
/// Data mark not found
/// データマークなし
/// </summary>
DataMarkNotFound = 0xF0,
}
#endregion
#region Internal constants
readonly byte[] ReservedEmpty = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const byte ReadOnly = 0x10;
#endregion
#region Internal structures
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct D88Header
{
/// <summary>
/// Disk name, nul-terminated ASCII
/// ディスクの名前(ASCII + '\0')
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public byte[] name;
/// <summary>
/// Reserved
/// ディスクの名前(ASCII + '\0')
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public byte[] reserved;
/// <summary>
/// Write protect status
/// ライトプロテクト: 0x00 なし、0x10 あり
/// </summary>
public byte write_protect;
/// <summary>
/// Disk type
/// ディスクの種類: 0x00 2D、 0x10 2DD、 0x20 2HD
/// </summary>
public DiskType disk_type;
/// <summary>
/// Disk image size
/// ディスクのサイズ
/// </summary>
public int disk_size;
/// <summary>
/// Track pointers
/// トラック部のオフセットテーブル 0 Track 163 Track
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 164)]
public int[] track_table;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SectorHeader
{
/// <summary>
/// Cylinder
/// ID の C
/// </summary>
public byte c;
/// <summary>
/// Head
/// ID の H
/// </summary>
public byte h;
/// <summary>
/// Sector number
/// ID の R
/// </summary>
public byte r;
/// <summary>
/// Sector size
/// ID の N
/// </summary>
public IBMSectorSizeCode n;
/// <summary>
/// Number of sectors in this track
/// このトラック内に存在するセクタの数
/// </summary>
public short spt;
/// <summary>
/// Density: 0x00 MFM, 0x40 FM
/// 記録密度: 0x00 倍密度、0x40 単密度
/// </summary>
public DensityType density;
/// <summary>
/// Deleted sector, 0x00 not deleted, 0x10 deleted
/// DELETED MARK 0x00 ノーマル、 0x10 DELETED
/// </summary>
public byte deleted_mark;
/// <summary>
/// Sector status
/// ステータス
/// </summary>
public byte status;
/// <summary>
/// Reserved
/// リザーブ
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] reserved;
/// <summary>
/// Size of data following this field
/// このセクタ部のデータサイズ
/// </summary>
public short size_of_data;
}
#endregion
List<byte[]> sectorsData;
public D88()
{
Name = "D88 Disk Image";
PluginUUID = new Guid("669EDC77-EC41-4720-A88C-49C38CFFBAA0");
ImageInfo = new ImageInfo()
{
readableSectorTags = new List<SectorTagType>(),
readableMediaTags = new List<MediaTagType>(),
imageHasPartitions = false,
imageHasSessions = false,
imageVersion = null,
imageApplication = null,
imageApplicationVersion = null,
imageCreator = null,
imageComments = null,
mediaManufacturer = null,
mediaModel = null,
mediaSerialNumber = null,
mediaBarcode = null,
mediaPartNumber = null,
mediaSequence = 0,
lastMediaSequence = 0,
driveManufacturer = null,
driveModel = null,
driveSerialNumber = null,
driveFirmwareRevision = null
};
}
public override bool IdentifyImage(Filter imageFilter)
{
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
// Even if disk name is supposedly ASCII, I'm pretty sure most emulators allow Shift-JIS to be used :p
Encoding shiftjis = Encoding.GetEncoding("shift_jis");
D88Header d88hdr = new D88Header();
if(stream.Length < Marshal.SizeOf(d88hdr))
return false;
byte[] hdr_b = new byte[Marshal.SizeOf(d88hdr)];
stream.Read(hdr_b, 0, hdr_b.Length);
GCHandle handle = GCHandle.Alloc(hdr_b, GCHandleType.Pinned);
d88hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
handle.Free();
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.name = \"{0}\"", StringHandlers.CToString(d88hdr.name, shiftjis));
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.reserved is empty? = {0}", d88hdr.reserved.SequenceEqual(ReservedEmpty));
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.write_protect = 0x{0:X2}", d88hdr.write_protect);
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.disk_type = {0} ({1})", d88hdr.disk_type, (byte)d88hdr.disk_type);
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.disk_size = {0}", d88hdr.disk_size);
if(d88hdr.disk_size != stream.Length)
return false;
if(d88hdr.disk_type != DiskType.D2 && d88hdr.disk_type != DiskType.DD2 && d88hdr.disk_type != DiskType.HD2)
return false;
if(!d88hdr.reserved.SequenceEqual(ReservedEmpty))
return false;
int counter = 0;
for(int i = 0; i < d88hdr.track_table.Length; i++)
{
if(d88hdr.track_table[i] > 0)
counter++;
if(d88hdr.track_table[i] < 0 || d88hdr.track_table[i] > stream.Length)
return false;
}
DicConsole.DebugWriteLine("D88 plugin", "{0} tracks", counter);
return counter > 0;
}
public override bool OpenImage(Filter imageFilter)
{
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
// Even if disk name is supposedly ASCII, I'm pretty sure most emulators allow Shift-JIS to be used :p
Encoding shiftjis = Encoding.GetEncoding("shift_jis");
D88Header d88hdr = new D88Header();
if(stream.Length < Marshal.SizeOf(d88hdr))
return false;
byte[] hdr_b = new byte[Marshal.SizeOf(d88hdr)];
stream.Read(hdr_b, 0, hdr_b.Length);
GCHandle handle = GCHandle.Alloc(hdr_b, GCHandleType.Pinned);
d88hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
handle.Free();
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.name = \"{0}\"", StringHandlers.CToString(d88hdr.name, shiftjis));
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.reserved is empty? = {0}", d88hdr.reserved.SequenceEqual(ReservedEmpty));
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.write_protect = 0x{0:X2}", d88hdr.write_protect);
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.disk_type = {0} ({1})", d88hdr.disk_type, (byte)d88hdr.disk_type);
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.disk_size = {0}", d88hdr.disk_size);
if(d88hdr.disk_size != stream.Length)
return false;
if(d88hdr.disk_type != DiskType.D2 && d88hdr.disk_type != DiskType.DD2 && d88hdr.disk_type != DiskType.HD2)
return false;
if(!d88hdr.reserved.SequenceEqual(ReservedEmpty))
return false;
int trkCounter = 0;
for(int i = 0; i < d88hdr.track_table.Length; i++)
{
if(d88hdr.track_table[i] > 0)
trkCounter++;
if(d88hdr.track_table[i] < 0 || d88hdr.track_table[i] > stream.Length)
return false;
}
DicConsole.DebugWriteLine("D88 plugin", "{0} tracks", trkCounter);
if(trkCounter == 0)
return false;
SectorHeader sechdr = new SectorHeader();
hdr_b = new byte[Marshal.SizeOf(sechdr)];
stream.Seek(d88hdr.track_table[0], SeekOrigin.Begin);
stream.Read(hdr_b, 0, hdr_b.Length);
handle = GCHandle.Alloc(hdr_b, GCHandleType.Pinned);
sechdr = (SectorHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SectorHeader));
handle.Free();
DicConsole.DebugWriteLine("D88 plugin", "sechdr.c = {0}", sechdr.c);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.h = {0}", sechdr.h);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.r = {0}", sechdr.r);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.n = {0}", sechdr.n);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.spt = {0}", sechdr.spt);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.density = {0}", sechdr.density);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.deleted_mark = {0}", sechdr.deleted_mark);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.status = {0}", sechdr.status);
DicConsole.DebugWriteLine("D88 plugin", "sechdr.size_of_data = {0}", sechdr.size_of_data);
short spt = sechdr.spt;
IBMSectorSizeCode bps = sechdr.n;
bool allEqual = true;
sectorsData = new List<byte[]>();
for(int i = 0; i < trkCounter; i++)
{
stream.Seek(d88hdr.track_table[i], SeekOrigin.Begin);
stream.Read(hdr_b, 0, hdr_b.Length);
SortedDictionary<byte, byte[]> sectors = new SortedDictionary<byte, byte[]>();
handle = GCHandle.Alloc(hdr_b, GCHandleType.Pinned);
sechdr = (SectorHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SectorHeader));
handle.Free();
if(sechdr.spt != spt || sechdr.n != bps)
{
DicConsole.DebugWriteLine("D88 plugin", "Disk tracks are not same size. spt = {0} (expected {1}), bps = {2} (expected {3}) at track {4} sector {5}", sechdr.spt, spt, sechdr.n, bps, i, 0);
allEqual = false;
}
short maxJ = sechdr.spt;
byte[] sec_b;
for(short j = 1; j < maxJ; j++)
{
sec_b = new byte[sechdr.size_of_data];
stream.Read(sec_b, 0, sec_b.Length);
sectors.Add(sechdr.r, sec_b);
stream.Read(hdr_b, 0, hdr_b.Length);
handle = GCHandle.Alloc(hdr_b, GCHandleType.Pinned);
sechdr = (SectorHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(SectorHeader));
handle.Free();
if(sechdr.spt != spt || sechdr.n != bps)
{
DicConsole.DebugWriteLine("D88 plugin", "Disk tracks are not same size. spt = {0} (expected {1}), bps = {2} (expected {3}) at track {4} sector {5}", sechdr.spt, spt, sechdr.n, bps, i, j, sechdr.deleted_mark);
allEqual = false;
}
}
sec_b = new byte[sechdr.size_of_data];
stream.Read(sec_b, 0, sec_b.Length);
sectors.Add(sechdr.r, sec_b);
foreach(KeyValuePair<byte, byte[]> kvp in sectors)
sectorsData.Add(kvp.Value);
}
DicConsole.DebugWriteLine("D88 plugin", "{0} sectors", sectorsData.Count());
/*
FileStream debugStream = new FileStream("debug.img", FileMode.CreateNew, FileAccess.ReadWrite);
for(int i = 0; i < sectorsData.Count; i++)
debugStream.Write(sectorsData[i], 0, sectorsData[i].Length);
debugStream.Close();
*/
ImageInfo.mediaType = MediaType.Unknown;
if(allEqual)
{
if(trkCounter == 154 && spt == 26 && bps == IBMSectorSizeCode.EighthKilo)
ImageInfo.mediaType = MediaType.NEC_8_SD;
else if(bps == IBMSectorSizeCode.QuarterKilo)
{
if(trkCounter == 80 && spt == 16)
ImageInfo.mediaType = MediaType.NEC_525_SS;
else if(trkCounter == 154 && spt == 26)
ImageInfo.mediaType = MediaType.NEC_8_DD;
else if(trkCounter == 160 && spt == 16)
ImageInfo.mediaType = MediaType.NEC_525_DS;
}
else if(trkCounter == 154 && spt == 8 && bps == IBMSectorSizeCode.Kilo)
ImageInfo.mediaType = MediaType.NEC_525_HD;
else if(bps == IBMSectorSizeCode.HalfKilo)
{
switch(d88hdr.track_table.Length)
{
case 40:
{
switch(spt)
{
case 8:
ImageInfo.mediaType = MediaType.DOS_525_SS_DD_8;
break;
case 9:
ImageInfo.mediaType = MediaType.DOS_525_SS_DD_9;
break;
}
}
break;
case 80:
{
switch(spt)
{
case 8:
ImageInfo.mediaType = MediaType.DOS_525_DS_DD_8;
break;
case 9:
ImageInfo.mediaType = MediaType.DOS_525_DS_DD_9;
break;
}
}
break;
case 160:
{
switch(spt)
{
case 15:
ImageInfo.mediaType = MediaType.NEC_35_HD_15;
break;
case 9:
ImageInfo.mediaType = MediaType.DOS_35_DS_DD_9;
break;
case 18:
ImageInfo.mediaType = MediaType.DOS_35_HD;
break;
case 36:
ImageInfo.mediaType = MediaType.DOS_35_ED;
break;
}
}
break;
case 480:
if(spt == 38)
ImageInfo.mediaType = MediaType.NEC_35_TD;
break;
}
}
}
DicConsole.DebugWriteLine("D88 plugin", "MediaType: {0}", ImageInfo.mediaType);
ImageInfo.imageSize = (ulong)d88hdr.disk_size;
ImageInfo.imageCreationTime = imageFilter.GetCreationTime();
ImageInfo.imageLastModificationTime = imageFilter.GetLastWriteTime();
ImageInfo.imageName = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
ImageInfo.sectors = (ulong)sectorsData.Count;
ImageInfo.imageComments = StringHandlers.CToString(d88hdr.name, shiftjis);
ImageInfo.xmlMediaType = XmlMediaType.BlockMedia;
ImageInfo.sectorSize = (uint)(128 << (int)bps);
switch(ImageInfo.mediaType)
{
case MediaType.NEC_525_SS:
ImageInfo.cylinders = 80;
ImageInfo.heads = 1;
ImageInfo.sectorsPerTrack = 16;
break;
case MediaType.NEC_8_SD:
case MediaType.NEC_8_DD:
ImageInfo.cylinders = 77;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 26;
break;
case MediaType.NEC_525_DS:
ImageInfo.cylinders = 80;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 16;
break;
case MediaType.NEC_525_HD:
ImageInfo.cylinders = 77;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 8;
break;
case MediaType.DOS_525_SS_DD_8:
ImageInfo.cylinders = 40;
ImageInfo.heads = 1;
ImageInfo.sectorsPerTrack = 8;
break;
case MediaType.DOS_525_SS_DD_9:
ImageInfo.cylinders = 40;
ImageInfo.heads = 1;
ImageInfo.sectorsPerTrack = 9;
break;
case MediaType.DOS_525_DS_DD_8:
ImageInfo.cylinders = 40;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 8;
break;
case MediaType.DOS_525_DS_DD_9:
ImageInfo.cylinders = 40;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 9;
break;
case MediaType.NEC_35_HD_15:
ImageInfo.cylinders = 80;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 15;
break;
case MediaType.DOS_35_DS_DD_9:
ImageInfo.cylinders = 80;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 9;
break;
case MediaType.DOS_35_HD:
ImageInfo.cylinders = 80;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 18;
break;
case MediaType.DOS_35_ED:
ImageInfo.cylinders = 80;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 36;
break;
case MediaType.NEC_35_TD:
ImageInfo.cylinders = 240;
ImageInfo.heads = 2;
ImageInfo.sectorsPerTrack = 38;
break;
}
return true;
}
public override bool ImageHasPartitions()
{
return false;
}
public override ulong GetImageSize()
{
return ImageInfo.imageSize;
}
public override ulong GetSectors()
{
return ImageInfo.sectors;
}
public override uint GetSectorSize()
{
return ImageInfo.sectorSize;
}
public override string GetImageFormat()
{
return "D88 disk image";
}
public override string GetImageVersion()
{
return ImageInfo.imageVersion;
}
public override string GetImageApplication()
{
return ImageInfo.imageApplication;
}
public override string GetImageApplicationVersion()
{
return ImageInfo.imageApplicationVersion;
}
public override string GetImageCreator()
{
return ImageInfo.imageCreator;
}
public override DateTime GetImageCreationTime()
{
return ImageInfo.imageCreationTime;
}
public override DateTime GetImageLastModificationTime()
{
return ImageInfo.imageLastModificationTime;
}
public override string GetImageName()
{
return ImageInfo.imageName;
}
public override string GetImageComments()
{
return ImageInfo.imageComments;
}
public override MediaType GetMediaType()
{
return ImageInfo.mediaType;
}
public override byte[] ReadSector(ulong sectorAddress)
{
return ReadSectors(sectorAddress, 1);
}
public override byte[] ReadSectors(ulong sectorAddress, uint length)
{
if(sectorAddress > ImageInfo.sectors - 1)
throw new ArgumentOutOfRangeException(nameof(sectorAddress), "Sector address not found");
if(sectorAddress + length > ImageInfo.sectors)
throw new ArgumentOutOfRangeException(nameof(length), "Requested more sectors than available");
MemoryStream buffer = new MemoryStream();
for(int i = 0; i < length; i++)
buffer.Write(sectorsData[(int)sectorAddress + i], 0, sectorsData[(int)sectorAddress + i].Length);
return buffer.ToArray();
}
#region Unsupported features
public override byte[] ReadDiskTag(MediaTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSector(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorLong(ulong sectorAddress)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override string GetMediaManufacturer()
{
return null;
}
public override string GetMediaModel()
{
return null;
}
public override string GetMediaSerialNumber()
{
return null;
}
public override string GetMediaBarcode()
{
return null;
}
public override string GetMediaPartNumber()
{
return null;
}
public override int GetMediaSequence()
{
return 0;
}
public override int GetLastDiskSequence()
{
return 0;
}
public override string GetDriveManufacturer()
{
return null;
}
public override string GetDriveModel()
{
return null;
}
public override string GetDriveSerialNumber()
{
return null;
}
public override List<Partition> GetPartitions()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetTracks()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetSessionTracks(Session session)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetSessionTracks(ushort session)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Session> GetSessions()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifySector(ulong sectorAddress)
{
return null;
}
public override bool? VerifySector(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{
FailingLBAs = new List<ulong>();
UnknownLBAs = new List<ulong>();
for(ulong i = 0; i < ImageInfo.sectors; i++)
UnknownLBAs.Add(i);
return null;
}
public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifyMediaImage()
{
return null;
}
#endregion
}
}