// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Structs.cs // Author(s) : Natalia Portillo // // Component : Apple ProDOS filesystem plugin. // // --[ 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-2025 Natalia Portillo // ****************************************************************************/ // ReSharper disable NotAccessedField.Local using System; using System.Diagnostics.CodeAnalysis; #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value namespace Aaru.Filesystems; // Information from Apple ProDOS 8 Technical Reference /// /// Implements detection of Apple ProDOS filesystem [SuppressMessage("ReSharper", "UnusedMember.Local")] [SuppressMessage("ReSharper", "UnusedType.Local")] [SuppressMessage("ReSharper", "InconsistentNaming")] public sealed partial class ProDOSPlugin { #region Nested type: DirectoryBlock struct DirectoryBlock { /// Pointer to previous directory block Offset 0x00, 2 bytes public ushort zero; /// Pointer to next directory block, 0 if last Offset 0x02, 2 bytes public ushort next_pointer; /// Directory entries Offset 0x2F, 39 bytes each, 13 entries public Entry[] entries; } #endregion #region Nested type: DirectoryHeader struct DirectoryHeader { /// Constant 0x0E Offset 0x04, mask 0xF0 public byte storage_type; /// Length of volume_name pascal string Offset 0x04, mask 0x0F public byte name_length; /// The name of the directory. Offset 0x05, 15 bytes public string directory_name; /// Reserved for future expansion Offset 0x14, 8 bytes public ulong reserved; /// Creation time of the volume Offset 0x1C, 4 bytes public DateTime creation_time; /// Version number of the volume format Offset 0x20, 1 byte public byte version; /// Reserved for future use Offset 0x21, 1 byte public byte min_version; /// Permissions for the volume Offset 0x22, 1 byte public byte access; /// Length of an entry in this directory Const 0x27 Offset 0x23, 1 byte public byte entry_length; /// Number of entries per block Const 0x0D Offset 0x24, 1 byte public byte entries_per_block; /// Number of active files in this directory Offset 0x25, 2 bytes public ushort file_count; /// Block address of parent directory block that contains this entry Offset 0x27, 2 bytes public ushort parent_pointer; /// Entry number within the block indicated in parent_pointer Offset 0x29, 1 byte public byte parent_entry_number; /// Length of the entry that holds this directory, in the parent entry Const 0x27 Offset 0x2A, 1 byte public byte parent_entry_length; } #endregion #region Nested type: DirectoryKeyBlock struct DirectoryKeyBlock { /// Always 0 Offset 0x00, 2 bytes public ushort zero; /// Pointer to next directory block, 0 if last Offset 0x02, 2 bytes public ushort next_pointer; /// Directory header Offset 0x04, 39 bytes public DirectoryHeader header; /// Directory entries Offset 0x2F, 39 bytes each, 12 entries public Entry[] entries; } #endregion #region Nested type: Entry /// ProDOS directory entry, decoded structure struct Entry { /// Type of file pointed by this entry Offset 0x00, mask 0xF0 public byte storage_type; /// Length of name_length pascal string Offset 0x00, mask 0x0F public byte name_length; /// Pascal string of file name Offset 0x01, 15 bytes public string file_name; /// Descriptor of internal structure of the file Offset 0x10, 1 byte public byte file_type; /// /// Block address of master index block for tree files. Block address of index block for sapling files. Block /// address of block for seedling files. Offset 0x11, 2 bytes /// public ushort key_pointer; /// Blocks used by file or directory, including index blocks. Offset 0x13, 2 bytes public ushort blocks_used; /// Size of file in bytes Offset 0x15, 3 bytes public uint EOF; /// File creation datetime Offset 0x18, 4 bytes public DateTime creation_time; /// Version of ProDOS that created this file Offset 0x1C, 1 byte public byte version; /// Minimum version of ProDOS needed to access this file Offset 0x1D, 1 byte public byte min_version; /// File permissions Offset 0x1E, 1 byte public byte access; /// General purpose field to store additional information about file format Offset 0x1F, 2 bytes public ushort aux_type; /// File last modification date time Offset 0x21, 4 bytes public DateTime last_mod; /// Block address pointer to key block of the directory containing this entry Offset 0x25, 2 bytes public ushort header_pointer; } #endregion #region Nested type: IndexBlock struct IndexBlock { /// Up to 256 pointers to blocks, 0 to indicate the block is sparsed (non-allocated) public ushort[] block_pointer; } #endregion #region Nested type: MasterIndexBlock struct MasterIndexBlock { /// Up to 128 pointers to index blocks public ushort[] index_block_pointer; } #endregion #region Nested type: RootDirectoryHeader struct RootDirectoryHeader { /// Constant 0x0F Offset 0x04, mask 0xF0 public byte storage_type; /// Length of volume_name pascal string Offset 0x04, mask 0x0F public byte name_length; /// The name of the volume. Offset 0x05, 15 bytes public string volume_name; /// Reserved for future expansion Offset 0x14, 8 bytes public ulong reserved; /// Creation time of the volume Offset 0x1C, 4 bytes public DateTime creation_time; /// Version number of the volume format Offset 0x20, 1 byte public byte version; /// Reserved for future use Offset 0x21, 1 byte public byte min_version; /// Permissions for the volume Offset 0x22, 1 byte public byte access; /// Length of an entry in this directory Const 0x27 Offset 0x23, 1 byte public byte entry_length; /// Number of entries per block Const 0x0D Offset 0x24, 1 byte public byte entries_per_block; /// Number of active files in this directory Offset 0x25, 2 bytes public ushort file_count; /// /// Block address of the first block of the volume's bitmap, one for every 4096 blocks or fraction Offset 0x27, 2 /// bytes /// public ushort bit_map_pointer; /// Total number of blocks in the volume Offset 0x29, 2 bytes public ushort total_blocks; } #endregion #region Nested type: RootDirectoryKeyBlock struct RootDirectoryKeyBlock { /// Always 0 Offset 0x00, 2 bytes public ushort zero; /// Pointer to next directory block, 0 if last Offset 0x02, 2 bytes public ushort next_pointer; /// Directory header Offset 0x04, 39 bytes public RootDirectoryHeader header; /// Directory entries Offset 0x2F, 39 bytes each, 12 entries public Entry[] entries; } #endregion }