// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : Structs.cs // Author(s) : Natalia Portillo // // Component : CP/M filesystem plugin. // // --[ Description ] ---------------------------------------------------------- // // CP/M filesystem structures. // // --[ 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.Runtime.InteropServices; namespace DiscImageChef.Filesystems.CPM { partial class CPM : Filesystem { /// /// Most of the times this structure is hard wired or generated by CP/M, not stored on disk /// class DiscParameterBlock { /// /// Sectors per track /// public ushort spt; /// /// Block shift /// public byte bsh; /// /// Block mask /// public byte blm; /// /// Extent mask /// public byte exm; /// /// Blocks on disk - 1 /// public ushort dsm; /// /// Directory entries - 1 /// public ushort drm; /// /// First byte of allocation bitmap /// public byte al0; /// /// Second byte of allocation bitmap /// public byte al1; /// /// Checksum vector size /// public ushort cks; /// /// Reserved tracks /// public ushort off; /// /// Physical sector shift /// public byte psh; /// /// Physical sector mask /// public byte phm; } /// /// Amstrad superblock, for PCW /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct AmstradSuperBlock { /// /// Format ID. 0 single-side, 3 double-side. 1 and 2 are for CPC but they don't use the superblock /// public byte format; /// /// Gives information about side ordering /// public byte sidedness; /// /// Tracks per side, aka, cylinders /// public byte tps; /// /// Sectors per track /// public byte spt; /// /// Physical sector shift /// public byte psh; /// /// Reserved tracks /// public byte off; /// /// Block size shift /// public byte bsh; /// /// How many blocks does the directory take /// public byte dirBlocks; /// /// GAP#3 length (intersector) /// public byte gapLen; /// /// GAP#4 length (end-of-track) /// public byte formatGap; /// /// Must be 0 /// public byte zero1; /// /// Must be 0 /// public byte zero2; /// /// Must be 0 /// public byte zero3; /// /// Must be 0 /// public byte zero4; /// /// Must be 0 /// public byte zero5; /// /// Indicates machine the boot code following the superblock is designed to boot /// public byte fiddle; } /// /// Superblock found on CP/M-86 hard disk volumes /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HardDiskSuperBlock { /// /// Value so the sum of all the superblock's sector bytes taken as 16-bit values gives 0 /// public ushort checksum; /// /// Copyright string /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x1F)] public byte[] copyright; /// /// First cylinder of disk where this volume resides /// public ushort firstCylinder; /// /// How many cylinders does this volume span /// public ushort cylinders; /// /// Heads on hard disk /// public byte heads; /// /// Sectors per track /// public byte sectorsPerTrack; /// /// Flags, only use by CCP/M where bit 0 equals verify on write /// public byte flags; /// /// Sector size / 128 /// public byte recordsPerSector; /// /// /// public ushort spt; /// /// /// public byte bsh; /// /// /// public byte blm; /// /// /// public byte exm; /// /// /// public ushort dsm; /// /// /// public ushort drm; /// /// /// public ushort al0; /// /// /// public ushort al1; /// /// /// public ushort cks; /// /// /// public ushort off; /// /// Must be zero /// public ushort zero1; /// /// Must be zero /// public ushort zero2; /// /// Must be zero /// public ushort zero3; /// /// Must be zero /// public ushort zero4; /// /// How many 128 bytes are in a block /// public ushort recordsPerBlock; /// /// Maximum number of bad blocks in the bad block list /// public ushort badBlockWordsMax; /// /// Used number of bad blocks in the bad block list /// public ushort badBlockWords; /// /// First block after the blocks reserved for bad block substitution /// public ushort firstSub; } /// /// Volume label entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct LabelEntry { /// /// Must be 0x20 /// public byte signature; /// /// Label in ASCII /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public byte[] label; /// /// Label flags. Bit 0 = label exists, bit 4 = creation timestamp, bit 5 = modification timestamp, bit 6 = access timestamp, bit 7 = password enabled /// public byte flags; /// /// Password decoder byte /// public byte passwordDecoder; /// /// Must be 0 /// public ushort reserved; /// /// Password XOR'ed with /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password; /// /// Label creation time /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] ctime; /// /// Label modification time /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] mtime; } /// /// CP/M 3 timestamp entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DateEntry { /// /// Must be 0x21 /// public byte signature; /// /// File 1 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date1; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] /// /// File 1 modification timestamp /// public byte[] date2; /// /// File 1 password mode /// public byte mode1; public byte zero1; /// /// File 2 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date3; /// /// File 2 modification timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date4; /// /// File 2 password mode /// public byte mode2; public byte zero2; /// /// File 3 create/access timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date5; /// /// File 3 modification timestamp /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] date6; /// /// File 3 password mode /// public byte mode3; public ushort zero3; } /// /// Password entry /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct PasswordEntry { /// /// 16 + user number /// public byte userNumber; /// /// Filename /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// /// Extension /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// /// Password mode. Bit 7 = required for read, bit 6 = required for write, bit 5 = required for delete /// public byte mode; /// /// Password decoder byte /// public byte passwordDecoder; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] reserved; /// /// Password XOR'ed with /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] password; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] reserved2; } /// /// Timestamp for Z80DOS or DOS+ /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct TrdPartyDateEntry { /// /// Must be 0x21 /// public byte signature; public byte zero; /// /// Creation year for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create1; /// /// Modification time for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify1; /// /// Access time for file 1 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access1; /// /// Creation year for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create2; /// /// Modification time for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify2; /// /// Access time for file 2 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access2; /// /// Creation year for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public byte[] create3; /// /// Modification time for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] modify3; /// /// Access time for file 3 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] access3; } /// /// Directory entry for <256 allocation blocks /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DirectoryEntry { /// /// User number. Bit 7 set in CP/M 1 means hidden /// public byte statusUser; /// /// Filename and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// /// Extension and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// /// Low byte of extent number /// public byte extentCounter; /// /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many bytes are free. /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. /// public byte lastRecordBytes; /// /// High byte of extent number /// public byte extentCounterHigh; /// /// How many records are used in this entry. 0x80 if all are used. /// public byte records; /// /// Allocation blocks /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] allocations; } /// /// Directory entry for &bt;256 allocation blocks /// [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DirectoryEntry16 { /// /// User number. Bit 7 set in CP/M 1 means hidden /// public byte statusUser; /// /// Filename and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] filename; /// /// Extension and bit 7 as flags /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] extension; /// /// Low byte of extent number /// public byte extentCounter; /// /// Last record bytes. In some implementations it means how many bytes are used in the last record, in others how many bytes are free. /// It always refer to 128 byte records even if blocks are way bigger, so it's mostly useless. /// public byte lastRecordBytes; /// /// High byte of extent number /// public byte extentCounterHigh; /// /// How many records are used in this entry. 0x80 if all are used. /// public byte records; /// /// Allocation blocks /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public ushort[] allocations; } } }