🎨Remove chains of if-else to get media type from it's geometry, plus add

a geometry class with a list of known geometries and ❤️LINQ❤️ queries.
This commit is contained in:
2017-12-28 04:57:26 +00:00
parent 6aba6d36e8
commit 741a3289a2
17 changed files with 1136 additions and 1529 deletions

View File

@@ -72,6 +72,7 @@
</e>
<e p="DiscImageChef.CommonTypes" t="IncludeRecursive">
<e p="DiscImageChef.CommonTypes.csproj" t="IncludeRecursive" />
<e p="Geometry.cs" t="Include" />
<e p="MediaType.cs" t="Include" />
<e p="MediaTypeFromSCSI.cs" t="Include" />
<e p="Partition.cs" t="Include" />
@@ -80,6 +81,7 @@
</e>
<e p="bin" t="ExcludeRecursive" />
<e p="obj" t="ExcludeRecursive" />
<e p="packages.config" t="Include" />
</e>
<e p="DiscImageChef.Console" t="IncludeRecursive">
<e p="DicConsole.cs" t="Include" />

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -32,8 +32,12 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51">
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Geometry.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Partition.cs" />
<Compile Include="MediaType.cs" />
@@ -44,6 +48,9 @@
<Link>LICENSE.LGPL</Link>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<MonoDevelop>

View File

@@ -0,0 +1,99 @@
using System.Linq;
namespace DiscImageChef.CommonTypes
{
public static class Geometry
{
static readonly (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding
encoding, bool variableSectorsPerTrack, MediaType type)[] KnownGeometries =
{
(32, 1, 8, 319, MediaEncoding.FM, false, MediaType.IBM23FD),
(35, 1, 9, 256, MediaEncoding.FM, false, MediaType.ECMA_66),
(35, 1, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32SS),
(35, 1, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33SS),
(35, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540),
(35, 2, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32DS),
(35, 2, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33DS),
(35, 2, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1571),
(40, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_8),
(40, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_9),
(40, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_40),
(40, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_40),
(40, 1, 18, 128, MediaEncoding.FM, false, MediaType.ATARI_525_SD),
(40, 1, 18, 256, MediaEncoding.MFM, false, MediaType.ATARI_525_DD),
(40, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540_Ext),
(40, 1, 26, 128, MediaEncoding.MFM, false, MediaType.ATARI_525_ED),
(40, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_8),
(40, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_9),
(40, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_70),
(70, 2, 9, 512, MediaEncoding.MFM, false, MediaType.Apricot_35),
(74, 1, 8, 512, MediaEncoding.FM, false, MediaType.IBM33FD_512),
(74, 1, 15, 256, MediaEncoding.FM, false, MediaType.IBM33FD_256),
(74, 1, 26, 128, MediaEncoding.FM, false, MediaType.IBM33FD_128),
(74, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.IBM53FD_1024),
(74, 2, 15, 256, MediaEncoding.FM, false, MediaType.IBM43FD_256),
(74, 2, 15, 512, MediaEncoding.MFM, false, MediaType.IBM53FD_512),
(74, 2, 26, 128, MediaEncoding.FM, false, MediaType.IBM43FD_128),
(74, 2, 26, 256, MediaEncoding.MFM, false, MediaType.IBM53FD_256),
(77, 1, 26, 128, MediaEncoding.FM, false, MediaType.RX01),
(77, 1, 26, 256, MediaEncoding.MFM, false, MediaType.RX02),
(77, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.NEC_525_HD),
(77, 2, 15, 512, MediaEncoding.MFM, false, MediaType.ECMA_99_15),
(77, 2, 26, 128, MediaEncoding.FM, false, MediaType.NEC_8_SD),
(77, 2, 26, 256, MediaEncoding.MFM, false, MediaType.RX03),
(80, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_8),
(80, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_9),
(80, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_80),
(80, 1, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonySS),
(80, 1, 10, 512, MediaEncoding.MFM, false, MediaType.RX50),
(80, 1, 11, 512, MediaEncoding.MFM, false, MediaType.ATARI_35_SS_DD_11),
(80, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_80),
(80, 2, 5, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_DD),
(80, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_8),
(80, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_9),
(80, 2, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonyDS),
(80, 2, 10, 512, MediaEncoding.MFM, false, MediaType.CBM_35_DD),
(80, 2, 10, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_HD),
(80, 2, 11, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_DD),
(80, 2, 15, 512, MediaEncoding.MFM, false, MediaType.DOS_525_HD),
(80, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_78),
(80, 2, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_DS_DD),
(80, 2, 18, 512, MediaEncoding.MFM, false, MediaType.DOS_35_HD),
(80, 2, 19, 512, MediaEncoding.MFM, false, MediaType.XDF_525),
(80, 2, 21, 512, MediaEncoding.MFM, false, MediaType.DMF),
(80, 2, 22, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_HD),
(80, 2, 23, 512, MediaEncoding.MFM, false, MediaType.XDF_35),
(80, 2, 36, 512, MediaEncoding.MFM, false, MediaType.DOS_35_ED),
(82, 2, 10, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_DD),
(82, 2, 17, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_525_HD),
(82, 2, 21, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_HD),
(240, 2, 38, 512, MediaEncoding.MFM, false, MediaType.NEC_35_TD),
(652, 2, 0, 512, MediaEncoding.MFM, false, MediaType.Floptical),
// Following ones are what the device itself report, not the physical geometry
(154, 16, 32, 512, MediaEncoding.MFM, false, MediaType.PocketZip),
(262, 32, 56, 512, MediaEncoding.MFM, false, MediaType.LS240),
(963, 8, 32, 512, MediaEncoding.MFM, false, MediaType.LS120),
(1021, 64, 32, 512, MediaEncoding.MFM, false, MediaType.Jaz),
(1024, 2, 32, 512, MediaEncoding.MFM, false, MediaType.FD32MB)
};
public static MediaType GetMediaType(
(ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding, bool
variableSectorsPerTrack) geometry)
{
return (from geom in KnownGeometries
where geom.cylinders == geometry.cylinders && geom.heads == geometry.heads &&
geom.sectorsPerTrack == geometry.sectorsPerTrack &&
geom.bytesPerSector == geometry.bytesPerSector &&
geom.encoding == geometry.encoding &&
geom.variableSectorsPerTrack == geometry.variableSectorsPerTrack
select geom.type).FirstOrDefault();
}
public static (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding
, bool variableSectorsPerTrack, MediaType type) GetGeometry(MediaType mediaType)
{
return (from geom in KnownGeometries where geom.type == mediaType select geom).FirstOrDefault();
}
}
}

View File

@@ -35,6 +35,16 @@
namespace DiscImageChef.CommonTypes
{
public enum MediaEncoding
{
Unknown,
FM,
MFM,
M2FM,
AppleGCR,
CommodoreGCR
}
/// <summary>
/// Contains an enumeration of all known types of media.
/// </summary>
@@ -293,9 +303,13 @@ namespace DiscImageChef.CommonTypes
#endregion Microsoft non standard floppy formats
#region IBM non standard floppy formats
/// <summary>
/// 5.25", DS, HD, 80 tracks, ? spt, ??? + ??? + ??? bytes/sector, MFM track 0 = ??15 sectors, 512
/// bytes/sector, falsified to DOS as 19 spt, 512 bps
/// </summary>
XDF_525,
/// <summary>
/// 3.5", DS, HD, 80 tracks, 4 spt, 8192 + 2048 + 1024 + 512 bytes/sector, MFMm track 0 = 19 sectors, 512
/// 3.5", DS, HD, 80 tracks, 4 spt, 8192 + 2048 + 1024 + 512 bytes/sector, MFM track 0 = 19 sectors, 512
/// bytes/sector, falsified to DOS as 23 spt, 512 bps
/// </summary>
XDF_35,

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.ValueTuple" version="4.4.0" targetFramework="net40" />
</packages>

View File

@@ -42,33 +42,33 @@ namespace DiscImageChef.DiscImages
{
public class Anex86 : IMediaImage
{
IFilter anexImageFilter;
IFilter anexImageFilter;
Anex86Header fdihdr;
ImageInfo imageInfo;
ImageInfo imageInfo;
public Anex86()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -76,7 +76,7 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "Anex86 Disk Image";
public Guid Id => new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7");
public Guid Id => new Guid("0410003E-6E7B-40E6-9328-BA5651ADF6B7");
public string ImageFormat => "Anex86 disk image";
@@ -102,19 +102,19 @@ namespace DiscImageChef.DiscImages
stream.Read(hdrB, 0, hdrB.Length);
GCHandle handle = GCHandle.Alloc(hdrB, GCHandleType.Pinned);
fdihdr = (Anex86Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Anex86Header));
fdihdr = (Anex86Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Anex86Header));
handle.Free();
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.unknown = {0}", fdihdr.unknown);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.hddtype = {0}", fdihdr.hddtype);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.hdrSize = {0}", fdihdr.hdrSize);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.dskSize = {0}", fdihdr.dskSize);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.bps = {0}", fdihdr.bps);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.spt = {0}", fdihdr.spt);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.heads = {0}", fdihdr.heads);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.unknown = {0}", fdihdr.unknown);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.hddtype = {0}", fdihdr.hddtype);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.hdrSize = {0}", fdihdr.hdrSize);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.dskSize = {0}", fdihdr.dskSize);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.bps = {0}", fdihdr.bps);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.spt = {0}", fdihdr.spt);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.heads = {0}", fdihdr.heads);
DicConsole.DebugWriteLine("Anex86 plugin", "fdihdr.cylinders = {0}", fdihdr.cylinders);
return stream.Length == fdihdr.hdrSize + fdihdr.dskSize &&
return stream.Length == fdihdr.hdrSize + fdihdr.dskSize &&
fdihdr.dskSize == fdihdr.bps * fdihdr.spt * fdihdr.heads * fdihdr.cylinders;
}
@@ -131,198 +131,26 @@ namespace DiscImageChef.DiscImages
stream.Read(hdrB, 0, hdrB.Length);
GCHandle handle = GCHandle.Alloc(hdrB, GCHandleType.Pinned);
fdihdr = (Anex86Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Anex86Header));
fdihdr = (Anex86Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Anex86Header));
handle.Free();
imageInfo.MediaType = MediaType.GENERIC_HDD;
switch(fdihdr.cylinders)
{
case 40:
switch(fdihdr.bps)
{
case 512:
switch(fdihdr.spt)
{
case 8:
switch(fdihdr.heads)
{
case 1:
imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
break;
case 2:
imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
break;
}
break;
case 9:
switch(fdihdr.heads)
{
case 1:
imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
break;
case 2:
imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
break;
}
break;
}
break;
}
break;
case 70:
switch(fdihdr.bps)
{
case 512:
switch(fdihdr.spt)
{
case 9:
if(fdihdr.heads == 1) imageInfo.MediaType = MediaType.Apricot_35;
break;
}
break;
}
break;
case 77:
switch(fdihdr.bps)
{
case 128:
switch(fdihdr.spt)
{
case 26:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_8_SD;
break;
}
break;
case 256:
switch(fdihdr.spt)
{
case 26:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_8_DD;
break;
}
break;
case 512:
switch(fdihdr.spt)
{
case 8:
if(fdihdr.heads == 1) imageInfo.MediaType = MediaType.Apricot_35;
break;
}
break;
case 1024:
switch(fdihdr.spt)
{
case 8:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_525_HD;
break;
}
break;
}
break;
case 80:
switch(fdihdr.bps)
{
case 256:
switch(fdihdr.spt)
{
case 16:
switch(fdihdr.heads)
{
case 1:
imageInfo.MediaType = MediaType.NEC_525_SS;
break;
case 2:
imageInfo.MediaType = MediaType.NEC_525_DS;
break;
}
break;
}
break;
case 512:
switch(fdihdr.spt)
{
case 8:
switch(fdihdr.heads)
{
case 1:
imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
break;
case 2:
imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
break;
}
break;
case 9:
switch(fdihdr.heads)
{
case 1:
imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
break;
case 2:
imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
break;
}
break;
case 15:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_35_HD_15;
break;
case 18:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.DOS_35_HD;
break;
case 36:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.DOS_35_ED;
break;
}
break;
}
break;
case 240:
switch(fdihdr.bps)
{
case 512:
switch(fdihdr.spt)
{
case 38:
if(fdihdr.heads == 2) imageInfo.MediaType = MediaType.NEC_35_TD;
break;
}
break;
}
break;
}
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)fdihdr.cylinders, (byte)fdihdr.heads, (ushort)fdihdr.spt,
(uint)fdihdr.bps, MediaEncoding.MFM, false));
if(imageInfo.MediaType == MediaType.Unknown) imageInfo.MediaType = MediaType.GENERIC_HDD;
DicConsole.DebugWriteLine("Anex86 plugin", "MediaType: {0}", imageInfo.MediaType);
imageInfo.ImageSize = (ulong)fdihdr.dskSize;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)fdihdr.dskSize;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = (ulong)(fdihdr.cylinders * fdihdr.heads * fdihdr.spt);
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
imageInfo.SectorSize = (uint)fdihdr.bps;
imageInfo.Cylinders = (uint)fdihdr.cylinders;
imageInfo.Heads = (uint)fdihdr.heads;
imageInfo.SectorsPerTrack = (uint)fdihdr.spt;
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = (ulong)(fdihdr.cylinders * fdihdr.heads * fdihdr.spt);
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
imageInfo.SectorSize = (uint)fdihdr.bps;
imageInfo.Cylinders = (uint)fdihdr.cylinders;
imageInfo.Heads = (uint)fdihdr.heads;
imageInfo.SectorsPerTrack = (uint)fdihdr.spt;
anexImageFilter = imageFilter;
@@ -429,7 +257,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -439,7 +267,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}

View File

@@ -63,25 +63,25 @@ namespace DiscImageChef.DiscImages
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -89,7 +89,7 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "ACT Apricot Disk Image";
public Guid Id => new Guid("43408CF3-6DB3-449F-A779-2B0E497C5B14");
public Guid Id => new Guid("43408CF3-6DB3-449F-A779-2B0E497C5B14");
public string ImageFormat => "ACT Apricot disk image";
@@ -124,9 +124,9 @@ namespace DiscImageChef.DiscImages
stream.Seek(signature.Length, SeekOrigin.Begin);
int totalCylinders = -1;
int totalHeads = -1;
int maxSector = -1;
int recordSize = Marshal.SizeOf(typeof(ApridiskRecord));
int totalHeads = -1;
int maxSector = -1;
int recordSize = Marshal.SizeOf(typeof(ApridiskRecord));
// Count cylinders
while(stream.Position < stream.Length)
@@ -134,7 +134,7 @@ namespace DiscImageChef.DiscImages
byte[] recB = new byte[recordSize];
stream.Read(recB, 0, recordSize);
GCHandle handle = GCHandle.Alloc(recB, GCHandleType.Pinned);
GCHandle handle = GCHandle.Alloc(recB, GCHandleType.Pinned);
ApridiskRecord record =
(ApridiskRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ApridiskRecord));
handle.Free();
@@ -176,8 +176,8 @@ namespace DiscImageChef.DiscImages
: "uncompressed");
if(record.cylinder > totalCylinders) totalCylinders = record.cylinder;
if(record.head > totalHeads) totalHeads = record.head;
if(record.sector > maxSector) maxSector = record.sector;
if(record.head > totalHeads) totalHeads = record.head;
if(record.sector > maxSector) maxSector = record.sector;
stream.Seek(record.headerSize - recordSize + record.dataSize, SeekOrigin.Current);
break;
@@ -198,7 +198,7 @@ namespace DiscImageChef.DiscImages
uint[][] spts = new uint[totalCylinders][];
imageInfo.Cylinders = (ushort)totalCylinders;
imageInfo.Heads = (byte)totalHeads;
imageInfo.Heads = (byte)totalHeads;
DicConsole.DebugWriteLine("Apridisk plugin",
"Found {0} cylinders and {1} heads with a maximum sector number of {2}",
@@ -208,7 +208,7 @@ namespace DiscImageChef.DiscImages
for(int i = 0; i < totalCylinders; i++)
{
sectorsData[i] = new byte[totalHeads][][];
spts[i] = new uint[totalHeads];
spts[i] = new uint[totalHeads];
for(int j = 0; j < totalHeads; j++) sectorsData[i][j] = new byte[maxSector + 1][];
}
@@ -224,7 +224,7 @@ namespace DiscImageChef.DiscImages
byte[] recB = new byte[recordSize];
stream.Read(recB, 0, recordSize);
GCHandle handle = GCHandle.Alloc(recB, GCHandleType.Pinned);
GCHandle handle = GCHandle.Alloc(recB, GCHandleType.Pinned);
ApridiskRecord record =
(ApridiskRecord)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ApridiskRecord));
handle.Free();
@@ -235,7 +235,7 @@ namespace DiscImageChef.DiscImages
case RecordType.Deleted:
case RecordType.Comment:
case RecordType.Creator:
stream.Seek(record.headerSize - recordSize + record.dataSize, SeekOrigin.Current);
stream.Seek(record.headerSize - recordSize + record.dataSize, SeekOrigin.Current);
headersizes += record.headerSize + record.dataSize;
break;
case RecordType.Sector:
@@ -248,7 +248,8 @@ namespace DiscImageChef.DiscImages
uint realLength = record.dataSize;
if(record.compression == CompressType.Compressed)
realLength = Decompress(data, out sectorsData[record.cylinder][record.head][record.sector]);
realLength =
Decompress(data, out sectorsData[record.cylinder][record.head][record.sector]);
else sectorsData[record.cylinder][record.head][record.sector] = data;
if(realLength < imageInfo.SectorSize) imageInfo.SectorSize = realLength;
@@ -266,7 +267,9 @@ namespace DiscImageChef.DiscImages
uint spt = uint.MaxValue;
for(ushort cyl = 0; cyl < imageInfo.Cylinders; cyl++)
{
for(ushort head = 0; head < imageInfo.Heads; head++) if(spts[cyl][head] < spt) spt = spts[cyl][head];
for(ushort head = 0; head < imageInfo.Heads; head++)
if(spts[cyl][head] < spt)
spt = spts[cyl][head];
}
imageInfo.SectorsPerTrack = spt;
@@ -274,19 +277,16 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("Apridisk plugin", "Found a minimum of {0} sectors per track",
imageInfo.SectorsPerTrack);
if(imageInfo.Cylinders == 70 && imageInfo.Heads == 1 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.Apricot_35;
else if(imageInfo.Cylinders == 80 && imageInfo.Heads == 1 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(imageInfo.Cylinders == 80 && imageInfo.Heads == 2 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, (byte)imageInfo.Heads,
(ushort)imageInfo.SectorsPerTrack, 512, MediaEncoding.MFM, false));
imageInfo.ImageSize = (ulong)stream.Length - headersizes;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)stream.Length - headersizes;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
/*
FileStream debugFs = new FileStream("debug.img", FileMode.CreateNew, FileAccess.Write);
@@ -298,30 +298,6 @@ namespace DiscImageChef.DiscImages
return true;
}
static uint Decompress(byte[] compressed, out byte[] decompressed)
{
int readp = 0;
int cLen = compressed.Length;
MemoryStream buffer = new MemoryStream();
uint uLen = 0;
while(cLen >= 3)
{
ushort blklen = BitConverter.ToUInt16(compressed, readp);
readp += 2;
for(int i = 0; i < blklen; i++) buffer.WriteByte(compressed[readp]);
uLen += blklen;
readp++;
cLen -= 3;
}
decompressed = buffer.ToArray();
return uLen;
}
public byte[] ReadSector(ulong sectorAddress)
{
(ushort cylinder, byte head, byte sector) = LbaToChs(sectorAddress);
@@ -356,15 +332,6 @@ namespace DiscImageChef.DiscImages
return buffer.ToArray();
}
(ushort cylinder, byte head, byte sector) LbaToChs(ulong lba)
{
ushort cylinder = (ushort)(lba / (imageInfo.Heads * imageInfo.SectorsPerTrack));
byte head = (byte)(lba / imageInfo.SectorsPerTrack % imageInfo.Heads);
byte sector = (byte)(lba % imageInfo.SectorsPerTrack + 1);
return (cylinder, head, sector);
}
public byte[] ReadDiskTag(MediaTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
@@ -441,7 +408,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -451,7 +418,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
@@ -461,10 +428,43 @@ namespace DiscImageChef.DiscImages
return null;
}
static uint Decompress(byte[] compressed, out byte[] decompressed)
{
int readp = 0;
int cLen = compressed.Length;
MemoryStream buffer = new MemoryStream();
uint uLen = 0;
while(cLen >= 3)
{
ushort blklen = BitConverter.ToUInt16(compressed, readp);
readp += 2;
for(int i = 0; i < blklen; i++) buffer.WriteByte(compressed[readp]);
uLen += blklen;
readp++;
cLen -= 3;
}
decompressed = buffer.ToArray();
return uLen;
}
(ushort cylinder, byte head, byte sector) LbaToChs(ulong lba)
{
ushort cylinder = (ushort)(lba / (imageInfo.Heads * imageInfo.SectorsPerTrack));
byte head = (byte)(lba / imageInfo.SectorsPerTrack % imageInfo.Heads);
byte sector = (byte)(lba % imageInfo.SectorsPerTrack + 1);
return (cylinder, head, sector);
}
enum RecordType : uint
{
Deleted = 0xE31D0000,
Sector = 0xE31D0001,
Sector = 0xE31D0001,
Comment = 0xE31D0002,
Creator = 0xE31D0003
}
@@ -472,19 +472,19 @@ namespace DiscImageChef.DiscImages
enum CompressType : ushort
{
Uncompresed = 0x9E90,
Compressed = 0x3E5A
Compressed = 0x3E5A
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct ApridiskRecord
{
public RecordType type;
public RecordType type;
public CompressType compression;
public ushort headerSize;
public uint dataSize;
public byte head;
public byte sector;
public ushort cylinder;
public ushort headerSize;
public uint dataSize;
public byte head;
public byte sector;
public ushort cylinder;
}
}
}

View File

@@ -43,17 +43,17 @@ namespace DiscImageChef.DiscImages
public class CopyQm : IMediaImage
{
const ushort COPYQM_MAGIC = 0x5143;
const byte COPYQM_MARK = 0x14;
const byte COPYQM_MARK = 0x14;
const byte COPYQM_FAT = 0;
const byte COPYQM_FAT = 0;
const byte COPYQM_BLIND = 1;
const byte COPYQM_HFS = 2;
const byte COPYQM_HFS = 2;
const byte COPYQM_525_DD = 1;
const byte COPYQM_525_HD = 2;
const byte COPYQM_35_DD = 3;
const byte COPYQM_35_HD = 4;
const byte COPYQM_35_ED = 6;
const byte COPYQM_35_DD = 3;
const byte COPYQM_35_HD = 4;
const byte COPYQM_35_ED = 6;
readonly uint[] copyQmCrcTable =
{
@@ -87,38 +87,38 @@ namespace DiscImageChef.DiscImages
0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
uint calculatedDataCrc;
byte[] decodedDisk;
uint calculatedDataCrc;
byte[] decodedDisk;
MemoryStream decodedImage;
CopyQmHeader header;
bool headerChecksumOk;
bool headerChecksumOk;
ImageInfo imageInfo;
public CopyQm()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -126,7 +126,7 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "Sydex CopyQM";
public Guid Id => new Guid("147E927D-3A92-4E0C-82CD-142F5A4FA76D");
public Guid Id => new Guid("147E927D-3A92-4E0C-82CD-142F5A4FA76D");
public string ImageFormat => "Sydex CopyQM";
@@ -161,46 +161,46 @@ namespace DiscImageChef.DiscImages
byte[] hdr = new byte[133];
stream.Read(hdr, 0, 133);
header = new CopyQmHeader();
header = new CopyQmHeader();
IntPtr hdrPtr = Marshal.AllocHGlobal(133);
Marshal.Copy(hdr, 0, hdrPtr, 133);
header = (CopyQmHeader)Marshal.PtrToStructure(hdrPtr, typeof(CopyQmHeader));
Marshal.FreeHGlobal(hdrPtr);
DicConsole.DebugWriteLine("CopyQM plugin", "header.magic = 0x{0:X4}", header.magic);
DicConsole.DebugWriteLine("CopyQM plugin", "header.mark = 0x{0:X2}", header.mark);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorSize = {0}", header.sectorSize);
DicConsole.DebugWriteLine("CopyQM plugin", "header.magic = 0x{0:X4}", header.magic);
DicConsole.DebugWriteLine("CopyQM plugin", "header.mark = 0x{0:X2}", header.mark);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorSize = {0}", header.sectorSize);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorPerCluster = {0}", header.sectorPerCluster);
DicConsole.DebugWriteLine("CopyQM plugin", "header.reservedSectors = {0}", header.reservedSectors);
DicConsole.DebugWriteLine("CopyQM plugin", "header.fatCopy = {0}", header.fatCopy);
DicConsole.DebugWriteLine("CopyQM plugin", "header.rootEntries = {0}", header.rootEntries);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectors = {0}", header.sectors);
DicConsole.DebugWriteLine("CopyQM plugin", "header.mediaType = 0x{0:X2}", header.mediaType);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerFat = {0}", header.sectorsPerFat);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerTrack = {0}", header.sectorsPerTrack);
DicConsole.DebugWriteLine("CopyQM plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("CopyQM plugin", "header.hidden = {0}", header.hidden);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsBig = {0}", header.sectorsBig);
DicConsole.DebugWriteLine("CopyQM plugin", "header.description = {0}", header.description);
DicConsole.DebugWriteLine("CopyQM plugin", "header.blind = {0}", header.blind);
DicConsole.DebugWriteLine("CopyQM plugin", "header.density = {0}", header.density);
DicConsole.DebugWriteLine("CopyQM plugin", "header.imageCylinders = {0}", header.imageCylinders);
DicConsole.DebugWriteLine("CopyQM plugin", "header.totalCylinders = {0}", header.totalCylinders);
DicConsole.DebugWriteLine("CopyQM plugin", "header.crc = 0x{0:X8}", header.crc);
DicConsole.DebugWriteLine("CopyQM plugin", "header.volumeLabel = {0}", header.volumeLabel);
DicConsole.DebugWriteLine("CopyQM plugin", "header.time = 0x{0:X4}", header.time);
DicConsole.DebugWriteLine("CopyQM plugin", "header.date = 0x{0:X4}", header.date);
DicConsole.DebugWriteLine("CopyQM plugin", "header.commentLength = {0}", header.commentLength);
DicConsole.DebugWriteLine("CopyQM plugin", "header.secbs = {0}", header.secbs);
DicConsole.DebugWriteLine("CopyQM plugin", "header.unknown = 0x{0:X4}", header.unknown);
DicConsole.DebugWriteLine("CopyQM plugin", "header.interleave = {0}", header.interleave);
DicConsole.DebugWriteLine("CopyQM plugin", "header.skew = {0}", header.skew);
DicConsole.DebugWriteLine("CopyQM plugin", "header.drive = {0}", header.drive);
DicConsole.DebugWriteLine("CopyQM plugin", "header.reservedSectors = {0}", header.reservedSectors);
DicConsole.DebugWriteLine("CopyQM plugin", "header.fatCopy = {0}", header.fatCopy);
DicConsole.DebugWriteLine("CopyQM plugin", "header.rootEntries = {0}", header.rootEntries);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectors = {0}", header.sectors);
DicConsole.DebugWriteLine("CopyQM plugin", "header.mediaType = 0x{0:X2}", header.mediaType);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerFat = {0}", header.sectorsPerFat);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsPerTrack = {0}", header.sectorsPerTrack);
DicConsole.DebugWriteLine("CopyQM plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("CopyQM plugin", "header.hidden = {0}", header.hidden);
DicConsole.DebugWriteLine("CopyQM plugin", "header.sectorsBig = {0}", header.sectorsBig);
DicConsole.DebugWriteLine("CopyQM plugin", "header.description = {0}", header.description);
DicConsole.DebugWriteLine("CopyQM plugin", "header.blind = {0}", header.blind);
DicConsole.DebugWriteLine("CopyQM plugin", "header.density = {0}", header.density);
DicConsole.DebugWriteLine("CopyQM plugin", "header.imageCylinders = {0}", header.imageCylinders);
DicConsole.DebugWriteLine("CopyQM plugin", "header.totalCylinders = {0}", header.totalCylinders);
DicConsole.DebugWriteLine("CopyQM plugin", "header.crc = 0x{0:X8}", header.crc);
DicConsole.DebugWriteLine("CopyQM plugin", "header.volumeLabel = {0}", header.volumeLabel);
DicConsole.DebugWriteLine("CopyQM plugin", "header.time = 0x{0:X4}", header.time);
DicConsole.DebugWriteLine("CopyQM plugin", "header.date = 0x{0:X4}", header.date);
DicConsole.DebugWriteLine("CopyQM plugin", "header.commentLength = {0}", header.commentLength);
DicConsole.DebugWriteLine("CopyQM plugin", "header.secbs = {0}", header.secbs);
DicConsole.DebugWriteLine("CopyQM plugin", "header.unknown = 0x{0:X4}", header.unknown);
DicConsole.DebugWriteLine("CopyQM plugin", "header.interleave = {0}", header.interleave);
DicConsole.DebugWriteLine("CopyQM plugin", "header.skew = {0}", header.skew);
DicConsole.DebugWriteLine("CopyQM plugin", "header.drive = {0}", header.drive);
byte[] cmt = new byte[header.commentLength];
stream.Read(cmt, 0, header.commentLength);
imageInfo.Comments = StringHandlers.CToString(cmt);
decodedImage = new MemoryStream();
decodedImage = new MemoryStream();
calculatedDataCrc = 0;
@@ -213,7 +213,7 @@ namespace DiscImageChef.DiscImages
if(runLength < 0)
{
byte repeatedByte = (byte)stream.ReadByte();
byte repeatedByte = (byte)stream.ReadByte();
byte[] repeatedArray = new byte[runLength * -1];
ArrayHelpers.ArrayFill(repeatedArray, repeatedByte);
@@ -253,7 +253,7 @@ namespace DiscImageChef.DiscImages
debugStream.Close();
*/
int sum = 0;
int sum = 0;
for(int i = 0; i < hdr.Length - 1; i++) sum += hdr[i];
headerChecksumOk = ((-1 * sum) & 0xFF) == header.headerChecksum;
@@ -263,90 +263,33 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("CopyQM plugin", "Calculated data CRC = 0x{0:X8}, {1}", calculatedDataCrc,
calculatedDataCrc == header.crc);
imageInfo.Application = "CopyQM";
imageInfo.CreationTime = DateHandlers.DosToDateTime(header.date, header.time);
imageInfo.Application = "CopyQM";
imageInfo.CreationTime = DateHandlers.DosToDateTime(header.date, header.time);
imageInfo.LastModificationTime = imageInfo.CreationTime;
imageInfo.MediaTitle = header.volumeLabel;
imageInfo.ImageSize = (ulong)(stream.Length - 133 - header.commentLength);
imageInfo.Sectors = (ulong)sectors;
imageInfo.SectorSize = header.sectorSize;
imageInfo.MediaTitle = header.volumeLabel;
imageInfo.ImageSize = (ulong)(stream.Length - 133 - header.commentLength);
imageInfo.Sectors = (ulong)sectors;
imageInfo.SectorSize = header.sectorSize;
switch(header.drive)
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)header.totalCylinders, (byte)header.heads, header.sectorsPerTrack,
(uint)header.sectorSize, MediaEncoding.MFM, false));
switch(imageInfo.MediaType)
{
case COPYQM_525_HD:
if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 15 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 16 &&
header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 16 &&
header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 10 &&
header.sectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
header.sectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
else if(header.heads == 2 && header.totalCylinders == 77 && header.sectorsPerTrack == 8 &&
header.sectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_525;
else goto case COPYQM_525_DD;
case MediaType.NEC_525_HD when header.drive == COPYQM_35_HD ||header.drive == COPYQM_35_ED:
imageInfo.MediaType = MediaType.NEC_35_HD_8;
break;
case COPYQM_525_DD:
if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 8 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 9 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
else if(header.heads == 2 && header.totalCylinders == 40 && header.sectorsPerTrack == 8 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
else if(header.heads == 2 && header.totalCylinders == 40 && header.sectorsPerTrack == 9 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 18 &&
header.sectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 26 &&
header.sectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
else if(header.heads == 1 && header.totalCylinders == 40 && header.sectorsPerTrack == 18 &&
header.sectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
else imageInfo.MediaType = MediaType.Unknown;
case MediaType.DOS_525_HD when header.drive == COPYQM_35_HD ||header.drive == COPYQM_35_ED:
imageInfo.MediaType = MediaType.NEC_35_HD_15;
break;
case COPYQM_35_ED:
if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 36 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
else goto case COPYQM_35_HD;
break;
case COPYQM_35_HD:
if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 18 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 21 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DMF;
else if(header.heads == 2 && header.totalCylinders == 82 && header.sectorsPerTrack == 21 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
header.sectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 15 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
else goto case COPYQM_35_DD;
break;
case COPYQM_35_DD:
if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 9 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 9 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(header.heads == 1 && header.totalCylinders == 80 && header.sectorsPerTrack == 8 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
else if(header.heads == 2 && header.totalCylinders == 80 && header.sectorsPerTrack == 5 &&
header.sectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
else if(header.heads == 2 && header.totalCylinders == 77 && header.sectorsPerTrack == 8 &&
header.sectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_35;
else if(header.heads == 1 && header.totalCylinders == 70 && header.sectorsPerTrack == 9 &&
header.sectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
else imageInfo.MediaType = MediaType.Unknown;
break;
default:
imageInfo.MediaType = MediaType.Unknown;
case MediaType.RX50 when header.drive == COPYQM_525_DD || header.drive == COPYQM_525_HD:
imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
break;
}
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
decodedDisk = decodedImage.ToArray();
decodedDisk = decodedImage.ToArray();
decodedImage.Close();
@@ -354,8 +297,8 @@ namespace DiscImageChef.DiscImages
if(!string.IsNullOrEmpty(imageInfo.Comments))
DicConsole.VerboseWriteLine("CopyQM comments: {0}", imageInfo.Comments);
imageInfo.Heads = header.heads;
imageInfo.Cylinders = header.imageCylinders;
imageInfo.Heads = header.heads;
imageInfo.Cylinders = header.totalCylinders;
imageInfo.SectorsPerTrack = header.sectorsPerTrack;
return true;
@@ -372,7 +315,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -383,7 +326,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -414,7 +357,7 @@ namespace DiscImageChef.DiscImages
byte[] buffer = new byte[length * imageInfo.SectorSize];
Array.Copy(decodedDisk, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
length * imageInfo.SectorSize);
length * imageInfo.SectorSize);
return buffer;
}
@@ -516,7 +459,8 @@ namespace DiscImageChef.DiscImages
/// <summary>0x18 Sectors on disk (part of FAT's BPB)</summary>
public uint sectorsBig;
/// <summary>0x1C Description</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 60)] public string description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 60)]
public string description;
/// <summary>0x58 Blind mode. 0 = DOS, 1 = blind, 2 = HFS</summary>
public byte blind;
/// <summary>0x59 Density. 0 = Double, 1 = High, 2 = Quad/Extra</summary>
@@ -528,7 +472,8 @@ namespace DiscImageChef.DiscImages
/// <summary>0x5C CRC32 of data</summary>
public uint crc;
/// <summary>0x60 DOS volume label</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] public string volumeLabel;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string volumeLabel;
/// <summary>0x6B Modification time</summary>
public ushort time;
/// <summary>0x6D Modification date</summary>
@@ -546,7 +491,8 @@ namespace DiscImageChef.DiscImages
/// <summary>0x76 Source drive type. 1 = 5.25" DD, 2 = 5.25" HD, 3 = 3.5" DD, 4 = 3.5" HD, 6 = 3.5" ED</summary>
public byte drive;
/// <summary>0x77 Filling bytes</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public byte[] fill;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
public byte[] fill;
/// <summary>0x84 Header checksum</summary>
public byte headerChecksum;
}

View File

@@ -45,12 +45,13 @@ namespace DiscImageChef.DiscImages
{
// Information from Quasi88's FORMAT.TXT file
// Japanese comments copied from there
// TODO: Solve media types
public class D88 : IMediaImage
{
const byte READ_ONLY = 0x10;
readonly byte[] reservedEmpty = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
ImageInfo imageInfo;
ImageInfo imageInfo;
List<byte[]> sectorsData;
@@ -58,31 +59,31 @@ namespace DiscImageChef.DiscImages
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
public string Name => "D88 Disk Image";
public Guid Id => new Guid("669EDC77-EC41-4720-A88C-49C38CFFBAA0");
public string Name => "D88 Disk Image";
public Guid Id => new Guid("669EDC77-EC41-4720-A88C-49C38CFFBAA0");
public ImageInfo Info => imageInfo;
public string ImageFormat => "D88 disk image";
@@ -111,7 +112,7 @@ namespace DiscImageChef.DiscImages
stream.Read(hdrB, 0, hdrB.Length);
GCHandle handle = GCHandle.Alloc(hdrB, GCHandleType.Pinned);
d88Hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
d88Hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
handle.Free();
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.name = \"{0}\"",
@@ -158,7 +159,7 @@ namespace DiscImageChef.DiscImages
stream.Read(hdrB, 0, hdrB.Length);
GCHandle handle = GCHandle.Alloc(hdrB, GCHandleType.Pinned);
d88Hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
d88Hdr = (D88Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D88Header));
handle.Free();
DicConsole.DebugWriteLine("D88 plugin", "d88hdr.name = \"{0}\"",
@@ -190,7 +191,7 @@ namespace DiscImageChef.DiscImages
if(trkCounter == 0) return false;
SectorHeader sechdr = new SectorHeader();
hdrB = new byte[Marshal.SizeOf(sechdr)];
hdrB = new byte[Marshal.SizeOf(sechdr)];
stream.Seek(d88Hdr.track_table[0], SeekOrigin.Begin);
stream.Read(hdrB, 0, hdrB.Length);
@@ -198,20 +199,20 @@ namespace DiscImageChef.DiscImages
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.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.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[]>();
short spt = sechdr.spt;
IBMSectorSizeCode bps = sechdr.n;
bool allEqual = true;
sectorsData = new List<byte[]>();
for(int i = 0; i < trkCounter; i++)
{
@@ -231,7 +232,7 @@ namespace DiscImageChef.DiscImages
allEqual = false;
}
short maxJ = sechdr.spt;
short maxJ = sechdr.spt;
byte[] secB;
for(short j = 1; j < maxJ; j++)
{
@@ -345,81 +346,81 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("D88 plugin", "MediaType: {0}", imageInfo.MediaType);
imageInfo.ImageSize = (ulong)d88Hdr.disk_size;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)d88Hdr.disk_size;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = (ulong)sectorsData.Count;
imageInfo.Comments = StringHandlers.CToString(d88Hdr.name, shiftjis);
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
imageInfo.SectorSize = (uint)(128 << (int)bps);
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Sectors = (ulong)sectorsData.Count;
imageInfo.Comments = 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.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.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.NEC_525_DS:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.NEC_525_HD:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.DOS_525_SS_DD_8:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.DOS_525_SS_DD_9:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.DOS_525_DS_DD_8:
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.DOS_525_DS_DD_9:
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.NEC_35_HD_15:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.DOS_35_DS_DD_9:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.DOS_35_HD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 18;
break;
case MediaType.DOS_35_ED:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 36;
break;
case MediaType.NEC_35_TD:
imageInfo.Cylinders = 240;
imageInfo.Heads = 2;
imageInfo.Cylinders = 240;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 38;
break;
}
@@ -523,7 +524,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -533,7 +534,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
@@ -545,7 +546,7 @@ namespace DiscImageChef.DiscImages
enum DiskType : byte
{
D2 = 0x00,
D2 = 0x00,
Dd2 = 0x10,
Hd2 = 0x20
}
@@ -553,7 +554,7 @@ namespace DiscImageChef.DiscImages
enum DensityType : byte
{
Mfm = 0x00,
Fm = 0x40
Fm = 0x40
}
/// <summary>
@@ -601,12 +602,14 @@ namespace DiscImageChef.DiscImages
/// Disk name, nul-terminated ASCII
/// ディスクの名前(ASCII + '\0')
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] public byte[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public byte[] name;
/// <summary>
/// Reserved
/// ディスクの名前(ASCII + '\0')
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
public byte[] reserved;
/// <summary>
/// Write protect status
/// ライトプロテクト: 0x00 なし、0x10 あり
@@ -626,7 +629,8 @@ namespace DiscImageChef.DiscImages
/// Track pointers
/// トラック部のオフセットテーブル 0 Track 163 Track
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 164)] public int[] track_table;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 164)]
public int[] track_table;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
@@ -676,7 +680,8 @@ namespace DiscImageChef.DiscImages
/// Reserved
/// リザーブ
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] reserved;
/// <summary>
/// Size of data following this field
/// このセクタ部のデータサイズ

View File

@@ -57,23 +57,23 @@ namespace DiscImageChef.DiscImages
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "DiskCopy",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "DiskCopy",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -81,7 +81,7 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "Digital Research DiskCopy";
public Guid Id => new Guid("9F0BE551-8BAB-4038-8B5A-691F1BF5FFF3");
public Guid Id => new Guid("9F0BE551-8BAB-4038-8B5A-691F1BF5FFF3");
public string ImageFormat => "Digital Research DiskCopy";
@@ -112,21 +112,21 @@ namespace DiscImageChef.DiscImages
string sig = StringHandlers.CToString(tmpFooter.signature);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.signature = \"{0}\"", sig);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.five = {0}", tmpFooter.bpb.five);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.five = {0}", tmpFooter.bpb.five);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.driveCode = {0}", tmpFooter.bpb.driveCode);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.unknown = {0}", tmpFooter.bpb.unknown);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.unknown = {0}", tmpFooter.bpb.unknown);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.cylinders = {0}", tmpFooter.bpb.cylinders);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.unknown2 = {0}", tmpFooter.bpb.unknown2);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.bps = {0}", tmpFooter.bpb.bps);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.spc = {0}", tmpFooter.bpb.spc);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.rsectors = {0}", tmpFooter.bpb.rsectors);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.fats_no = {0}", tmpFooter.bpb.fats_no);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.sectors = {0}", tmpFooter.bpb.sectors);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.unknown2 = {0}", tmpFooter.bpb.unknown2);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.bps = {0}", tmpFooter.bpb.bps);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.spc = {0}", tmpFooter.bpb.spc);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.rsectors = {0}", tmpFooter.bpb.rsectors);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.fats_no = {0}", tmpFooter.bpb.fats_no);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.sectors = {0}", tmpFooter.bpb.sectors);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.media_descriptor = {0}",
tmpFooter.bpb.media_descriptor);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.spfat = {0}", tmpFooter.bpb.spfat);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.sptrack = {0}", tmpFooter.bpb.sptrack);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.heads = {0}", tmpFooter.bpb.heads);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.spfat = {0}", tmpFooter.bpb.spfat);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.sptrack = {0}", tmpFooter.bpb.sptrack);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.heads = {0}", tmpFooter.bpb.heads);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.hsectors = {0}", tmpFooter.bpb.hsectors);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.drive_no = {0}", tmpFooter.bpb.drive_no);
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "tmp_footer.bpb.unknown3 = {0}", tmpFooter.bpb.unknown3);
@@ -159,7 +159,7 @@ namespace DiscImageChef.DiscImages
stream.Seek(-buffer.Length, SeekOrigin.End);
stream.Read(buffer, 0, buffer.Length);
footer = new DriFooter();
footer = new DriFooter();
IntPtr ftrPtr = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, ftrPtr, buffer.Length);
footer = (DriFooter)Marshal.PtrToStructure(ftrPtr, typeof(DriFooter));
@@ -176,98 +176,51 @@ namespace DiscImageChef.DiscImages
if(footer.bpb.sectors * footer.bpb.bps + Marshal.SizeOf(footer) != stream.Length) return false;
imageInfo.Cylinders = footer.bpb.cylinders;
imageInfo.Heads = footer.bpb.heads;
imageInfo.SectorsPerTrack = footer.bpb.sptrack;
imageInfo.Sectors = footer.bpb.sectors;
imageInfo.SectorSize = footer.bpb.bps;
imageInfo.Cylinders = footer.bpb.cylinders;
imageInfo.Heads = footer.bpb.heads;
imageInfo.SectorsPerTrack = footer.bpb.sptrack;
imageInfo.Sectors = footer.bpb.sectors;
imageInfo.SectorSize = footer.bpb.bps;
imageInfo.ApplicationVersion = matchSignature.Groups["version"].Value;
driImageFilter = imageFilter;
imageInfo.ImageSize = (ulong)(stream.Length - Marshal.SizeOf(footer));
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)(stream.Length - Marshal.SizeOf(footer));
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
DicConsole.DebugWriteLine("DRI DiskCopy plugin", "Image application = {0} version {1}",
imageInfo.Application, imageInfo.ApplicationVersion);
// Correct some incorrect data in images of NEC 2HD disks
if(imageInfo.Cylinders == 77 && imageInfo.Heads == 2 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 512 &&
(footer.bpb.driveCode == DriDriveCodes.md2hd || footer.bpb.driveCode == DriDriveCodes.mf2hd))
if(imageInfo.Cylinders == 77 && imageInfo.Heads == 2 &&
imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 512 &&
(footer.bpb.driveCode == DriDriveCodes.md2hd ||
footer.bpb.driveCode == DriDriveCodes.mf2hd))
{
imageInfo.SectorsPerTrack = 8;
imageInfo.SectorSize = 1024;
imageInfo.SectorSize = 1024;
}
switch(footer.bpb.driveCode)
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, (byte)imageInfo.Heads,
(ushort)imageInfo.SectorsPerTrack, imageInfo.SectorSize, MediaEncoding.MFM, false
));
switch(imageInfo.MediaType)
{
case DriDriveCodes.md2hd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
else goto case DriDriveCodes.md2dd;
case MediaType.NEC_525_HD when footer.bpb.driveCode == DriDriveCodes.mf2hd ||
footer.bpb.driveCode == DriDriveCodes.mf2ed:
imageInfo.MediaType = MediaType.NEC_35_HD_8;
break;
case DriDriveCodes.md2dd:
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
else imageInfo.MediaType = MediaType.Unknown;
case MediaType.DOS_525_HD when footer.bpb.driveCode == DriDriveCodes.mf2hd ||
footer.bpb.driveCode == DriDriveCodes.mf2ed:
imageInfo.MediaType = MediaType.NEC_35_HD_15;
break;
case DriDriveCodes.mf2ed:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
else goto case DriDriveCodes.mf2hd;
break;
case DriDriveCodes.mf2hd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
else goto case DriDriveCodes.mf2dd;
break;
case DriDriveCodes.mf2dd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
else imageInfo.MediaType = MediaType.Unknown;
break;
default:
imageInfo.MediaType = MediaType.Unknown;
case MediaType.RX50 when footer.bpb.driveCode == DriDriveCodes.md2dd ||
footer.bpb.driveCode == DriDriveCodes.md2hd:
imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
break;
}
@@ -289,7 +242,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -300,7 +253,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -336,7 +289,7 @@ namespace DiscImageChef.DiscImages
byte[] buffer = new byte[length * imageInfo.SectorSize];
Stream stream = driImageFilter.GetDataForkStream();
stream.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
stream.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
return buffer;
@@ -406,7 +359,8 @@ namespace DiscImageChef.DiscImages
struct DriFooter
{
/// <summary>Signature: "DiskImage 2.01 (C) 1990,1991 Digital Research Inc\0"</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 51)] public byte[] signature;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 51)]
public byte[] signature;
/// <summary>Information about the disk image, mostly imitates FAT BPB</summary>
public DriBpb bpb;
/// <summary>Information about the disk image, mostly imitates FAT BPB, copy</summary>
@@ -457,7 +411,8 @@ namespace DiscImageChef.DiscImages
/// <summary>Sectors per track (again?)</summary>
public ushort sptrack2;
/// <summary>Seems to be 0</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 144)] public byte[] unknown5;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 144)]
public byte[] unknown5;
}
/// <summary>

View File

@@ -66,7 +66,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using DiscImageChef.CommonTypes;
using DiscImageChef.Console;
@@ -76,17 +75,6 @@ namespace DiscImageChef.DiscImages
{
public class HdCopy : IMediaImage
{
readonly MediaTypeTableEntry[] mediaTypes =
{
new MediaTypeTableEntry {Tracks = 80, SectorsPerTrack = 8, MediaType = MediaType.DOS_35_DS_DD_8},
new MediaTypeTableEntry {Tracks = 80, SectorsPerTrack = 9, MediaType = MediaType.DOS_35_DS_DD_9},
new MediaTypeTableEntry {Tracks = 80, SectorsPerTrack = 18, MediaType = MediaType.DOS_35_HD},
new MediaTypeTableEntry {Tracks = 80, SectorsPerTrack = 36, MediaType = MediaType.DOS_35_ED},
new MediaTypeTableEntry {Tracks = 40, SectorsPerTrack = 8, MediaType = MediaType.DOS_525_DS_DD_8},
new MediaTypeTableEntry {Tracks = 40, SectorsPerTrack = 9, MediaType = MediaType.DOS_525_DS_DD_9},
new MediaTypeTableEntry {Tracks = 80, SectorsPerTrack = 15, MediaType = MediaType.DOS_525_HD}
};
/// <summary>
/// The HDCP file header after the image has been opened
/// </summary>
@@ -95,7 +83,7 @@ namespace DiscImageChef.DiscImages
/// <summary>
/// The ImageFilter we're reading from, after the file has been opened
/// </summary>
IFilter hdcpImageFilter;
IFilter hdcpImageFilter;
ImageInfo imageInfo;
/// <summary>
@@ -112,25 +100,25 @@ namespace DiscImageChef.DiscImages
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -138,10 +126,10 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "HD-Copy disk image";
public Guid Id => new Guid("8D57483F-71A5-42EC-9B87-66AEC439C792");
public Guid Id => new Guid("8D57483F-71A5-42EC-9B87-66AEC439C792");
public string ImageFormat => "HD-Copy image";
public List<Partition> Partitions =>
public string ImageFormat => "HD-Copy image";
public List<Partition> Partitions =>
throw new FeatureUnsupportedImageException("Feature not supported by image format");
public List<Track> Tracks =>
@@ -158,10 +146,10 @@ namespace DiscImageChef.DiscImages
if(stream.Length < 2 + 2 * 82) return false;
byte[] header = new byte[2 + 2 * 82];
stream.Read(header, 0, 2 + 2 * 82);
stream.Read(header, 0, 2 + 2 * 82);
IntPtr hdrPtr = Marshal.AllocHGlobal(2 + 2 * 82);
Marshal.Copy(header, 0, hdrPtr, 2 + 2 * 82);
Marshal.Copy(header, 0, hdrPtr, 2 + 2 * 82);
HdcpFileHeader fheader = (HdcpFileHeader)Marshal.PtrToStructure(hdrPtr, typeof(HdcpFileHeader));
Marshal.FreeHGlobal(hdrPtr);
@@ -177,7 +165,9 @@ namespace DiscImageChef.DiscImages
if(fheader.trackMap[0] != 1 || fheader.trackMap[1] != 1) return false;
// all other tracks must be either present (=1) or absent (=0)
for(int i = 0; i < 2 * 82; i++) if(fheader.trackMap[i] > 1) return false;
for(int i = 0; i < 2 * 82; i++)
if(fheader.trackMap[i] > 1)
return false;
// TODO: validate the tracks
// For now, having a valid header should be sufficient.
@@ -186,54 +176,51 @@ namespace DiscImageChef.DiscImages
public bool OpenImage(IFilter imageFilter)
{
long currentOffset;
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
byte[] header = new byte[2 + 2 * 82];
stream.Read(header, 0, 2 + 2 * 82);
stream.Read(header, 0, 2 + 2 * 82);
IntPtr hdrPtr = Marshal.AllocHGlobal(2 + 2 * 82);
Marshal.Copy(header, 0, hdrPtr, 2 + 2 * 82);
Marshal.Copy(header, 0, hdrPtr, 2 + 2 * 82);
HdcpFileHeader fheader = (HdcpFileHeader)Marshal.PtrToStructure(hdrPtr, typeof(HdcpFileHeader));
Marshal.FreeHGlobal(hdrPtr);
DicConsole.DebugWriteLine("HDCP plugin",
"Detected HD-Copy image with {0} tracks and {1} sectors per track.",
fheader.lastCylinder + 1, fheader.sectorsPerTrack);
imageInfo.Cylinders = (uint)fheader.lastCylinder + 1;
imageInfo.Cylinders = (uint)fheader.lastCylinder + 1;
imageInfo.SectorsPerTrack = fheader.sectorsPerTrack;
imageInfo.SectorSize = 512; // only 512 bytes per sector supported
imageInfo.Heads = 2; // only 2-sided floppies are supported
imageInfo.Sectors = 2 * imageInfo.Cylinders * imageInfo.SectorsPerTrack;
imageInfo.ImageSize = imageInfo.Sectors * imageInfo.SectorSize;
imageInfo.SectorSize = 512; // only 512 bytes per sector supported
imageInfo.Heads = 2; // only 2-sided floppies are supported
imageInfo.Sectors = 2 * imageInfo.Cylinders * imageInfo.SectorsPerTrack;
imageInfo.ImageSize = imageInfo.Sectors * imageInfo.SectorSize;
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.MediaType =
(from ent in mediaTypes
where ent.Tracks == imageInfo.Cylinders && ent.SectorsPerTrack == imageInfo.SectorsPerTrack
select ent.MediaType).FirstOrDefault();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, 2, (ushort)imageInfo.SectorsPerTrack, 512,
MediaEncoding.MFM, false));
// the start offset of the track data
currentOffset = 2 + 2 * 82;
long currentOffset = 2 + 2 * 82;
// build table of track offsets
for(int i = 0; i < imageInfo.Cylinders * 2; i++)
if(fheader.trackMap[i] == 0) trackOffset[i] = -1;
for(int i = 0; i < imageInfo.Cylinders * 2; i++)
if(fheader.trackMap[i] == 0)
trackOffset[i] = -1;
else
{
// track is present, read the block header
if(currentOffset + 3 >= stream.Length) return false;
byte[] blkHeader = new byte[2];
short blkLength;
stream.Read(blkHeader, 0, 2);
blkLength = BitConverter.ToInt16(blkHeader, 0);
short blkLength = BitConverter.ToInt16(blkHeader, 0);
// assume block sizes are positive
if(blkLength < 0) return false;
@@ -251,57 +238,14 @@ namespace DiscImageChef.DiscImages
if(currentOffset > stream.Length) return false;
// save some variables for later use
fileHeader = fheader;
fileHeader = fheader;
hdcpImageFilter = imageFilter;
return true;
}
void ReadTrackIntoCache(Stream stream, int tracknum)
{
byte[] trackData = new byte[imageInfo.SectorSize * imageInfo.SectorsPerTrack];
byte[] blkHeader = new byte[3];
byte escapeByte;
short compressedLength;
// check that track is present
if(trackOffset[tracknum] == -1)
throw new InvalidDataException("Tried reading a track that is not present in image");
stream.Seek(trackOffset[tracknum], SeekOrigin.Begin);
// read the compressed track data
stream.Read(blkHeader, 0, 3);
compressedLength = (short)(BitConverter.ToInt16(blkHeader, 0) - 1);
escapeByte = blkHeader[2];
byte[] cBuffer = new byte[compressedLength];
stream.Read(cBuffer, 0, compressedLength);
// decompress the data
int sIndex = 0; // source buffer position
int dIndex = 0; // destination buffer position
while(sIndex < compressedLength)
if(cBuffer[sIndex] == escapeByte)
{
sIndex++; // skip over escape byte
byte fillByte = cBuffer[sIndex++];
byte fillCount = cBuffer[sIndex++];
// fill destination buffer
for(int i = 0; i < fillCount; i++) trackData[dIndex++] = fillByte;
}
else trackData[dIndex++] = cBuffer[sIndex++];
// check that the number of bytes decompressed matches a whole track
if(dIndex != imageInfo.SectorSize * imageInfo.SectorsPerTrack)
throw new InvalidDataException("Track decompression yielded incomplete data");
// store track in cache
trackCache[tracknum] = trackData;
}
public byte[] ReadSector(ulong sectorAddress)
{
int trackNum = (int)(sectorAddress / imageInfo.SectorsPerTrack);
int trackNum = (int)(sectorAddress / imageInfo.SectorsPerTrack);
int sectorOffset = (int)(sectorAddress % (imageInfo.SectorsPerTrack * imageInfo.SectorSize));
if(sectorAddress > imageInfo.Sectors - 1)
@@ -412,7 +356,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -422,7 +366,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
@@ -432,6 +376,48 @@ namespace DiscImageChef.DiscImages
return null;
}
void ReadTrackIntoCache(Stream stream, int tracknum)
{
byte[] trackData = new byte[imageInfo.SectorSize * imageInfo.SectorsPerTrack];
byte[] blkHeader = new byte[3];
// check that track is present
if(trackOffset[tracknum] == -1)
throw new InvalidDataException("Tried reading a track that is not present in image");
stream.Seek(trackOffset[tracknum], SeekOrigin.Begin);
// read the compressed track data
stream.Read(blkHeader, 0, 3);
short compressedLength = (short)(BitConverter.ToInt16(blkHeader, 0) - 1);
byte escapeByte = blkHeader[2];
byte[] cBuffer = new byte[compressedLength];
stream.Read(cBuffer, 0, compressedLength);
// decompress the data
int sIndex = 0; // source buffer position
int dIndex = 0; // destination buffer position
while(sIndex < compressedLength)
if(cBuffer[sIndex] == escapeByte)
{
sIndex++; // skip over escape byte
byte fillByte = cBuffer[sIndex++];
byte fillCount = cBuffer[sIndex++];
// fill destination buffer
for(int i = 0; i < fillCount; i++) trackData[dIndex++] = fillByte;
}
else
trackData[dIndex++] = cBuffer[sIndex++];
// check that the number of bytes decompressed matches a whole track
if(dIndex != imageInfo.SectorSize * imageInfo.SectorsPerTrack)
throw new InvalidDataException("Track decompression yielded incomplete data");
// store track in cache
trackCache[tracknum] = trackData;
}
/// <summary>
/// The global header of a HDCP image file
/// </summary>
@@ -454,7 +440,8 @@ namespace DiscImageChef.DiscImages
/// 0 means track is not present, 1 means it is present.
/// The first 2 tracks are always present.
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2 * 82)] public byte[] trackMap;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2 * 82)]
public byte[] trackMap;
}
/// <summary>
@@ -473,12 +460,5 @@ namespace DiscImageChef.DiscImages
/// </summary>
public byte escape;
}
struct MediaTypeTableEntry
{
public byte Tracks;
public byte SectorsPerTrack;
public MediaType MediaType;
}
}
}

View File

@@ -43,12 +43,11 @@ namespace DiscImageChef.DiscImages
{
public class Imd : IMediaImage
{
const byte SECTOR_CYLINDER_MAP_MASK = 0x80;
const byte SECTOR_HEAD_MAP_MASK = 0x40;
const byte COMMENT_END = 0x1A;
const string REGEX_HEADER =
@"IMD (?<version>\d.\d+):\s+(?<day>\d+)\/\s*(?<month>\d+)\/(?<year>\d+)\s+(?<hour>\d+):(?<minute>\d+):(?<second>\d+)\r\n"
;
const byte SECTOR_CYLINDER_MAP_MASK = 0x80;
const byte SECTOR_HEAD_MAP_MASK = 0x40;
const byte COMMENT_END = 0x1A;
const string REGEX_HEADER =
@"IMD (?<version>\d.\d+):\s+(?<day>\d+)\/\s*(?<month>\d+)\/(?<year>\d+)\s+(?<hour>\d+):(?<minute>\d+):(?<second>\d+)\r\n";
ImageInfo imageInfo;
List<byte[]> sectorsData;
@@ -57,31 +56,31 @@ namespace DiscImageChef.DiscImages
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
public string Name => "Dunfield's IMD";
public Guid Id => new Guid("0D67162E-38A3-407D-9B1A-CF40080A48CB");
public string Name => "Dunfield's IMD";
public Guid Id => new Guid("0D67162E-38A3-407D-9B1A-CF40080A48CB");
public ImageInfo Info => imageInfo;
public string ImageFormat => "IMageDisk";
@@ -126,26 +125,26 @@ namespace DiscImageChef.DiscImages
}
imageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
sectorsData = new List<byte[]>();
sectorsData = new List<byte[]>();
byte currentCylinder = 0;
imageInfo.Cylinders = 1;
imageInfo.Heads = 1;
ulong currentLba = 0;
imageInfo.Cylinders = 1;
imageInfo.Heads = 1;
ulong currentLba = 0;
TransferRate mode = TransferRate.TwoHundred;
while(stream.Position + 5 < stream.Length)
{
mode = (TransferRate)stream.ReadByte();
byte cylinder = (byte)stream.ReadByte();
byte head = (byte)stream.ReadByte();
byte spt = (byte)stream.ReadByte();
byte n = (byte)stream.ReadByte();
byte[] idmap = new byte[spt];
byte[] cylmap = new byte[spt];
byte[] headmap = new byte[spt];
ushort[] bps = new ushort[spt];
mode = (TransferRate)stream.ReadByte();
byte cylinder = (byte)stream.ReadByte();
byte head = (byte)stream.ReadByte();
byte spt = (byte)stream.ReadByte();
byte n = (byte)stream.ReadByte();
byte[] idmap = new byte[spt];
byte[] cylmap = new byte[spt];
byte[] headmap = new byte[spt];
ushort[] bps = new ushort[spt];
if(cylinder != currentCylinder)
{
@@ -155,16 +154,19 @@ namespace DiscImageChef.DiscImages
if((head & 1) == 1) imageInfo.Heads = 2;
stream.Read(idmap, 0, idmap.Length);
stream.Read(idmap, 0, idmap.Length);
if((head & SECTOR_CYLINDER_MAP_MASK) == SECTOR_CYLINDER_MAP_MASK) stream.Read(cylmap, 0, cylmap.Length);
if((head & SECTOR_HEAD_MAP_MASK) == SECTOR_HEAD_MAP_MASK) stream.Read(headmap, 0, headmap.Length);
if((head & SECTOR_HEAD_MAP_MASK) == SECTOR_HEAD_MAP_MASK)
stream.Read(headmap, 0, headmap.Length);
if(n == 0xFF)
{
byte[] bpsbytes = new byte[spt * 2];
stream.Read(bpsbytes, 0, bpsbytes.Length);
for(int i = 0; i < spt; i++) bps[i] = BitConverter.ToUInt16(bpsbytes, i * 2);
}
else for(int i = 0; i < spt; i++) bps[i] = (ushort)(128 << n);
else
for(int i = 0; i < spt; i++)
bps[i] = (ushort)(128 << n);
if(spt > imageInfo.SectorsPerTrack) imageInfo.SectorsPerTrack = spt;
@@ -173,7 +175,7 @@ namespace DiscImageChef.DiscImages
for(int i = 0; i < spt; i++)
{
SectorType type = (SectorType)stream.ReadByte();
byte[] data = new byte[bps[i]];
byte[] data = new byte[bps[i]];
// TODO; Handle disks with different bps in track 0
if(bps[i] > imageInfo.SectorSize) imageInfo.SectorSize = bps[i];
@@ -212,99 +214,31 @@ namespace DiscImageChef.DiscImages
imageInfo.Application = "IMD";
// TODO: The header is the date of dump or the date of the application compilation?
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
imageInfo.Sectors = currentLba;
imageInfo.MediaType = MediaType.Unknown;
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
imageInfo.Comments = StringHandlers.CToString(cmt.ToArray());
imageInfo.Sectors = currentLba;
imageInfo.MediaType = MediaType.Unknown;
switch(mode)
MediaEncoding mediaEncoding = MediaEncoding.MFM;
if(mode == TransferRate.TwoHundred || mode == TransferRate.ThreeHundred || mode == TransferRate.FiveHundred)
mediaEncoding = MediaEncoding.FM;
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, (byte)imageInfo.Heads,
(ushort)imageInfo.SectorsPerTrack, imageInfo.SectorSize, mediaEncoding, false));
switch(imageInfo.MediaType)
{
case TransferRate.TwoHundred:
case TransferRate.ThreeHundred:
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_40;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
case MediaType.NEC_525_HD when mode == TransferRate.FiveHundredMfm:
imageInfo.MediaType = MediaType.NEC_35_HD_8;
break;
case TransferRate.FiveHundred:
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 32 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 319) imageInfo.MediaType = MediaType.IBM23FD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 73 && imageInfo.SectorsPerTrack == 26 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.IBM23FD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 26 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.NEC_8_SD;
case MediaType.DOS_525_HD when mode == TransferRate.FiveHundredMfm:
imageInfo.MediaType = MediaType.NEC_35_HD_15;
break;
case TransferRate.TwoHundredMfm:
case TransferRate.ThreeHundredMfm:
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_40;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.RX50;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.FDFORMAT_35_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
break;
case TransferRate.FiveHundredMfm:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 23 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.XDF_35;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.SHARP_525_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_DS_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 11 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_SS_DD_11;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 11 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.ATARI_35_DS_DD_11;
break;
default:
imageInfo.MediaType = MediaType.Unknown;
case MediaType.RX50 when mode == TransferRate.FiveHundredMfm:
imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
break;
}
@@ -335,7 +269,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -346,7 +280,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -464,14 +398,14 @@ namespace DiscImageChef.DiscImages
enum SectorType : byte
{
Unavailable = 0,
Normal = 1,
Compressed = 2,
Deleted = 3,
CompressedDeleted = 4,
Error = 5,
CompressedError = 6,
DeletedError = 7,
Unavailable = 0,
Normal = 1,
Compressed = 2,
Deleted = 3,
CompressedDeleted = 4,
Error = 5,
CompressedError = 6,
DeletedError = 7,
CompressedDeletedError = 8
}
}

View File

@@ -43,30 +43,30 @@ namespace DiscImageChef.DiscImages
public class MaxiDisk : IMediaImage
{
/// <summary>Disk image file</summary>
IFilter hdkImageFilter;
IFilter hdkImageFilter;
ImageInfo imageInfo;
public MaxiDisk()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "MAXI Disk",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "MAXI Disk",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
@@ -74,7 +74,7 @@ namespace DiscImageChef.DiscImages
public ImageInfo Info => imageInfo;
public string Name => "MAXI Disk image";
public Guid Id => new Guid("D27D924A-7034-466E-ADE1-B81EF37E469E");
public Guid Id => new Guid("D27D924A-7034-466E-ADE1-B81EF37E469E");
public string ImageFormat => "MAXI Disk";
@@ -102,10 +102,10 @@ namespace DiscImageChef.DiscImages
HdkHeader tmpHeader = (HdkHeader)Marshal.PtrToStructure(ftrPtr, typeof(HdkHeader));
Marshal.FreeHGlobal(ftrPtr);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.unknown = {0}", tmpHeader.unknown);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.diskType = {0}", tmpHeader.diskType);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.heads = {0}", tmpHeader.heads);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.cylinders = {0}", tmpHeader.cylinders);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.unknown = {0}", tmpHeader.unknown);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.diskType = {0}", tmpHeader.diskType);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.heads = {0}", tmpHeader.heads);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.cylinders = {0}", tmpHeader.cylinders);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.bytesPerSector = {0}", tmpHeader.bytesPerSector);
DicConsole.DebugWriteLine("MAXI Disk plugin", "tmp_header.sectorsPerTrack = {0}",
tmpHeader.sectorsPerTrack);
@@ -166,67 +166,22 @@ namespace DiscImageChef.DiscImages
if(expectedFileSize != stream.Length) return false;
imageInfo.Cylinders = tmpHeader.cylinders;
imageInfo.Heads = tmpHeader.heads;
imageInfo.Cylinders = tmpHeader.cylinders;
imageInfo.Heads = tmpHeader.heads;
imageInfo.SectorsPerTrack = tmpHeader.sectorsPerTrack;
imageInfo.Sectors = (ulong)(tmpHeader.heads * tmpHeader.cylinders * tmpHeader.sectorsPerTrack);
imageInfo.SectorSize = (uint)(128 << tmpHeader.bytesPerSector);
imageInfo.Sectors = (ulong)(tmpHeader.heads * tmpHeader.cylinders * tmpHeader.sectorsPerTrack);
imageInfo.SectorSize = (uint)(128 << tmpHeader.bytesPerSector);
hdkImageFilter = imageFilter;
imageInfo.ImageSize = (ulong)(stream.Length - 8);
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)(stream.Length - 8);
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_DS_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 16 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_DD_80;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 10 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ACORN_525_SS_SD_80;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_525_HD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_SD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 26 &&
imageInfo.SectorSize == 128) imageInfo.MediaType = MediaType.ATARI_525_ED;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 256) imageInfo.MediaType = MediaType.ATARI_525_DD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_ED;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DMF_82;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 77 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.NEC_35_HD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.NEC_35_HD_15;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 5 &&
imageInfo.SectorSize == 1024) imageInfo.MediaType = MediaType.ACORN_35_DS_DD;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9 &&
imageInfo.SectorSize == 512) imageInfo.MediaType = MediaType.Apricot_35;
else imageInfo.MediaType = MediaType.Unknown;
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, (byte)imageInfo.Heads,
(ushort)imageInfo.SectorsPerTrack, imageInfo.SectorSize, MediaEncoding.MFM, false
));
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
@@ -244,7 +199,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -255,7 +210,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -292,7 +247,7 @@ namespace DiscImageChef.DiscImages
Stream stream = hdkImageFilter.GetDataForkStream();
stream.Seek((long)(8 + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
stream.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
return buffer;
}
@@ -372,17 +327,17 @@ namespace DiscImageChef.DiscImages
enum HdkDiskTypes : byte
{
Dos360 = 0,
Maxi420 = 1,
Dos720 = 2,
Maxi800 = 3,
Dos1200 = 4,
Dos360 = 0,
Maxi420 = 1,
Dos720 = 2,
Maxi800 = 3,
Dos1200 = 4,
Maxi1400 = 5,
Dos1440 = 6,
Mac1440 = 7,
Dos1440 = 6,
Mac1440 = 7,
Maxi1600 = 8,
Dmf = 9,
Dos2880 = 10,
Dmf = 9,
Dos2880 = 10,
Maxi3200 = 11
}
}

View File

@@ -45,39 +45,38 @@ namespace DiscImageChef.DiscImages
public class RayDim : IMediaImage
{
const string REGEX_SIGNATURE =
@"Disk IMage VER (?<major>\d).(?<minor>\d) Copyright \(C\) (?<year>\d{4}) Ray Arachelian, All Rights Reserved\."
;
@"Disk IMage VER (?<major>\d).(?<minor>\d) Copyright \(C\) (?<year>\d{4}) Ray Arachelian, All Rights Reserved\.";
MemoryStream disk;
ImageInfo imageInfo;
ImageInfo imageInfo;
public RayDim()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "Ray Arachelian's Disk IMage",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Application = "Ray Arachelian's Disk IMage",
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
public string Name => "Ray Arachelian's Disk IMage";
public Guid Id => new Guid("F541F4E7-C1E3-4A2D-B07F-D863E87AB961");
public string Name => "Ray Arachelian's Disk IMage";
public Guid Id => new Guid("F541F4E7-C1E3-4A2D-B07F-D863E87AB961");
public ImageInfo Info => imageInfo;
public string ImageFormat => "Ray Arachelian's Disk IMage";
@@ -109,8 +108,8 @@ namespace DiscImageChef.DiscImages
string signature = StringHandlers.CToString(header.signature);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.signature = {0}", signature);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.diskType = {0}", header.diskType);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.diskType = {0}", header.diskType);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.cylinders = {0}", header.cylinders);
DicConsole.DebugWriteLine("Ray Arachelian's Disk IMage plugin", "header.sectorsPerTrack = {0}",
header.sectorsPerTrack);
@@ -148,14 +147,14 @@ namespace DiscImageChef.DiscImages
imageInfo.ApplicationVersion = $"{sm.Groups["major"].Value}.{sm.Groups["minor"].Value}";
imageInfo.Cylinders = (uint)(header.cylinders + 1);
imageInfo.Heads = (uint)(header.heads + 1);
imageInfo.Cylinders = (uint)(header.cylinders + 1);
imageInfo.Heads = (uint)(header.heads + 1);
imageInfo.SectorsPerTrack = header.sectorsPerTrack;
imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
imageInfo.SectorSize = 512;
imageInfo.Sectors = imageInfo.Cylinders * imageInfo.Heads * imageInfo.SectorsPerTrack;
imageInfo.SectorSize = 512;
byte[] sectors = new byte[imageInfo.SectorsPerTrack * imageInfo.SectorSize];
disk = new MemoryStream();
disk = new MemoryStream();
for(int i = 0; i < imageInfo.SectorsPerTrack * imageInfo.SectorSize; i++)
{
@@ -164,55 +163,22 @@ namespace DiscImageChef.DiscImages
disk.Write(sectors, 0, sectors.Length);
}
switch(header.diskType)
imageInfo.MediaType =
Geometry.GetMediaType(((ushort)imageInfo.Cylinders, (byte)imageInfo.Heads,
(ushort)imageInfo.SectorsPerTrack, 512, MediaEncoding.MFM, false));
switch(imageInfo.MediaType)
{
case RayDiskTypes.Md2hd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15)
imageInfo.MediaType = MediaType.DOS_525_HD;
else goto case RayDiskTypes.Md2dd;
case MediaType.NEC_525_HD when header.diskType == RayDiskTypes.Mf2hd ||
header.diskType == RayDiskTypes.Mf2ed:
imageInfo.MediaType = MediaType.NEC_35_HD_8;
break;
case RayDiskTypes.Md2dd:
if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8)
imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 8)
imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 40 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
else imageInfo.MediaType = MediaType.Unknown;
case MediaType.DOS_525_HD when header.diskType == RayDiskTypes.Mf2hd ||
header.diskType == RayDiskTypes.Mf2ed:
imageInfo.MediaType = MediaType.NEC_35_HD_15;
break;
case RayDiskTypes.Mf2ed:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 36)
imageInfo.MediaType = MediaType.DOS_35_ED;
else goto case RayDiskTypes.Mf2hd;
break;
case RayDiskTypes.Mf2hd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 18)
imageInfo.MediaType = MediaType.DOS_35_HD;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 21)
imageInfo.MediaType = MediaType.DMF;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 82 && imageInfo.SectorsPerTrack == 21)
imageInfo.MediaType = MediaType.DMF_82;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 15)
imageInfo.MediaType = MediaType.NEC_35_HD_15;
else goto case RayDiskTypes.Mf2dd;
break;
case RayDiskTypes.Mf2dd:
if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
else if(imageInfo.Heads == 2 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8)
imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 80 && imageInfo.SectorsPerTrack == 8)
imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
else if(imageInfo.Heads == 1 && imageInfo.Cylinders == 70 && imageInfo.SectorsPerTrack == 9)
imageInfo.MediaType = MediaType.Apricot_35;
else imageInfo.MediaType = MediaType.Unknown;
break;
default:
imageInfo.MediaType = MediaType.Unknown;
case MediaType.RX50 when header.diskType == RayDiskTypes.Md2dd || header.diskType == RayDiskTypes.Md2hd:
imageInfo.MediaType = MediaType.ATARI_35_SS_DD;
break;
}
@@ -232,7 +198,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -243,7 +209,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -278,7 +244,7 @@ namespace DiscImageChef.DiscImages
byte[] buffer = new byte[length * imageInfo.SectorSize];
disk.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
disk.Seek((long)(sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
disk.Read(buffer, 0, (int)(length * imageInfo.SectorSize));
return buffer;
@@ -347,11 +313,12 @@ namespace DiscImageChef.DiscImages
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct RayHdr
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] signature;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
public byte[] signature;
public RayDiskTypes diskType;
public byte cylinders;
public byte sectorsPerTrack;
public byte heads;
public byte cylinders;
public byte sectorsPerTrack;
public byte heads;
}
[SuppressMessage("ReSharper", "InconsistentNaming")]

View File

@@ -43,44 +43,44 @@ namespace DiscImageChef.DiscImages
{
public class SaveDskF : IMediaImage
{
const ushort SDF_MAGIC_OLD = 0x58AA;
const ushort SDF_MAGIC = 0x59AA;
const ushort SDF_MAGIC_OLD = 0x58AA;
const ushort SDF_MAGIC = 0x59AA;
const ushort SDF_MAGIC_COMPRESSED = 0x5AAA;
uint calculatedChk;
byte[] decodedDisk;
uint calculatedChk;
byte[] decodedDisk;
SaveDskFHeader header;
ImageInfo imageInfo;
ImageInfo imageInfo;
public SaveDskF()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
public string Name => "IBM SaveDskF";
public Guid Id => new Guid("288CE058-1A51-4034-8C45-5A256CAE1461");
public string Name => "IBM SaveDskF";
public Guid Id => new Guid("288CE058-1A51-4034-8C45-5A256CAE1461");
public ImageInfo Info => imageInfo;
public string ImageFormat => "IBM SaveDskF";
@@ -103,15 +103,15 @@ namespace DiscImageChef.DiscImages
byte[] hdr = new byte[40];
stream.Read(hdr, 0, 40);
header = new SaveDskFHeader();
header = new SaveDskFHeader();
IntPtr hdrPtr = Marshal.AllocHGlobal(40);
Marshal.Copy(hdr, 0, hdrPtr, 40);
header = (SaveDskFHeader)Marshal.PtrToStructure(hdrPtr, typeof(SaveDskFHeader));
Marshal.FreeHGlobal(hdrPtr);
return (header.magic == SDF_MAGIC || header.magic == SDF_MAGIC_COMPRESSED ||
header.magic == SDF_MAGIC_OLD) && header.fatCopies <= 2 && header.padding == 0 &&
header.commentOffset < stream.Length && header.dataOffset < stream.Length;
return (header.magic == SDF_MAGIC || header.magic == SDF_MAGIC_COMPRESSED ||
header.magic == SDF_MAGIC_OLD) && header.fatCopies <= 2 && header.padding == 0 &&
header.commentOffset < stream.Length && header.dataOffset < stream.Length;
}
public bool OpenImage(IFilter imageFilter)
@@ -122,31 +122,31 @@ namespace DiscImageChef.DiscImages
byte[] hdr = new byte[40];
stream.Read(hdr, 0, 40);
header = new SaveDskFHeader();
header = new SaveDskFHeader();
IntPtr hdrPtr = Marshal.AllocHGlobal(40);
Marshal.Copy(hdr, 0, hdrPtr, 40);
header = (SaveDskFHeader)Marshal.PtrToStructure(hdrPtr, typeof(SaveDskFHeader));
Marshal.FreeHGlobal(hdrPtr);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.magic = 0x{0:X4}", header.magic);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.mediaType = 0x{0:X2}", header.mediaType);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorSize = {0}", header.sectorSize);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clusterMask = {0}", header.clusterMask);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clusterShift = {0}", header.clusterShift);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.magic = 0x{0:X4}", header.magic);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.mediaType = 0x{0:X2}", header.mediaType);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorSize = {0}", header.sectorSize);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clusterMask = {0}", header.clusterMask);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clusterShift = {0}", header.clusterShift);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.reservedSectors = {0}", header.reservedSectors);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.fatCopies = {0}", header.fatCopies);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.rootEntries = {0}", header.rootEntries);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.firstCluster = {0}", header.firstCluster);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clustersCopied = {0}", header.clustersCopied);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorsPerFat = {0}", header.sectorsPerFat);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.checksum = 0x{0:X8}", header.checksum);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.cylinders = {0}", header.cylinders);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.fatCopies = {0}", header.fatCopies);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.rootEntries = {0}", header.rootEntries);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.firstCluster = {0}", header.firstCluster);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.clustersCopied = {0}", header.clustersCopied);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorsPerFat = {0}", header.sectorsPerFat);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.checksum = 0x{0:X8}", header.checksum);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.cylinders = {0}", header.cylinders);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.heads = {0}", header.heads);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorsPerTrack = {0}", header.sectorsPerTrack);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.padding = {0}", header.padding);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorsCopied = {0}", header.sectorsCopied);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.commentOffset = {0}", header.commentOffset);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.dataOffset = {0}", header.dataOffset);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.padding = {0}", header.padding);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.sectorsCopied = {0}", header.sectorsCopied);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.commentOffset = {0}", header.commentOffset);
DicConsole.DebugWriteLine("SaveDskF plugin", "header.dataOffset = {0}", header.dataOffset);
if(header.dataOffset == 0 && header.magic == SDF_MAGIC_OLD) header.dataOffset = 512;
@@ -161,7 +161,7 @@ namespace DiscImageChef.DiscImages
int b;
do
{
b = stream.ReadByte();
b = stream.ReadByte();
if(b >= 0) calculatedChk += (uint)b;
}
while(b >= 0);
@@ -169,108 +169,17 @@ namespace DiscImageChef.DiscImages
DicConsole.DebugWriteLine("SaveDskF plugin", "Calculated checksum = 0x{0:X8}, {1}", calculatedChk,
calculatedChk == header.checksum);
imageInfo.Application = "SaveDskF";
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.Application = "SaveDskF";
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = imageFilter.GetFilename();
imageInfo.ImageSize = (ulong)(stream.Length - header.dataOffset);
imageInfo.Sectors = (ulong)(header.sectorsPerTrack * header.heads * header.cylinders);
imageInfo.SectorSize = header.sectorSize;
imageInfo.MediaTitle = imageFilter.GetFilename();
imageInfo.ImageSize = (ulong)(stream.Length - header.dataOffset);
imageInfo.Sectors = (ulong)(header.sectorsPerTrack * header.heads * header.cylinders);
imageInfo.SectorSize = header.sectorSize;
imageInfo.MediaType = MediaType.Unknown;
switch(header.cylinders)
{
case 40:
switch(header.heads)
{
case 1:
switch(header.sectorsPerTrack)
{
case 8:
imageInfo.MediaType = MediaType.DOS_525_SS_DD_8;
break;
case 9:
imageInfo.MediaType = MediaType.DOS_525_SS_DD_9;
break;
}
break;
case 2:
switch(header.sectorsPerTrack)
{
case 8:
imageInfo.MediaType = MediaType.DOS_525_DS_DD_8;
break;
case 9:
imageInfo.MediaType = MediaType.DOS_525_DS_DD_9;
break;
}
break;
}
break;
case 70:
switch(header.heads)
{
case 1:
switch(header.sectorsPerTrack)
{
case 9:
imageInfo.MediaType = MediaType.Apricot_35;
break;
}
break;
}
break;
case 80:
switch(header.heads)
{
case 1:
switch(header.sectorsPerTrack)
{
case 8:
imageInfo.MediaType = MediaType.DOS_35_SS_DD_8;
break;
case 9:
imageInfo.MediaType = MediaType.DOS_35_SS_DD_9;
break;
}
break;
case 2:
switch(header.sectorsPerTrack)
{
case 8:
imageInfo.MediaType = MediaType.DOS_35_DS_DD_8;
break;
case 9:
imageInfo.MediaType = MediaType.DOS_35_DS_DD_9;
break;
case 15:
imageInfo.MediaType = MediaType.DOS_525_HD;
break;
case 18:
imageInfo.MediaType = MediaType.DOS_35_HD;
break;
case 23:
imageInfo.MediaType = MediaType.XDF_35;
break;
case 36:
imageInfo.MediaType = MediaType.DOS_35_ED;
break;
}
break;
}
break;
default:
imageInfo.MediaType = MediaType.Unknown;
break;
}
imageInfo.MediaType =
Geometry.GetMediaType((header.cylinders, (byte)header.heads, header.sectorsPerTrack, header.sectorSize,
MediaEncoding.MFM, false));
imageInfo.XmlMediaType = XmlMediaType.BlockMedia;
@@ -288,8 +197,8 @@ namespace DiscImageChef.DiscImages
decodedDisk = new byte[imageInfo.Sectors * imageInfo.SectorSize];
stream.Read(decodedDisk, 0, (int)(stream.Length - header.dataOffset));
imageInfo.Cylinders = header.cylinders;
imageInfo.Heads = header.heads;
imageInfo.Cylinders = header.cylinders;
imageInfo.Heads = header.heads;
imageInfo.SectorsPerTrack = header.sectorsPerTrack;
return true;
@@ -306,7 +215,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -317,7 +226,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -348,7 +257,7 @@ namespace DiscImageChef.DiscImages
byte[] buffer = new byte[length * imageInfo.SectorSize];
Array.Copy(decodedDisk, (int)sectorAddress * imageInfo.SectorSize, buffer, 0,
length * imageInfo.SectorSize);
length * imageInfo.SectorSize);
return buffer;
}

View File

@@ -41,41 +41,41 @@ namespace DiscImageChef.DiscImages
{
public class ZZZRawImage : IMediaImage
{
bool differentTrackZeroSize;
string extension;
bool differentTrackZeroSize;
string extension;
ImageInfo imageInfo;
IFilter rawImageFilter;
IFilter rawImageFilter;
public ZZZRawImage()
{
imageInfo = new ImageInfo
{
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
ReadableSectorTags = new List<SectorTagType>(),
ReadableMediaTags = new List<MediaTagType>(),
HasPartitions = false,
HasSessions = false,
Version = null,
Application = null,
ApplicationVersion = null,
Creator = null,
Comments = null,
MediaManufacturer = null,
MediaModel = null,
MediaSerialNumber = null,
MediaBarcode = null,
MediaPartNumber = null,
MediaSequence = 0,
LastMediaSequence = 0,
DriveManufacturer = null,
DriveModel = null,
DriveSerialNumber = null,
DriveFirmwareRevision = null
};
}
public string Name => "Raw Disk Image";
// Non-random UUID to recognize this specific plugin
public Guid Id => new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
public Guid Id => new Guid("12345678-AAAA-BBBB-CCCC-123456789000");
public ImageInfo Info => imageInfo;
public string ImageFormat => "Raw disk image (sector by sector copy)";
@@ -89,17 +89,17 @@ namespace DiscImageChef.DiscImages
Track trk = new Track
{
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackRawBytesPerSector = (int)imageInfo.SectorSize,
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
};
List<Track> lst = new List<Track> {trk};
return lst;
@@ -115,11 +115,11 @@ namespace DiscImageChef.DiscImages
Session sess = new Session
{
EndSector = imageInfo.Sectors - 1,
EndTrack = 1,
EndSector = imageInfo.Sectors - 1,
EndTrack = 1,
SessionSequence = 1,
StartSector = 0,
StartTrack = 1
StartSector = 0,
StartTrack = 1
};
List<Session> lst = new List<Session> {sess};
return lst;
@@ -134,14 +134,14 @@ namespace DiscImageChef.DiscImages
throw new FeatureUnsupportedImageException("Feature not supported by image format");
List<Partition> parts = new List<Partition>();
Partition part = new Partition
Partition part = new Partition
{
Start = 0,
Length = imageInfo.Sectors,
Offset = 0,
Start = 0,
Length = imageInfo.Sectors,
Offset = 0,
Sequence = 0,
Type = "MODE1/2048",
Size = imageInfo.Sectors * imageInfo.SectorSize
Type = "MODE1/2048",
Size = imageInfo.Sectors * imageInfo.SectorSize
};
parts.Add(part);
return parts;
@@ -183,7 +183,7 @@ namespace DiscImageChef.DiscImages
case 1222400:
case 1304320:
case 1255168: return true;
default: return false;
default: return false;
}
}
@@ -202,10 +202,12 @@ namespace DiscImageChef.DiscImages
imageInfo.SectorSize = 256;
break;
default:
if((extension == ".adf" || extension == ".adl" || extension == ".ssd" || extension == ".dsd") &&
(imageFilter.GetDataForkLength() == 163840 || imageFilter.GetDataForkLength() == 327680 ||
imageFilter.GetDataForkLength() == 655360)) imageInfo.SectorSize = 256;
else if((extension == ".adf" || extension == ".adl") && imageFilter.GetDataForkLength() == 819200)
if((extension == ".adf" || extension == ".adl" ||
extension == ".ssd" || extension == ".dsd") &&
(imageFilter.GetDataForkLength() == 163840 || imageFilter.GetDataForkLength() == 327680 ||
imageFilter.GetDataForkLength() == 655360)) imageInfo.SectorSize = 256;
else if((extension == ".adf" || extension == ".adl") &&
imageFilter.GetDataForkLength() == 819200)
imageInfo.SectorSize = 1024;
else
switch(imageFilter.GetDataForkLength())
@@ -218,9 +220,9 @@ namespace DiscImageChef.DiscImages
imageInfo.SectorSize = 128;
break;
case 116480:
case 287488: // T0S0 = 128bps
case 988416: // T0S0 = 128bps
case 995072: // T0S0 = 128bps, T0S1 = 256bps
case 287488: // T0S0 = 128bps
case 988416: // T0S0 = 128bps
case 995072: // T0S0 = 128bps, T0S1 = 256bps
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
case 232960:
case 143360:
@@ -229,7 +231,7 @@ namespace DiscImageChef.DiscImages
case 102400:
case 204800:
case 655360:
case 80384: // T0S0 = 128bps
case 80384: // T0S0 = 128bps
case 325632: // T0S0 = 128bps, T0S1 = 256bps
case 653312: // T0S0 = 128bps, T0S1 = 256bps
@@ -248,7 +250,7 @@ namespace DiscImageChef.DiscImages
case 81664:
imageInfo.SectorSize = 319;
break;
case 306432: // T0S0 = 128bps
case 306432: // T0S0 = 128bps
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.SectorSize = 512;
@@ -268,12 +270,12 @@ namespace DiscImageChef.DiscImages
break;
}
imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.ImageSize = (ulong)imageFilter.GetDataForkLength();
imageInfo.CreationTime = imageFilter.GetCreationTime();
imageInfo.LastModificationTime = imageFilter.GetLastWriteTime();
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
differentTrackZeroSize = false;
rawImageFilter = imageFilter;
imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());
differentTrackZeroSize = false;
rawImageFilter = imageFilter;
switch(imageFilter.GetDataForkLength())
{
@@ -290,63 +292,63 @@ namespace DiscImageChef.DiscImages
imageInfo.Sectors = 455;
break;
case 287488: // T0S0 = 128bps
imageInfo.Sectors = 1136;
imageInfo.Sectors = 1136;
differentTrackZeroSize = true;
break;
case 988416: // T0S0 = 128bps
imageInfo.Sectors = 3874;
imageInfo.Sectors = 3874;
differentTrackZeroSize = true;
break;
case 995072: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 3900;
imageInfo.Sectors = 3900;
differentTrackZeroSize = true;
break;
case 1021696: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 4004;
imageInfo.Sectors = 4004;
differentTrackZeroSize = true;
break;
case 81664:
imageInfo.Sectors = 256;
break;
case 306432: // T0S0 = 128bps
imageInfo.Sectors = 618;
imageInfo.Sectors = 618;
differentTrackZeroSize = true;
break;
case 1146624: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 2272;
imageInfo.Sectors = 2272;
differentTrackZeroSize = true;
break;
case 1177344: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 2332;
imageInfo.Sectors = 2332;
differentTrackZeroSize = true;
break;
case 1222400: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 1236;
imageInfo.Sectors = 1236;
differentTrackZeroSize = true;
break;
case 1304320: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 1316;
imageInfo.Sectors = 1316;
differentTrackZeroSize = true;
break;
case 1255168: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 1268;
imageInfo.Sectors = 1268;
differentTrackZeroSize = true;
break;
case 80384: // T0S0 = 128bps
imageInfo.Sectors = 322;
imageInfo.Sectors = 322;
differentTrackZeroSize = true;
break;
case 325632: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 1280;
imageInfo.Sectors = 1280;
differentTrackZeroSize = true;
break;
case 653312: // T0S0 = 128bps, T0S1 = 256bps
imageInfo.Sectors = 2560;
imageInfo.Sectors = 2560;
differentTrackZeroSize = true;
break;
case 1880064: // IBM XDF, 3,5", real number of sectors
imageInfo.Sectors = 670;
imageInfo.SectorSize = 8192; // Biggest sector size
imageInfo.Sectors = 670;
imageInfo.SectorSize = 8192; // Biggest sector size
differentTrackZeroSize = true;
break;
case 175531:
@@ -385,17 +387,17 @@ namespace DiscImageChef.DiscImages
}
// Sharp X68000 SASI hard disks
if(extension == ".hdf")
if(extension == ".hdf")
if(imageInfo.ImageSize % 256 == 0)
{
imageInfo.SectorSize = 256;
imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
imageInfo.MediaType = MediaType.GENERIC_HDD;
imageInfo.Sectors = imageInfo.ImageSize / imageInfo.SectorSize;
imageInfo.MediaType = MediaType.GENERIC_HDD;
}
if(imageInfo.XmlMediaType == XmlMediaType.OpticalDisc)
{
imageInfo.HasSessions = true;
imageInfo.HasSessions = true;
imageInfo.HasPartitions = true;
}
@@ -404,319 +406,319 @@ namespace DiscImageChef.DiscImages
switch(imageInfo.MediaType)
{
case MediaType.ACORN_35_DS_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 5;
break;
case MediaType.ACORN_35_DS_HD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.ACORN_525_DS_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.ACORN_525_SS_DD_40:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.ACORN_525_SS_DD_80:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.ACORN_525_SS_SD_40:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.ACORN_525_SS_SD_80:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.Apple32DS:
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 13;
break;
case MediaType.Apple32SS:
imageInfo.Cylinders = 36;
imageInfo.Heads = 1;
imageInfo.Cylinders = 36;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 13;
break;
case MediaType.Apple33DS:
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.Apple33SS:
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.Cylinders = 35;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.AppleSonyDS:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.AppleSonySS:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.ATARI_35_DS_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.ATARI_35_DS_DD_11:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 11;
break;
case MediaType.ATARI_35_SS_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.ATARI_35_SS_DD_11:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 11;
break;
case MediaType.ATARI_525_ED:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.ATARI_525_SD:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 18;
break;
case MediaType.CBM_35_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.CBM_AMIGA_35_DD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 11;
break;
case MediaType.CBM_AMIGA_35_HD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 22;
break;
case MediaType.DMF:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 21;
break;
case MediaType.DOS_35_DS_DD_9:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.Apricot_35:
imageInfo.Cylinders = 70;
imageInfo.Heads = 1;
imageInfo.Cylinders = 70;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.DOS_35_ED:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 36;
break;
case MediaType.DOS_35_HD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 18;
break;
case MediaType.DOS_35_SS_DD_9:
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.Cylinders = 80;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.DOS_525_DS_DD_8:
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.DOS_525_DS_DD_9:
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.DOS_525_HD:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.DOS_525_SS_DD_8:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.DOS_525_SS_DD_9:
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.Cylinders = 40;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.ECMA_54:
imageInfo.Cylinders = 77;
imageInfo.Heads = 1;
imageInfo.Cylinders = 77;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.ECMA_59:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.ECMA_66:
imageInfo.Cylinders = 35;
imageInfo.Heads = 1;
imageInfo.Cylinders = 35;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 9;
break;
case MediaType.ECMA_69_8:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.ECMA_70:
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.Cylinders = 40;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.ECMA_78:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 16;
break;
case MediaType.ECMA_99_15:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.ECMA_99_26:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.ECMA_99_8:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.FDFORMAT_35_DD:
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.FDFORMAT_35_HD:
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 21;
break;
case MediaType.FDFORMAT_525_HD:
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.Cylinders = 82;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 17;
break;
case MediaType.IBM23FD:
imageInfo.Cylinders = 32;
imageInfo.Heads = 1;
imageInfo.Cylinders = 32;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.IBM33FD_128:
imageInfo.Cylinders = 73;
imageInfo.Heads = 1;
imageInfo.Cylinders = 73;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.IBM33FD_256:
imageInfo.Cylinders = 74;
imageInfo.Heads = 1;
imageInfo.Cylinders = 74;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.IBM33FD_512:
imageInfo.Cylinders = 74;
imageInfo.Heads = 1;
imageInfo.Cylinders = 74;
imageInfo.Heads = 1;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.IBM43FD_128:
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.IBM43FD_256:
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.IBM53FD_1024:
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.IBM53FD_256:
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 26;
break;
case MediaType.IBM53FD_512:
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.Cylinders = 74;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 15;
break;
case MediaType.NEC_35_TD:
imageInfo.Cylinders = 240;
imageInfo.Heads = 2;
imageInfo.Cylinders = 240;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 38;
break;
case MediaType.NEC_525_HD:
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.Cylinders = 77;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 8;
break;
case MediaType.XDF_35:
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.Cylinders = 80;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 23;
break;
// Following ones are what the device itself report, not the physical geometry
case MediaType.Jaz:
imageInfo.Cylinders = 1021;
imageInfo.Heads = 64;
imageInfo.Cylinders = 1021;
imageInfo.Heads = 64;
imageInfo.SectorsPerTrack = 32;
break;
case MediaType.PocketZip:
imageInfo.Cylinders = 154;
imageInfo.Heads = 16;
imageInfo.Cylinders = 154;
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 32;
break;
case MediaType.LS120:
imageInfo.Cylinders = 963;
imageInfo.Heads = 8;
imageInfo.Cylinders = 963;
imageInfo.Heads = 8;
imageInfo.SectorsPerTrack = 32;
break;
case MediaType.LS240:
imageInfo.Cylinders = 262;
imageInfo.Heads = 32;
imageInfo.Cylinders = 262;
imageInfo.Heads = 32;
imageInfo.SectorsPerTrack = 56;
break;
case MediaType.FD32MB:
imageInfo.Cylinders = 1024;
imageInfo.Heads = 2;
imageInfo.Cylinders = 1024;
imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 32;
break;
default:
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.Cylinders = (uint)(imageInfo.Sectors / 16 / 63);
imageInfo.Heads = 16;
imageInfo.SectorsPerTrack = 63;
break;
}
@@ -761,7 +763,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -772,7 +774,7 @@ namespace DiscImageChef.DiscImages
}
public bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas)
out List<ulong> unknownLbas)
{
failingLbas = new List<ulong>();
unknownLbas = new List<ulong>();
@@ -797,18 +799,18 @@ namespace DiscImageChef.DiscImages
Track trk = new Track
{
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFilter = rawImageFilter,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFilter = rawImageFilter,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackRawBytesPerSector = (int)imageInfo.SectorSize,
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
};
List<Track> lst = new List<Track> {trk};
return lst;
@@ -824,18 +826,18 @@ namespace DiscImageChef.DiscImages
Track trk = new Track
{
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFilter = rawImageFilter,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackBytesPerSector = (int)imageInfo.SectorSize,
TrackEndSector = imageInfo.Sectors - 1,
TrackFilter = rawImageFilter,
TrackFile = rawImageFilter.GetFilename(),
TrackFileOffset = 0,
TrackFileType = "BINARY",
TrackRawBytesPerSector = (int)imageInfo.SectorSize,
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
TrackSequence = 1,
TrackStartSector = 0,
TrackSubchannelType = TrackSubchannelType.None,
TrackType = TrackType.Data,
TrackSession = 1
};
List<Track> lst = new List<Track> {trk};
return lst;
@@ -881,6 +883,41 @@ namespace DiscImageChef.DiscImages
return ReadSectors(sectorAddress, length);
}
public byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorLong(ulong sectorAddress)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsLong(ulong sectorAddress, uint length)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadDiskTag(MediaTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
MediaType CalculateDiskType()
{
if(imageInfo.SectorSize == 2048)
@@ -897,9 +934,9 @@ namespace DiscImageChef.DiscImages
switch(imageInfo.ImageSize)
{
case 80384: return MediaType.ECMA_66;
case 81664: return MediaType.IBM23FD;
case 92160: return MediaType.ATARI_525_SD;
case 80384: return MediaType.ECMA_66;
case 81664: return MediaType.IBM23FD;
case 92160: return MediaType.ATARI_525_SD;
case 102400: return MediaType.ACORN_525_SS_SD_40;
case 116480: return MediaType.Apple32SS;
case 133120: return MediaType.ATARI_525_ED;
@@ -938,7 +975,7 @@ namespace DiscImageChef.DiscImages
case 737280: return MediaType.DOS_35_DS_DD_9;
case 819200:
if(imageInfo.SectorSize == 256) return MediaType.CBM_35_DD;
if((extension == ".adf" || extension == ".adl") && imageInfo.SectorSize == 1024)
if((extension == ".adf" || extension == ".adl") && imageInfo.SectorSize == 1024)
return MediaType.ACORN_35_DS_DD;
if(extension == ".st") return MediaType.ATARI_35_DS_DD;
@@ -948,37 +985,37 @@ namespace DiscImageChef.DiscImages
if(extension == ".st") return MediaType.ATARI_35_DS_DD_11;
return MediaType.CBM_AMIGA_35_DD;
case 988416: return MediaType.IBM43FD_256;
case 995072: return MediaType.IBM53FD_256;
case 1021696: return MediaType.ECMA_99_26;
case 1146624: return MediaType.IBM53FD_512;
case 1177344: return MediaType.ECMA_99_15;
case 1222400: return MediaType.IBM53FD_1024;
case 1228800: return MediaType.DOS_525_HD;
case 1255168: return MediaType.ECMA_69_8;
case 1261568: return MediaType.NEC_525_HD;
case 1304320: return MediaType.ECMA_99_8;
case 1427456: return MediaType.FDFORMAT_525_HD;
case 1474560: return MediaType.DOS_35_HD;
case 1638400: return MediaType.ACORN_35_DS_HD;
case 1720320: return MediaType.DMF;
case 1763328: return MediaType.FDFORMAT_35_HD;
case 1802240: return MediaType.CBM_AMIGA_35_HD;
case 1880064: return MediaType.XDF_35;
case 1884160: return MediaType.XDF_35;
case 2949120: return MediaType.DOS_35_ED;
case 9338880: return MediaType.NEC_35_TD;
case 33554432: return MediaType.FD32MB;
case 40387584: return MediaType.PocketZip;
case 126222336: return MediaType.LS120;
case 127923200: return MediaType.ECMA_154;
case 201410560: return MediaType.HiFD;
case 229632000: return MediaType.ECMA_201;
case 240386048: return MediaType.LS240;
case 481520640: return MediaType.ECMA_183_512;
case 533403648: return MediaType.ECMA_183;
case 596787200: return MediaType.ECMA_184_512;
case 654540800: return MediaType.ECMA_184;
case 988416: return MediaType.IBM43FD_256;
case 995072: return MediaType.IBM53FD_256;
case 1021696: return MediaType.ECMA_99_26;
case 1146624: return MediaType.IBM53FD_512;
case 1177344: return MediaType.ECMA_99_15;
case 1222400: return MediaType.IBM53FD_1024;
case 1228800: return MediaType.DOS_525_HD;
case 1255168: return MediaType.ECMA_69_8;
case 1261568: return MediaType.NEC_525_HD;
case 1304320: return MediaType.ECMA_99_8;
case 1427456: return MediaType.FDFORMAT_525_HD;
case 1474560: return MediaType.DOS_35_HD;
case 1638400: return MediaType.ACORN_35_DS_HD;
case 1720320: return MediaType.DMF;
case 1763328: return MediaType.FDFORMAT_35_HD;
case 1802240: return MediaType.CBM_AMIGA_35_HD;
case 1880064: return MediaType.XDF_35;
case 1884160: return MediaType.XDF_35;
case 2949120: return MediaType.DOS_35_ED;
case 9338880: return MediaType.NEC_35_TD;
case 33554432: return MediaType.FD32MB;
case 40387584: return MediaType.PocketZip;
case 126222336: return MediaType.LS120;
case 127923200: return MediaType.ECMA_154;
case 201410560: return MediaType.HiFD;
case 229632000: return MediaType.ECMA_201;
case 240386048: return MediaType.LS240;
case 481520640: return MediaType.ECMA_183_512;
case 533403648: return MediaType.ECMA_183;
case 596787200: return MediaType.ECMA_184_512;
case 654540800: return MediaType.ECMA_184;
case 1070617600: return MediaType.Jaz;
#region Commodore
@@ -993,40 +1030,5 @@ namespace DiscImageChef.DiscImages
default: return MediaType.GENERIC_HDD;
}
}
public byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorLong(ulong sectorAddress)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsLong(ulong sectorAddress, uint length)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadDiskTag(MediaTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
}
}

View File

@@ -51,8 +51,8 @@ namespace DiscImageChef.Tests.Images
// TODO: Add "unknown" media types
readonly MediaType[] mediatypes =
{
MediaType.DOS_35_DS_DD_9, MediaType.Unknown, MediaType.Unknown, MediaType.DOS_35_HD, MediaType.DOS_35_HD,
MediaType.DMF, MediaType.DMF
MediaType.DOS_35_DS_DD_9, MediaType.CBM_35_DD, MediaType.CBM_35_DD, MediaType.DOS_35_HD,
MediaType.DOS_35_HD, MediaType.DMF, MediaType.DMF
};
readonly string[] md5S =
@@ -67,18 +67,18 @@ namespace DiscImageChef.Tests.Images
{
for(int i = 0; i < testfiles.Length; i++)
{
string location = Path.Combine(Consts.TestFilesRoot, "images", "copyqm", testfiles[i]);
IFilter filter = new LZip();
string location = Path.Combine(Consts.TestFilesRoot, "images", "copyqm", testfiles[i]);
IFilter filter = new LZip();
filter.Open(location);
IMediaImage image = new DiscImages.CopyQm();
Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]);
Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]);
Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]);
Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]);
Assert.AreEqual(true, image.OpenImage(filter), testfiles[i]);
Assert.AreEqual(sectors[i], image.Info.Sectors, testfiles[i]);
Assert.AreEqual(sectorsize[i], image.Info.SectorSize, testfiles[i]);
Assert.AreEqual(mediatypes[i], image.Info.MediaType, testfiles[i]);
// How many sectors to read at once
const uint SECTORS_TO_READ = 256;
ulong doneSectors = 0;
ulong doneSectors = 0;
Md5Context ctx = new Md5Context();
ctx.Init();
@@ -89,13 +89,13 @@ namespace DiscImageChef.Tests.Images
if(image.Info.Sectors - doneSectors >= SECTORS_TO_READ)
{
sector = image.ReadSectors(doneSectors, SECTORS_TO_READ);
sector = image.ReadSectors(doneSectors, SECTORS_TO_READ);
doneSectors += SECTORS_TO_READ;
}
else
{
sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors));
doneSectors += image.Info.Sectors - doneSectors;
sector = image.ReadSectors(doneSectors, (uint)(image.Info.Sectors - doneSectors));
doneSectors += image.Info.Sectors - doneSectors;
}
ctx.Update(sector);