diff --git a/FileSystemIDandChk/ArrayFill.cs b/FileSystemIDandChk/ArrayFill.cs new file mode 100644 index 000000000..c3394a14c --- /dev/null +++ b/FileSystemIDandChk/ArrayFill.cs @@ -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[] destinationArray, T value) + { + // if called with a single value, wrap the value in an array and call the main function + ArrayFill(destinationArray, new T[] { value }); + } + + public static void ArrayFill(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); + } + } +} + diff --git a/FileSystemIDandChk/FileSystemIDandChk.csproj b/FileSystemIDandChk/FileSystemIDandChk.csproj index 8d1845997..a3fb878c5 100644 --- a/FileSystemIDandChk/FileSystemIDandChk.csproj +++ b/FileSystemIDandChk/FileSystemIDandChk.csproj @@ -3,7 +3,7 @@ Debug x86 - 9.0.21022 + 8.0.30703 2.0 {7A4B05BE-73C9-4F34-87FE-E80CCF1F732D} Exe @@ -73,6 +73,7 @@ + diff --git a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs index dfedd3056..8fb9b7a46 100644 --- a/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs +++ b/FileSystemIDandChk/ImagePlugins/ImagePlugin.cs @@ -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 diff --git a/FileSystemIDandChk/ImagePlugins/TeleDisk.cs b/FileSystemIDandChk/ImagePlugins/TeleDisk.cs index 61ea445fc..3a5e6c4bc 100644 --- a/FileSystemIDandChk/ImagePlugins/TeleDisk.cs +++ b/FileSystemIDandChk/ImagePlugins/TeleDisk.cs @@ -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 sectorsData; // LBA, data + UInt32 totalDiskSize; + UInt64 imageSizeWithoutHeaders; + string imageName; + string telediskVersion; + UInt32 biggestSectorSize; #endregion public TeleDisk(PluginBase Core) @@ -286,6 +292,9 @@ namespace FileSystemIDandChk.ImagePlugins header.dosAllocation = headerBytes[8]; 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); @@ -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(); + 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 diff --git a/FileSystemIDandChk/Main.cs b/FileSystemIDandChk/Main.cs index 9d17adc09..6b3546d39 100644 --- a/FileSystemIDandChk/Main.cs +++ b/FileSystemIDandChk/Main.cs @@ -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) diff --git a/FileSystemIDandChk/TODO b/FileSystemIDandChk/TODO index d56f0285a..6062d0372 100644 --- a/FileSystemIDandChk/TODO +++ b/FileSystemIDandChk/TODO @@ -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 @@ -62,4 +62,8 @@ Things to test/debug: --- After moving to disc images, HFS CDs with 512 bytes/sector are not detected anymore Other things: ---- Surprise! \ No newline at end of file +--- 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. \ No newline at end of file