* FileSystemIDandChk/ArrayFill.cs:

* FileSystemIDandChk/FileSystemIDandChk.csproj:
	  Added array filling class from mykohsu.

	* FileSystemIDandChk/Main.cs:
	  Print disk type as identified by image plugin

	* FileSystemIDandChk/ImagePlugins/ImagePlugin.cs:
	  Added more disk types

	* FileSystemIDandChk/ImagePlugins/TeleDisk.cs:
	  Added link to Dave's document.
	Completely implemented OpenImage() for standard
	  (non-compressed) teledisk images.
	Implemented GetImageSize(), GetSectors(), GetSectorSize(),
	  ReadSectors(), GetImageVersion(),
	  GetImageApplicationVersion(), GetImageCreationTime(),
	  GetImageLastModificationtime(), GetImageName(),
	  GetDiskType(), data sector decoders.

	* FileSystemIDandChk/TODO:
	  Discovered a filesystem specification present on ECMA-67.
	  Dunno if CP/M, FAT or a different one, must check.
	Teledisk plugin is working, but lacks "advanced compression"
	  and variable sectors per track support.
This commit is contained in:
2014-06-07 04:54:15 +01:00
parent 4a35b934e5
commit 8e0dde88bc
6 changed files with 661 additions and 16 deletions

View File

@@ -0,0 +1,70 @@
/***************************************************************************
FileSystem identifier and checker
----------------------------------------------------------------------------
Filename : ArrayFill.cs
Version : 1.0
Author(s) : https://github.com/mykohsu
Component : Helpers
Revision : $Revision$
Last change by : $Author$
Date : $Date$
--[ Description ] ----------------------------------------------------------
Fills an array with a
--[ License ] --------------------------------------------------------------
No license specified by creator.
Published on https://github.com/mykohsu/Extensions/blob/master/ArrayExtensions.cs
Assuming open source.
----------------------------------------------------------------------------
Copyright (C) 2014 mykohsu
****************************************************************************/
//$Id$
using System;
namespace FileSystemIDandChk
{
public static class ArrayHelpers
{
public static void ArrayFill<T>(T[] destinationArray, T value)
{
// if called with a single value, wrap the value in an array and call the main function
ArrayFill<T>(destinationArray, new T[] { value });
}
public static void ArrayFill<T>(T[] destinationArray, T[] value)
{
if (destinationArray == null)
{
throw new ArgumentNullException("destinationArray");
}
if (value.Length > destinationArray.Length)
{
throw new ArgumentException("Length of value array must not be more than length of destination");
}
// set the initial array value
Array.Copy(value, destinationArray, value.Length);
int arrayToFillHalfLength = destinationArray.Length / 2;
int copyLength;
for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1)
{
Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
}
Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}
}
}

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7A4B05BE-73C9-4F34-87FE-E80CCF1F732D}</ProjectGuid>
<OutputType>Exe</OutputType>
@@ -73,6 +73,7 @@
<Compile Include="ImagePlugins\DiskCopy42.cs" />
<Compile Include="Plugins\LisaFS.cs" />
<Compile Include="ImagePlugins\TeleDisk.cs" />
<Compile Include="ArrayFill.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

View File

@@ -365,7 +365,94 @@ namespace FileSystemIDandChk.ImagePlugins
// 8", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM
RX01,
// 8", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM
RX02
RX02,
// Acorn standard floppy formats
// 5,25", SS, SD, 40 tracks, 10 spt, 256 bytes/sector, FM
ACORN_525_SS_SD_40,
// 5,25", SS, SD, 80 tracks, 10 spt, 256 bytes/sector, FM
ACORN_525_SS_SD_80,
// 5,25", SS, DD, 40 tracks, 16 spt, 256 bytes/sector, MFM
ACORN_525_SS_DD_40,
// 5,25", SS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM
ACORN_525_SS_DD_80,
// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM
ACORN_525_DS_DD,
// Atari standard floppy formats
// 5,25", SS, SD, 40 tracks, 18 spt, 128 bytes/sector, FM
ATARI_525_SD,
// 5,25", SS, ED, 40 tracks, 26 spt, 128 bytes/sector, MFM
ATARI_525_ED,
// 5,25", SS, DD, 40 tracks, 18 spt, 256 bytes/sector, MFM
ATARI_525_DD,
// Commodore standard floppy formats
// 3,5", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM
CBM_35_DD,
// 3,5", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM (Amiga)
CBM_AMIGA_35_DD,
// 3,5", DS, HD, 80 tracks, 22 spt, 512 bytes/sector, MFM (Amiga)
CBM_AMIGA_35_HD,
// NEC standard floppy formats
// 8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
NEC_8_SD,
// 8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, MFM
NEC_8_DD,
// 5,25", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM
NEC_525_HD,
// 3,5", DS, HD, 80 tracks, 8 spt, 1024 bytes/sector, MFM
NEC_35_HD_8,
// 3,5", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM
NEC_35_HD_15,
// SHARP standard floppy formats
// 5,25", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM
SHARP_525,
// 3,5", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM
SHARP_35,
// ECMA standards
// 5,25", DS, DD, 80 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_99_8,
// 5,25", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_99_15,
// 5,25", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_99_26,
// 3,5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM
ECMA_100,
// 3,5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM
ECMA_125,
// 3,5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM
ECMA_147,
// 8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
ECMA_54,
// 8", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM
ECMA_59,
// 5,25", SS, DD, 35 tracks, 9 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector
ECMA_66,
// 8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_69_8,
// 8", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_69_15,
// 8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector
ECMA_69_26,
// 5,25", DS, DD, 40 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector
ECMA_70,
// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector
ECMA_78,
// 5,25", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM
ECMA_78_2,
// 3,5", M.O., 250000 sectors, 512 bytes/sector
ECMA_154,
// 5,25", M.O., 940470 sectors, 512 bytes/sector
ECMA_183_512,
// 5,25", M.O., 520902 sectors, 1024 bytes/sector
ECMA_183_1024,
// 5,25", M.O., 1165600 sectors, 512 bytes/sector
ECMA_184_512,
// 5,25", M.O., 639200 sectors, 1024 bytes/sector
ECMA_184_1024,
// 3,5", M.O., 448500 sectors, 512 bytes/sector
ECMA_201,
// FDFORMAT, non-standard floppy formats
// 5,25", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM
FDFORMAT_525_DD
};
// Track (as partitioning element) types
public enum TrackType

View File

@@ -41,6 +41,7 @@ using System.IO;
using System.Collections.Generic;
// Created following notes from Dave Dunfield
// http://www.classiccmp.org/dunfield/img54306/td0notes.txt
namespace FileSystemIDandChk.ImagePlugins
{
class TeleDisk : ImagePlugin
@@ -193,7 +194,12 @@ namespace FileSystemIDandChk.ImagePlugins
string comment;
DateTime creationDate;
DateTime modificationDate;
Dictionary<UInt32, byte[]> sectorsData; // LBA, data
UInt32 totalDiskSize;
UInt64 imageSizeWithoutHeaders;
string imageName;
string telediskVersion;
UInt32 biggestSectorSize;
#endregion
public TeleDisk(PluginBase Core)
@@ -287,6 +293,9 @@ namespace FileSystemIDandChk.ImagePlugins
header.sides = headerBytes[9];
header.crc = BitConverter.ToUInt16(headerBytes, 10);
imageName = Path.GetFileNameWithoutExtension(imagePath);
telediskVersion = String.Format("{0}.{1}", (header.version & 0xF0) >> 4, header.version & 0x0F);
byte[] headerBytesForCRC = new byte[10];
Array.Copy(headerBytes, headerBytesForCRC, 10);
UInt16 calculatedHeaderCRC = TeleDiskCRC(0x0000, headerBytesForCRC);
@@ -398,7 +407,165 @@ namespace FileSystemIDandChk.ImagePlugins
Console.WriteLine("DEBUG (TeleDisk plugin): Image modified on {0}", modificationDate);
}
return false;
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Parsing image");
totalDiskSize = 0;
byte spt = 0;
imageSizeWithoutHeaders = 0;
sectorsData = new Dictionary<uint, byte[]>();
biggestSectorSize = 0;
while (true)
{
TDTrackHeader TDTrack = new TDTrackHeader();
byte[] TDTrackForCRC = new byte[3];
byte TDTrackCalculatedCRC;
TDTrack.sectors = (byte)stream.ReadByte();
TDTrack.cylinder = (byte)stream.ReadByte();
TDTrack.head = (byte)stream.ReadByte();
TDTrack.crc = (byte)stream.ReadByte();
TDTrackForCRC[0] = TDTrack.sectors;
TDTrackForCRC[1] = TDTrack.cylinder;
TDTrackForCRC[2] = TDTrack.head;
TDTrackCalculatedCRC = (byte)(TeleDiskCRC(0, TDTrackForCRC) & 0xFF);
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): Track follows");
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack cylinder: {0}\t", TDTrack.cylinder);
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack head: {0}\t", TDTrack.head);
Console.WriteLine("DEBUG (TeleDisk plugin): \tSectors in track: {0}\t", TDTrack.sectors);
Console.WriteLine("DEBUG (TeleDisk plugin): \tTrack header CRC: 0x{0:X2} (calculated 0x{1:X2})\t", TDTrack.crc, TDTrackCalculatedCRC);
}
if (TDTrack.sectors == 0xFF) // End of disk image
{
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): End of disk image arrived");
Console.WriteLine("DEBUG (TeleDisk plugin): Total of {0} data sectors, for {1} bytes", sectorsData.Count, totalDiskSize);
}
break;
}
if (spt != TDTrack.sectors)
{
if (spt != 0)
throw new FeatureUnsupportedImageException("Variable number of sectors per track. This kind of image is not yet supported");
else
spt = TDTrack.sectors;
}
for (byte processedSectors = 0; processedSectors < TDTrack.sectors; processedSectors++)
{
TDSectorHeader TDSector = new TDSectorHeader();
TDDataHeader TDData = new TDDataHeader();
byte[] dataSizeBytes = new byte[2];
byte[] data;
byte[] decodedData;
TDSector.cylinder = (byte)stream.ReadByte();
TDSector.head = (byte)stream.ReadByte();
TDSector.sectorNumber = (byte)stream.ReadByte();
TDSector.sectorSize = (byte)stream.ReadByte();
TDSector.flags = (byte)stream.ReadByte();
TDSector.crc = (byte)stream.ReadByte();
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): \tSector follows");
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark cylinder: {0}", TDSector.cylinder);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark head: {0}", TDSector.head);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tAddressMark sector number: {0}", TDSector.sectorNumber);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector size: {0}", TDSector.sectorSize);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector flags: 0x{0:X2}", TDSector.flags);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector CRC (plus headers): 0x{0:X2}", TDSector.crc);
}
UInt32 LBA = (uint)((TDSector.cylinder * header.sides * spt) + (TDSector.head * spt) + (TDSector.sectorNumber - 1));
if ((TDSector.flags & FlagsSectorDataless) != FlagsSectorDataless && (TDSector.flags & FlagsSectorSkipped) != FlagsSectorSkipped)
{
stream.Read(dataSizeBytes, 0, 2);
TDData.dataSize = BitConverter.ToUInt16(dataSizeBytes, 0);
TDData.dataSize--; // Sydex decided to including dataEncoding byte as part of it
imageSizeWithoutHeaders += TDData.dataSize;
TDData.dataEncoding = (byte)stream.ReadByte();
data = new byte[TDData.dataSize];
stream.Read(data, 0, TDData.dataSize);
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tData size (in-image): {0}", TDData.dataSize);
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tData encoding: 0x{0:X2}", TDData.dataEncoding);
}
decodedData = DecodeTeleDiskData(TDSector.sectorSize, TDData.dataEncoding, data);
}
else
{
switch (TDSector.sectorSize)
{
case SectorSize128:
decodedData = new byte[128];
break;
case SectorSize256:
decodedData = new byte[256];
break;
case SectorSize512:
decodedData = new byte[512];
break;
case SectorSize1K:
decodedData = new byte[1024];
break;
case SectorSize2K:
decodedData = new byte[2048];
break;
case SectorSize4K:
decodedData = new byte[4096];
break;
case SectorSize8K:
decodedData = new byte[8192];
break;
default:
throw new ImageNotSupportedException(String.Format("Sector size {0} for cylinder {1} head {2} sector {3} is incorrect.",
TDSector.sectorSize, TDSector.cylinder, TDSector.head, TDSector.sectorNumber));
}
ArrayHelpers.ArrayFill(decodedData, (byte)0);
}
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tLBA: {0}", LBA);
if ((TDSector.flags & FlagsSectorNoID) != FlagsSectorNoID)
{
if (sectorsData.ContainsKey(LBA))
{
if ((TDSector.flags & FlagsSectorDuplicate) == FlagsSectorDuplicate)
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector {0} on cylinder {1} head {2} is duplicate, and marked so",
TDSector.sectorNumber, TDSector.cylinder, TDSector.head);
}
else
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): \t\tSector {0} on cylinder {1} head {2} is duplicate, but is not marked so",
TDSector.sectorNumber, TDSector.cylinder, TDSector.head);
}
}
else
{
sectorsData.Add(LBA, decodedData);
totalDiskSize += (uint)decodedData.Length;
}
}
if (decodedData.Length > biggestSectorSize)
biggestSectorSize = (uint)decodedData.Length;
}
}
return true;
}
public override bool ImageHasPartitions()
@@ -408,17 +575,17 @@ namespace FileSystemIDandChk.ImagePlugins
public override UInt64 GetImageSize()
{
throw new NotImplementedException("Not yet implemented.");
return this.imageSizeWithoutHeaders;
}
public override UInt64 GetSectors()
{
throw new NotImplementedException("Not yet implemented.");
return (ulong)this.sectorsData.Count;
}
public override UInt32 GetSectorSize()
{
throw new NotImplementedException("Not yet implemented.");
return this.biggestSectorSize;
}
public override byte[] ReadSector(UInt64 sectorAddress)
@@ -428,7 +595,35 @@ namespace FileSystemIDandChk.ImagePlugins
public override byte[] ReadSectors(UInt64 sectorAddress, UInt32 length)
{
throw new NotImplementedException("Not yet implemented.");
byte[] data = new byte[1]; // To make compiler happy
bool first = true;
int dataPosition = 0;
for (ulong i = sectorAddress; i < (sectorAddress + length); i++)
{
if (!this.sectorsData.ContainsKey((uint)i))
throw new ImageNotSupportedException(String.Format("Requested sector {0} not found", i));
byte[] sector;
if(!this.sectorsData.TryGetValue((uint)i, out sector))
throw new ImageNotSupportedException(String.Format("Error reading sector {0}", i));
if (first)
{
data = new byte[sector.Length];
Array.Copy(sector, data, sector.Length);
first = false;
}
else
{
Array.Resize(ref data, dataPosition + sector.Length);
Array.Copy(sector, 0, data, dataPosition, sector.Length);
}
dataPosition += sector.Length;
}
return data;
}
public override byte[] ReadSectorLong(UInt64 sectorAddress)
@@ -448,7 +643,7 @@ namespace FileSystemIDandChk.ImagePlugins
public override string GetImageVersion()
{
throw new NotImplementedException("Not yet implemented.");
return this.telediskVersion;
}
public override string GetImageApplication()
@@ -458,26 +653,203 @@ namespace FileSystemIDandChk.ImagePlugins
public override string GetImageApplicationVersion()
{
throw new NotImplementedException("Not yet implemented.");
return this.telediskVersion;
}
public override DateTime GetImageCreationTime()
{
throw new NotImplementedException("Not yet implemented.");
return this.creationDate;
}
public override DateTime GetImageLastModificationTime()
{
throw new NotImplementedException("Not yet implemented.");
return this.modificationDate;
}
public override string GetImageName()
{
throw new NotImplementedException("Not yet implemented.");
return this.imageName;
}
public override DiskType GetDiskType()
{
switch (this.header.driveType)
{
case DriveType525DD:
case DriveType525HD_DDDisk:
case DriveType525HD:
{
switch (this.totalDiskSize)
{
case 163840:
{
// Acorn disk uses 256 bytes/sector
if(this.biggestSectorSize == 256)
return DiskType.ACORN_525_SS_DD_40;
else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_SS_DD_8;
}
case 184320:
{
// Atari disk uses 256 bytes/sector
if(this.biggestSectorSize == 256)
return DiskType.ATARI_525_DD;
else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_SS_DD_9;
}
case 327680:
{
// Acorn disk uses 256 bytes/sector
if(this.biggestSectorSize == 256)
return DiskType.ACORN_525_SS_DD_80;
else // DOS disks use 512 bytes/sector
return DiskType.DOS_525_DS_DD_8;
}
case 368640:
return DiskType.DOS_525_DS_DD_9;
case 1228800:
return DiskType.DOS_525_HD;
case 102400:
return DiskType.ACORN_525_SS_SD_40;
case 204800:
return DiskType.ACORN_525_SS_SD_80;
case 655360:
return DiskType.ACORN_525_DS_DD;
case 92160:
return DiskType.ATARI_525_SD;
case 133120:
return DiskType.ATARI_525_ED;
case 1310720:
return DiskType.NEC_525_HD;
case 1261568:
return DiskType.SHARP_525;
case 839680:
return DiskType.FDFORMAT_525_DD;
case 1304320:
return DiskType.ECMA_99_8;
case 1223424:
return DiskType.ECMA_99_15;
case 1061632:
return DiskType.ECMA_99_26;
case 80384:
return DiskType.ECMA_66;
case 325632:
return DiskType.ECMA_70;
case 653312:
return DiskType.ECMA_78;
case 737280:
return DiskType.ECMA_78_2;
default:
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 5,25\" disk with {0} bytes", this.totalDiskSize);
return DiskType.Unknown;
}
}
break;
}
case DriveType35DD:
case DriveType35ED:
case DriveType35HD:
{
switch (this.totalDiskSize)
{
case 327680:
return DiskType.DOS_35_SS_DD_8;
case 368640:
return DiskType.DOS_35_SS_DD_9;
case 655360:
return DiskType.DOS_35_DS_DD_8;
case 737280:
return DiskType.DOS_35_DS_DD_9;
case 1474560:
return DiskType.DOS_35_HD;
case 2949120:
return DiskType.DOS_35_ED;
case 1720320:
return DiskType.DMF;
case 1763328:
return DiskType.DMF_82;
case 1884160: // Irreal size, seen as BIOS with TSR, 23 sectors/track
case 1860608: // Real data size, sum of all sectors
return DiskType.XDF_35;
case 819200:
return DiskType.CBM_35_DD;
case 901120:
return DiskType.CBM_AMIGA_35_DD;
case 1802240:
return DiskType.CBM_AMIGA_35_HD;
case 1310720:
return DiskType.NEC_35_HD_8;
case 1228800:
return DiskType.NEC_35_HD_15;
case 1261568:
return DiskType.SHARP_35;
default:
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 3,5\" disk with {0} bytes", this.totalDiskSize);
return DiskType.Unknown;
}
}
}
case DriveType8inch:
{
switch (this.totalDiskSize)
{
case 81664:
return DiskType.IBM23FD;
case 242944:
return DiskType.IBM33FD_128;
case 287488:
return DiskType.IBM33FD_256;
case 306432:
return DiskType.IBM33FD_512;
case 499200:
return DiskType.IBM43FD_128;
case 574976:
return DiskType.IBM43FD_256;
case 995072:
return DiskType.IBM53FD_256;
case 1146624:
return DiskType.IBM53FD_512;
case 1222400:
return DiskType.IBM53FD_1024;
case 256256:
// Same size, with same disk geometry, for DEC RX01, NEC and ECMA, return ECMA
return DiskType.ECMA_54;
case 512512:
{
// DEC disk uses 256 bytes/sector
if(this.biggestSectorSize == 256)
return DiskType.RX02;
else // ECMA disks use 128 bytes/sector
return DiskType.ECMA_59;
}
case 1261568:
return DiskType.NEC_8_DD;
case 1255168:
return DiskType.ECMA_69_8;
case 1177344:
return DiskType.ECMA_69_15;
case 1021696:
return DiskType.ECMA_69_26;
default:
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown 8\" disk with {0} bytes", this.totalDiskSize);
return DiskType.Unknown;
}
}
}
default:
{
if (MainClass.isDebug)
Console.WriteLine("DEBUG (TeleDisk plugin): Unknown drive type {1} with {0} bytes", this.totalDiskSize, this.header.driveType);
return DiskType.Unknown;
}
}
throw new NotImplementedException("Not yet implemented.");
}
@@ -503,6 +875,116 @@ namespace FileSystemIDandChk.ImagePlugins
return crc;
}
static byte[] DecodeTeleDiskData(byte sectorSize, byte encodingType, byte[] encodedData)
{
byte[] decodedData;
switch (sectorSize)
{
case SectorSize128:
decodedData = new byte[128];
break;
case SectorSize256:
decodedData = new byte[256];
break;
case SectorSize512:
decodedData = new byte[512];
break;
case SectorSize1K:
decodedData = new byte[1024];
break;
case SectorSize2K:
decodedData = new byte[2048];
break;
case SectorSize4K:
decodedData = new byte[4096];
break;
case SectorSize8K:
decodedData = new byte[8192];
break;
default:
throw new ImageNotSupportedException(String.Format("Sector size {0} is incorrect.", sectorSize));
}
switch (encodingType)
{
case dataBlockCopy:
Array.Copy(encodedData, decodedData, decodedData.Length);
break;
case dataBlockPattern:
{
int ins = 0;
int outs = 0;
while (ins < encodedData.Length)
{
UInt16 repeatNumber;
byte[] repeatValue = new byte[2];
repeatNumber = BitConverter.ToUInt16(encodedData, ins);
Array.Copy(encodedData, ins + 2, repeatValue, 0, 2);
byte[] decodedPiece = new byte[repeatNumber*2];
ArrayHelpers.ArrayFill(decodedPiece, repeatValue);
Array.Copy(decodedPiece, 0, decodedData, outs, decodedPiece.Length);
ins += 4;
outs += decodedPiece.Length;
}
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Input data size: {0} bytes", encodedData.Length);
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Processed input: {0} bytes", ins);
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Output data size: {0} bytes", decodedData.Length);
Console.WriteLine("DEBUG (TeleDisk plugin): (Block pattern decoder): Processed Output: {0} bytes", outs);
}
break;
}
case dataBlockRLE:
{
int ins = 0;
int outs = 0;
while (ins < encodedData.Length)
{
byte Run;
byte Length;
byte Encoding;
byte[] Piece;
Encoding = encodedData[ins];
if (Encoding == 0x00)
{
Length = encodedData[ins + 1];
Piece = new byte[Length];
Array.Copy(encodedData, ins + 2, decodedData, outs, Length);
ins += (2 + Length);
outs += Length;
}
else
{
Length = (byte)(Encoding * 2);
Run = encodedData[ins + 1];
byte[] Part = new byte[Length];
Array.Copy(encodedData, ins + 2, Part, 0, Length);
Piece = new byte[Length * Run];
ArrayHelpers.ArrayFill(Piece, Part);
Array.Copy(Piece, 0, decodedData, outs, Piece.Length);
ins += (2 + Length);
outs += Piece.Length;
}
}
if (MainClass.isDebug)
{
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Input data size: {0} bytes", encodedData.Length);
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Processed input: {0} bytes", ins);
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Output data size: {0} bytes", decodedData.Length);
Console.WriteLine("DEBUG (TeleDisk plugin): (RLE decoder): Processed Output: {0} bytes", outs);
}
break;
}
default:
throw new ImageNotSupportedException(String.Format("Data encoding {0} is incorrect.", encodingType));
}
return decodedData;
}
#endregion
#region Unsupported features

View File

@@ -69,7 +69,7 @@ namespace FileSystemIDandChk
if (isDebug)
{
plugins.RegisterAllPlugins();
Runner("/Users/claunia/Desktop/disk_images/dc42.dc42");
Runner("/Users/claunia/Desktop/disk_images/teledisk.td0");
}
else
{
@@ -169,6 +169,7 @@ namespace FileSystemIDandChk
Console.WriteLine("DEBUG: Correctly opened image file.");
Console.WriteLine("DEBUG: Image without headers is {0} bytes.", _imageFormat.GetImageSize());
Console.WriteLine("DEBUG: Image has {0} sectors.", _imageFormat.GetSectors());
Console.WriteLine("DEBUG: Image identifies disk type as {0}.", _imageFormat.GetDiskType());
}
}
catch (Exception ex)

View File

@@ -6,7 +6,6 @@
--- Add support for Alcohol images
--- Add support for Nero images
--- Add support for cdrdao images
--- Add support for Teledisk images
--- Add support for dump(8) images
--- Add support for IMD images
--- Add support for Kryoflux images
@@ -47,6 +46,7 @@ Filesystem plugins:
--- Add support for exFAT
--- Add support for FAT+
--- Add support for ReFS
--- Add support for ECMA-67
Partitioning scheme plugins:
--- Add support for Acorn partitions
@@ -63,3 +63,7 @@ Things to test/debug:
Other things:
--- Surprise!
Teledisk plugin:
--- Add support for "advanced compression"
--- Handle variable sectors per track situation. Teledisk seems to be able to read garbage from previous formattings.