2017-09-24 19:15:22 +01:00
|
|
|
|
// /***************************************************************************
|
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
//
|
|
|
|
|
|
// Filename : Apricot.cs
|
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Component : Partitioning scheme plugins.
|
2017-09-24 19:15:22 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
|
//
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Manages ACT Apricot partitions.
|
2017-09-24 19:15:22 +01:00
|
|
|
|
//
|
|
|
|
|
|
// --[ 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/>.
|
|
|
|
|
|
//
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-12-19 03:50:57 +00:00
|
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
2017-09-24 19:15:22 +01:00
|
|
|
|
// ****************************************************************************/
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-09-24 19:15:22 +01:00
|
|
|
|
using System;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
using DiscImageChef.CommonTypes;
|
|
|
|
|
|
using DiscImageChef.Console;
|
2017-12-20 17:15:26 +00:00
|
|
|
|
using DiscImageChef.DiscImages;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
|
namespace DiscImageChef.Partitions
|
2017-09-24 19:15:22 +01:00
|
|
|
|
{
|
2017-12-26 06:05:12 +00:00
|
|
|
|
public class Apricot : IPartition
|
2017-09-24 19:15:22 +01:00
|
|
|
|
{
|
2017-12-24 03:11:33 +00:00
|
|
|
|
readonly int[] baudRates = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 19200};
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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 int[] lineModes = {256, 200};
|
|
|
|
|
|
readonly int[] lineWidths = {80, 40};
|
2017-12-24 03:11:33 +00:00
|
|
|
|
readonly string[] operatingSystemCodes = {"Invalid", "MS-DOS", "UCSD Pascal", "CP/M", "Concurrent CP/M"};
|
2017-12-19 20:33:03 +00:00
|
|
|
|
readonly string[] parityTypes = {"None", "Odd", "Even", "Mark", "Space"};
|
2017-12-24 03:11:33 +00:00
|
|
|
|
readonly string[] printDevices = {"Parallel", "Serial"};
|
|
|
|
|
|
readonly double[] stopBits = {1, 1.5, 2};
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-12-26 07:28:40 +00:00
|
|
|
|
public string Name => "ACT Apricot partitions";
|
|
|
|
|
|
public Guid Id => new Guid("8CBF5864-7B5A-47A0-8CEB-199C74FA22DE");
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-12-26 07:28:40 +00:00
|
|
|
|
public bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
2017-09-24 19:16:00 +01:00
|
|
|
|
{
|
|
|
|
|
|
partitions = new List<Partition>();
|
|
|
|
|
|
|
|
|
|
|
|
// I think Apricot can't chain partitions so.
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(sectorOffset != 0) return false;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
|
|
|
|
|
byte[] sector = imagePlugin.ReadSector(0);
|
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(sector.Length < 512) return false;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-12-24 03:11:33 +00:00
|
|
|
|
IntPtr lblPtr = Marshal.AllocHGlobal(512);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
Marshal.Copy(sector, 0, lblPtr, 512);
|
2017-12-22 16:53:11 +00:00
|
|
|
|
ApricotLabel label = (ApricotLabel)Marshal.PtrToStructure(lblPtr, typeof(ApricotLabel));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
Marshal.FreeHGlobal(lblPtr);
|
|
|
|
|
|
|
|
|
|
|
|
// Not much to check but...
|
2017-12-26 06:05:12 +00:00
|
|
|
|
ulong deviceSectors = imagePlugin.Info.Sectors;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
ulong deviceSizeAccordingToLabel = label.cylinders * label.heads * label.spt;
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(label.operatingSystem > 4 || label.bootType > 5 || label.partitionCount > 8 ||
|
|
|
|
|
|
deviceSizeAccordingToLabel > deviceSectors || label.firstDataBlock > deviceSectors) return false;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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");
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.writeProtected = {0}", label.writeProtected);
|
|
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.copyProtected = {0}", label.copyProtected);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.bootType = {0} ({1})", label.bootType,
|
|
|
|
|
|
label.bootType < bootTypeCodes.Length
|
|
|
|
|
|
? bootTypeCodes[label.bootType]
|
|
|
|
|
|
: "Unknown");
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.bootOffset:label.bootSegment = {0:X4}:{1:X4}",
|
|
|
|
|
|
label.bootOffset, label.bootSegment);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.prnDevice = {0} ({1})", label.prnDevice,
|
|
|
|
|
|
label.prnDevice < printDevices.Length
|
|
|
|
|
|
? printDevices[label.prnDevice]
|
|
|
|
|
|
: "Unknown");
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.imageOff = {0}", label.imageOff);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.txBits = {0}", label.txBits);
|
|
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.rxBits = {0}", label.rxBits);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.stopBits = {0} ({1} bits)", label.stopBits,
|
|
|
|
|
|
label.stopBits < stopBits.Length ? stopBits[label.stopBits] : 0);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.parityCheck = {0}", label.parityCheck);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.parityType = {0} ({1})", label.parityType,
|
|
|
|
|
|
label.parityType < parityTypes.Length
|
|
|
|
|
|
? parityTypes[label.parityType]
|
|
|
|
|
|
: "Unknown");
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.biosErrorReportSerial = {0}",
|
|
|
|
|
|
label.biosErrorReportSerial);
|
|
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.spareSerial is null? = {0}",
|
|
|
|
|
|
ArrayHelpers.ArrayIsNullOrEmpty(label.spareSerial));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.parkingEnabled = {0}", label.parkingEnabled);
|
|
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.formatProtection = {0}", label.formatProtection);
|
2017-12-19 20:33:03 +00:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.spareRamDisk is null? = {0}",
|
|
|
|
|
|
ArrayHelpers.ArrayIsNullOrEmpty(label.spareRamDisk));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
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++)
|
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
|
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);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
|
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.spare is null? = {0}",
|
|
|
|
|
|
ArrayHelpers.ArrayIsNullOrEmpty(label.spare));
|
2017-09-24 19:16:00 +01:00
|
|
|
|
DicConsole.DebugWriteLine("Apricot partitions", "label.cpmDoubleSided = {0}", label.cpmDoubleSided);
|
|
|
|
|
|
|
|
|
|
|
|
// Only hard disks can contain partitions
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(!label.winchester) return false;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
};
|
2017-12-19 20:33:03 +00:00
|
|
|
|
if(part.Start < deviceSectors && part.End < deviceSectors) partitions.Add(part);
|
2017-09-24 19:16:00 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return partitions.Count > 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Apricot Label.</summary>
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
|
struct ApricotLabel
|
2017-09-24 19:16:00 +01:00
|
|
|
|
{
|
|
|
|
|
|
/// <summary>Version of format which created disk</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] version;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Operating system.</summary>
|
|
|
|
|
|
public byte operatingSystem;
|
|
|
|
|
|
/// <summary>Software write protection.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool writeProtected;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Copy protected.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool copyProtected;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Boot type.</summary>
|
|
|
|
|
|
public byte bootType;
|
|
|
|
|
|
/// <summary>Partitions.</summary>
|
|
|
|
|
|
public byte partitionCount;
|
|
|
|
|
|
/// <summary>Is hard disk?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool winchester;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Sector size.</summary>
|
|
|
|
|
|
public ushort sectorSize;
|
|
|
|
|
|
/// <summary>Sectors per track.</summary>
|
|
|
|
|
|
public ushort spt;
|
|
|
|
|
|
/// <summary>Tracks per side.</summary>
|
|
|
|
|
|
public uint cylinders;
|
|
|
|
|
|
/// <summary>Sides.</summary>
|
|
|
|
|
|
public byte heads;
|
|
|
|
|
|
/// <summary>Interleave factor.</summary>
|
|
|
|
|
|
public byte interleave;
|
|
|
|
|
|
/// <summary>Skew factor.</summary>
|
|
|
|
|
|
public ushort skew;
|
|
|
|
|
|
/// <summary>Sector where boot code starts.</summary>
|
|
|
|
|
|
public uint bootLocation;
|
|
|
|
|
|
/// <summary>Size in sectors of boot code.</summary>
|
|
|
|
|
|
public ushort bootSize;
|
|
|
|
|
|
/// <summary>Address at which to load boot code.</summary>
|
|
|
|
|
|
public uint bootAddress;
|
|
|
|
|
|
/// <summary>Offset where to jump to boot.</summary>
|
|
|
|
|
|
public ushort bootOffset;
|
|
|
|
|
|
/// <summary>Segment where to jump to boot.</summary>
|
|
|
|
|
|
public ushort bootSegment;
|
|
|
|
|
|
/// <summary>First data sector.</summary>
|
|
|
|
|
|
public uint firstDataBlock;
|
|
|
|
|
|
/// <summary>Generation.</summary>
|
|
|
|
|
|
public ushort generation;
|
|
|
|
|
|
/// <summary>Copy count.</summary>
|
|
|
|
|
|
public ushort copyCount;
|
|
|
|
|
|
/// <summary>Maximum number of copies.</summary>
|
|
|
|
|
|
public ushort maxCopies;
|
|
|
|
|
|
/// <summary>Serial number.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] serialNumber;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Part number.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] partNumber;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Copyright.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] copyright;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>BPB for whole disk.</summary>
|
|
|
|
|
|
public ApricotParameterBlock mainBPB;
|
|
|
|
|
|
/// <summary>Name of FONT file.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] fontName;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Name of KEYBOARD file.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] keyboardName;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Minor BIOS version.</summary>
|
|
|
|
|
|
public byte biosMinorVersion;
|
|
|
|
|
|
/// <summary>Major BIOS version.</summary>
|
|
|
|
|
|
public byte biosMajorVersion;
|
|
|
|
|
|
/// <summary>Diagnostics enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool diagnosticsFlag;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Printer device.</summary>
|
|
|
|
|
|
public byte prnDevice;
|
|
|
|
|
|
/// <summary>Bell volume.</summary>
|
|
|
|
|
|
public byte bellVolume;
|
|
|
|
|
|
/// <summary>Cache enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool enableCache;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Graphics enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool enableGraphics;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Length in sectors of DOS.</summary>
|
|
|
|
|
|
public byte dosLength;
|
|
|
|
|
|
/// <summary>Length in sectors of FONT file.</summary>
|
|
|
|
|
|
public byte fontLength;
|
|
|
|
|
|
/// <summary>Length in sectors of KEYBOARD file.</summary>
|
|
|
|
|
|
public byte keyboardLength;
|
|
|
|
|
|
/// <summary>Starting sector of DOS.</summary>
|
|
|
|
|
|
public ushort dosStart;
|
|
|
|
|
|
/// <summary>Starting sector of FONT file.</summary>
|
|
|
|
|
|
public ushort fontStart;
|
|
|
|
|
|
/// <summary>Starting sector of KEYBOARD file.</summary>
|
|
|
|
|
|
public ushort keyboardStart;
|
|
|
|
|
|
/// <summary>Keyboard click volume.</summary>
|
|
|
|
|
|
public byte keyboardVolume;
|
|
|
|
|
|
/// <summary>Auto-repeat enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool autorepeat;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Auto-repeat lead-in.</summary>
|
|
|
|
|
|
public byte autorepeatLeadIn;
|
|
|
|
|
|
/// <summary>Auto-repeat interval.</summary>
|
|
|
|
|
|
public byte autorepeatInterval;
|
|
|
|
|
|
/// <summary>Microscreen mode.</summary>
|
|
|
|
|
|
public byte microscreenMode;
|
|
|
|
|
|
/// <summary>Spare area for keyboard values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] spareKeyboard;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Screen line mode.</summary>
|
|
|
|
|
|
public byte lineMode;
|
|
|
|
|
|
/// <summary>Screen line width.</summary>
|
|
|
|
|
|
public byte lineWidth;
|
|
|
|
|
|
/// <summary>Screen disabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool imageOff;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area for screen values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public byte[] spareScreen;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>TX baud rate.</summary>
|
|
|
|
|
|
public byte txBaudRate;
|
|
|
|
|
|
/// <summary>RX baud rate.</summary>
|
|
|
|
|
|
public byte rxBaudRate;
|
|
|
|
|
|
/// <summary>TX bits.</summary>
|
|
|
|
|
|
public byte txBits;
|
|
|
|
|
|
/// <summary>RX bits.</summary>
|
|
|
|
|
|
public byte rxBits;
|
|
|
|
|
|
/// <summary>Stop bits.</summary>
|
|
|
|
|
|
public byte stopBits;
|
|
|
|
|
|
/// <summary>Parity enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool parityCheck;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Parity type.</summary>
|
|
|
|
|
|
public byte parityType;
|
|
|
|
|
|
/// <summary>Xon/Xoff enabled on TX.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool txXonXoff;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Xon/Xoff enabled on RX.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool rxXonXoff;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Xon character.</summary>
|
|
|
|
|
|
public byte xonCharacter;
|
|
|
|
|
|
/// <summary>Xoff character.</summary>
|
|
|
|
|
|
public byte xoffCharacter;
|
|
|
|
|
|
/// <summary>Xon/Xoff buffer on RX.</summary>
|
|
|
|
|
|
public ushort rxXonXoffBuffer;
|
|
|
|
|
|
/// <summary>DTR/DSR enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool dtrDsr;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>CTS/RTS enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool ctsRts;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>NULLs after CR.</summary>
|
|
|
|
|
|
public byte nullsAfterCr;
|
|
|
|
|
|
/// <summary>NULLs after 0xFF.</summary>
|
|
|
|
|
|
public byte nullsAfterFF;
|
|
|
|
|
|
/// <summary>Send LF after CR in serial port.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool lfAfterCRSerial;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>BIOS error report in serial port.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool biosErrorReportSerial;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area for serial port values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public byte[] spareSerial;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Send LF after CR in parallel port.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool lfAfterCrParallel;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Select line supported?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool selectLine;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Paper empty supported?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool paperEmpty;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Fault line supported?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool faultLine;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>BIOS error report in parallel port.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool biosErrorReportParallel;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area for parallel port values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] spareParallel;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area for Winchester values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public byte[] spareWinchester;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Parking enabled?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool parkingEnabled;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Format protection?.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.U1)] public bool formatProtection;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area for RAM disk values expansion.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] spareRamDisk;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>List of bad blocks.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public ushort[] badBlocks;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Array of partition BPBs.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public ApricotParameterBlock[] partitions;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>Spare area.</summary>
|
2017-12-19 20:33:03 +00:00
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)] public byte[] spare;
|
2017-09-24 19:16:00 +01:00
|
|
|
|
/// <summary>CP/M double side indicator?.</summary>
|
|
|
|
|
|
public bool cpmDoubleSided;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
2017-12-20 02:08:37 +00:00
|
|
|
|
struct ApricotParameterBlock
|
2017-09-24 19:16:00 +01:00
|
|
|
|
{
|
|
|
|
|
|
/// <summary>Bytes per sector</summary>
|
|
|
|
|
|
public ushort bps;
|
|
|
|
|
|
/// <summary>Sectors per cluster</summary>
|
|
|
|
|
|
public byte spc;
|
|
|
|
|
|
/// <summary>Reserved sectors between BPB and FAT</summary>
|
|
|
|
|
|
public ushort rsectors;
|
|
|
|
|
|
/// <summary>Number of FATs</summary>
|
|
|
|
|
|
public byte fats_no;
|
|
|
|
|
|
/// <summary>Number of entries on root directory</summary>
|
|
|
|
|
|
public ushort root_ent;
|
|
|
|
|
|
/// <summary>Sectors in volume</summary>
|
|
|
|
|
|
public ushort sectors;
|
|
|
|
|
|
/// <summary>Media descriptor</summary>
|
|
|
|
|
|
public byte media;
|
|
|
|
|
|
/// <summary>Sectors per FAT</summary>
|
|
|
|
|
|
public ushort spfat;
|
|
|
|
|
|
/// <summary>Disk type</summary>
|
|
|
|
|
|
public byte diskType;
|
|
|
|
|
|
/// <summary>Volume starting sector</summary>
|
|
|
|
|
|
public ushort startSector;
|
2017-09-24 19:15:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-09-24 19:16:00 +01:00
|
|
|
|
}
|