From 8fc390e624abab3d488cae015f5008c628b33f49 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sun, 24 Sep 2017 19:16:00 +0100 Subject: [PATCH] Added support for ACT Apricot partitions. --- DiscImageChef.Partitions/Apricot.cs | 416 +++++++++++++++++- .../DiscImageChef.Partitions.csproj | 1 + README.md | 1 + 3 files changed, 415 insertions(+), 3 deletions(-) diff --git a/DiscImageChef.Partitions/Apricot.cs b/DiscImageChef.Partitions/Apricot.cs index ef0255a51..74fc7ccdf 100644 --- a/DiscImageChef.Partitions/Apricot.cs +++ b/DiscImageChef.Partitions/Apricot.cs @@ -29,13 +29,423 @@ // ---------------------------------------------------------------------------- // Copyright © 2011-2017 Natalia Portillo // ****************************************************************************/ + using System; -namespace DiscImageChef.Partitions +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using DiscImageChef.CommonTypes; +using DiscImageChef.ImagePlugins; +using DiscImageChef.Console; + +namespace DiscImageChef.PartPlugins { - public class Apricot + public class Apricot : PartPlugin { + readonly string[] operatingSystemCodes = { "Invalid", "MS-DOS", "UCSD Pascal", "CP/M", "Concurrent CP/M" }; + readonly string[] bootTypeCodes = { "Non-bootable", "Apricot & XI RAM BIOS", "Generic ROM BIOS", "Apricot & XI ROM BIOS", "Apricot Portable ROM BIOS", "Apricot F1 ROM BIOS" }; + readonly string[] diskTypeCodes = { "MF1DD 70-track", "MF1DD", "MF2DD", "Winchester 5M", "Winchester 10M", "Winchester 20M" }; + readonly string[] printDevices = { "Parallel", "Serial" }; + readonly int[] lineModes = { 256, 200 }; + readonly int[] lineWidths = { 80, 40 }; + readonly int[] baudRates = { 50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200 }; + readonly double[] stopBits = { 1, 1.5, 2 }; + readonly string[] parityTypes = { "None", "Odd", "Even", "Mark", "Space" }; + public Apricot() { + Name = "ACT Apricot partitions"; + PluginUUID = new Guid("8CBF5864-7B5A-47A0-8CEB-199C74FA22DE"); + } + + public override bool GetInformation(ImagePlugin imagePlugin, out List partitions, ulong sectorOffset) + { + partitions = new List(); + + // I think Apricot can't chain partitions so. + if(sectorOffset != 0) + return false; + + byte[] sector = imagePlugin.ReadSector(0); + + if(sector.Length < 512) + return false; + + ApricotLabel label = new ApricotLabel(); + IntPtr lblPtr = Marshal.AllocHGlobal(512); + Marshal.Copy(sector, 0, lblPtr, 512); + label = (ApricotLabel)Marshal.PtrToStructure(lblPtr, typeof(ApricotLabel)); + Marshal.FreeHGlobal(lblPtr); + + // Not much to check but... + ulong deviceSectors = imagePlugin.GetSectors(); + ulong deviceSizeAccordingToLabel = label.cylinders * label.heads * label.spt; + if(label.operatingSystem > 4 || label.bootType > 5 || label.partitionCount > 8 || deviceSizeAccordingToLabel > deviceSectors || label.firstDataBlock > deviceSectors) + return false; + + DicConsole.DebugWriteLine("Apricot partitions", "label.version = \"{0}\"", StringHandlers.CToString(label.version)); + DicConsole.DebugWriteLine("Apricot partitions", "label.operatingSystem = {0} ({1})", label.operatingSystem, label.operatingSystem < operatingSystemCodes.Length ? operatingSystemCodes[label.operatingSystem] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.writeProtected = {0}", label.writeProtected); + DicConsole.DebugWriteLine("Apricot partitions", "label.copyProtected = {0}", label.copyProtected); + DicConsole.DebugWriteLine("Apricot partitions", "label.bootType = {0} ({1})", label.bootType, label.bootType < bootTypeCodes.Length ? bootTypeCodes[label.bootType] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitionCount = {0}", label.partitionCount); + DicConsole.DebugWriteLine("Apricot partitions", "label.winchester = {0}", label.winchester); + DicConsole.DebugWriteLine("Apricot partitions", "label.sectorSize = {0}", label.sectorSize); + DicConsole.DebugWriteLine("Apricot partitions", "label.spt = {0}", label.spt); + DicConsole.DebugWriteLine("Apricot partitions", "label.cylinders = {0}", label.cylinders); + DicConsole.DebugWriteLine("Apricot partitions", "label.heads = {0}", label.heads); + DicConsole.DebugWriteLine("Apricot partitions", "label.interleave = {0}", label.interleave); + DicConsole.DebugWriteLine("Apricot partitions", "label.skew = {0}", label.skew); + DicConsole.DebugWriteLine("Apricot partitions", "label.bootLocation = {0}", label.bootLocation); + DicConsole.DebugWriteLine("Apricot partitions", "label.bootSize = {0}", label.bootSize); + DicConsole.DebugWriteLine("Apricot partitions", "label.bootAddress = 0x{0:X8}", label.bootAddress); + DicConsole.DebugWriteLine("Apricot partitions", "label.bootOffset:label.bootSegment = {0:X4}:{1:X4}", label.bootOffset, label.bootSegment); + DicConsole.DebugWriteLine("Apricot partitions", "label.firstDataBlock = {0}", label.firstDataBlock); + DicConsole.DebugWriteLine("Apricot partitions", "label.generation = {0}", label.generation); + DicConsole.DebugWriteLine("Apricot partitions", "label.copyCount = {0}", label.copyCount); + DicConsole.DebugWriteLine("Apricot partitions", "label.maxCopies = {0}", label.maxCopies); + DicConsole.DebugWriteLine("Apricot partitions", "label.serialNumber = \"{0}\"", StringHandlers.CToString(label.serialNumber)); + DicConsole.DebugWriteLine("Apricot partitions", "label.partNumber = \"{0}\"", StringHandlers.CToString(label.partNumber)); + DicConsole.DebugWriteLine("Apricot partitions", "label.copyright = \"{0}\"", StringHandlers.CToString(label.copyright)); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.bps = {0}", label.mainBPB.bps); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.spc = {0}", label.mainBPB.spc); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.rsectors = {0}", label.mainBPB.rsectors); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.fats_no = {0}", label.mainBPB.fats_no); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.root_ent = {0}", label.mainBPB.root_ent); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.sectors = {0}", label.mainBPB.sectors); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.media = {0}", label.mainBPB.media); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.spfat = {0}", label.mainBPB.spfat); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.diskType = {0} ({1})", label.mainBPB.diskType, label.mainBPB.diskType < diskTypeCodes.Length ? diskTypeCodes[label.mainBPB.diskType] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.mainBPB.startSector = {0}", label.mainBPB.startSector); + DicConsole.DebugWriteLine("Apricot partitions", "label.fontName = \"{0}\"", StringHandlers.CToString(label.fontName)); + DicConsole.DebugWriteLine("Apricot partitions", "label.keyboardName = \"{0}\"", StringHandlers.CToString(label.keyboardName)); + DicConsole.DebugWriteLine("Apricot partitions", "label.biosMajorVersion = {0}", label.biosMajorVersion); + DicConsole.DebugWriteLine("Apricot partitions", "label.biosMinorVersion = {0}", label.biosMinorVersion); + DicConsole.DebugWriteLine("Apricot partitions", "label.diagnosticsFlag = {0}", label.diagnosticsFlag); + DicConsole.DebugWriteLine("Apricot partitions", "label.prnDevice = {0} ({1})", label.prnDevice, label.prnDevice < printDevices.Length ? printDevices[label.prnDevice] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.bellVolume = {0}", label.bellVolume); + DicConsole.DebugWriteLine("Apricot partitions", "label.enableCache = {0}", label.enableCache); + DicConsole.DebugWriteLine("Apricot partitions", "label.enableGraphics = {0}", label.enableGraphics); + DicConsole.DebugWriteLine("Apricot partitions", "label.dosLength = {0}", label.dosLength); + DicConsole.DebugWriteLine("Apricot partitions", "label.fontLength = {0}", label.fontLength); + DicConsole.DebugWriteLine("Apricot partitions", "label.keyboardLength = {0}", label.keyboardLength); + DicConsole.DebugWriteLine("Apricot partitions", "label.dosStart = {0}", label.dosStart); + DicConsole.DebugWriteLine("Apricot partitions", "label.fontStart = {0}", label.fontStart); + DicConsole.DebugWriteLine("Apricot partitions", "label.keyboardStart = {0}", label.keyboardStart); + DicConsole.DebugWriteLine("Apricot partitions", "label.keyboardVolume = {0}", label.keyboardVolume); + DicConsole.DebugWriteLine("Apricot partitions", "label.autorepeat = {0}", label.autorepeat); + DicConsole.DebugWriteLine("Apricot partitions", "label.autorepeatLeadIn = {0}", label.autorepeatLeadIn); + DicConsole.DebugWriteLine("Apricot partitions", "label.autorepeatInterval = {0}", label.autorepeatInterval); + DicConsole.DebugWriteLine("Apricot partitions", "label.microscreenMode = {0}", label.microscreenMode); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareKeyboard is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareKeyboard)); + DicConsole.DebugWriteLine("Apricot partitions", "label.lineMode = {0} ({1} lines)", label.lineMode, label.lineMode < lineModes.Length ? lineModes[label.lineMode] : 0); + DicConsole.DebugWriteLine("Apricot partitions", "label.lineWidth = {0} ({1} columns)", label.lineWidth, label.lineWidth < lineWidths.Length ? lineWidths[label.lineWidth] : 0); + DicConsole.DebugWriteLine("Apricot partitions", "label.imageOff = {0}", label.imageOff); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareScreen is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareScreen)); + DicConsole.DebugWriteLine("Apricot partitions", "label.txBaudRate = {0} ({1} bps)", label.txBaudRate, label.txBaudRate < baudRates.Length ? baudRates[label.txBaudRate] : 0); + DicConsole.DebugWriteLine("Apricot partitions", "label.rxBaudRate = {0} ({1} bps)", label.rxBaudRate, label.rxBaudRate < baudRates.Length ? baudRates[label.rxBaudRate] : 0); + DicConsole.DebugWriteLine("Apricot partitions", "label.txBits = {0}", label.txBits); + DicConsole.DebugWriteLine("Apricot partitions", "label.rxBits = {0}", label.rxBits); + DicConsole.DebugWriteLine("Apricot partitions", "label.stopBits = {0} ({1} bits)", label.stopBits, label.stopBits < stopBits.Length ? stopBits[label.stopBits] : 0); + DicConsole.DebugWriteLine("Apricot partitions", "label.parityCheck = {0}", label.parityCheck); + DicConsole.DebugWriteLine("Apricot partitions", "label.parityType = {0} ({1})", label.parityType, label.parityType < parityTypes.Length ? parityTypes[label.parityType] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.txXonXoff = {0}", label.txXonXoff); + DicConsole.DebugWriteLine("Apricot partitions", "label.rxXonXoff = {0}", label.rxXonXoff); + DicConsole.DebugWriteLine("Apricot partitions", "label.xonCharacter = {0}", label.xonCharacter); + DicConsole.DebugWriteLine("Apricot partitions", "label.xoffCharacter = {0}", label.xoffCharacter); + DicConsole.DebugWriteLine("Apricot partitions", "label.rxXonXoffBuffer = {0}", label.rxXonXoffBuffer); + DicConsole.DebugWriteLine("Apricot partitions", "label.dtrDsr = {0}", label.dtrDsr); + DicConsole.DebugWriteLine("Apricot partitions", "label.ctsRts = {0}", label.ctsRts); + DicConsole.DebugWriteLine("Apricot partitions", "label.nullsAfterCr = {0}", label.nullsAfterCr); + DicConsole.DebugWriteLine("Apricot partitions", "label.nullsAfterFF = {0}", label.nullsAfterFF); + DicConsole.DebugWriteLine("Apricot partitions", "label.lfAfterCRSerial = {0}", label.lfAfterCRSerial); + DicConsole.DebugWriteLine("Apricot partitions", "label.biosErrorReportSerial = {0}", label.biosErrorReportSerial); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareSerial is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareSerial)); + DicConsole.DebugWriteLine("Apricot partitions", "label.lfAfterCrParallel = {0}", label.lfAfterCrParallel); + DicConsole.DebugWriteLine("Apricot partitions", "label.selectLine = {0}", label.selectLine); + DicConsole.DebugWriteLine("Apricot partitions", "label.paperEmpty = {0}", label.paperEmpty); + DicConsole.DebugWriteLine("Apricot partitions", "label.faultLine = {0}", label.faultLine); + DicConsole.DebugWriteLine("Apricot partitions", "label.biosErrorReportParallel = {0}", label.biosErrorReportParallel); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareParallel is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareParallel)); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareWinchester is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareWinchester)); + DicConsole.DebugWriteLine("Apricot partitions", "label.parkingEnabled = {0}", label.parkingEnabled); + DicConsole.DebugWriteLine("Apricot partitions", "label.formatProtection = {0}", label.formatProtection); + DicConsole.DebugWriteLine("Apricot partitions", "label.spareRamDisk is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spareRamDisk)); + for(int i = 0; i < 32; i++) + DicConsole.DebugWriteLine("Apricot partitions", "label.badBlocks[{1}] = {0}", label.badBlocks[i], i); + for(int i = 0; i < 8; i++) + { + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].bps = {0}", label.partitions[i].bps, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].spc = {0}", label.partitions[i].spc, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].rsectors = {0}", label.partitions[i].rsectors, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].fats_no = {0}", label.partitions[i].fats_no, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].root_ent = {0}", label.partitions[i].root_ent, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].sectors = {0}", label.partitions[i].sectors, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].media = {0}", label.partitions[i].media, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].spfat = {0}", label.partitions[i].spfat, i); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].diskType = {0} ({2})", label.partitions[i].diskType, i, label.partitions[i].diskType < diskTypeCodes.Length ? diskTypeCodes[label.partitions[i].diskType] : "Unknown"); + DicConsole.DebugWriteLine("Apricot partitions", "label.partitions[{1}].startSector = {0}", label.partitions[i].startSector, i); + } + DicConsole.DebugWriteLine("Apricot partitions", "label.spare is null? = {0}", ArrayHelpers.ArrayIsNullOrEmpty(label.spare)); + DicConsole.DebugWriteLine("Apricot partitions", "label.cpmDoubleSided = {0}", label.cpmDoubleSided); + + // Only hard disks can contain partitions + if(!label.winchester) + return false; + + for(byte i = 0; i < label.partitionCount; i++) + { + Partition part = new Partition + { + Start = label.partitions[i].startSector, + Size = (ulong)(label.partitions[i].sectors * label.sectorSize), + Length = label.partitions[i].sectors, + Type = "ACT Apricot partition", + Sequence = i, + Scheme = Name, + Offset = (ulong)(label.partitions[i].startSector * label.sectorSize) + }; + if(part.Start < deviceSectors && part.End < deviceSectors) + partitions.Add(part); + } + + return partitions.Count > 0; + } + + /// Apricot Label. + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ApricotLabel + { + /// Version of format which created disk + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] version; + /// Operating system. + public byte operatingSystem; + /// Software write protection. + [MarshalAs(UnmanagedType.U1)] + public bool writeProtected; + /// Copy protected. + [MarshalAs(UnmanagedType.U1)] + public bool copyProtected; + /// Boot type. + public byte bootType; + /// Partitions. + public byte partitionCount; + /// Is hard disk?. + [MarshalAs(UnmanagedType.U1)] + public bool winchester; + /// Sector size. + public ushort sectorSize; + /// Sectors per track. + public ushort spt; + /// Tracks per side. + public uint cylinders; + /// Sides. + public byte heads; + /// Interleave factor. + public byte interleave; + /// Skew factor. + public ushort skew; + /// Sector where boot code starts. + public uint bootLocation; + /// Size in sectors of boot code. + public ushort bootSize; + /// Address at which to load boot code. + public uint bootAddress; + /// Offset where to jump to boot. + public ushort bootOffset; + /// Segment where to jump to boot. + public ushort bootSegment; + /// First data sector. + public uint firstDataBlock; + /// Generation. + public ushort generation; + /// Copy count. + public ushort copyCount; + /// Maximum number of copies. + public ushort maxCopies; + /// Serial number. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] serialNumber; + /// Part number. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] partNumber; + /// Copyright. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + public byte[] copyright; + /// BPB for whole disk. + public ApricotParameterBlock mainBPB; + /// Name of FONT file. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] fontName; + /// Name of KEYBOARD file. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] keyboardName; + /// Minor BIOS version. + public byte biosMinorVersion; + /// Major BIOS version. + public byte biosMajorVersion; + /// Diagnostics enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool diagnosticsFlag; + /// Printer device. + public byte prnDevice; + /// Bell volume. + public byte bellVolume; + /// Cache enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool enableCache; + /// Graphics enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool enableGraphics; + /// Length in sectors of DOS. + public byte dosLength; + /// Length in sectors of FONT file. + public byte fontLength; + /// Length in sectors of KEYBOARD file. + public byte keyboardLength; + /// Starting sector of DOS. + public ushort dosStart; + /// Starting sector of FONT file. + public ushort fontStart; + /// Starting sector of KEYBOARD file. + public ushort keyboardStart; + /// Keyboard click volume. + public byte keyboardVolume; + /// Auto-repeat enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool autorepeat; + /// Auto-repeat lead-in. + public byte autorepeatLeadIn; + /// Auto-repeat interval. + public byte autorepeatInterval; + /// Microscreen mode. + public byte microscreenMode; + /// Spare area for keyboard values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] spareKeyboard; + /// Screen line mode. + public byte lineMode; + /// Screen line width. + public byte lineWidth; + /// Screen disabled?. + [MarshalAs(UnmanagedType.U1)] + public bool imageOff; + /// Spare area for screen values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] + public byte[] spareScreen; + /// TX baud rate. + public byte txBaudRate; + /// RX baud rate. + public byte rxBaudRate; + /// TX bits. + public byte txBits; + /// RX bits. + public byte rxBits; + /// Stop bits. + public byte stopBits; + /// Parity enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool parityCheck; + /// Parity type. + public byte parityType; + /// Xon/Xoff enabled on TX. + [MarshalAs(UnmanagedType.U1)] + public bool txXonXoff; + /// Xon/Xoff enabled on RX. + [MarshalAs(UnmanagedType.U1)] + public bool rxXonXoff; + /// Xon character. + public byte xonCharacter; + /// Xoff character. + public byte xoffCharacter; + /// Xon/Xoff buffer on RX. + public ushort rxXonXoffBuffer; + /// DTR/DSR enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool dtrDsr; + /// CTS/RTS enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool ctsRts; + /// NULLs after CR. + public byte nullsAfterCr; + /// NULLs after 0xFF. + public byte nullsAfterFF; + /// Send LF after CR in serial port. + [MarshalAs(UnmanagedType.U1)] + public bool lfAfterCRSerial; + /// BIOS error report in serial port. + [MarshalAs(UnmanagedType.U1)] + public bool biosErrorReportSerial; + /// Spare area for serial port values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] + public byte[] spareSerial; + /// Send LF after CR in parallel port. + [MarshalAs(UnmanagedType.U1)] + public bool lfAfterCrParallel; + /// Select line supported?. + [MarshalAs(UnmanagedType.U1)] + public bool selectLine; + /// Paper empty supported?. + [MarshalAs(UnmanagedType.U1)] + public bool paperEmpty; + /// Fault line supported?. + [MarshalAs(UnmanagedType.U1)] + public bool faultLine; + /// BIOS error report in parallel port. + [MarshalAs(UnmanagedType.U1)] + public bool biosErrorReportParallel; + /// Spare area for parallel port values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] spareParallel; + /// Spare area for Winchester values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + public byte[] spareWinchester; + /// Parking enabled?. + [MarshalAs(UnmanagedType.U1)] + public bool parkingEnabled; + /// Format protection?. + [MarshalAs(UnmanagedType.U1)] + public bool formatProtection; + /// Spare area for RAM disk values expansion. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] spareRamDisk; + /// List of bad blocks. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public ushort[] badBlocks; + /// Array of partition BPBs. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public ApricotParameterBlock[] partitions; + /// Spare area. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)] + public byte[] spare; + /// CP/M double side indicator?. + public bool cpmDoubleSided; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct ApricotParameterBlock + { + /// Bytes per sector + public ushort bps; + /// Sectors per cluster + public byte spc; + /// Reserved sectors between BPB and FAT + public ushort rsectors; + /// Number of FATs + public byte fats_no; + /// Number of entries on root directory + public ushort root_ent; + /// Sectors in volume + public ushort sectors; + /// Media descriptor + public byte media; + /// Sectors per FAT + public ushort spfat; + /// Disk type + public byte diskType; + /// Volume starting sector + public ushort startSector; } } -} +} \ No newline at end of file diff --git a/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj b/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj index cb78af24e..c1230e9f8 100644 --- a/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj +++ b/DiscImageChef.Partitions/DiscImageChef.Partitions.csproj @@ -56,6 +56,7 @@ + diff --git a/README.md b/README.md index 903c121b1..dd79d1b09 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ Supported disk image formats Supported partitioning schemes ============================== * Acorn Linux and RISCiX partitions +* ACT Apricot partitions * Amiga Rigid Disk Block (RDB) * Apple Partition Map * Atari AHDI and ICDPro