2017-08-08 13:40:32 +01:00
|
|
|
|
// /***************************************************************************
|
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
|
|
|
|
// Filename : BlockMedia.cs
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
2017-08-08 13:40:32 +01:00
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Component : Core algorithms.
|
2017-08-08 13:40:32 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// 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/>.
|
|
|
|
|
|
//
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2018-12-29 17:34:38 +00:00
|
|
|
|
// Copyright © 2011-2019 Natalia Portillo
|
2017-08-08 13:40:32 +01:00
|
|
|
|
// ****************************************************************************/
|
2017-12-19 03:50:57 +00:00
|
|
|
|
|
2017-12-03 01:49:33 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2017-12-26 06:05:12 +00:00
|
|
|
|
using System.Text;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
using DiscImageChef.CommonTypes;
|
2018-06-25 19:08:16 +01:00
|
|
|
|
using DiscImageChef.CommonTypes.Enums;
|
|
|
|
|
|
using DiscImageChef.CommonTypes.Interfaces;
|
|
|
|
|
|
using DiscImageChef.CommonTypes.Metadata;
|
2017-12-03 01:49:33 +00:00
|
|
|
|
using DiscImageChef.Console;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using DiscImageChef.Decoders.ATA;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
using DiscImageChef.Decoders.PCMCIA;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
using DiscImageChef.DiscImages;
|
2017-12-03 01:49:33 +00:00
|
|
|
|
using DiscImageChef.Filters;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
using Schemas;
|
2018-06-25 19:08:16 +01:00
|
|
|
|
using MediaType = DiscImageChef.CommonTypes.Metadata.MediaType;
|
2017-12-03 01:49:33 +00:00
|
|
|
|
using Tuple = DiscImageChef.Decoders.PCMCIA.Tuple;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
namespace DiscImageChef.Core
|
|
|
|
|
|
{
|
|
|
|
|
|
public static partial class Sidecar
|
|
|
|
|
|
{
|
2017-12-23 01:46:08 +00:00
|
|
|
|
/// <summary>
|
2017-12-23 17:41:23 +00:00
|
|
|
|
/// Creates a metadata sidecar for a block media (e.g. floppy, hard disk, flash card, usb stick)
|
2017-12-23 01:46:08 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="image">Image</param>
|
|
|
|
|
|
/// <param name="filterId">Filter uuid</param>
|
|
|
|
|
|
/// <param name="imagePath">Image path</param>
|
|
|
|
|
|
/// <param name="fi">Image file information</param>
|
|
|
|
|
|
/// <param name="plugins">Image plugins</param>
|
|
|
|
|
|
/// <param name="imgChecksums">List of image checksums</param>
|
|
|
|
|
|
/// <param name="sidecar">Metadata sidecar</param>
|
2018-06-22 08:08:38 +01:00
|
|
|
|
static void BlockMedia(IMediaImage image, Guid filterId, string imagePath,
|
|
|
|
|
|
FileInfo fi, PluginBase plugins,
|
2017-12-26 06:05:12 +00:00
|
|
|
|
List<ChecksumType> imgChecksums, ref CICMMetadataType sidecar, Encoding encoding)
|
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(),
|
2018-06-22 08:08:38 +01:00
|
|
|
|
Image = new ImageType
|
2017-12-19 20:33:03 +00:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
format = image.Format,
|
|
|
|
|
|
offset = 0,
|
2017-12-19 20:33:03 +00:00
|
|
|
|
offsetSpecified = true,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Value = Path.GetFileName(imagePath)
|
2017-12-19 20:33:03 +00:00
|
|
|
|
},
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = fi.Length,
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Sequence = new SequenceType {MediaTitle = image.Info.MediaTitle}
|
2017-08-08 14:18:31 +01:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(image.Info.MediaSequence != 0 && image.Info.LastMediaSequence != 0)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
|
sidecar.BlockMedia[0].Sequence.MediaSequence = image.Info.MediaSequence;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].Sequence.TotalMedia = image.Info.LastMediaSequence;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sidecar.BlockMedia[0].Sequence.MediaSequence = 1;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].Sequence.TotalMedia = 1;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
foreach(MediaTagType tagType in image.Info.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 =
|
2018-12-31 13:17:27 +00:00
|
|
|
|
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
|
|
|
|
|
|
{
|
2018-12-31 13:17:27 +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:
|
2018-06-22 08:08:38 +01:00
|
|
|
|
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)
|
2017-12-23 17:41:23 +00:00
|
|
|
|
switch(tuple.Code)
|
|
|
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
|
case TupleCodes.CISTPL_MANFID:
|
|
|
|
|
|
ManufacturerIdentificationTuple manfid =
|
|
|
|
|
|
CIS.DecodeManufacturerIdentificationTuple(tuple);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
|
if(manfid != null)
|
|
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.ManufacturerCode =
|
|
|
|
|
|
manfid.ManufacturerID;
|
|
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.CardCode = manfid.CardID;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.ManufacturerCodeSpecified = true;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.CardCodeSpecified = true;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
}
|
2018-01-28 20:29:46 +00:00
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
|
break;
|
|
|
|
|
|
case TupleCodes.CISTPL_VERS_1:
|
|
|
|
|
|
Level1VersionTuple vers = CIS.DecodeLevel1VersionTuple(tuple);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
|
if(vers != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.Manufacturer = vers.Manufacturer;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.ProductName = vers.Product;
|
2018-06-22 08:08:38 +01:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.Compliance =
|
2017-12-21 17:58:51 +00:00
|
|
|
|
$"{vers.MajorVersion}.{vers.MinorVersion}";
|
2017-12-23 17:41:23 +00:00
|
|
|
|
sidecar.BlockMedia[0].PCMCIA.AdditionalInformation =
|
|
|
|
|
|
vers.AdditionalInformation;
|
2017-12-21 04:43:29 +00:00
|
|
|
|
}
|
2018-01-28 20:29:46 +00:00
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
|
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
|
|
|
|
|
|
{
|
2018-12-31 13:17:27 +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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_CID).Length
|
2017-08-08 14:18:31 +01:00
|
|
|
|
};
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_CSD).Length
|
2017-08-08 14:18:31 +01:00
|
|
|
|
};
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_SCR).Length
|
2017-09-29 14:43:59 +01:00
|
|
|
|
};
|
|
|
|
|
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_OCR).Length
|
2017-09-29 14:43:59 +01:00
|
|
|
|
};
|
|
|
|
|
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_CID).Length
|
2017-09-29 14:43:59 +01:00
|
|
|
|
};
|
|
|
|
|
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_CSD).Length
|
2017-09-29 14:43:59 +01:00
|
|
|
|
};
|
|
|
|
|
|
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(),
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SD_OCR).Length
|
2017-09-29 14:43:59 +01:00
|
|
|
|
};
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.MMC_ExtendedCSD:
|
|
|
|
|
|
if(sidecar.BlockMedia[0].MultiMediaCard == null)
|
2018-06-22 08:08:38 +01:00
|
|
|
|
sidecar.BlockMedia[0].MultiMediaCard = new MultiMediaCardType();
|
2017-09-29 14:43:59 +01:00
|
|
|
|
sidecar.BlockMedia[0].MultiMediaCard.ExtendedCSD = new DumpType
|
|
|
|
|
|
{
|
2018-12-31 13:17:27 +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;
|
2018-02-02 15:33:25 +00:00
|
|
|
|
case MediaTagType.USB_Descriptors:
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(sidecar.BlockMedia[0].USB == null) sidecar.BlockMedia[0].USB = new USBType();
|
2018-02-02 15:33:25 +00:00
|
|
|
|
sidecar.BlockMedia[0].USB.Descriptors = new DumpType
|
|
|
|
|
|
{
|
2018-12-31 13:17:27 +00:00
|
|
|
|
Checksums = Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.USB_Descriptors))
|
|
|
|
|
|
.ToArray(),
|
2018-02-02 15:33:25 +00:00
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.USB_Descriptors).Length
|
|
|
|
|
|
};
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.SCSI_MODESENSE_6:
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(sidecar.BlockMedia[0].SCSI == null) sidecar.BlockMedia[0].SCSI = new SCSIType();
|
2018-02-02 15:33:25 +00:00
|
|
|
|
sidecar.BlockMedia[0].SCSI.ModeSense = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums =
|
|
|
|
|
|
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_6).Length
|
|
|
|
|
|
};
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MediaTagType.SCSI_MODESENSE_10:
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(sidecar.BlockMedia[0].SCSI == null) sidecar.BlockMedia[0].SCSI = new SCSIType();
|
2018-02-02 15:33:25 +00:00
|
|
|
|
sidecar.BlockMedia[0].SCSI.ModeSense10 = new DumpType
|
|
|
|
|
|
{
|
|
|
|
|
|
Checksums =
|
|
|
|
|
|
Checksum.GetChecksums(image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10)).ToArray(),
|
|
|
|
|
|
Size = image.ReadDiskTag(MediaTagType.SCSI_MODESENSE_10).Length
|
|
|
|
|
|
};
|
|
|
|
|
|
break;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If there is only one track, and it's the same as the image file (e.g. ".iso" files), don't re-checksum.
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(image.Id == new Guid("12345678-AAAA-BBBB-CCCC-123456789000") &&
|
2017-12-23 17:41:23 +00:00
|
|
|
|
filterId == new 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();
|
|
|
|
|
|
|
2017-09-21 18:30:49 +01:00
|
|
|
|
// For fast debugging, skip checksum
|
|
|
|
|
|
//goto skipImageChecksum;
|
|
|
|
|
|
|
2018-01-28 20:29:46 +00:00
|
|
|
|
uint sectorsToRead = 512;
|
|
|
|
|
|
ulong sectors = image.Info.Sectors;
|
|
|
|
|
|
ulong doneSectors = 0;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
InitProgress2();
|
|
|
|
|
|
while(doneSectors < sectors)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] sector;
|
|
|
|
|
|
|
2017-12-20 17:26:28 +00:00
|
|
|
|
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);
|
2017-12-20 17:26:28 +00:00
|
|
|
|
doneSectors += sectors - doneSectors;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
contentChkWorker.Update(sector);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-09-21 18:30:49 +01:00
|
|
|
|
// 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();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
MediaType.MediaTypeToString(image.Info.MediaType, out string dskType, out string dskSubType);
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].DiskType = dskType;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
sidecar.BlockMedia[0].DiskSubType = dskSubType;
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Statistics.AddMedia(image.Info.MediaType, false);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
sidecar.BlockMedia[0].Dimensions = Dimensions.DimensionsFromMediaType(image.Info.MediaType);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].LogicalBlocks = (long)image.Info.Sectors;
|
2017-12-26 06:05:12 +00:00
|
|
|
|
sidecar.BlockMedia[0].LogicalBlockSize = (int)image.Info.SectorSize;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
// TODO: Detect it
|
2017-12-26 06:05:12 +00:00
|
|
|
|
sidecar.BlockMedia[0].PhysicalBlockSize = (int)image.Info.SectorSize;
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
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,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
EndSector = (int)partitions[i].End,
|
|
|
|
|
|
Name = partitions[i].Name,
|
|
|
|
|
|
Sequence = (int)partitions[i].Sequence,
|
2017-08-08 14:18:31 +01:00
|
|
|
|
StartSector = (int)partitions[i].Start,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Type = partitions[i].Type
|
2017-08-08 14:18:31 +01:00
|
|
|
|
};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
List<FileSystemType> lstFs = new List<FileSystemType>();
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(!plugin.Identify(image, partitions[i])) continue;
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
plugin.GetInformation(image, partitions[i], out _, encoding);
|
|
|
|
|
|
lstFs.Add(plugin.XmlFsType);
|
|
|
|
|
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
2018-01-28 20:29:46 +00:00
|
|
|
|
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
2017-08-08 13:40:32 +01:00
|
|
|
|
catch
|
2018-01-28 20:29:46 +00:00
|
|
|
|
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
|
|
|
|
|
//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
|
|
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].FileSystemInformation[0] =
|
2018-06-22 08:08:38 +01:00
|
|
|
|
new PartitionType {StartSector = 0, EndSector = (int)(image.Info.Sectors - 1)};
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
Partition wholePart = new Partition
|
|
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Name = "Whole device",
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Length = image.Info.Sectors,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Size = image.Info.Sectors * image.Info.SectorSize
|
2017-08-08 13:40:32 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
List<FileSystemType> lstFs = new List<FileSystemType>();
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
foreach(IFilesystem plugin in plugins.PluginsList.Values)
|
2017-08-08 13:40:32 +01:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(!plugin.Identify(image, wholePart)) continue;
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
plugin.GetInformation(image, wholePart, out _, encoding);
|
|
|
|
|
|
lstFs.Add(plugin.XmlFsType);
|
|
|
|
|
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
2017-08-08 13:40:32 +01:00
|
|
|
|
}
|
2018-01-28 20:29:46 +00:00
|
|
|
|
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
|
2017-08-08 13:40:32 +01:00
|
|
|
|
catch
|
2018-01-28 20:29:46 +00:00
|
|
|
|
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
|
2017-08-08 13:40:32 +01:00
|
|
|
|
{
|
|
|
|
|
|
//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
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(image.Info.Cylinders > 0 && image.Info.Heads > 0 && image.Info.SectorsPerTrack > 0)
|
2017-08-08 14:28:11 +01:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].CylindersSpecified = true;
|
|
|
|
|
|
sidecar.BlockMedia[0].HeadsSpecified = true;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].Cylinders = image.Info.Cylinders;
|
|
|
|
|
|
sidecar.BlockMedia[0].Heads = image.Info.Heads;
|
|
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrack = image.Info.SectorsPerTrack;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(image.Info.ReadableMediaTags.Contains(MediaTagType.ATA_IDENTIFY))
|
2017-08-08 14:28:11 +01:00
|
|
|
|
{
|
2017-12-23 17:41:23 +00:00
|
|
|
|
Identify.IdentifyDevice? ataId = Identify.Decode(image.ReadDiskTag(MediaTagType.ATA_IDENTIFY));
|
2017-08-08 14:28:11 +01:00
|
|
|
|
if(ataId.HasValue)
|
2018-01-28 20:29:46 +00:00
|
|
|
|
if(ataId.Value.CurrentCylinders > 0 && ataId.Value.CurrentHeads > 0 &&
|
2017-12-19 20:33:03 +00:00
|
|
|
|
ataId.Value.CurrentSectorsPerTrack > 0)
|
2017-08-08 14:28:11 +01:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].CylindersSpecified = true;
|
|
|
|
|
|
sidecar.BlockMedia[0].HeadsSpecified = true;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].Cylinders = ataId.Value.CurrentCylinders;
|
|
|
|
|
|
sidecar.BlockMedia[0].Heads = ataId.Value.CurrentHeads;
|
|
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.CurrentSectorsPerTrack;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
else if(ataId.Value.Cylinders > 0 && ataId.Value.Heads > 0 && ataId.Value.SectorsPerTrack > 0)
|
|
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].CylindersSpecified = true;
|
|
|
|
|
|
sidecar.BlockMedia[0].HeadsSpecified = true;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrackSpecified = true;
|
2018-01-28 20:29:46 +00:00
|
|
|
|
sidecar.BlockMedia[0].Cylinders = ataId.Value.Cylinders;
|
|
|
|
|
|
sidecar.BlockMedia[0].Heads = ataId.Value.Heads;
|
|
|
|
|
|
sidecar.BlockMedia[0].SectorsPerTrack = ataId.Value.SectorsPerTrack;
|
2017-08-08 14:28:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-08-08 13:40:32 +01:00
|
|
|
|
|
2018-01-28 20:29:46 +00:00
|
|
|
|
if(image.DumpHardware != null) sidecar.BlockMedia[0].DumpHardwareArray = image.DumpHardware.ToArray();
|
|
|
|
|
|
|
2017-12-03 01:49:33 +00:00
|
|
|
|
// TODO: This is more of a hack, redo it planned for >4.0
|
2017-12-04 19:35:42 +00:00
|
|
|
|
string trkFormat = null;
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
switch(image.Info.MediaType)
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.Apple32SS:
|
|
|
|
|
|
case CommonTypes.MediaType.Apple32DS:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Apple GCR (DOS 3.2)";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.Apple33SS:
|
|
|
|
|
|
case CommonTypes.MediaType.Apple33DS:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Apple GCR (DOS 3.3)";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.AppleSonySS:
|
|
|
|
|
|
case CommonTypes.MediaType.AppleSonyDS:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Apple GCR (Sony)";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.AppleFileWare:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Apple GCR (Twiggy)";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.DOS_525_SS_DD_9:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_525_DS_DD_8:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_525_DS_DD_9:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_525_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_SS_DD_8:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_SS_DD_9:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_DS_DD_8:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_DS_DD_9:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_35_ED:
|
|
|
|
|
|
case CommonTypes.MediaType.DMF:
|
|
|
|
|
|
case CommonTypes.MediaType.DMF_82:
|
|
|
|
|
|
case CommonTypes.MediaType.XDF_525:
|
|
|
|
|
|
case CommonTypes.MediaType.XDF_35:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM53FD_256:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM53FD_512:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM53FD_1024:
|
|
|
|
|
|
case CommonTypes.MediaType.RX02:
|
|
|
|
|
|
case CommonTypes.MediaType.RX03:
|
|
|
|
|
|
case CommonTypes.MediaType.RX50:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_525_SS_DD_40:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_525_SS_DD_80:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_525_DS_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_35_DS_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_35_DS_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_525_ED:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_525_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_35_SS_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_35_DS_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_35_SS_DD_11:
|
|
|
|
|
|
case CommonTypes.MediaType.ATARI_35_DS_DD_11:
|
|
|
|
|
|
case CommonTypes.MediaType.DOS_525_SS_DD_8:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_8_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_525_SS:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_525_DS:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_525_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_35_HD_8:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_35_HD_15:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_35_TD:
|
|
|
|
|
|
case CommonTypes.MediaType.FDFORMAT_525_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.FDFORMAT_525_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.FDFORMAT_35_DD:
|
|
|
|
|
|
case CommonTypes.MediaType.FDFORMAT_35_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.Apricot_35:
|
|
|
|
|
|
case CommonTypes.MediaType.CompactFloppy:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "IBM MFM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.ATARI_525_SD:
|
|
|
|
|
|
case CommonTypes.MediaType.NEC_8_SD:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_525_SS_SD_40:
|
|
|
|
|
|
case CommonTypes.MediaType.ACORN_525_SS_SD_80:
|
|
|
|
|
|
case CommonTypes.MediaType.RX01:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM23FD:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM33FD_128:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM33FD_256:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM33FD_512:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM43FD_128:
|
|
|
|
|
|
case CommonTypes.MediaType.IBM43FD_256:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "IBM FM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.CBM_35_DD:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Commodore MFM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.CBM_AMIGA_35_HD:
|
|
|
|
|
|
case CommonTypes.MediaType.CBM_AMIGA_35_DD:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Amiga MFM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.CBM_1540:
|
|
|
|
|
|
case CommonTypes.MediaType.CBM_1540_Ext:
|
|
|
|
|
|
case CommonTypes.MediaType.CBM_1571:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Commodore GCR";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.SHARP_525_9:
|
|
|
|
|
|
case CommonTypes.MediaType.SHARP_35_9: break;
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_99_15:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_99_26:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_99_8:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "ISO MFM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
2017-12-21 14:30:38 +00:00
|
|
|
|
case CommonTypes.MediaType.ECMA_54:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_59:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_66:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_69_8:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_69_15:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_69_26:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_70:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_78:
|
|
|
|
|
|
case CommonTypes.MediaType.ECMA_78_2:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "ISO FM";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
2017-12-04 19:35:42 +00:00
|
|
|
|
trkFormat = "Unknown";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-04 19:35:42 +00:00
|
|
|
|
#region SuperCardPro
|
|
|
|
|
|
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
|
2017-12-19 20:33:03 +00:00
|
|
|
|
Path.GetFileNameWithoutExtension(imagePath) + ".scp");
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
|
|
|
|
|
if(File.Exists(scpFilePath))
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
SuperCardPro scpImage = new SuperCardPro();
|
|
|
|
|
|
ZZZNoFilter scpFilter = new ZZZNoFilter();
|
2017-12-04 19:35:42 +00:00
|
|
|
|
scpFilter.Open(scpFilePath);
|
|
|
|
|
|
|
2017-12-28 19:56:36 +00:00
|
|
|
|
if(image.Info.Heads <= 2 && scpImage.Identify(scpFilter))
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-28 19:56:36 +00:00
|
|
|
|
try { scpImage.Open(scpFilter); }
|
2017-12-19 20:33:03 +00:00
|
|
|
|
catch(NotImplementedException) { }
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(image.Info.Heads == 2 && scpImage.Header.heads == 0 || image.Info.Heads == 1 &&
|
|
|
|
|
|
(scpImage.Header.heads == 1 || scpImage.Header.heads == 2))
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(scpImage.Header.end + 1 >= image.Info.Cylinders)
|
2017-12-04 19:35:42 +00:00
|
|
|
|
{
|
|
|
|
|
|
List<BlockTrackType> scpBlockTrackTypes = new List<BlockTrackType>();
|
2018-01-28 20:29:46 +00:00
|
|
|
|
long currentSector = 0;
|
|
|
|
|
|
Stream scpStream = scpFilter.GetDataForkStream();
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
for(byte t = scpImage.Header.start; t <= scpImage.Header.end; t++)
|
2017-12-04 19:35:42 +00:00
|
|
|
|
{
|
2017-12-21 23:00:30 +00:00
|
|
|
|
BlockTrackType scpBlockTrackType = new BlockTrackType
|
|
|
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Cylinder = t / image.Info.Heads,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Head = t % image.Info.Heads,
|
2018-06-22 08:08:38 +01:00
|
|
|
|
Image = new ImageType
|
2017-12-21 23:00:30 +00:00
|
|
|
|
{
|
2017-12-28 19:56:36 +00:00
|
|
|
|
format = scpImage.Format,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Value = Path.GetFileName(scpFilePath),
|
2017-12-21 23:00:30 +00:00
|
|
|
|
offset = scpImage.Header.offsets[t]
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(scpBlockTrackType.Cylinder < image.Info.Cylinders)
|
2017-12-04 19:35:42 +00:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
scpBlockTrackType.StartSector = currentSector;
|
|
|
|
|
|
currentSector += image.Info.SectorsPerTrack;
|
|
|
|
|
|
scpBlockTrackType.EndSector = currentSector - 1;
|
|
|
|
|
|
scpBlockTrackType.Sectors = image.Info.SectorsPerTrack;
|
|
|
|
|
|
scpBlockTrackType.BytesPerSector = (int)image.Info.SectorSize;
|
|
|
|
|
|
scpBlockTrackType.Format = trkFormat;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-26 02:51:10 +00:00
|
|
|
|
if(scpImage.ScpTracks.TryGetValue(t, out SuperCardPro.TrackHeader scpTrack))
|
2017-12-04 19:35:42 +00:00
|
|
|
|
{
|
|
|
|
|
|
byte[] trackContents =
|
2018-06-22 08:08:38 +01:00
|
|
|
|
new byte[scpTrack.Entries.Last().dataOffset +
|
2017-12-23 17:41:23 +00:00
|
|
|
|
scpTrack.Entries.Last().trackLength - scpImage.Header.offsets[t] + 1];
|
2017-12-20 17:15:26 +00:00
|
|
|
|
scpStream.Position = scpImage.Header.offsets[t];
|
2017-12-04 19:35:42 +00:00
|
|
|
|
scpStream.Read(trackContents, 0, trackContents.Length);
|
2018-01-28 20:29:46 +00:00
|
|
|
|
scpBlockTrackType.Size = trackContents.Length;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
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
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
scpImage.Header.end + 1, image.Info.Cylinders);
|
2017-12-04 19:35:42 +00:00
|
|
|
|
else
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
2, image.Info.Heads);
|
2017-12-03 01:49:33 +00:00
|
|
|
|
}
|
2017-12-04 19:35:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-12-04 19:35:42 +00:00
|
|
|
|
#region KryoFlux
|
2018-06-22 08:08:38 +01:00
|
|
|
|
string kfFile = null;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
string basename = Path.Combine(Path.GetDirectoryName(imagePath),
|
2017-12-19 20:33:03 +00:00
|
|
|
|
Path.GetFileNameWithoutExtension(imagePath));
|
2017-12-04 19:35:42 +00:00
|
|
|
|
bool kfDir = false;
|
|
|
|
|
|
|
|
|
|
|
|
if(Directory.Exists(basename))
|
|
|
|
|
|
{
|
|
|
|
|
|
string[] possibleKfStarts = Directory.GetFiles(basename, "*.raw", SearchOption.TopDirectoryOnly);
|
|
|
|
|
|
if(possibleKfStarts.Length > 0)
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-04 19:35:42 +00:00
|
|
|
|
kfFile = possibleKfStarts[0];
|
2018-01-28 20:29:46 +00:00
|
|
|
|
kfDir = true;
|
2017-12-03 01:49:33 +00:00
|
|
|
|
}
|
2017-12-04 19:35:42 +00:00
|
|
|
|
}
|
2018-06-22 08:08:38 +01: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";
|
2017-12-03 01:49:33 +00:00
|
|
|
|
|
2017-12-04 19:35:42 +00:00
|
|
|
|
if(kfFile != null)
|
|
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
KryoFlux kfImage = new KryoFlux();
|
2017-12-21 14:30:38 +00:00
|
|
|
|
ZZZNoFilter kfFilter = new ZZZNoFilter();
|
2017-12-04 19:35:42 +00:00
|
|
|
|
kfFilter.Open(kfFile);
|
2017-12-28 19:56:36 +00:00
|
|
|
|
if(image.Info.Heads <= 2 && kfImage.Identify(kfFilter))
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-28 19:56:36 +00:00
|
|
|
|
try { kfImage.Open(kfFilter); }
|
2017-12-19 20:33:03 +00:00
|
|
|
|
catch(NotImplementedException) { }
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(kfImage.Info.Heads == image.Info.Heads)
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(kfImage.Info.Cylinders >= image.Info.Cylinders)
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-04 19:35:42 +00:00
|
|
|
|
List<BlockTrackType> kfBlockTrackTypes = new List<BlockTrackType>();
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-12-04 19:35:42 +00:00
|
|
|
|
long currentSector = 0;
|
2017-12-03 01:49:33 +00:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
foreach(KeyValuePair<byte, IFilter> kvp in kfImage.tracks)
|
2017-12-03 01:49:33 +00:00
|
|
|
|
{
|
2017-12-21 23:00:30 +00:00
|
|
|
|
BlockTrackType kfBlockTrackType = new BlockTrackType
|
|
|
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Cylinder = kvp.Key / image.Info.Heads,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Head = kvp.Key % image.Info.Heads,
|
2018-06-22 08:08:38 +01:00
|
|
|
|
Image = new ImageType
|
2017-12-21 23:00:30 +00:00
|
|
|
|
{
|
2017-12-28 19:56:36 +00:00
|
|
|
|
format = kfImage.Format,
|
2018-06-22 08:08:38 +01:00
|
|
|
|
Value = kfDir
|
|
|
|
|
|
? Path
|
|
|
|
|
|
.Combine(Path.GetFileName(Path.GetDirectoryName(kvp.Value.GetBasePath())),
|
|
|
|
|
|
kvp.Value.GetFilename())
|
|
|
|
|
|
: kvp.Value.GetFilename(),
|
2017-12-21 23:00:30 +00:00
|
|
|
|
offset = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(kfBlockTrackType.Cylinder < image.Info.Cylinders)
|
2017-12-04 19:35:42 +00:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
kfBlockTrackType.StartSector = currentSector;
|
|
|
|
|
|
currentSector += image.Info.SectorsPerTrack;
|
|
|
|
|
|
kfBlockTrackType.EndSector = currentSector - 1;
|
|
|
|
|
|
kfBlockTrackType.Sectors = image.Info.SectorsPerTrack;
|
|
|
|
|
|
kfBlockTrackType.BytesPerSector = (int)image.Info.SectorSize;
|
|
|
|
|
|
kfBlockTrackType.Format = trkFormat;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
}
|
2017-12-03 01:49:33 +00:00
|
|
|
|
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Stream kfStream = kvp.Value.GetDataForkStream();
|
2017-12-04 19:35:42 +00:00
|
|
|
|
byte[] trackContents = new byte[kfStream.Length];
|
2018-06-22 08:08:38 +01:00
|
|
|
|
kfStream.Position = 0;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
kfStream.Read(trackContents, 0, trackContents.Length);
|
2018-01-28 20:29:46 +00:00
|
|
|
|
kfBlockTrackType.Size = trackContents.Length;
|
2017-12-04 19:35:42 +00:00
|
|
|
|
kfBlockTrackType.Checksums = Checksum.GetChecksums(trackContents).ToArray();
|
|
|
|
|
|
|
|
|
|
|
|
kfBlockTrackTypes.Add(kfBlockTrackType);
|
2017-12-03 01:49:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-04 19:35:42 +00:00
|
|
|
|
sidecar.BlockMedia[0].Track =
|
|
|
|
|
|
kfBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
|
2017-12-03 01:49:33 +00:00
|
|
|
|
}
|
2017-12-04 19:35:42 +00:00
|
|
|
|
else
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
kfImage.Info.Cylinders, image.Info.Cylinders);
|
2017-12-03 01:49:33 +00:00
|
|
|
|
else
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
kfImage.Info.Heads, image.Info.Heads);
|
2017-12-03 01:49:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2017-12-04 19:35:42 +00:00
|
|
|
|
|
2017-12-05 00:07:36 +00:00
|
|
|
|
#region DiscFerret
|
|
|
|
|
|
string dfiFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
|
2017-12-19 20:33:03 +00:00
|
|
|
|
Path.GetFileNameWithoutExtension(imagePath) + ".dfi");
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(!File.Exists(dfiFilePath)) return;
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2018-01-28 20:29:46 +00:00
|
|
|
|
DiscFerret dfiImage = new DiscFerret();
|
2017-12-21 14:30:38 +00:00
|
|
|
|
ZZZNoFilter dfiFilter = new ZZZNoFilter();
|
2017-12-21 06:06:19 +00:00
|
|
|
|
dfiFilter.Open(dfiFilePath);
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2017-12-28 19:56:36 +00:00
|
|
|
|
if(!dfiImage.Identify(dfiFilter)) return;
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2017-12-28 19:56:36 +00:00
|
|
|
|
try { dfiImage.Open(dfiFilter); }
|
2017-12-21 06:06:19 +00:00
|
|
|
|
catch(NotImplementedException) { }
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2018-06-22 08:08:38 +01:00
|
|
|
|
if(image.Info.Heads == dfiImage.Info.Heads)
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(dfiImage.Info.Cylinders >= image.Info.Cylinders)
|
2017-12-21 06:06:19 +00:00
|
|
|
|
{
|
|
|
|
|
|
List<BlockTrackType> dfiBlockTrackTypes = new List<BlockTrackType>();
|
2018-01-28 20:29:46 +00:00
|
|
|
|
long currentSector = 0;
|
|
|
|
|
|
Stream dfiStream = dfiFilter.GetDataForkStream();
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
|
foreach(int t in dfiImage.TrackOffsets.Keys)
|
|
|
|
|
|
{
|
2017-12-21 23:00:30 +00:00
|
|
|
|
BlockTrackType dfiBlockTrackType = new BlockTrackType
|
|
|
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
|
Cylinder = t / image.Info.Heads,
|
2018-01-28 20:29:46 +00:00
|
|
|
|
Head = t % image.Info.Heads,
|
|
|
|
|
|
Image = new ImageType {format = dfiImage.Format, Value = Path.GetFileName(dfiFilePath)}
|
2017-12-21 23:00:30 +00:00
|
|
|
|
};
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
2017-12-26 06:05:12 +00:00
|
|
|
|
if(dfiBlockTrackType.Cylinder < image.Info.Cylinders)
|
2017-12-21 06:06:19 +00:00
|
|
|
|
{
|
2018-01-28 20:29:46 +00:00
|
|
|
|
dfiBlockTrackType.StartSector = currentSector;
|
|
|
|
|
|
currentSector += image.Info.SectorsPerTrack;
|
|
|
|
|
|
dfiBlockTrackType.EndSector = currentSector - 1;
|
|
|
|
|
|
dfiBlockTrackType.Sectors = image.Info.SectorsPerTrack;
|
|
|
|
|
|
dfiBlockTrackType.BytesPerSector = (int)image.Info.SectorSize;
|
|
|
|
|
|
dfiBlockTrackType.Format = trkFormat;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
}
|
2017-12-05 00:07:36 +00:00
|
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
|
if(dfiImage.TrackOffsets.TryGetValue(t, out long offset) &&
|
|
|
|
|
|
dfiImage.TrackLengths.TryGetValue(t, out long length))
|
|
|
|
|
|
{
|
|
|
|
|
|
dfiBlockTrackType.Image.offset = offset;
|
2018-06-22 08:08:38 +01:00
|
|
|
|
byte[] trackContents = new byte[length];
|
|
|
|
|
|
dfiStream.Position = offset;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
dfiStream.Read(trackContents, 0, trackContents.Length);
|
2018-01-28 20:29:46 +00:00
|
|
|
|
dfiBlockTrackType.Size = trackContents.Length;
|
2017-12-21 06:06:19 +00:00
|
|
|
|
dfiBlockTrackType.Checksums = Checksum.GetChecksums(trackContents).ToArray();
|
2017-12-05 00:07:36 +00:00
|
|
|
|
}
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
|
|
dfiBlockTrackTypes.Add(dfiBlockTrackType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sidecar.BlockMedia[0].Track =
|
|
|
|
|
|
dfiBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
|
2017-12-05 00:07:36 +00:00
|
|
|
|
}
|
2017-12-21 06:06:19 +00:00
|
|
|
|
else
|
|
|
|
|
|
DicConsole
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("DiscFerret image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
dfiImage.Info.Cylinders, image.Info.Cylinders);
|
2017-12-21 06:06:19 +00:00
|
|
|
|
else
|
|
|
|
|
|
DicConsole
|
2018-01-28 20:29:46 +00:00
|
|
|
|
.ErrorWriteLine("DiscFerret image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
|
|
|
|
|
|
dfiImage.Info.Heads, image.Info.Heads);
|
2017-12-05 00:07:36 +00:00
|
|
|
|
#endregion
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
2017-08-08 14:28:11 +01: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
|
|
|
|
}
|