Files
Aaru/DiscImageChef.Core/Sidecar/BlockMedia.cs

744 lines
37 KiB
C#
Raw Normal View History

2017-08-08 13:40:32 +01:00
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : BlockMedia.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
2017-08-08 13:40:32 +01:00
//
// Component : Core algorithms.
2017-08-08 13:40:32 +01:00
//
// --[ Description ] ----------------------------------------------------------
//
// Contains logic to create sidecar from a block media dump.
2017-08-08 13:40:32 +01:00
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2018 Natalia Portillo
2017-08-08 13:40:32 +01:00
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
2017-08-08 13:40:32 +01:00
using DiscImageChef.CommonTypes;
using DiscImageChef.Console;
2017-08-08 13:40:32 +01:00
using DiscImageChef.Decoders.PCMCIA;
using DiscImageChef.Filesystems;
using DiscImageChef.Filters;
using DiscImageChef.DiscImages;
2017-08-08 13:40:32 +01:00
using Schemas;
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
2017-08-08 13:40:32 +01:00
namespace DiscImageChef.Core
{
public static partial class Sidecar
{
2017-12-19 20:33:03 +00:00
static void BlockMedia(ImagePlugin image, System.Guid filterId, string imagePath, FileInfo fi,
PluginBase plugins, List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar)
2017-08-08 13:40:32 +01:00
{
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia = new[]
{
2017-12-19 20:33:03 +00:00
new BlockMediaType
{
Checksums = imgChecksums.ToArray(),
Image = new ImageType
{
format = image.GetImageFormat(),
offset = 0,
offsetSpecified = true,
Value = Path.GetFileName(imagePath)
},
Size = fi.Length,
Sequence = new SequenceType {MediaTitle = image.GetImageName()}
2017-08-08 14:18:31 +01:00
}
};
2017-08-08 13:40:32 +01:00
if(image.GetMediaSequence() != 0 && image.GetLastDiskSequence() != 0)
{
sidecar.BlockMedia[0].Sequence.MediaSequence = image.GetMediaSequence();
sidecar.BlockMedia[0].Sequence.TotalMedia = image.GetMediaSequence();
}
else
{
sidecar.BlockMedia[0].Sequence.MediaSequence = 1;
sidecar.BlockMedia[0].Sequence.TotalMedia = 1;
}
foreach(MediaTagType tagType in image.ImageInfo.ReadableMediaTags)
2017-08-08 13:40:32 +01:00
switch(tagType)
{
case MediaTagType.ATAPI_IDENTIFY:
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].ATA = new ATAType
{
Identify = new DumpType
{
2017-12-19 20:33:03 +00:00
Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY)).ToArray(),
2017-08-08 14:18:31 +01:00
Size = image.ReadDiskTag(MediaTagType.ATAPI_IDENTIFY).Length
}
};
2017-08-08 13:40:32 +01:00
break;
case MediaTagType.ATA_IDENTIFY:
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].ATA = new ATAType
{
Identify = new DumpType
{
2017-12-19 20:33:03 +00:00
Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY)).ToArray(),
2017-08-08 14:18:31 +01:00
Size = image.ReadDiskTag(MediaTagType.ATA_IDENTIFY).Length
}
};
2017-08-08 13:40:32 +01:00
break;
case MediaTagType.PCMCIA_CIS:
byte[] cis = image.ReadDiskTag(MediaTagType.PCMCIA_CIS);
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].PCMCIA = new PCMCIAType
{
2017-12-19 20:33:03 +00:00
CIS = new DumpType {Checksums = Checksum.GetChecksums(cis).ToArray(), Size = cis.Length}
2017-08-08 14:18:31 +01:00
};
2017-08-08 13:40:32 +01:00
Tuple[] tuples = CIS.GetTuples(cis);
if(tuples != null)
foreach(Tuple tuple in tuples)
switch(tuple.Code) {
case TupleCodes.CISTPL_MANFID:
ManufacturerIdentificationTuple manfid =
CIS.DecodeManufacturerIdentificationTuple(tuple);
2017-08-08 13:40:32 +01:00
if(manfid != null)
{
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode = manfid.ManufacturerID;
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
}
break;
case TupleCodes.CISTPL_VERS_1:
Level1VersionTuple vers = CIS.DecodeLevel1VersionTuple(tuple);
2017-08-08 13:40:32 +01:00
if(vers != null)
{
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
sidecar.BlockMedia[0].PCMCIA.Compliance =
string.Format("{0}.{1}", vers.MajorVersion, vers.MinorVersion);
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation = vers.AdditionalInformation;
}
break;
2017-08-08 13:40:32 +01:00
}
2017-12-19 20:33:03 +00:00
2017-08-08 13:40:32 +01:00
break;
case MediaTagType.SCSI_INQUIRY:
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].SCSI = new SCSIType
{
Inquiry = new DumpType
{
2017-12-19 20:33:03 +00:00
Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_INQUIRY)).ToArray(),
2017-08-08 14:18:31 +01:00
Size = image.ReadDiskTag(MediaTagType.SCSI_INQUIRY).Length
}
};
2017-08-08 13:40:32 +01:00
break;
case MediaTagType.SD_CID:
if(sidecar.BlockMedia[0].SecureDigital == null)
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].SecureDigital.CID = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CID)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_CID).Length
};
2017-08-08 13:40:32 +01:00
break;
case MediaTagType.SD_CSD:
if(sidecar.BlockMedia[0].SecureDigital == null)
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].SecureDigital.CSD = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_CSD).Length
};
2017-08-08 13:40:32 +01:00
break;
2017-09-29 14:43:59 +01:00
case MediaTagType.SD_SCR:
2017-08-08 13:40:32 +01:00
if(sidecar.BlockMedia[0].SecureDigital == null)
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
2017-09-29 14:43:59 +01:00
sidecar.BlockMedia[0].SecureDigital.SCR = new DumpType
2017-08-08 14:18:31 +01:00
{
2017-09-29 14:43:59 +01:00
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_SCR)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_SCR).Length
};
break;
case MediaTagType.SD_OCR:
if(sidecar.BlockMedia[0].SecureDigital == null)
sidecar.BlockMedia[0].SecureDigital = new SecureDigitalType();
sidecar.BlockMedia[0].SecureDigital.OCR = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_OCR)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_OCR).Length
};
break;
case MediaTagType.MMC_CID:
if(sidecar.BlockMedia[0].MultiMediaCard == null)
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
sidecar.BlockMedia[0].MultiMediaCard.CID = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CID)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_CID).Length
};
break;
case MediaTagType.MMC_CSD:
if(sidecar.BlockMedia[0].MultiMediaCard == null)
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
sidecar.BlockMedia[0].MultiMediaCard.CSD = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_CSD)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_CSD).Length
};
break;
case MediaTagType.MMC_OCR:
if(sidecar.BlockMedia[0].MultiMediaCard == null)
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
sidecar.BlockMedia[0].MultiMediaCard.OCR = new DumpType
{
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SD_OCR)).ToArray(),
Size = image.ReadDiskTag(MediaTagType.SD_OCR).Length
};
break;
case MediaTagType.MMC_ExtendedCSD:
if(sidecar.BlockMedia[0].MultiMediaCard == null)
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
{
2017-12-19 20:33:03 +00:00
Checksums =
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD)).ToArray(),
2017-09-29 14:43:59 +01:00
Size = image.ReadDiskTag(MediaTagType.MMC_ExtendedCSD).Length
2017-08-08 14:18:31 +01:00
};
2017-08-08 13:40:32 +01:00
break;
}
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
if(image.PluginUuid == new System.Guid("12345678-AAAA-BBBB-CCCC-123456789000") &&
2017-12-20 23:07:46 +00:00
filterId == new System.Guid("12345678-AAAA-BBBB-CCCC-123456789000")) sidecar.BlockMedia[0].ContentChecksums = sidecar.BlockMedia[0].Checksums;
2017-08-08 13:40:32 +01:00
else
{
Checksum contentChkWorker = new Checksum();
// For fast debugging, skip checksum
//goto skipImageChecksum;
2017-08-08 13:40:32 +01:00
uint sectorsToRead = 512;
ulong sectors = image.GetSectors();
ulong doneSectors = 0;
InitProgress2();
while(doneSectors < sectors)
{
byte[] sector;
if(sectors - doneSectors >= sectorsToRead)
2017-08-08 13:40:32 +01:00
{
sector = image.ReadSectors(doneSectors, sectorsToRead);
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)sectors);
doneSectors += sectorsToRead;
}
else
{
sector = image.ReadSectors(doneSectors, (uint)(sectors - doneSectors));
UpdateProgress2("Hashings sector {0} of {1}", (long)doneSectors, (long)sectors);
doneSectors += sectors - doneSectors;
2017-08-08 13:40:32 +01:00
}
contentChkWorker.Update(sector);
}
// For fast debugging, skip checksum
//skipImageChecksum:
2017-08-08 13:40:32 +01:00
List<ChecksumType> cntChecksums = contentChkWorker.End();
sidecar.BlockMedia[0].ContentChecksums = cntChecksums.ToArray();
EndProgress2();
}
Metadata.MediaType.MediaTypeToString(image.ImageInfo.MediaType, out string dskType, out string dskSubType);
2017-08-08 13:40:32 +01:00
sidecar.BlockMedia[0].DiskType = dskType;
sidecar.BlockMedia[0].DiskSubType = dskSubType;
Statistics.AddMedia(image.ImageInfo.MediaType, false);
2017-08-08 13:40:32 +01:00
sidecar.BlockMedia[0].Dimensions = Metadata.Dimensions.DimensionsFromMediaType(image.ImageInfo.MediaType);
2017-08-08 13:40:32 +01:00
sidecar.BlockMedia[0].LogicalBlocks = (long)image.GetSectors();
sidecar.BlockMedia[0].LogicalBlockSize = (int)image.GetSectorSize();
// TODO: Detect it
sidecar.BlockMedia[0].PhysicalBlockSize = (int)image.GetSectorSize();
UpdateStatus("Checking filesystems...");
List<Partition> partitions = Partitions.GetAll(image);
Partitions.AddSchemesToStats(partitions);
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[1];
if(partitions.Count > 0)
{
sidecar.BlockMedia[0].FileSystemInformation = new PartitionType[partitions.Count];
for(int i = 0; i < partitions.Count; i++)
{
2017-08-08 14:18:31 +01:00
sidecar.BlockMedia[0].FileSystemInformation[i] = new PartitionType
{
Description = partitions[i].Description,
EndSector = (int)partitions[i].End,
2017-08-08 14:18:31 +01:00
Name = partitions[i].Name,
Sequence = (int)partitions[i].Sequence,
StartSector = (int)partitions[i].Start,
Type = partitions[i].Type
};
2017-08-08 13:40:32 +01:00
List<FileSystemType> lstFs = new List<FileSystemType>();
foreach(Filesystem plugin in plugins.PluginsList.Values)
2017-08-08 13:40:32 +01:00
try
{
if(!plugin.Identify(image, partitions[i])) continue;
plugin.GetInformation(image, partitions[i], out string foo);
lstFs.Add(plugin.XmlFSType);
Statistics.AddFilesystem(plugin.XmlFSType.Type);
2017-08-08 13:40:32 +01:00
}
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
2017-12-19 20:33:03 +00:00
if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[i].FileSystems = lstFs.ToArray();
2017-08-08 13:40:32 +01:00
}
}
else
{
2017-12-19 20:33:03 +00:00
sidecar.BlockMedia[0].FileSystemInformation[0] =
new PartitionType {StartSector = 0, EndSector = (int)(image.GetSectors() - 1)};
2017-08-08 13:40:32 +01:00
Partition wholePart = new Partition
{
Name = "Whole device",
Length = image.GetSectors(),
Size = image.GetSectors() * image.GetSectorSize()
};
List<FileSystemType> lstFs = new List<FileSystemType>();
foreach(Filesystem plugin in plugins.PluginsList.Values)
2017-08-08 13:40:32 +01:00
try
{
if(!plugin.Identify(image, wholePart)) continue;
plugin.GetInformation(image, wholePart, out string foo);
lstFs.Add(plugin.XmlFSType);
Statistics.AddFilesystem(plugin.XmlFSType.Type);
2017-08-08 13:40:32 +01:00
}
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
catch
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
{
//DicConsole.DebugWriteLine("Create-sidecar command", "Plugin {0} crashed", _plugin.Name);
}
2017-12-19 20:33:03 +00:00
if(lstFs.Count > 0) sidecar.BlockMedia[0].FileSystemInformation[0].FileSystems = lstFs.ToArray();
2017-08-08 13:40:32 +01:00
}
if(image.ImageInfo.Cylinders > 0 && image.ImageInfo.Heads > 0 && image.ImageInfo.SectorsPerTrack > 0)
{
sidecar.BlockMedia[0].CylindersSpecified = true;
sidecar.BlockMedia[0].HeadsSpecified = true;
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
sidecar.BlockMedia[0].Cylinders = image.ImageInfo.Cylinders;
sidecar.BlockMedia[0].Heads = image.ImageInfo.Heads;
sidecar.BlockMedia[0].SectorsPerTrack = image.ImageInfo.SectorsPerTrack;
}
if(image.ImageInfo.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
{
2017-12-19 20:33:03 +00:00
Decoders.ATA.Identify.IdentifyDevice? ataId =
Decoders.ATA.Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
if(ataId.HasValue)
2017-12-19 20:33:03 +00:00
if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 &&
ataId.Value.CurrentSectorsPerTrack > 0)
{
sidecar.BlockMedia[0].CylindersSpecified = true;
sidecar.BlockMedia[0].HeadsSpecified = true;
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
sidecar.BlockMedia[0].Cylinders = ataId.Value.CurrentCylinders;
sidecar.BlockMedia[0].Heads = ataId.Value.CurrentHeads;
sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.CurrentSectorsPerTrack;
}
else if(ataId.Value.Cylinders > 0 && ataId.Value.Heads > 0 && ataId.Value.SectorsPerTrack > 0)
{
sidecar.BlockMedia[0].CylindersSpecified = true;
sidecar.BlockMedia[0].HeadsSpecified = true;
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
sidecar.BlockMedia[0].Cylinders = ataId.Value.Cylinders;
sidecar.BlockMedia[0].Heads = ataId.Value.Heads;
sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.SectorsPerTrack;
}
}
2017-08-08 13:40:32 +01:00
// TODO: This is more of a hack, redo it planned for >4.0
string trkFormat = null;
2017-12-19 20:33:03 +00:00
switch(image.ImageInfo.MediaType)
{
case MediaType.Apple32SS:
case MediaType.Apple32DS:
trkFormat = "Apple GCR (DOS 3.2)";
break;
case MediaType.Apple33SS:
case MediaType.Apple33DS:
trkFormat = "Apple GCR (DOS 3.3)";
break;
case MediaType.AppleSonySS:
case MediaType.AppleSonyDS:
trkFormat = "Apple GCR (Sony)";
break;
case MediaType.AppleFileWare:
trkFormat = "Apple GCR (Twiggy)";
break;
case MediaType.DOS_525_SS_DD_9:
case MediaType.DOS_525_DS_DD_8:
case MediaType.DOS_525_DS_DD_9:
case MediaType.DOS_525_HD:
case MediaType.DOS_35_SS_DD_8:
case MediaType.DOS_35_SS_DD_9:
case MediaType.DOS_35_DS_DD_8:
case MediaType.DOS_35_DS_DD_9:
case MediaType.DOS_35_HD:
case MediaType.DOS_35_ED:
case MediaType.DMF:
case MediaType.DMF_82:
case MediaType.XDF_525:
case MediaType.XDF_35:
case MediaType.IBM53FD_256:
case MediaType.IBM53FD_512:
case MediaType.IBM53FD_1024:
case MediaType.RX02:
case MediaType.RX03:
case MediaType.RX50:
case MediaType.ACORN_525_SS_DD_40:
case MediaType.ACORN_525_SS_DD_80:
case MediaType.ACORN_525_DS_DD:
case MediaType.ACORN_35_DS_DD:
case MediaType.ACORN_35_DS_HD:
case MediaType.ATARI_525_ED:
case MediaType.ATARI_525_DD:
case MediaType.ATARI_35_SS_DD:
case MediaType.ATARI_35_DS_DD:
case MediaType.ATARI_35_SS_DD_11:
case MediaType.ATARI_35_DS_DD_11:
case MediaType.DOS_525_SS_DD_8:
case MediaType.NEC_8_DD:
case MediaType.NEC_525_SS:
case MediaType.NEC_525_DS:
case MediaType.NEC_525_HD:
case MediaType.NEC_35_HD_8:
case MediaType.NEC_35_HD_15:
case MediaType.NEC_35_TD:
case MediaType.FDFORMAT_525_DD:
case MediaType.FDFORMAT_525_HD:
case MediaType.FDFORMAT_35_DD:
case MediaType.FDFORMAT_35_HD:
case MediaType.Apricot_35:
case MediaType.CompactFloppy:
trkFormat = "IBM MFM";
break;
case MediaType.ATARI_525_SD:
case MediaType.NEC_8_SD:
case MediaType.ACORN_525_SS_SD_40:
case MediaType.ACORN_525_SS_SD_80:
case MediaType.RX01:
case MediaType.IBM23FD:
case MediaType.IBM33FD_128:
case MediaType.IBM33FD_256:
case MediaType.IBM33FD_512:
case MediaType.IBM43FD_128:
case MediaType.IBM43FD_256:
trkFormat = "IBM FM";
break;
case MediaType.CBM_35_DD:
trkFormat = "Commodore MFM";
break;
case MediaType.CBM_AMIGA_35_HD:
case MediaType.CBM_AMIGA_35_DD:
trkFormat = "Amiga MFM";
break;
case MediaType.CBM_1540:
case MediaType.CBM_1540_Ext:
case MediaType.CBM_1571:
trkFormat = "Commodore GCR";
break;
case MediaType.SHARP_525:
case MediaType.SHARP_525_9:
2017-12-19 20:33:03 +00:00
case MediaType.SHARP_35: break;
case MediaType.SHARP_35_9: break;
case MediaType.ECMA_99_15:
case MediaType.ECMA_99_26:
case MediaType.ECMA_100:
case MediaType.ECMA_125:
case MediaType.ECMA_147:
case MediaType.ECMA_99_8:
trkFormat = "ISO MFM";
break;
case MediaType.ECMA_54:
case MediaType.ECMA_59:
case MediaType.ECMA_66:
case MediaType.ECMA_69_8:
case MediaType.ECMA_69_15:
case MediaType.ECMA_69_26:
case MediaType.ECMA_70:
case MediaType.ECMA_78:
case MediaType.ECMA_78_2:
trkFormat = "ISO FM";
break;
default:
trkFormat = "Unknown";
break;
}
#region SuperCardPro
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
2017-12-19 20:33:03 +00:00
Path.GetFileNameWithoutExtension(imagePath) + ".scp");
if(File.Exists(scpFilePath))
{
DiscImages.SuperCardPro scpImage = new SuperCardPro();
Filters.ZZZNoFilter scpFilter = new ZZZNoFilter();
scpFilter.Open(scpFilePath);
if(image.ImageInfo.Heads <= 2 && scpImage.IdentifyImage(scpFilter))
{
2017-12-19 20:33:03 +00:00
try { scpImage.OpenImage(scpFilter); }
catch(NotImplementedException) { }
if(image.ImageInfo.Heads == 2 && scpImage.Header.heads == 0 ||
image.ImageInfo.Heads == 1 && (scpImage.Header.heads == 1 || scpImage.Header.heads == 2))
if(scpImage.Header.end + 1 >= image.ImageInfo.Cylinders)
{
List<BlockTrackType> scpBlockTrackTypes = new List<BlockTrackType>();
long currentSector = 0;
Stream scpStream = scpFilter.GetDataForkStream();
for(byte t = scpImage.Header.start; t <= scpImage.Header.end; t++)
{
BlockTrackType scpBlockTrackType = new BlockTrackType();
scpBlockTrackType.Cylinder = t / image.ImageInfo.Heads;
scpBlockTrackType.Head = t % image.ImageInfo.Heads;
scpBlockTrackType.Image = new ImageType();
scpBlockTrackType.Image.format = scpImage.GetImageFormat();
scpBlockTrackType.Image.Value = Path.GetFileName(scpFilePath);
scpBlockTrackType.Image.offset = scpImage.Header.offsets[t];
if(scpBlockTrackType.Cylinder < image.ImageInfo.Cylinders)
{
scpBlockTrackType.StartSector = currentSector;
currentSector += image.ImageInfo.SectorsPerTrack;
scpBlockTrackType.EndSector = currentSector - 1;
scpBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack;
scpBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize;
scpBlockTrackType.Format = trkFormat;
}
if(scpImage.Tracks.TryGetValue(t, out SuperCardPro.TrackHeader scpTrack))
{
byte[] trackContents =
new byte[scpTrack.Entries.Last().dataOffset +
scpTrack.Entries.Last().trackLength - scpImage.Header.offsets[t] +
1];
scpStream.Position = scpImage.Header.offsets[t];
scpStream.Read(trackContents, 0, trackContents.Length);
scpBlockTrackType.Size = trackContents.Length;
scpBlockTrackType.Checksums = Checksum.GetChecksums(trackContents).ToArray();
}
scpBlockTrackTypes.Add(scpBlockTrackType);
}
sidecar.BlockMedia[0].Track =
scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
}
else
2017-12-19 20:33:03 +00:00
DicConsole
.ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
scpImage.Header.end + 1, image.ImageInfo.Cylinders);
else
2017-12-19 20:33:03 +00:00
DicConsole
.ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
2, image.ImageInfo.Heads);
}
}
#endregion
2017-12-19 20:33:03 +00:00
#region KryoFlux
string kfFile = null;
string basename = Path.Combine(Path.GetDirectoryName(imagePath),
2017-12-19 20:33:03 +00:00
Path.GetFileNameWithoutExtension(imagePath));
bool kfDir = false;
if(Directory.Exists(basename))
{
string[] possibleKfStarts = Directory.GetFiles(basename, "*.raw", SearchOption.TopDirectoryOnly);
if(possibleKfStarts.Length > 0)
{
kfFile = possibleKfStarts[0];
kfDir = true;
}
}
2017-12-19 20:33:03 +00:00
else if(File.Exists(basename + "00.0.raw")) kfFile = basename + "00.0.raw";
else if(File.Exists(basename + "00.1.raw")) kfFile = basename + "00.1.raw";
if(kfFile != null)
{
DiscImages.KryoFlux kfImage = new KryoFlux();
Filters.ZZZNoFilter kfFilter = new ZZZNoFilter();
kfFilter.Open(kfFile);
if(image.ImageInfo.Heads <= 2 && kfImage.IdentifyImage(kfFilter))
{
2017-12-19 20:33:03 +00:00
try { kfImage.OpenImage(kfFilter); }
catch(NotImplementedException) { }
if(kfImage.ImageInfo.Heads == image.ImageInfo.Heads)
if(kfImage.ImageInfo.Cylinders >= image.ImageInfo.Cylinders)
{
List<BlockTrackType> kfBlockTrackTypes = new List<BlockTrackType>();
2017-12-19 20:33:03 +00:00
long currentSector = 0;
foreach(KeyValuePair<byte, Filter> kvp in kfImage.tracks)
{
BlockTrackType kfBlockTrackType = new BlockTrackType();
kfBlockTrackType.Cylinder = kvp.Key / image.ImageInfo.Heads;
kfBlockTrackType.Head = kvp.Key % image.ImageInfo.Heads;
kfBlockTrackType.Image = new ImageType();
kfBlockTrackType.Image.format = kfImage.GetImageFormat();
kfBlockTrackType.Image.Value =
kfDir
2017-12-19 20:33:03 +00:00
? Path.Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())),
kvp.Value.GetFilename())
: kvp.Value.GetFilename();
kfBlockTrackType.Image.offset = 0;
if(kfBlockTrackType.Cylinder < image.ImageInfo.Cylinders)
{
kfBlockTrackType.StartSector = currentSector;
currentSector += image.ImageInfo.SectorsPerTrack;
kfBlockTrackType.EndSector = currentSector - 1;
kfBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack;
kfBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize;
kfBlockTrackType.Format = trkFormat;
}
Stream kfStream = kvp.Value.GetDataForkStream();
byte[] trackContents = new byte[kfStream.Length];
kfStream.Position = 0;
kfStream.Read(trackContents, 0, trackContents.Length);
kfBlockTrackType.Size = trackContents.Length;
kfBlockTrackType.Checksums = Checksum.GetChecksums(trackContents).ToArray();
kfBlockTrackTypes.Add(kfBlockTrackType);
}
sidecar.BlockMedia[0].Track =
kfBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
}
else
2017-12-19 20:33:03 +00:00
DicConsole
.ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.Cylinders, image.ImageInfo.Cylinders);
else
2017-12-19 20:33:03 +00:00
DicConsole
.ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.Heads, image.ImageInfo.Heads);
}
}
#endregion
#region DiscFerret
string dfiFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
2017-12-19 20:33:03 +00:00
Path.GetFileNameWithoutExtension(imagePath) + ".dfi");
if(!File.Exists(dfiFilePath)) return;
DiscImages.DiscFerret dfiImage = new DiscFerret();
Filters.ZZZNoFilter dfiFilter = new ZZZNoFilter();
dfiFilter.Open(dfiFilePath);
if(!dfiImage.IdentifyImage(dfiFilter)) return;
try { dfiImage.OpenImage(dfiFilter); }
catch(NotImplementedException) { }
if(image.ImageInfo.Heads == dfiImage.ImageInfo.Heads)
if(dfiImage.ImageInfo.Cylinders >= image.ImageInfo.Cylinders)
{
List<BlockTrackType> dfiBlockTrackTypes = new List<BlockTrackType>();
long currentSector = 0;
Stream dfiStream = dfiFilter.GetDataForkStream();
foreach(int t in dfiImage.TrackOffsets.Keys)
{
BlockTrackType dfiBlockTrackType = new BlockTrackType();
dfiBlockTrackType.Cylinder = t / image.ImageInfo.Heads;
dfiBlockTrackType.Head = t % image.ImageInfo.Heads;
dfiBlockTrackType.Image = new ImageType();
dfiBlockTrackType.Image.format = dfiImage.GetImageFormat();
dfiBlockTrackType.Image.Value = Path.GetFileName(dfiFilePath);
if(dfiBlockTrackType.Cylinder < image.ImageInfo.Cylinders)
{
dfiBlockTrackType.StartSector = currentSector;
currentSector += image.ImageInfo.SectorsPerTrack;
dfiBlockTrackType.EndSector = currentSector - 1;
dfiBlockTrackType.Sectors = image.ImageInfo.SectorsPerTrack;
dfiBlockTrackType.BytesPerSector = (int)image.ImageInfo.SectorSize;
dfiBlockTrackType.Format = trkFormat;
}
if(dfiImage.TrackOffsets.TryGetValue(t, out long offset) &&
dfiImage.TrackLengths.TryGetValue(t, out long length))
{
dfiBlockTrackType.Image.offset = offset;
byte[] trackContents = new byte[length];
dfiStream.Position = offset;
dfiStream.Read(trackContents, 0, trackContents.Length);
dfiBlockTrackType.Size = trackContents.Length;
dfiBlockTrackType.Checksums = Checksum.GetChecksums(trackContents).ToArray();
}
dfiBlockTrackTypes.Add(dfiBlockTrackType);
}
sidecar.BlockMedia[0].Track =
dfiBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
}
else
DicConsole
.ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
dfiImage.ImageInfo.Cylinders, image.ImageInfo.Cylinders);
else
DicConsole
.ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
dfiImage.ImageInfo.Heads, image.ImageInfo.Heads);
#endregion
2017-12-19 20:33:03 +00:00
// TODO: Implement support for getting CHS from SCSI mode pages
2017-08-08 13:40:32 +01:00
}
}
2017-12-19 20:33:03 +00:00
}