Added preliminary support for KryoFlux STREAM disk image format (only sidecar creation)

This commit is contained in:
2017-12-04 19:35:42 +00:00
parent d0462f61df
commit 824ac802b3
5 changed files with 771 additions and 70 deletions

View File

@@ -419,31 +419,24 @@ namespace DiscImageChef.Core
} }
// TODO: This is more of a hack, redo it planned for >4.0 // TODO: This is more of a hack, redo it planned for >4.0
#region SuperCardPro string trkFormat = null;
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
Path.GetFileNameWithoutExtension(imagePath) + ".scp");
ImagePlugins.SuperCardPro scpImage = new SuperCardPro();
Filters.ZZZNoFilter scpFilter = new ZZZNoFilter();
scpFilter.Open(scpFilePath);
string scpFormat = null;
switch(image.ImageInfo.mediaType) switch(image.ImageInfo.mediaType)
{ {
case MediaType.Apple32SS: case MediaType.Apple32SS:
case MediaType.Apple32DS: case MediaType.Apple32DS:
scpFormat = "Apple GCR (DOS 3.2)"; trkFormat = "Apple GCR (DOS 3.2)";
break; break;
case MediaType.Apple33SS: case MediaType.Apple33SS:
case MediaType.Apple33DS: case MediaType.Apple33DS:
scpFormat = "Apple GCR (DOS 3.3)"; trkFormat = "Apple GCR (DOS 3.3)";
break; break;
case MediaType.AppleSonySS: case MediaType.AppleSonySS:
case MediaType.AppleSonyDS: case MediaType.AppleSonyDS:
scpFormat = "Apple GCR (Sony)"; trkFormat = "Apple GCR (Sony)";
break; break;
case MediaType.AppleFileWare: case MediaType.AppleFileWare:
scpFormat = "Apple GCR (Twiggy)"; trkFormat = "Apple GCR (Twiggy)";
break; break;
case MediaType.DOS_525_SS_DD_9: case MediaType.DOS_525_SS_DD_9:
case MediaType.DOS_525_DS_DD_8: case MediaType.DOS_525_DS_DD_8:
@@ -490,7 +483,7 @@ namespace DiscImageChef.Core
case MediaType.FDFORMAT_35_HD: case MediaType.FDFORMAT_35_HD:
case MediaType.Apricot_35: case MediaType.Apricot_35:
case MediaType.CompactFloppy: case MediaType.CompactFloppy:
scpFormat = "IBM MFM"; trkFormat = "IBM MFM";
break; break;
case MediaType.ATARI_525_SD: case MediaType.ATARI_525_SD:
case MediaType.NEC_8_SD: case MediaType.NEC_8_SD:
@@ -503,19 +496,19 @@ namespace DiscImageChef.Core
case MediaType.IBM33FD_512: case MediaType.IBM33FD_512:
case MediaType.IBM43FD_128: case MediaType.IBM43FD_128:
case MediaType.IBM43FD_256: case MediaType.IBM43FD_256:
scpFormat = "IBM FM"; trkFormat = "IBM FM";
break; break;
case MediaType.CBM_35_DD: case MediaType.CBM_35_DD:
scpFormat = "Commodore MFM"; trkFormat = "Commodore MFM";
break; break;
case MediaType.CBM_AMIGA_35_HD: case MediaType.CBM_AMIGA_35_HD:
case MediaType.CBM_AMIGA_35_DD: case MediaType.CBM_AMIGA_35_DD:
scpFormat = "Amiga MFM"; trkFormat = "Amiga MFM";
break; break;
case MediaType.CBM_1540: case MediaType.CBM_1540:
case MediaType.CBM_1540_Ext: case MediaType.CBM_1540_Ext:
case MediaType.CBM_1571: case MediaType.CBM_1571:
scpFormat = "Commodore GCR"; trkFormat = "Commodore GCR";
break; break;
case MediaType.SHARP_525: case MediaType.SHARP_525:
case MediaType.SHARP_525_9: case MediaType.SHARP_525_9:
@@ -529,7 +522,7 @@ namespace DiscImageChef.Core
case MediaType.ECMA_125: case MediaType.ECMA_125:
case MediaType.ECMA_147: case MediaType.ECMA_147:
case MediaType.ECMA_99_8: case MediaType.ECMA_99_8:
scpFormat = "ISO MFM"; trkFormat = "ISO MFM";
break; break;
case MediaType.ECMA_54: case MediaType.ECMA_54:
case MediaType.ECMA_59: case MediaType.ECMA_59:
@@ -540,78 +533,186 @@ namespace DiscImageChef.Core
case MediaType.ECMA_70: case MediaType.ECMA_70:
case MediaType.ECMA_78: case MediaType.ECMA_78:
case MediaType.ECMA_78_2: case MediaType.ECMA_78_2:
scpFormat = "ISO FM"; trkFormat = "ISO FM";
break; break;
default: default:
scpFormat = "Unknown"; trkFormat = "Unknown";
break; break;
} }
if(image.ImageInfo.heads <= 2 && File.Exists(scpFilePath) && scpImage.IdentifyImage(scpFilter)) #region SuperCardPro
string scpFilePath = Path.Combine(Path.GetDirectoryName(imagePath),
Path.GetFileNameWithoutExtension(imagePath) + ".scp");
if(File.Exists(scpFilePath))
{ {
try ImagePlugins.SuperCardPro scpImage = new SuperCardPro();
{ Filters.ZZZNoFilter scpFilter = new ZZZNoFilter();
scpImage.OpenImage(scpFilter); scpFilter.Open(scpFilePath);
}
catch(NotImplementedException)
{
}
if((image.ImageInfo.heads == 2 && scpImage.header.heads == 0) || if(image.ImageInfo.heads <= 2 && scpImage.IdentifyImage(scpFilter))
(image.ImageInfo.heads == 1 && (scpImage.header.heads == 1 || scpImage.header.heads == 2)))
{ {
if(scpImage.header.end + 1 >= image.ImageInfo.cylinders)
try
{ {
ImageType scpImageType = new ImageType(); scpImage.OpenImage(scpFilter);
scpImageType.format = "SuperCardPro"; }
scpImageType.Value = Path.GetFileName(scpFilePath); catch(NotImplementedException)
List<BlockTrackType> scpBlockTrackTypes = new List<BlockTrackType>(); {
long currentSector = 0; }
Stream scpStream = scpFilter.GetDataForkStream();
for(byte t = scpImage.header.start; t <= scpImage.header.end; t++) 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)
{ {
BlockTrackType scpBlockTrackType = new BlockTrackType(); List<BlockTrackType> scpBlockTrackTypes = new List<BlockTrackType>();
scpBlockTrackType.Cylinder = t / image.ImageInfo.heads; long currentSector = 0;
scpBlockTrackType.Head = t % image.ImageInfo.heads; Stream scpStream = scpFilter.GetDataForkStream();
scpBlockTrackType.Image = scpImageType;
scpBlockTrackType.Image.offset = scpImage.header.offsets[t];
if(scpBlockTrackType.Cylinder < image.ImageInfo.cylinders) for(byte t = scpImage.header.start; t <= scpImage.header.end; t++)
{ {
scpBlockTrackType.StartSector = currentSector; BlockTrackType scpBlockTrackType = new BlockTrackType();
currentSector += image.ImageInfo.sectorsPerTrack; scpBlockTrackType.Cylinder = t / image.ImageInfo.heads;
scpBlockTrackType.EndSector = currentSector - 1; scpBlockTrackType.Head = t % image.ImageInfo.heads;
scpBlockTrackType.Sectors = image.ImageInfo.sectorsPerTrack; scpBlockTrackType.Image = new ImageType();
scpBlockTrackType.BytesPerSector = (int)image.ImageInfo.sectorSize; scpBlockTrackType.Image.format = scpImage.GetImageFormat();
scpBlockTrackType.Format = scpFormat; 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);
} }
if(scpImage.tracks.TryGetValue(t, out SuperCardPro.TrackHeader scpTrack)) sidecar.BlockMedia[0].Track =
{ scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray();
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);
} }
else
sidecar.BlockMedia[0].Track = DicConsole.ErrorWriteLine(
scpBlockTrackTypes.OrderBy(t => t.Cylinder).ThenBy(t => t.Head).ToArray(); "SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
scpImage.header.end + 1, image.ImageInfo.cylinders);
} }
else else
DicConsole.ErrorWriteLine("SuperCardPro image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...", scpImage.header.end + 1, image.ImageInfo.cylinders); DicConsole.ErrorWriteLine(
"SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
2, image.ImageInfo.heads);
} }
else
DicConsole.ErrorWriteLine("SuperCardPro image do not contain same number of heads ({0}) than disk image ({1}), ignoring...", 2, image.ImageInfo.heads);
} }
#endregion #endregion
#region KryoFlux
string kfFile = null;
string basename = Path.Combine(Path.GetDirectoryName(imagePath),
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;
}
}
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)
{
ImagePlugins.KryoFlux kfImage = new KryoFlux();
Filters.ZZZNoFilter kfFilter = new ZZZNoFilter();
kfFilter.Open(kfFile);
if(image.ImageInfo.heads <= 2 && kfImage.IdentifyImage(kfFilter))
{
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>();
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
? 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
DicConsole.ErrorWriteLine(
"KryoFlux image do not contain same number of tracks ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.cylinders, image.ImageInfo.cylinders);
}
else
DicConsole.ErrorWriteLine(
"KryoFluximage do not contain same number of heads ({0}) than disk image ({1}), ignoring...",
kfImage.ImageInfo.heads, image.ImageInfo.heads);
}
}
#endregion
// TODO: Implement support for getting CHS from SCSI mode pages // TODO: Implement support for getting CHS from SCSI mode pages
} }
} }

View File

@@ -51,6 +51,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="KryoFlux.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Apple2MG.cs" /> <Compile Include="Apple2MG.cs" />
<Compile Include="CDRWin.cs" /> <Compile Include="CDRWin.cs" />

View File

@@ -0,0 +1,598 @@
// /***************************************************************************
// The Disc Image Chef
// ----------------------------------------------------------------------------
//
// Filename : KryoFlux.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Disc image plugins.
//
// --[ Description ] ----------------------------------------------------------
//
// Manages KryoFlux disk images.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2017 Natalia Portillo
// ****************************************************************************/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
using DiscImageChef.Console;
using DiscImageChef.Filters;
namespace DiscImageChef.ImagePlugins
{
public class KryoFlux : ImagePlugin
{
#region Internal Structures
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct OobBlock
{
public BlockIds blockId;
public OobTypes blockType;
public ushort length;
}
#endregion Internal Structures
#region Internal Constants
public enum BlockIds : byte
{
Flux2 = 0x00,
Flux2_1 = 0x01,
Flux2_2 = 0x02,
Flux2_3 = 0x03,
Flux2_4 = 0x04,
Flux2_5 = 0x05,
Flux2_6 = 0x06,
Flux2_7 = 0x07,
Nop1 = 0x08,
Nop2 = 0x09,
Nop3 = 0x0A,
Ovl16 = 0x0B,
Flux3 = 0x0C,
Oob = 0x0D
}
public enum OobTypes : byte
{
Invalid = 0x00,
StreamInfo = 0x01,
Index = 0x02,
StreamEnd = 0x03,
KFInfo = 0x04,
EOF = 0x0D
}
const string hostDate = "host_date";
const string hostTime = "host_time";
const string kfName = "name";
const string kfVersion= "version";
const string kfDate = "date";
const string kfTime = "time";
const string kfHwId = "hwid";
const string kfHwRv = "hwrv";
const string kfSck = "sck";
const string kfIck = "ick";
#endregion Internal Constants
#region Internal variables
// TODO: These variables have been made public so create-sidecar can access to this information until I define an API >4.0
public SortedDictionary<byte, Filter> tracks;
#endregion Internal variables
public KryoFlux()
{
Name = "KryoFlux STREAM";
PluginUUID = new Guid("4DBC95E4-93EE-4F7A-9492-919887E60EFE");
ImageInfo = new ImageInfo()
{
readableSectorTags = new List<SectorTagType>(),
readableMediaTags = new List<MediaTagType>(),
imageHasPartitions = false,
imageHasSessions = false,
imageVersion = null,
imageApplication = null,
imageApplicationVersion = null,
imageCreator = null,
imageComments = null,
mediaManufacturer = null,
mediaModel = null,
mediaSerialNumber = null,
mediaBarcode = null,
mediaPartNumber = null,
mediaSequence = 0,
lastMediaSequence = 0,
driveManufacturer = null,
driveModel = null,
driveSerialNumber = null,
driveFirmwareRevision = null
};
}
#region Public methods
public override bool IdentifyImage(Filter imageFilter)
{
OobBlock header = new OobBlock();
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
if(stream.Length < Marshal.SizeOf(header))
return false;
byte[] hdr = new byte[Marshal.SizeOf(header)];
stream.Read(hdr, 0, Marshal.SizeOf(header));
IntPtr hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(header));
Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(header));
header = (OobBlock)Marshal.PtrToStructure(hdrPtr, typeof(OobBlock));
Marshal.FreeHGlobal(hdrPtr);
OobBlock footer = new OobBlock();
stream.Seek(-Marshal.SizeOf(footer), SeekOrigin.End);
hdr = new byte[Marshal.SizeOf(footer)];
stream.Read(hdr, 0, Marshal.SizeOf(footer));
hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(footer));
Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(footer));
footer = (OobBlock)Marshal.PtrToStructure(hdrPtr, typeof(OobBlock));
Marshal.FreeHGlobal(hdrPtr);
return header.blockId == BlockIds.Oob && header.blockType == OobTypes.KFInfo &&
footer.blockId == BlockIds.Oob && footer.blockType == OobTypes.EOF && footer.length == 0x0D0D;
}
public override bool OpenImage(Filter imageFilter)
{
OobBlock header = new OobBlock();
Stream stream = imageFilter.GetDataForkStream();
stream.Seek(0, SeekOrigin.Begin);
if(stream.Length < Marshal.SizeOf(header))
return false;
byte[] hdr = new byte[Marshal.SizeOf(header)];
stream.Read(hdr, 0, Marshal.SizeOf(header));
IntPtr hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(header));
Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(header));
header = (OobBlock)Marshal.PtrToStructure(hdrPtr, typeof(OobBlock));
Marshal.FreeHGlobal(hdrPtr);
OobBlock footer = new OobBlock();
stream.Seek(-Marshal.SizeOf(footer), SeekOrigin.End);
hdr = new byte[Marshal.SizeOf(footer)];
stream.Read(hdr, 0, Marshal.SizeOf(footer));
hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(footer));
Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(footer));
footer = (OobBlock)Marshal.PtrToStructure(hdrPtr, typeof(OobBlock));
Marshal.FreeHGlobal(hdrPtr);
if(header.blockId != BlockIds.Oob || header.blockType != OobTypes.KFInfo ||
footer.blockId != BlockIds.Oob || footer.blockType != OobTypes.EOF ||
footer.length != 0x0D0D) return false;
#region TODO: This is supposing NoFilter, shouldn't
tracks = new SortedDictionary<byte, Filter>();
byte step = 1;
byte heads = 2;
bool topHead = false;
string basename = Path.Combine(imageFilter.GetParentFolder(),
imageFilter.GetFilename().Substring(0, imageFilter.GetFilename().Length - 8));
for(byte t = 0; t < 166; t += step)
{
int cylinder = t / heads;
int head = topHead ? 1 : t % heads;
string trackfile = Directory.Exists(basename)
? Path.Combine(basename, string.Format("{0:D2}.{1:D1}.raw", cylinder, head))
: string.Format("{0}{1:D2}.{2:D1}.raw", basename, cylinder, head);
if(!File.Exists(trackfile))
{
if(cylinder == 0)
{
if(head == 0)
{
DicConsole.DebugWriteLine("KryoFlux plugin", "Cannot find cyl 0 hd 0, supposing only top head was dumped");
topHead = true;
heads = 1;
continue;
}
DicConsole.DebugWriteLine("KryoFlux plugin", "Cannot find cyl 0 hd 1, supposing only bottom head was dumped");
heads = 1;
continue;
}
else if(cylinder == 1)
{
DicConsole.DebugWriteLine("KryoFlux plugin", "Cannot find cyl 1, supposing double stepping");
step = 2;
continue;
}
else
{
DicConsole.DebugWriteLine("KryoFlux plugin", "Arrived end of disk at cylinder {0}", cylinder);
step = 2;
break;
}
}
ZZZNoFilter trackFilter = new ZZZNoFilter();
trackFilter.Open(trackfile);
if(!trackFilter.IsOpened())
throw new IOException("Could not open KryoFlux track file.");
ImageInfo.imageCreationTime = DateTime.MaxValue;
ImageInfo.imageLastModificationTime = DateTime.MinValue;
Stream trackStream = trackFilter.GetDataForkStream();
while(trackStream.Position < trackStream.Length)
{
byte blockId = (byte)trackStream.ReadByte();
switch(blockId)
{
case (byte)BlockIds.Oob:
{
trackStream.Position--;
OobBlock oobBlk = new OobBlock();
byte[] oob = new byte[Marshal.SizeOf(oobBlk)];
trackStream.Read(oob, 0, Marshal.SizeOf(oobBlk));
IntPtr oobPtr = Marshal.AllocHGlobal(Marshal.SizeOf(oobBlk));
Marshal.Copy(oob, 0, oobPtr, Marshal.SizeOf(oobBlk));
oobBlk = (OobBlock)Marshal.PtrToStructure(oobPtr, typeof(OobBlock));
Marshal.FreeHGlobal(oobPtr);
if(oobBlk.blockType == OobTypes.EOF)
{
trackStream.Position = trackStream.Length;
break;
}
if(oobBlk.blockType != OobTypes.KFInfo)
{
trackStream.Position += oobBlk.length;
break;
}
byte[] kfinfo = new byte[oobBlk.length];
trackStream.Read(kfinfo, 0, oobBlk.length);
string kfinfoStr = StringHandlers.CToString(kfinfo);
string[] lines = kfinfoStr.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
DateTime blockDate = DateTime.Now;
DateTime blockTime = DateTime.Now;
bool foundDate = false;
foreach(string line in lines)
{
string[] kvp = line.Split('=');
if(kvp.Length != 2)
continue;
kvp[0] = kvp[0].Trim();
kvp[1] = kvp[1].Trim();
DicConsole.DebugWriteLine("KryoFlux plugin", "\"{0}\" = \"{1}\"", kvp[0], kvp[1]);
if(kvp[0] == hostDate)
{
if(DateTime.TryParseExact(kvp[1], "yyyy.MM.dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal,
out blockDate))
foundDate = true;
}
else if(kvp[0] == hostTime)
{
DateTime.TryParseExact(kvp[1], "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal,
out blockTime);
}
else if(kvp[0] == kfName)
ImageInfo.imageApplication = kvp[1];
else if(kvp[0] == kfVersion)
ImageInfo.imageApplicationVersion = kvp[1];
}
if(foundDate)
{
DateTime blockTimestamp = new DateTime(blockDate.Year, blockDate.Month, blockDate.Day,
blockTime.Hour, blockTime.Minute, blockTime.Second);
DicConsole.DebugWriteLine("KryoFlux plugin", "Found timestamp: {0}", blockTimestamp);
if(blockTimestamp < ImageInfo.imageCreationTime)
ImageInfo.imageCreationTime = blockTimestamp;
if(blockTimestamp > ImageInfo.imageLastModificationTime)
ImageInfo.imageLastModificationTime= blockTimestamp;
}
break;
}
case (byte)BlockIds.Flux2:
case (byte)BlockIds.Flux2_1:
case (byte)BlockIds.Flux2_2:
case (byte)BlockIds.Flux2_3:
case (byte)BlockIds.Flux2_4:
case (byte)BlockIds.Flux2_5:
case (byte)BlockIds.Flux2_6:
case (byte)BlockIds.Flux2_7:
case (byte)BlockIds.Nop2:
trackStream.Position++;
continue;
case (byte)BlockIds.Nop3:
case (byte)BlockIds.Flux3:
trackStream.Position += 2;
continue;
default:
continue;
}
}
tracks.Add(t, trackFilter);
}
ImageInfo.heads = heads;
ImageInfo.cylinders = (uint)(tracks.Count / heads);
#endregion TODO: This is supposing NoFilter, shouldn't
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override bool ImageHasPartitions()
{
return ImageInfo.imageHasPartitions;
}
public override ulong GetImageSize()
{
return ImageInfo.imageSize;
}
public override ulong GetSectors()
{
return ImageInfo.sectors;
}
public override uint GetSectorSize()
{
return ImageInfo.sectorSize;
}
public override byte[] ReadDiskTag(MediaTagType tag)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override byte[] ReadSector(ulong sectorAddress)
{
return ReadSectors(sectorAddress, 1);
}
public override byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override byte[] ReadSectors(ulong sectorAddress, uint length)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override byte[] ReadSectorLong(ulong sectorAddress)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override byte[] ReadSectorLong(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsLong(ulong sectorAddress, uint length)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override string GetImageFormat()
{
return "KryoFlux STREAM";
}
public override string GetImageVersion()
{
return ImageInfo.imageVersion;
}
public override string GetImageApplication()
{
return ImageInfo.imageApplication;
}
public override string GetImageApplicationVersion()
{
return ImageInfo.imageApplicationVersion;
}
public override string GetImageCreator()
{
return ImageInfo.imageCreator;
}
public override DateTime GetImageCreationTime()
{
return ImageInfo.imageCreationTime;
}
public override DateTime GetImageLastModificationTime()
{
return ImageInfo.imageLastModificationTime;
}
public override string GetImageName()
{
return ImageInfo.imageName;
}
public override string GetImageComments()
{
return ImageInfo.imageComments;
}
public override string GetMediaManufacturer()
{
return ImageInfo.mediaManufacturer;
}
public override string GetMediaModel()
{
return ImageInfo.mediaModel;
}
public override string GetMediaSerialNumber()
{
return ImageInfo.mediaSerialNumber;
}
public override string GetMediaBarcode()
{
return ImageInfo.mediaBarcode;
}
public override string GetMediaPartNumber()
{
return ImageInfo.mediaPartNumber;
}
public override MediaType GetMediaType()
{
return ImageInfo.mediaType;
}
public override int GetMediaSequence()
{
return ImageInfo.mediaSequence;
}
public override int GetLastDiskSequence()
{
return ImageInfo.lastMediaSequence;
}
public override string GetDriveManufacturer()
{
return ImageInfo.driveManufacturer;
}
public override string GetDriveModel()
{
return ImageInfo.driveModel;
}
public override string GetDriveSerialNumber()
{
return ImageInfo.driveSerialNumber;
}
public override bool? VerifySector(ulong sectorAddress)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
public override bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{
throw new NotImplementedException("Flux decoding is not yet implemented.");
}
#endregion Public methods
#region Unsupported features
public override byte[] ReadSector(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectors(ulong sectorAddress, uint length, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Partition> GetPartitions()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetTracks()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetSessionTracks(Session session)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Track> GetSessionTracks(ushort session)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override List<Session> GetSessions()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifySector(ulong sectorAddress, uint track)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
public override bool? VerifyMediaImage()
{
throw new FeatureUnsupportedImageException("Feature not supported by image format");
}
#endregion Unsupported features
}
}

View File

@@ -441,7 +441,7 @@ namespace DiscImageChef.ImagePlugins
throw new NotImplementedException("Flux decoding is not yet implemented."); throw new NotImplementedException("Flux decoding is not yet implemented.");
} }
public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs) public override bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{ {
throw new NotImplementedException("Flux decoding is not yet implemented."); throw new NotImplementedException("Flux decoding is not yet implemented.");
} }
@@ -507,7 +507,7 @@ namespace DiscImageChef.ImagePlugins
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }
public override bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs) public override bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> FailingLBAs, out List<ulong> UnknownLBAs)
{ {
throw new FeatureUnsupportedImageException("Feature not supported by image format"); throw new FeatureUnsupportedImageException("Feature not supported by image format");
} }

View File

@@ -215,4 +215,5 @@ Supported filters
Partially supported disk image formats Partially supported disk image formats
====================================== ======================================
This disk image formats cannot be read, but their contents can be checksummed on sidecar creation This disk image formats cannot be read, but their contents can be checksummed on sidecar creation
* KryoFlux STREAM
* SuperCardPro * SuperCardPro