diff --git a/DiscImageChef.Filesystems/FAT.cs b/DiscImageChef.Filesystems/FAT.cs
index 45c71c0ac..b783272f2 100644
--- a/DiscImageChef.Filesystems/FAT.cs
+++ b/DiscImageChef.Filesystems/FAT.cs
@@ -148,6 +148,7 @@ namespace DiscImageChef.Filesystems
ushort apricot_fat_sectors = BitConverter.ToUInt16(bpb_sector, 0x5B);
bool apricot_correct_spc = apricot_spc == 1 || apricot_spc == 2 || apricot_spc == 4 || apricot_spc == 8 || apricot_spc == 16 || apricot_spc == 32 || apricot_spc == 64;
int bits_in_apricot_bps = Helpers.CountBits.Count(apricot_bps);
+ byte apricot_partitions = bpb_sector[0x0C];
DicConsole.DebugWriteLine("FAT plugin", "apricot_bps = {0}", apricot_bps);
DicConsole.DebugWriteLine("FAT plugin", "apricot_spc = {0}", apricot_spc);
@@ -209,7 +210,7 @@ namespace DiscImageChef.Filesystems
// Apricot BPB
if(bits_in_apricot_bps == 1 && apricot_correct_spc && apricot_reserved_secs < (partition.End - partition.Start) && apricot_fats_no <= 2 && apricot_root_entries > 0 &&
- apricot_fat_sectors > 0 && apricot_sectors <= (partition.End - partition.Start) + 1)
+ apricot_fat_sectors > 0 && apricot_sectors <= (partition.End - partition.Start) + 1 && apricot_partitions == 0)
return true;
// All FAT12 without BPB can only be used on floppies, without partitions.
@@ -307,7 +308,7 @@ namespace DiscImageChef.Filesystems
BIOSParameterBlockEBPB EBPB = new BIOSParameterBlockEBPB();
FAT32ParameterBlockShort shortFat32BPB = new FAT32ParameterBlockShort();
FAT32ParameterBlock Fat32BPB = new FAT32ParameterBlock();
- ApricotParameterBlock ApricotBPB = new ApricotParameterBlock();
+ ApricotLabel ApricotBPB = new ApricotLabel();
byte[] bpb_sector = imagePlugin.ReadSectors(partition.Start, 2);
@@ -326,7 +327,7 @@ namespace DiscImageChef.Filesystems
EBPB = (BIOSParameterBlockEBPB)Marshal.PtrToStructure(bpbPtr, typeof(BIOSParameterBlockEBPB));
shortFat32BPB = (FAT32ParameterBlockShort)Marshal.PtrToStructure(bpbPtr, typeof(FAT32ParameterBlockShort));
Fat32BPB = (FAT32ParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(FAT32ParameterBlock));
- ApricotBPB = (ApricotParameterBlock)Marshal.PtrToStructure(bpbPtr, typeof(ApricotParameterBlock));
+ ApricotBPB = (ApricotLabel)Marshal.PtrToStructure(bpbPtr, typeof(ApricotLabel));
Marshal.FreeHGlobal(bpbPtr);
@@ -340,7 +341,7 @@ namespace DiscImageChef.Filesystems
int bits_in_bps_dos40 = Helpers.CountBits.Count(EBPB.bps);
int bits_in_bps_fat32_short = Helpers.CountBits.Count(shortFat32BPB.bps);
int bits_in_bps_fat32 = Helpers.CountBits.Count(Fat32BPB.bps);
- int bits_in_bps_apricot = Helpers.CountBits.Count(ApricotBPB.bps);
+ int bits_in_bps_apricot = Helpers.CountBits.Count(ApricotBPB.mainBPB.bps);
bool correct_spc_atari = atariBPB.spc == 1 || atariBPB.spc == 2 || atariBPB.spc == 4 || atariBPB.spc == 8 || atariBPB.spc == 16 || atariBPB.spc == 32 || atariBPB.spc == 64;
bool correct_spc_msx = msxBPB.spc == 1 || msxBPB.spc == 2 || msxBPB.spc == 4 || msxBPB.spc == 8 || msxBPB.spc == 16 || msxBPB.spc == 32 || msxBPB.spc == 64;
@@ -352,7 +353,7 @@ namespace DiscImageChef.Filesystems
bool correct_spc_dos40 = EBPB.spc == 1 || EBPB.spc == 2 || EBPB.spc == 4 || EBPB.spc == 8 || EBPB.spc == 16 || EBPB.spc == 32 || EBPB.spc == 64;
bool correct_spc_fat32_short = shortFat32BPB.spc == 1 || shortFat32BPB.spc == 2 || shortFat32BPB.spc == 4 || shortFat32BPB.spc == 8 || shortFat32BPB.spc == 16 || shortFat32BPB.spc == 32 || shortFat32BPB.spc == 64;
bool correct_spc_fat32 = Fat32BPB.spc == 1 || Fat32BPB.spc == 2 || Fat32BPB.spc == 4 || Fat32BPB.spc == 8 || Fat32BPB.spc == 16 || Fat32BPB.spc == 32 || Fat32BPB.spc == 64;
- bool correct_spc_apricot = ApricotBPB.spc == 1 || ApricotBPB.spc == 2 || ApricotBPB.spc == 4 || ApricotBPB.spc == 8 || ApricotBPB.spc == 16 || ApricotBPB.spc == 32 || ApricotBPB.spc == 64;
+ bool correct_spc_apricot = ApricotBPB.mainBPB.spc == 1 || ApricotBPB.mainBPB.spc == 2 || ApricotBPB.mainBPB.spc == 4 || ApricotBPB.mainBPB.spc == 8 || ApricotBPB.mainBPB.spc == 16 || ApricotBPB.mainBPB.spc == 32 || ApricotBPB.mainBPB.spc == 64;
// This is to support FAT partitions on hybrid ISO/USB images
if(imagePlugin.ImageInfo.xmlMediaType == ImagePlugins.XmlMediaType.OpticalDisc)
@@ -373,7 +374,7 @@ namespace DiscImageChef.Filesystems
shortFat32BPB.huge_sectors /= 4;
Fat32BPB.sectors /= 4;
Fat32BPB.big_sectors /= 4;
- ApricotBPB.sectors /= 4;
+ ApricotBPB.mainBPB.sectors /= 4;
}
andos_oem_correct = dos33BPB.oem_name[0] < 0x20 && dos33BPB.oem_name[1] >= 0x20 && dos33BPB.oem_name[2] >= 0x20 && dos33BPB.oem_name[3] >= 0x20 &&
@@ -394,7 +395,7 @@ namespace DiscImageChef.Filesystems
DicConsole.DebugWriteLine("FAT plugin", "Using MSX BPB");
useMSXBPB = true;
}
- else if(bits_in_bps_apricot == 1 && correct_spc_apricot && ApricotBPB.fats_no <= 2 && ApricotBPB.root_ent > 0 && ApricotBPB.sectors <= (partition.End - partition.Start) + 1 && ApricotBPB.spfat > 0)
+ else if(bits_in_bps_apricot == 1 && correct_spc_apricot && ApricotBPB.mainBPB.fats_no <= 2 && ApricotBPB.mainBPB.root_ent > 0 && ApricotBPB.mainBPB.sectors <= (partition.End - partition.Start) + 1 && ApricotBPB.mainBPB.spfat > 0 && ApricotBPB.partitionCount == 0)
{
DicConsole.DebugWriteLine("FAT plugin", "Using Apricot BPB");
useApricotBPB = true;
@@ -956,15 +957,20 @@ namespace DiscImageChef.Filesystems
else if(useApricotBPB)
{
isFAT12 = true;
- fakeBPB.bps = ApricotBPB.bps;
- fakeBPB.spc = ApricotBPB.spc;
- fakeBPB.rsectors = ApricotBPB.rsectors;
- fakeBPB.fats_no = ApricotBPB.fats_no;
- fakeBPB.root_ent = ApricotBPB.root_ent;
- fakeBPB.sectors = ApricotBPB.sectors;
- fakeBPB.media = ApricotBPB.media;
- fakeBPB.spfat = ApricotBPB.spfat;
- fakeBPB.boot_code = ApricotBPB.boot_code;
+ fakeBPB.bps = ApricotBPB.mainBPB.bps;
+ fakeBPB.spc = ApricotBPB.mainBPB.spc;
+ fakeBPB.rsectors = ApricotBPB.mainBPB.rsectors;
+ fakeBPB.fats_no = ApricotBPB.mainBPB.fats_no;
+ fakeBPB.root_ent = ApricotBPB.mainBPB.root_ent;
+ fakeBPB.sectors = ApricotBPB.mainBPB.sectors;
+ fakeBPB.media = ApricotBPB.mainBPB.media;
+ fakeBPB.spfat = ApricotBPB.mainBPB.spfat;
+ fakeBPB.sptrk = ApricotBPB.spt;
+ xmlFSType.Bootable = ApricotBPB.bootType > 0;
+
+ if(ApricotBPB.bootLocation > 0 && ApricotBPB.bootLocation + ApricotBPB.bootSize < imagePlugin.GetSectors())
+ fakeBPB.boot_code = imagePlugin.ReadSectors(ApricotBPB.bootLocation,
+ (uint)(ApricotBPB.sectorSize * ApricotBPB.bootSize) / imagePlugin.GetSectorSize());
}
if(!isFAT32)
@@ -1727,13 +1733,220 @@ namespace DiscImageChef.Filesystems
public ushort boot_signature;
}
- /// Apricot BIOS Parameter Block.
+ /// 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
{
- /// Boot specific information
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
- public byte[] boot_code;
/// Bytes per sector
public ushort bps;
/// Sectors per cluster
@@ -1752,11 +1965,8 @@ namespace DiscImageChef.Filesystems
public ushort spfat;
/// Disk type
public byte diskType;
- /// Reserved
- public ushort reserved;
- /// Unknown.
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 416)]
- public byte[] unknown;
+ /// Volume starting sector
+ public ushort startSector;
}
public const uint fsinfo_signature1 = 0x41615252;
diff --git a/DiscImageChef.Partitions/Apricot.cs b/DiscImageChef.Partitions/Apricot.cs
new file mode 100644
index 000000000..ef0255a51
--- /dev/null
+++ b/DiscImageChef.Partitions/Apricot.cs
@@ -0,0 +1,41 @@
+// /***************************************************************************
+// The Disc Image Chef
+// ----------------------------------------------------------------------------
+//
+// Filename : Apricot.cs
+// Author(s) : Natalia Portillo
+//
+// Component : Component
+//
+// --[ Description ] ----------------------------------------------------------
+//
+// Description
+//
+// --[ 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 .
+//
+// ----------------------------------------------------------------------------
+// Copyright © 2011-2017 Natalia Portillo
+// ****************************************************************************/
+using System;
+namespace DiscImageChef.Partitions
+{
+ public class Apricot
+ {
+ public Apricot()
+ {
+ }
+ }
+}