mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
1514 lines
72 KiB
C#
1514 lines
72 KiB
C#
// /***************************************************************************
|
|
// The Disc Image Chef
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// Filename : RDB.cs
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
//
|
|
// Component : Partitioning scheme plugins.
|
|
//
|
|
// --[ Description ] ----------------------------------------------------------
|
|
//
|
|
// Manages Amiga Rigid Disk Block.
|
|
//
|
|
// --[ 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/>.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright © 2011-2018 Natalia Portillo
|
|
// ****************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using DiscImageChef.Checksums;
|
|
using DiscImageChef.CommonTypes;
|
|
using DiscImageChef.CommonTypes.Interfaces;
|
|
using DiscImageChef.Console;
|
|
|
|
namespace DiscImageChef.Partitions
|
|
{
|
|
public class AmigaRigidDiskBlock : IPartition
|
|
{
|
|
/// <summary>
|
|
/// RDB magic number "RDSK"
|
|
/// </summary>
|
|
const uint RIGID_DISK_BLOCK_MAGIC = 0x5244534B;
|
|
/// <summary>
|
|
/// Bad block list magic number "BADB"
|
|
/// </summary>
|
|
const uint BAD_BLOCK_LIST_MAGIC = 0x42414442;
|
|
/// <summary>
|
|
/// Partition entry magic number "PART"
|
|
/// </summary>
|
|
const uint PARTITION_BLOCK_MAGIC = 0x50415254;
|
|
/// <summary>
|
|
/// Filesystem header magic number "FSHD"
|
|
/// </summary>
|
|
const uint FILESYSTEM_HEADER_MAGIC = 0x46534844;
|
|
/// <summary>
|
|
/// LoadSeg block magic number "LSEG"
|
|
/// </summary>
|
|
const uint LOAD_SEG_MAGIC = 0x4C534547;
|
|
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System, "DOS\0"
|
|
/// </summary>
|
|
const uint TYPEID_OFS = 0x444F5300;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System, "DOS\1"
|
|
/// </summary>
|
|
const uint TYPEID_FFS = 0x444F5301;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with international characters, "DOS\2"
|
|
/// </summary>
|
|
const uint TYPEID_OFS_INTL = 0x444F5302;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with international characters, "DOS\3"
|
|
/// </summary>
|
|
const uint TYPEID_FFS_INTL = 0x444F5303;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with directory cache, "DOS\4"
|
|
/// </summary>
|
|
const uint TYPEID_OFS_CACHE = 0x444F5304;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with directory cache, "DOS\5"
|
|
/// </summary>
|
|
const uint TYPEID_FFS_CACHE = 0x444F5305;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with long filenames, "DOS\6"
|
|
/// </summary>
|
|
const uint TYPEID_OFS2 = 0x444F5306;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with long filenames, "DOS\7"
|
|
/// </summary>
|
|
const uint TYPEID_FFS2 = 0x444F5307;
|
|
/// <summary>
|
|
/// Type ID for Amiga UNIX boot filesystem
|
|
/// </summary>
|
|
const uint TYPEID_AMIX_BOOT = 0x554E4900;
|
|
/// <summary>
|
|
/// Type ID for Amiga UNIX System V filesystem
|
|
/// </summary>
|
|
const uint TYPEID_AMIX_SYSV = 0x554E4901;
|
|
/// <summary>
|
|
/// Type ID for Amiga UNIX BSD filesystem
|
|
/// </summary>
|
|
const uint TYPEID_AMIX_FFS = 0x554E4902;
|
|
/// <summary>
|
|
/// Type ID for Amiga UNIX Reserved partition (swap)
|
|
/// </summary>
|
|
const uint TYPEID_AMIX_RESERVED = 0x72657376;
|
|
/// <summary>
|
|
/// Type ID for ProfessionalFileSystem, "PFS\1"
|
|
/// </summary>
|
|
const uint TYPEID_PFS = 0x50465301;
|
|
/// <summary>
|
|
/// Type ID for ProfessionalFileSystem, "PFS\2"
|
|
/// </summary>
|
|
const uint TYPEID_PFS2 = 0x50465302;
|
|
/// <summary>
|
|
/// Type ID for ProfessionalFileSystem, "muAF"
|
|
/// </summary>
|
|
const uint TYPEID_PFS_MUSER = 0x6D754146;
|
|
/// <summary>
|
|
/// Type ID for ProfessionalFileSystem, "AFS\1"
|
|
/// </summary>
|
|
const uint TYPEID_AFS = 0x41465301;
|
|
/// <summary>
|
|
/// Type ID for SmartFileSystem v1, "SFS\0"
|
|
/// </summary>
|
|
const uint TYPEID_SFS = 0x53465300;
|
|
/// <summary>
|
|
/// Type ID for SmartFileSystem v2, "SFS\2"
|
|
/// </summary>
|
|
const uint TYPEID_SFS2 = 0x53465302;
|
|
/// <summary>
|
|
/// Type ID for JXFS, "JXF\4"
|
|
/// </summary>
|
|
const uint TYPEID_JXFS = 0x4A584604;
|
|
/// <summary>
|
|
/// Type ID for FAT, as set by CrossDOS, "MSD\0"
|
|
/// </summary>
|
|
const uint TYPEID_CROSS_DOS = 0x4D534400;
|
|
/// <summary>
|
|
/// Type ID for HFS, as set by CrossMac, "MAC\0"
|
|
/// </summary>
|
|
const uint TYPEID_CROSS_MAC = 0x4D414300;
|
|
/// <summary>
|
|
/// Type ID for 4.2UFS, for BFFS, "BFFS"
|
|
/// </summary>
|
|
const uint TYPEID_BFFS = 0x42464653;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with multi-user patches, "muF\0"
|
|
/// </summary>
|
|
const uint TYPEID_OFS_MUSER = 0x6D754600;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with multi-user patches, "muF\1"
|
|
/// </summary>
|
|
const uint TYPEID_FFS_MUSER = 0x6D754601;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with international characters and multi-user patches, "muF\2"
|
|
/// </summary>
|
|
const uint TYPEID_OFS_INTL_MUSER = 0x6D754602;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with international characters and multi-user patches, "muF\3"
|
|
/// </summary>
|
|
const uint TYPEID_FFS_INTL_MUSER = 0x6D754603;
|
|
/// <summary>
|
|
/// Type ID for Amiga Original File System with directory cache and multi-user patches, "muF\4"
|
|
/// </summary>
|
|
const uint TYPEID_OFS_CACHE_MUSER = 0x6D754604;
|
|
/// <summary>
|
|
/// Type ID for Amiga Fast File System with directory cache and multi-user patches, "muF\5"
|
|
/// </summary>
|
|
const uint TYPEID_FFS_CACHE_MUSER = 0x6D754605;
|
|
/// <summary>
|
|
/// Type ID for BSD unused, "BSD\0"
|
|
/// </summary>
|
|
const uint TYPEID_OLD_BSD_UNUSED = 0x42534400;
|
|
/// <summary>
|
|
/// Type ID for BSD swap, "BSD\1"
|
|
/// </summary>
|
|
const uint TYPEID_OLD_BSD_SWAP = 0x42534401;
|
|
/// <summary>
|
|
/// Type ID for BSD 4.2 FFS, "BSD\7"
|
|
/// </summary>
|
|
const uint TYPEID_OLD_BSD42_FFS = 0x42534407;
|
|
/// <summary>
|
|
/// Type ID for BSD 4.4 LFS, "BSD\9"
|
|
/// </summary>
|
|
const uint TYPEID_OLD_BSD44_LFS = 0x42534409;
|
|
/// <summary>
|
|
/// Type ID for NetBSD unused root partition, "NBR\0"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_ROOT_UNUSED = 0x4E425200;
|
|
/// <summary>
|
|
/// Type ID for NetBSD 4.2 FFS root partition, "NBR\7"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_ROOT_42FFS = 0x4E425207;
|
|
/// <summary>
|
|
/// Type ID for NetBSD 4.4 LFS root partition, "NBR\9"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_ROOT_44LFS = 0x4E425209;
|
|
/// <summary>
|
|
/// Type ID for NetBSD unused user partition, "NBR\0"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_USER_UNUSED = 0x4E425500;
|
|
/// <summary>
|
|
/// Type ID for NetBSD 4.2 FFS user partition, "NBR\7"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_USER_42FFS = 0x4E425507;
|
|
/// <summary>
|
|
/// Type ID for NetBSD 4.4 LFS user partition, "NBR\9"
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_USER_44LFS = 0x4E425509;
|
|
/// <summary>
|
|
/// Type ID for NetBSD swap partition
|
|
/// </summary>
|
|
const uint TYPEID_NETBSD_SWAP = 0x4E425300;
|
|
/// <summary>
|
|
/// Type ID for Linux filesystem partition, "LNX\0"
|
|
/// </summary>
|
|
const uint TYPEID_LINUX = 0x4C4E5800;
|
|
/// <summary>
|
|
/// Type ID for Linux swap partition, "SWP\0"
|
|
/// </summary>
|
|
const uint TYPEID_LINUX_SWAP = 0x53575000;
|
|
/// <summary>
|
|
/// Type ID for RaidFrame partition, "RAID"
|
|
/// </summary>
|
|
const uint TYPEID_RAID_FRAME = 0x52414944;
|
|
/// <summary>
|
|
/// Type ID for RaidFrame partition, "RAI\0"
|
|
/// </summary>
|
|
const uint TYPEID_RAID_FRAME0 = 0x52414900;
|
|
|
|
/// <summary>
|
|
/// No disks to be configured after this one
|
|
/// </summary>
|
|
const uint FLAGS_NO_DISKS = 0x00000001;
|
|
/// <summary>
|
|
/// No LUNs to be configured after this one
|
|
/// </summary>
|
|
const uint FLAGS_NO_LUNS = 0x00000002;
|
|
/// <summary>
|
|
/// No target IDs to be configured after this one
|
|
/// </summary>
|
|
const uint FLAGS_NO_TARGETS = 0x00000004;
|
|
/// <summary>
|
|
/// Don't try to perform reselection with this drive
|
|
/// </summary>
|
|
const uint FLAGS_NO_RESELECTION = 0x00000008;
|
|
/// <summary>
|
|
/// Disk identification is valid
|
|
/// </summary>
|
|
const uint FLAGS_VALID_DISK_ID = 0x00000010;
|
|
/// <summary>
|
|
/// Controller identification is valid
|
|
/// </summary>
|
|
const uint FLAGS_VALID_CONTROLLER_ID = 0x00000020;
|
|
/// <summary>
|
|
/// Drive supports synchronous SCSI mode
|
|
/// </summary>
|
|
const uint FLAGS_SYNCH_SCSI = 0x00000040;
|
|
|
|
/// <summary>
|
|
/// Partition is bootable
|
|
/// </summary>
|
|
const uint FLAGS_BOOTABLE = 0x00000001;
|
|
/// <summary>
|
|
/// Partition should not be mounted automatically
|
|
/// </summary>
|
|
const uint FLAGS_NO_AUTOMOUNT = 0x00000002;
|
|
|
|
public string Name => "Amiga Rigid Disk Block";
|
|
public Guid Id => new Guid("8D72ED97-1854-4170-9CE4-6E8446FD9863");
|
|
public string Author => "Natalia Portillo";
|
|
|
|
public bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset)
|
|
{
|
|
partitions = new List<Partition>();
|
|
BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;
|
|
ulong rdbBlock = 0;
|
|
bool foundRdb = false;
|
|
|
|
while(rdbBlock < 16)
|
|
{
|
|
if(imagePlugin.Info.Sectors <= rdbBlock) return false;
|
|
|
|
if(rdbBlock + sectorOffset >= imagePlugin.Info.Sectors) break;
|
|
|
|
byte[] tmpSector = imagePlugin.ReadSector(rdbBlock + sectorOffset);
|
|
uint magic = BigEndianBitConverter.ToUInt32(tmpSector, 0);
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Possible magic at block {0} is 0x{1:X8}", rdbBlock,
|
|
magic);
|
|
|
|
if(magic == RIGID_DISK_BLOCK_MAGIC)
|
|
{
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Found RDB magic at block {0}", rdbBlock);
|
|
|
|
foundRdb = true;
|
|
break;
|
|
}
|
|
|
|
rdbBlock++;
|
|
}
|
|
|
|
if(!foundRdb) return false;
|
|
|
|
rdbBlock += sectorOffset;
|
|
|
|
RigidDiskBlock rdb = new RigidDiskBlock();
|
|
|
|
byte[] sector = imagePlugin.ReadSector(rdbBlock);
|
|
|
|
rdb.Magic = BigEndianBitConverter.ToUInt32(sector, 0x00);
|
|
rdb.Size = BigEndianBitConverter.ToUInt32(sector, 0x04);
|
|
rdb.Checksum = BigEndianBitConverter.ToInt32(sector, 0x08);
|
|
rdb.TargetId = BigEndianBitConverter.ToUInt32(sector, 0x0C);
|
|
rdb.BlockSize = BigEndianBitConverter.ToUInt32(sector, 0x10);
|
|
rdb.Flags = BigEndianBitConverter.ToUInt32(sector, 0x04);
|
|
rdb.BadblockPtr = BigEndianBitConverter.ToUInt32(sector, 0x18);
|
|
rdb.PartitionPtr = BigEndianBitConverter.ToUInt32(sector, 0x1C);
|
|
rdb.FsheaderPtr = BigEndianBitConverter.ToUInt32(sector, 0x20);
|
|
rdb.Driveinitcode = BigEndianBitConverter.ToUInt32(sector, 0x24);
|
|
rdb.Reserved1 = BigEndianBitConverter.ToUInt32(sector, 0x28);
|
|
rdb.Reserved2 = BigEndianBitConverter.ToUInt32(sector, 0x2C);
|
|
rdb.Reserved3 = BigEndianBitConverter.ToUInt32(sector, 0x30);
|
|
rdb.Reserved4 = BigEndianBitConverter.ToUInt32(sector, 0x34);
|
|
rdb.Reserved5 = BigEndianBitConverter.ToUInt32(sector, 0x38);
|
|
rdb.Reserved6 = BigEndianBitConverter.ToUInt32(sector, 0x3C);
|
|
rdb.Cylinders = BigEndianBitConverter.ToUInt32(sector, 0x40);
|
|
rdb.Spt = BigEndianBitConverter.ToUInt32(sector, 0x44);
|
|
rdb.Heads = BigEndianBitConverter.ToUInt32(sector, 0x48);
|
|
rdb.Interleave = BigEndianBitConverter.ToUInt32(sector, 0x4C);
|
|
rdb.Parking = BigEndianBitConverter.ToUInt32(sector, 0x50);
|
|
rdb.Reserved7 = BigEndianBitConverter.ToUInt32(sector, 0x54);
|
|
rdb.Reserved8 = BigEndianBitConverter.ToUInt32(sector, 0x58);
|
|
rdb.Reserved9 = BigEndianBitConverter.ToUInt32(sector, 0x5C);
|
|
rdb.Writeprecomp = BigEndianBitConverter.ToUInt32(sector, 0x60);
|
|
rdb.Reducedwrite = BigEndianBitConverter.ToUInt32(sector, 0x64);
|
|
rdb.Steprate = BigEndianBitConverter.ToUInt32(sector, 0x68);
|
|
rdb.Reserved10 = BigEndianBitConverter.ToUInt32(sector, 0x6C);
|
|
rdb.Reserved11 = BigEndianBitConverter.ToUInt32(sector, 0x70);
|
|
rdb.Reserved12 = BigEndianBitConverter.ToUInt32(sector, 0x74);
|
|
rdb.Reserved13 = BigEndianBitConverter.ToUInt32(sector, 0x78);
|
|
rdb.Reserved14 = BigEndianBitConverter.ToUInt32(sector, 0x7C);
|
|
rdb.RdbBlockLow = BigEndianBitConverter.ToUInt32(sector, 0x80);
|
|
rdb.RdbBlockHigh = BigEndianBitConverter.ToUInt32(sector, 0x84);
|
|
rdb.LowCylinder = BigEndianBitConverter.ToUInt32(sector, 0x88);
|
|
rdb.HighCylinder = BigEndianBitConverter.ToUInt32(sector, 0x8C);
|
|
rdb.CylBlocks = BigEndianBitConverter.ToUInt32(sector, 0x90);
|
|
rdb.AutoParkSeconds = BigEndianBitConverter.ToUInt32(sector, 0x94);
|
|
rdb.HighCylinder = BigEndianBitConverter.ToUInt32(sector, 0x98);
|
|
rdb.Reserved15 = BigEndianBitConverter.ToUInt32(sector, 0x9C);
|
|
|
|
byte[] tmpString = new byte[8];
|
|
Array.Copy(sector, 0xA0, tmpString, 0, 8);
|
|
rdb.DiskVendor = StringHandlers.SpacePaddedToString(tmpString);
|
|
tmpString = new byte[16];
|
|
Array.Copy(sector, 0xA8, tmpString, 0, 16);
|
|
rdb.DiskProduct = StringHandlers.SpacePaddedToString(tmpString);
|
|
tmpString = new byte[4];
|
|
Array.Copy(sector, 0xB8, tmpString, 0, 4);
|
|
rdb.DiskRevision = StringHandlers.SpacePaddedToString(tmpString);
|
|
|
|
tmpString = new byte[8];
|
|
Array.Copy(sector, 0xBC, tmpString, 0, 8);
|
|
rdb.ControllerVendor = StringHandlers.SpacePaddedToString(tmpString);
|
|
tmpString = new byte[16];
|
|
Array.Copy(sector, 0xC4, tmpString, 0, 16);
|
|
rdb.ControllerProduct = StringHandlers.SpacePaddedToString(tmpString);
|
|
tmpString = new byte[4];
|
|
Array.Copy(sector, 0xD4, tmpString, 0, 4);
|
|
rdb.ControllerRevision = StringHandlers.SpacePaddedToString(tmpString);
|
|
|
|
rdb.Reserved16 = BigEndianBitConverter.ToUInt32(sector, 0xD8);
|
|
rdb.Reserved17 = BigEndianBitConverter.ToUInt32(sector, 0xDC);
|
|
rdb.Reserved18 = BigEndianBitConverter.ToUInt32(sector, 0xE0);
|
|
rdb.Reserved19 = BigEndianBitConverter.ToUInt32(sector, 0xE4);
|
|
rdb.Reserved20 = BigEndianBitConverter.ToUInt32(sector, 0xE8);
|
|
rdb.Reserved21 = BigEndianBitConverter.ToUInt32(sector, 0xEC);
|
|
rdb.Reserved22 = BigEndianBitConverter.ToUInt32(sector, 0xF0);
|
|
rdb.Reserved23 = BigEndianBitConverter.ToUInt32(sector, 0xF4);
|
|
rdb.Reserved24 = BigEndianBitConverter.ToUInt32(sector, 0xF8);
|
|
rdb.Reserved25 = BigEndianBitConverter.ToUInt32(sector, 0xFC);
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.magic = 0x{0:X8}", rdb.Magic);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.size = {0} longs, {1} bytes", rdb.Size, rdb.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.checksum = 0x{0:X8}", rdb.Checksum);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.targetID = {0}", rdb.TargetId);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.block_size = {0}", rdb.BlockSize);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.badblock_ptr = {0}", rdb.BadblockPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.partition_ptr = {0}", rdb.PartitionPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.fsheader_ptr = {0}", rdb.FsheaderPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.driveinitcode = {0}", rdb.Driveinitcode);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved1 = 0x{0:X8}", rdb.Reserved1);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved2 = 0x{0:X8}", rdb.Reserved2);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved3 = 0x{0:X8}", rdb.Reserved3);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved4 = 0x{0:X8}", rdb.Reserved4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved5 = 0x{0:X8}", rdb.Reserved5);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved6 = 0x{0:X8}", rdb.Reserved6);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.cylinders = {0}", rdb.Cylinders);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.spt = {0}", rdb.Spt);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.heads = {0}", rdb.Heads);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.interleave = {0}", rdb.Interleave);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.parking = {0}", rdb.Parking);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved7 = 0x{0:X8}", rdb.Reserved7);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved8 = 0x{0:X8}", rdb.Reserved8);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved9 = 0x{0:X8}", rdb.Reserved9);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.writeprecomp = {0}", rdb.Writeprecomp);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reducedwrite = {0}", rdb.Reducedwrite);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.steprate = {0}", rdb.Steprate);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved10 = 0x{0:X8}", rdb.Reserved10);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved11 = 0x{0:X8}", rdb.Reserved11);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved12 = 0x{0:X8}", rdb.Reserved12);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved13 = 0x{0:X8}", rdb.Reserved13);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved14 = 0x{0:X8}", rdb.Reserved14);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.RDBBlockLow = {0}", rdb.RdbBlockLow);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.RDBBlockHigh = {0}", rdb.RdbBlockHigh);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.LowCylinder = {0}", rdb.LowCylinder);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.HighCylinder = {0}", rdb.HighCylinder);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.CylBlocks = {0}", rdb.CylBlocks);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.AutoParkSeconds = {0}", rdb.AutoParkSeconds);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.HighCylinder = {0}", rdb.HighCylinder);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved15 = 0x{0:X8}", rdb.Reserved15);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.diskVendor = \"{0}\"", rdb.DiskVendor);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.diskProduct = \"{0}\"", rdb.DiskProduct);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.diskRevision = \"{0}\"", rdb.DiskRevision);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.controllerVendor = \"{0}\"", rdb.ControllerVendor);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.controllerProduct = \"{0}\"", rdb.ControllerProduct);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.controllerRevision = \"{0}\"", rdb.ControllerRevision);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved16 = 0x{0:X8}", rdb.Reserved16);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved17 = 0x{0:X8}", rdb.Reserved17);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved18 = 0x{0:X8}", rdb.Reserved18);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved19 = 0x{0:X8}", rdb.Reserved19);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved20 = 0x{0:X8}", rdb.Reserved20);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved21 = 0x{0:X8}", rdb.Reserved21);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved22 = 0x{0:X8}", rdb.Reserved22);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved23 = 0x{0:X8}", rdb.Reserved23);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved24 = 0x{0:X8}", rdb.Reserved24);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "RDB.reserved25 = 0x{0:X8}", rdb.Reserved25);
|
|
|
|
// Reading BadBlock list
|
|
List<BadBlockList> badBlockChain = new List<BadBlockList>();
|
|
ulong nextBlock = rdb.BadblockPtr;
|
|
while(nextBlock != 0xFFFFFFFF)
|
|
{
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Going to block {0} in search of a BadBlock block",
|
|
nextBlock);
|
|
|
|
sector = imagePlugin.ReadSector(nextBlock);
|
|
uint magic = BigEndianBitConverter.ToUInt32(sector, 0);
|
|
|
|
if(magic != BAD_BLOCK_LIST_MAGIC) break;
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Found BadBlock block");
|
|
|
|
BadBlockList chainEntry = new BadBlockList
|
|
{
|
|
Magic = BigEndianBitConverter.ToUInt32(sector, 0x00),
|
|
Size = BigEndianBitConverter.ToUInt32(sector, 0x04),
|
|
Checksum = BigEndianBitConverter.ToInt32(sector, 0x08),
|
|
TargetId = BigEndianBitConverter.ToUInt32(sector, 0x0C),
|
|
NextPtr = BigEndianBitConverter.ToUInt32(sector, 0x10),
|
|
Reserved = BigEndianBitConverter.ToUInt32(sector, 0x14)
|
|
};
|
|
ulong entries = (chainEntry.Size - 6) / 2;
|
|
chainEntry.BlockPairs = new BadBlockEntry[entries];
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.magic = 0x{0:X8}", chainEntry.Magic);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.size = {0} longs, {1} bytes", chainEntry.Size,
|
|
chainEntry.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.checksum = 0x{0:X8}", chainEntry.Checksum);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.targetID = {0}", chainEntry.TargetId);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.next_ptr = {0}", chainEntry.NextPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "chainEntry.reserved = 0x{0:X8}", chainEntry.Reserved);
|
|
|
|
for(ulong i = 0; i < entries; i++)
|
|
{
|
|
chainEntry.BlockPairs[i].BadBlock = BigEndianBitConverter.ToUInt32(sector, (int)(0x18 + i * 8 + 0));
|
|
chainEntry.BlockPairs[i].GoodBlock =
|
|
BigEndianBitConverter.ToUInt32(sector, (int)(0x18 + i * 8 + 4));
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Bad block at {0} replaced with good block at {1}",
|
|
chainEntry.BlockPairs[i].BadBlock, chainEntry.BlockPairs[i].GoodBlock);
|
|
}
|
|
|
|
badBlockChain.Add(chainEntry);
|
|
nextBlock = chainEntry.NextPtr;
|
|
}
|
|
|
|
// Reading BadBlock list
|
|
List<PartitionEntry> partitionEntries = new List<PartitionEntry>();
|
|
nextBlock = rdb.PartitionPtr;
|
|
while(nextBlock != 0xFFFFFFFF)
|
|
{
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Going to block {0} in search of a PartitionEntry block",
|
|
nextBlock + sectorOffset);
|
|
|
|
sector = imagePlugin.ReadSector(nextBlock + sectorOffset);
|
|
uint magic = BigEndianBitConverter.ToUInt32(sector, 0);
|
|
|
|
if(magic != PARTITION_BLOCK_MAGIC) break;
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Found PartitionEntry block");
|
|
|
|
PartitionEntry partEntry = new PartitionEntry
|
|
{
|
|
Magic = BigEndianBitConverter.ToUInt32(sector, 0x00),
|
|
Size = BigEndianBitConverter.ToUInt32(sector, 0x04),
|
|
Checksum = BigEndianBitConverter.ToInt32(sector, 0x08),
|
|
TargetId = BigEndianBitConverter.ToUInt32(sector, 0x0C),
|
|
NextPtr = BigEndianBitConverter.ToUInt32(sector, 0x10),
|
|
Flags = BigEndianBitConverter.ToUInt32(sector, 0x14),
|
|
Reserved1 = BigEndianBitConverter.ToUInt32(sector, 0x18),
|
|
Reserved2 = BigEndianBitConverter.ToUInt32(sector, 0x1C),
|
|
DevFlags = BigEndianBitConverter.ToUInt32(sector, 0x20),
|
|
DriveNameLen = sector[0x24],
|
|
Reserved3 = BigEndianBitConverter.ToUInt32(sector, 0x44),
|
|
Reserved4 = BigEndianBitConverter.ToUInt32(sector, 0x48),
|
|
Reserved5 = BigEndianBitConverter.ToUInt32(sector, 0x4C),
|
|
Reserved6 = BigEndianBitConverter.ToUInt32(sector, 0x50),
|
|
Reserved7 = BigEndianBitConverter.ToUInt32(sector, 0x54),
|
|
Reserved8 = BigEndianBitConverter.ToUInt32(sector, 0x58),
|
|
Reserved9 = BigEndianBitConverter.ToUInt32(sector, 0x5C),
|
|
Reserved10 = BigEndianBitConverter.ToUInt32(sector, 0x60),
|
|
Reserved11 = BigEndianBitConverter.ToUInt32(sector, 0x64),
|
|
Reserved12 = BigEndianBitConverter.ToUInt32(sector, 0x68),
|
|
Reserved13 = BigEndianBitConverter.ToUInt32(sector, 0x6C),
|
|
Reserved14 = BigEndianBitConverter.ToUInt32(sector, 0x70),
|
|
Reserved15 = BigEndianBitConverter.ToUInt32(sector, 0x74),
|
|
Reserved16 = BigEndianBitConverter.ToUInt32(sector, 0x78),
|
|
Reserved17 = BigEndianBitConverter.ToUInt32(sector, 0x7C),
|
|
DosEnvVec = new DosEnvironmentVector
|
|
{
|
|
Size = BigEndianBitConverter.ToUInt32(sector, 0x80),
|
|
BlockSize = BigEndianBitConverter.ToUInt32(sector, 0x84),
|
|
SecOrg = BigEndianBitConverter.ToUInt32(sector, 0x88),
|
|
Surfaces = BigEndianBitConverter.ToUInt32(sector, 0x8C),
|
|
Spb = BigEndianBitConverter.ToUInt32(sector, 0x90),
|
|
Bpt = BigEndianBitConverter.ToUInt32(sector, 0x94),
|
|
Reservedblocks = BigEndianBitConverter.ToUInt32(sector, 0x98),
|
|
Prealloc = BigEndianBitConverter.ToUInt32(sector, 0x9C),
|
|
Interleave = BigEndianBitConverter.ToUInt32(sector, 0xA0),
|
|
LowCylinder = BigEndianBitConverter.ToUInt32(sector, 0xA4),
|
|
HighCylinder = BigEndianBitConverter.ToUInt32(sector, 0xA8),
|
|
NumBuffer = BigEndianBitConverter.ToUInt32(sector, 0xAC),
|
|
BufMemType = BigEndianBitConverter.ToUInt32(sector, 0xB0),
|
|
MaxTransfer = BigEndianBitConverter.ToUInt32(sector, 0xB4),
|
|
Mask = BigEndianBitConverter.ToUInt32(sector, 0xB8),
|
|
BootPriority = BigEndianBitConverter.ToUInt32(sector, 0xBC),
|
|
DosType = BigEndianBitConverter.ToUInt32(sector, 0xC0),
|
|
Baud = BigEndianBitConverter.ToUInt32(sector, 0xC4),
|
|
Control = BigEndianBitConverter.ToUInt32(sector, 0xC8),
|
|
BootBlocks = BigEndianBitConverter.ToUInt32(sector, 0xCC)
|
|
}
|
|
};
|
|
|
|
byte[] driveName = new byte[32];
|
|
Array.Copy(sector, 0x24, driveName, 0, 32);
|
|
partEntry.DriveName = StringHandlers.PascalToString(driveName, Encoding.GetEncoding("iso-8859-1"));
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.magic = 0x{0:X8}", partEntry.Magic);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.size = {0} longs, {1} bytes", partEntry.Size,
|
|
partEntry.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.checksum = 0x{0:X8}", partEntry.Checksum);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.targetID = {0}", partEntry.TargetId);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.next_ptr = {0}", partEntry.NextPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.flags = 0x{0:X8}", partEntry.Flags);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved1 = 0x{0:X8}", partEntry.Reserved1);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved2 = 0x{0:X8}", partEntry.Reserved2);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.devFlags = 0x{0:X8}", partEntry.DevFlags);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.driveNameLen = {0}",
|
|
partEntry.DriveNameLen);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.driveName = \"{0}\"", partEntry.DriveName);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved3 = 0x{0:X8}", partEntry.Reserved3);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved4 = 0x{0:X8}", partEntry.Reserved4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved5 = 0x{0:X8}", partEntry.Reserved5);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved6 = 0x{0:X8}", partEntry.Reserved6);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved7 = 0x{0:X8}", partEntry.Reserved7);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved8 = 0x{0:X8}", partEntry.Reserved8);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved9 = 0x{0:X8}", partEntry.Reserved9);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved10 = 0x{0:X8}", partEntry.Reserved10);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved11 = 0x{0:X8}", partEntry.Reserved11);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved12 = 0x{0:X8}", partEntry.Reserved12);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved13 = 0x{0:X8}", partEntry.Reserved13);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved14 = 0x{0:X8}", partEntry.Reserved14);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved15 = 0x{0:X8}", partEntry.Reserved15);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved16 = 0x{0:X8}", partEntry.Reserved16);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.reserved17 = 0x{0:X8}", partEntry.Reserved17);
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.size = {0} longs, {1} bytes",
|
|
partEntry.DosEnvVec.Size, partEntry.DosEnvVec.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.block_size = {0} longs, {1} bytes",
|
|
partEntry.DosEnvVec.BlockSize, partEntry.DosEnvVec.BlockSize * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.sec_org = 0x{0:X8}",
|
|
partEntry.DosEnvVec.SecOrg);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.surfaces = {0}",
|
|
partEntry.DosEnvVec.Surfaces);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.spb = {0}", partEntry.DosEnvVec.Spb);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.bpt = {0}", partEntry.DosEnvVec.Bpt);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.reservedblocks = {0}",
|
|
partEntry.DosEnvVec.Reservedblocks);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.prealloc = {0}",
|
|
partEntry.DosEnvVec.Prealloc);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.interleave = {0}",
|
|
partEntry.DosEnvVec.Interleave);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.lowCylinder = {0}",
|
|
partEntry.DosEnvVec.LowCylinder);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.highCylinder = {0}",
|
|
partEntry.DosEnvVec.HighCylinder);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.numBuffer = {0}",
|
|
partEntry.DosEnvVec.NumBuffer);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.bufMemType = {0}",
|
|
partEntry.DosEnvVec.BufMemType);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.maxTransfer = {0}",
|
|
partEntry.DosEnvVec.MaxTransfer);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.Mask = 0x{0:X8}",
|
|
partEntry.DosEnvVec.Mask);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.bootPriority = {0}",
|
|
partEntry.DosEnvVec.BootPriority);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.dosType = {0}",
|
|
AmigaDosTypeToString(partEntry.DosEnvVec.DosType, true));
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.baud = {0}",
|
|
partEntry.DosEnvVec.Baud);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.control = 0x{0:X8}",
|
|
partEntry.DosEnvVec.Control);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "partEntry.dosEnvVec.bootBlocks = {0}",
|
|
partEntry.DosEnvVec.BootBlocks);
|
|
|
|
partitionEntries.Add(partEntry);
|
|
nextBlock = partEntry.NextPtr;
|
|
}
|
|
|
|
// Reading BadBlock list
|
|
List<FileSystemHeader> fshdEntries = new List<FileSystemHeader>();
|
|
List<LoadSegment> segmentEntries = new List<LoadSegment>();
|
|
nextBlock = rdb.FsheaderPtr;
|
|
while(nextBlock != 0xFFFFFFFF)
|
|
{
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin",
|
|
"Going to block {0} in search of a FileSystemHeader block", nextBlock);
|
|
|
|
sector = imagePlugin.ReadSector(nextBlock);
|
|
uint magic = BigEndianBitConverter.ToUInt32(sector, 0);
|
|
|
|
if(magic != FILESYSTEM_HEADER_MAGIC) break;
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Found FileSystemHeader block");
|
|
|
|
FileSystemHeader fshd = new FileSystemHeader
|
|
{
|
|
Magic = BigEndianBitConverter.ToUInt32(sector, 0x00),
|
|
Size = BigEndianBitConverter.ToUInt32(sector, 0x04),
|
|
Checksum = BigEndianBitConverter.ToInt32(sector, 0x08),
|
|
TargetId = BigEndianBitConverter.ToUInt32(sector, 0x0C),
|
|
NextPtr = BigEndianBitConverter.ToUInt32(sector, 0x10),
|
|
Flags = BigEndianBitConverter.ToUInt32(sector, 0x14),
|
|
Reserved1 = BigEndianBitConverter.ToUInt32(sector, 0x18),
|
|
Reserved2 = BigEndianBitConverter.ToUInt32(sector, 0x1C),
|
|
DosType = BigEndianBitConverter.ToUInt32(sector, 0x20),
|
|
Version = BigEndianBitConverter.ToUInt32(sector, 0x24),
|
|
PatchFlags = BigEndianBitConverter.ToUInt32(sector, 0x28),
|
|
Dnode = new DeviceNode
|
|
{
|
|
Type = BigEndianBitConverter.ToUInt32(sector, 0x2C),
|
|
Task = BigEndianBitConverter.ToUInt32(sector, 0x30),
|
|
Locked = BigEndianBitConverter.ToUInt32(sector, 0x34),
|
|
Handler = BigEndianBitConverter.ToUInt32(sector, 0x38),
|
|
StackSize = BigEndianBitConverter.ToUInt32(sector, 0x3C),
|
|
Priority = BigEndianBitConverter.ToUInt32(sector, 0x40),
|
|
Startup = BigEndianBitConverter.ToUInt32(sector, 0x44),
|
|
SeglistPtr = BigEndianBitConverter.ToUInt32(sector, 0x48),
|
|
GlobalVec = BigEndianBitConverter.ToUInt32(sector, 0x4C)
|
|
}
|
|
};
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.magic = 0x{0:X8}", fshd.Magic);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.size = {0} longs, {1} bytes", fshd.Size,
|
|
fshd.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.checksum = 0x{0:X8}", fshd.Checksum);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.targetID = {0}", fshd.TargetId);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.next_ptr = {0}", fshd.NextPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.flags = 0x{0:X8}", fshd.Flags);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.reserved1 = 0x{0:X8}", fshd.Reserved1);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.reserved2 = 0x{0:X8}", fshd.Reserved2);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dosType = {0}",
|
|
AmigaDosTypeToString(fshd.DosType));
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.version = {0:D2}.{1:D2} (0x{2:X8})",
|
|
(fshd.Version & 0xFFFF0000) >> 16, fshd.Version & 0xFFFF, fshd.Version);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.patchFlags = 0x{0:X8}", fshd.PatchFlags);
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.type = {0}", fshd.Dnode.Type);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.task = {0}", fshd.Dnode.Task);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.locked = {0}", fshd.Dnode.Locked);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.handler = {0}", fshd.Dnode.Handler);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.stackSize = {0}", fshd.Dnode.StackSize);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.priority = {0}", fshd.Dnode.Priority);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.startup = {0}", fshd.Dnode.Startup);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.seglist_ptr = {0}",
|
|
fshd.Dnode.SeglistPtr);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "FSHD.dnode.global_vec = 0x{0:X8}", fshd.Dnode.GlobalVec);
|
|
|
|
nextBlock = fshd.Dnode.SeglistPtr;
|
|
bool thereAreLoadSegments = false;
|
|
Sha1Context sha1Ctx = new Sha1Context();
|
|
while(nextBlock != 0xFFFFFFFF)
|
|
{
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Going to block {0} in search of a LoadSegment block",
|
|
nextBlock);
|
|
|
|
sector = imagePlugin.ReadSector(nextBlock);
|
|
uint magicSeg = BigEndianBitConverter.ToUInt32(sector, 0);
|
|
|
|
if(magicSeg != LOAD_SEG_MAGIC) break;
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "Found LoadSegment block");
|
|
|
|
thereAreLoadSegments = true;
|
|
LoadSegment loadSeg = new LoadSegment
|
|
{
|
|
Magic = BigEndianBitConverter.ToUInt32(sector, 0x00),
|
|
Size = BigEndianBitConverter.ToUInt32(sector, 0x04),
|
|
Checksum = BigEndianBitConverter.ToInt32(sector, 0x08),
|
|
TargetId = BigEndianBitConverter.ToUInt32(sector, 0x0C),
|
|
NextPtr = BigEndianBitConverter.ToUInt32(sector, 0x10)
|
|
};
|
|
loadSeg.LoadData = new byte[(loadSeg.Size - 5) * 4];
|
|
Array.Copy(sector, 0x14, loadSeg.LoadData, 0, (loadSeg.Size - 5) * 4);
|
|
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "loadSeg.magic = 0x{0:X8}", loadSeg.Magic);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "loadSeg.size = {0} longs, {1} bytes", loadSeg.Size,
|
|
loadSeg.Size * 4);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "loadSeg.checksum = 0x{0:X8}", loadSeg.Checksum);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "loadSeg.targetID = {0}", loadSeg.TargetId);
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "loadSeg.next_ptr = {0}", loadSeg.NextPtr);
|
|
|
|
segmentEntries.Add(loadSeg);
|
|
nextBlock = loadSeg.NextPtr;
|
|
|
|
sha1Ctx.Update(loadSeg.LoadData);
|
|
}
|
|
|
|
if(thereAreLoadSegments)
|
|
{
|
|
string loadSegSha1 = sha1Ctx.End();
|
|
DicConsole.DebugWriteLine("Amiga RDB plugin", "LoadSegment data SHA1: {0}", loadSegSha1);
|
|
}
|
|
|
|
fshdEntries.Add(fshd);
|
|
nextBlock = fshd.NextPtr;
|
|
}
|
|
|
|
ulong sequence = 0;
|
|
foreach(Partition entry in partitionEntries.Select(rdbEntry => new Partition
|
|
{
|
|
Description =
|
|
AmigaDosTypeToDescriptionString(rdbEntry
|
|
.DosEnvVec
|
|
.DosType),
|
|
Name = rdbEntry.DriveName,
|
|
Sequence = sequence,
|
|
Length =
|
|
(rdbEntry.DosEnvVec.HighCylinder + 1 -
|
|
rdbEntry.DosEnvVec.LowCylinder) *
|
|
rdbEntry.DosEnvVec.Surfaces *
|
|
rdbEntry.DosEnvVec.Bpt,
|
|
Start =
|
|
rdbEntry.DosEnvVec.LowCylinder *
|
|
rdbEntry.DosEnvVec.Surfaces *
|
|
rdbEntry.DosEnvVec.Bpt + sectorOffset,
|
|
Type =
|
|
AmigaDosTypeToString(rdbEntry.DosEnvVec
|
|
.DosType),
|
|
Scheme = Name,
|
|
Offset =
|
|
(rdbEntry.DosEnvVec.LowCylinder *
|
|
rdbEntry.DosEnvVec.Surfaces *
|
|
rdbEntry.DosEnvVec.Bpt + sectorOffset) *
|
|
rdb.BlockSize,
|
|
Size = (rdbEntry.DosEnvVec.HighCylinder + 1 -
|
|
rdbEntry.DosEnvVec.LowCylinder) *
|
|
rdbEntry.DosEnvVec.Surfaces *
|
|
rdbEntry.DosEnvVec.Bpt * rdb.BlockSize
|
|
}))
|
|
{
|
|
partitions.Add(entry);
|
|
sequence++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static string AmigaDosTypeToDescriptionString(uint amigaDosType)
|
|
{
|
|
switch(amigaDosType)
|
|
{
|
|
case TYPEID_OFS: return "Amiga Original File System";
|
|
case TYPEID_FFS: return "Amiga Fast File System";
|
|
case TYPEID_OFS_INTL: return "Amiga Original File System with international characters";
|
|
case TYPEID_FFS_INTL: return "Amiga Fast File System with international characters";
|
|
case TYPEID_OFS_CACHE: return "Amiga Original File System with directory cache";
|
|
case TYPEID_FFS_CACHE: return "Amiga Fast File System with directory cache";
|
|
case TYPEID_OFS2: return "Amiga Original File System with long filenames";
|
|
case TYPEID_FFS2: return "Amiga Fast File System with long filenames";
|
|
case TYPEID_AMIX_SYSV: return "Amiga UNIX System V filesystem";
|
|
case TYPEID_AMIX_BOOT: return "Amiga UNIX boot filesystem";
|
|
case TYPEID_AMIX_FFS: return "Amiga UNIX BSD filesystem";
|
|
case TYPEID_AMIX_RESERVED: return "Amiga UNIX Reserved partition (swap)";
|
|
case TYPEID_PFS:
|
|
case TYPEID_PFS2:
|
|
case TYPEID_PFS_MUSER:
|
|
case TYPEID_AFS: return "ProfessionalFileSystem";
|
|
case TYPEID_SFS: return "SmartFileSystem v1";
|
|
case TYPEID_SFS2: return "SmartFileSystem v2";
|
|
case TYPEID_JXFS: return "JXFS";
|
|
case TYPEID_CROSS_DOS: return "FAT, as set by CrossDOS";
|
|
case TYPEID_CROSS_MAC: return "HFS, as set by CrossMac";
|
|
case TYPEID_BFFS: return "4.2UFS, for BFFS";
|
|
case TYPEID_OFS_MUSER: return "Amiga Original File System with multi-user patches";
|
|
case TYPEID_FFS_MUSER: return "Amiga Fast File System with multi-user patches";
|
|
case TYPEID_OFS_INTL_MUSER:
|
|
return "Amiga Original File System with international characters and multi-user patches";
|
|
case TYPEID_FFS_INTL_MUSER:
|
|
return "Amiga Fast File System with international characters and multi-user patches";
|
|
case TYPEID_OFS_CACHE_MUSER:
|
|
return "Amiga Original File System with directory cache and multi-user patches";
|
|
case TYPEID_FFS_CACHE_MUSER:
|
|
return "Amiga Fast File System with directory cache and multi-user patches";
|
|
case TYPEID_OLD_BSD_UNUSED: return "BSD unused";
|
|
case TYPEID_OLD_BSD_SWAP: return "BSD swap";
|
|
case TYPEID_OLD_BSD42_FFS: return "BSD 4.2 FFS";
|
|
case TYPEID_OLD_BSD44_LFS: return "BSD 4.4 LFS";
|
|
case TYPEID_NETBSD_ROOT_UNUSED: return "NetBSD unused root partition";
|
|
case TYPEID_NETBSD_ROOT_42FFS: return "NetBSD 4.2 FFS root partition";
|
|
case TYPEID_NETBSD_ROOT_44LFS: return "NetBSD 4.4 LFS root partition";
|
|
case TYPEID_NETBSD_USER_UNUSED: return "NetBSD unused user partition";
|
|
case TYPEID_NETBSD_USER_42FFS: return "NetBSD 4.2 FFS user partition";
|
|
case TYPEID_NETBSD_USER_44LFS: return "NetBSD 4.4 LFS user partition";
|
|
case TYPEID_NETBSD_SWAP: return "NetBSD swap partition";
|
|
case TYPEID_LINUX: return "Linux filesystem partition";
|
|
case TYPEID_LINUX_SWAP: return "Linux swap partition";
|
|
case TYPEID_RAID_FRAME:
|
|
case TYPEID_RAID_FRAME0: return "RaidFrame partition";
|
|
|
|
default:
|
|
{
|
|
if((amigaDosType & TYPEID_OFS) == TYPEID_OFS)
|
|
return $"Unknown Amiga DOS filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_AMIX_SYSV) == TYPEID_AMIX_SYSV)
|
|
return $"Unknown Amiga UNIX filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & 0x50465300) == 0x50465300 || (amigaDosType & 0x41465300) == 0x41465300)
|
|
return $"Unknown ProfessionalFileSystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_SFS) == TYPEID_SFS)
|
|
return $"Unknown SmartFileSystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_OFS_MUSER) == TYPEID_OFS_MUSER)
|
|
return $"Unknown Amiga DOS multi-user filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_OLD_BSD_UNUSED) == TYPEID_OLD_BSD_UNUSED)
|
|
return $"Unknown BSD filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_NETBSD_ROOT_UNUSED) == TYPEID_NETBSD_ROOT_UNUSED)
|
|
return $"Unknown NetBSD root filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_NETBSD_USER_UNUSED) == TYPEID_NETBSD_USER_UNUSED)
|
|
return $"Unknown NetBSD user filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_NETBSD_SWAP) == TYPEID_NETBSD_SWAP)
|
|
return $"Unknown NetBSD swap filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
if((amigaDosType & TYPEID_LINUX) == TYPEID_LINUX ||
|
|
(amigaDosType & TYPEID_LINUX_SWAP) == TYPEID_LINUX_SWAP)
|
|
return $"Unknown Linux filesystem type {AmigaDosTypeToString(amigaDosType)}";
|
|
|
|
return $"Unknown partition type {AmigaDosTypeToString(amigaDosType)}";
|
|
}
|
|
}
|
|
}
|
|
|
|
static string AmigaDosTypeToString(uint amigaDosType, bool quoted = true)
|
|
{
|
|
byte[] textPart = new byte[3];
|
|
|
|
textPart[0] = (byte)((amigaDosType & 0xFF000000) >> 24);
|
|
textPart[1] = (byte)((amigaDosType & 0x00FF0000) >> 16);
|
|
textPart[2] = (byte)((amigaDosType & 0x0000FF00) >> 8);
|
|
|
|
string textPartString = Encoding.ASCII.GetString(textPart);
|
|
|
|
return quoted ? $"\"{textPartString}\\{amigaDosType & 0xFF}\"" : $"{textPartString}\\{amigaDosType & 0xFF}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Amiga Rigid Disk Block, header for partitioning scheme
|
|
/// Can be in any sector from 0 to 15, inclusive
|
|
/// </summary>
|
|
struct RigidDiskBlock
|
|
{
|
|
/// <summary>
|
|
/// "RDSK"
|
|
/// </summary>
|
|
public uint Magic;
|
|
/// <summary>
|
|
/// Size in longs
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Checksum
|
|
/// </summary>
|
|
public int Checksum;
|
|
/// <summary>
|
|
/// SCSI target ID, 7 for non-SCSI
|
|
/// </summary>
|
|
public uint TargetId;
|
|
/// <summary>
|
|
/// Block size in bytes
|
|
/// </summary>
|
|
public uint BlockSize;
|
|
/// <summary>
|
|
/// Flags
|
|
/// </summary>
|
|
public uint Flags;
|
|
/// <summary>
|
|
/// Pointer to first BadBlockList, 0xFFFFFFFF means last block in device
|
|
/// </summary>
|
|
public uint BadblockPtr;
|
|
/// <summary>
|
|
/// Pointer to first PartitionEntry, 0xFFFFFFFF means last block in device
|
|
/// </summary>
|
|
public uint PartitionPtr;
|
|
/// <summary>
|
|
/// Pointer to first FileSystemHeader, 0xFFFFFFFF means last block in device
|
|
/// </summary>
|
|
public uint FsheaderPtr;
|
|
/// <summary>
|
|
/// Optional drive specific init code
|
|
/// </summary>
|
|
public uint Driveinitcode;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved1;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved2;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved3;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved4;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved5;
|
|
/// <summary>
|
|
/// Reserved, should be 0xFFFFFFFF
|
|
/// </summary>
|
|
public uint Reserved6;
|
|
/// <summary>
|
|
/// Cylinders in drive
|
|
/// </summary>
|
|
public uint Cylinders;
|
|
/// <summary>
|
|
/// Sectors per track
|
|
/// </summary>
|
|
public uint Spt;
|
|
/// <summary>
|
|
/// Heads in drive
|
|
/// </summary>
|
|
public uint Heads;
|
|
/// <summary>
|
|
/// Drive interleave
|
|
/// </summary>
|
|
public uint Interleave;
|
|
/// <summary>
|
|
/// Cylinder for parking heads
|
|
/// </summary>
|
|
public uint Parking;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved7;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved8;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved9;
|
|
/// <summary>
|
|
/// Starting cylinder for write precompensation
|
|
/// </summary>
|
|
public uint Writeprecomp;
|
|
/// <summary>
|
|
/// Starting cylinder for reduced write current
|
|
/// </summary>
|
|
public uint Reducedwrite;
|
|
/// <summary>
|
|
/// Drive step rate
|
|
/// </summary>
|
|
public uint Steprate;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved10;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved11;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved12;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved13;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved14;
|
|
/// <summary>
|
|
/// Low block of RDB reserved blocks
|
|
/// </summary>
|
|
public uint RdbBlockLow;
|
|
/// <summary>
|
|
/// High block of RDB reserved blocks
|
|
/// </summary>
|
|
public uint RdbBlockHigh;
|
|
/// <summary>
|
|
/// Low cylinder for partitionable area
|
|
/// </summary>
|
|
public uint LowCylinder;
|
|
/// <summary>
|
|
/// High cylinder for partitionable area
|
|
/// </summary>
|
|
public uint HighCylinder;
|
|
/// <summary>
|
|
/// Blocks per cylinder
|
|
/// </summary>
|
|
public uint CylBlocks;
|
|
/// <summary>
|
|
/// Seconds for head autoparking
|
|
/// </summary>
|
|
public uint AutoParkSeconds;
|
|
/// <summary>
|
|
/// Highest block used by RDB
|
|
/// </summary>
|
|
public uint HighRdskBlock;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved15;
|
|
/// <summary>
|
|
/// Disk vendor, 8 bytes
|
|
/// </summary>
|
|
public string DiskVendor;
|
|
/// <summary>
|
|
/// Disk product, 16 bytes
|
|
/// </summary>
|
|
public string DiskProduct;
|
|
/// <summary>
|
|
/// Disk revision, 4 bytes
|
|
/// </summary>
|
|
public string DiskRevision;
|
|
/// <summary>
|
|
/// Controller vendor, 8 bytes
|
|
/// </summary>
|
|
public string ControllerVendor;
|
|
/// <summary>
|
|
/// Controller product, 16 bytes
|
|
/// </summary>
|
|
public string ControllerProduct;
|
|
/// <summary>
|
|
/// Controller revision, 4 bytes
|
|
/// </summary>
|
|
public string ControllerRevision;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved16;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved17;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved18;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved19;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved20;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved21;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved22;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved23;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved24;
|
|
/// <summary>
|
|
/// Reserved, should be zero
|
|
/// </summary>
|
|
public uint Reserved25;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pair for spare blocks
|
|
/// </summary>
|
|
struct BadBlockEntry
|
|
{
|
|
/// <summary>
|
|
/// Bad block pointer
|
|
/// </summary>
|
|
public uint BadBlock;
|
|
/// <summary>
|
|
/// Replacement block pointer
|
|
/// </summary>
|
|
public uint GoodBlock;
|
|
}
|
|
|
|
/// <summary>
|
|
/// List of bad blocks and spares
|
|
/// </summary>
|
|
struct BadBlockList
|
|
{
|
|
/// <summary>
|
|
/// "BADB"
|
|
/// </summary>
|
|
public uint Magic;
|
|
/// <summary>
|
|
/// Size in longs
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Checksum
|
|
/// </summary>
|
|
public int Checksum;
|
|
/// <summary>
|
|
/// SCSI target ID, 7 for non-SCSI
|
|
/// </summary>
|
|
public uint TargetId;
|
|
/// <summary>
|
|
/// Pointer for next BadBlockList
|
|
/// </summary>
|
|
public uint NextPtr;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved;
|
|
/// <summary>
|
|
/// Bad block entries, up to block filling, 8 bytes each
|
|
/// </summary>
|
|
public BadBlockEntry[] BlockPairs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// DOSEnvVec, used by AmigaDOS
|
|
/// </summary>
|
|
struct DosEnvironmentVector
|
|
{
|
|
/// <summary>
|
|
/// Size in longs, should be 16, minimum 11
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Block size in longs
|
|
/// </summary>
|
|
public uint BlockSize;
|
|
/// <summary>
|
|
/// Unknown, 0
|
|
/// </summary>
|
|
public uint SecOrg;
|
|
/// <summary>
|
|
/// Heads in drive
|
|
/// </summary>
|
|
public uint Surfaces;
|
|
/// <summary>
|
|
/// Sectors per block
|
|
/// </summary>
|
|
public uint Spb;
|
|
/// <summary>
|
|
/// Blocks per track
|
|
/// </summary>
|
|
public uint Bpt;
|
|
/// <summary>
|
|
/// DOS reserved blocks at start of partition
|
|
/// </summary>
|
|
public uint Reservedblocks;
|
|
/// <summary>
|
|
/// DOS reserved blocks at end of partition
|
|
/// </summary>
|
|
public uint Prealloc;
|
|
/// <summary>
|
|
/// Interleave
|
|
/// </summary>
|
|
public uint Interleave;
|
|
/// <summary>
|
|
/// First cylinder of a partition, inclusive
|
|
/// </summary>
|
|
public uint LowCylinder;
|
|
/// <summary>
|
|
/// Last cylinder of a partition, inclusive
|
|
/// </summary>
|
|
public uint HighCylinder;
|
|
/// <summary>
|
|
/// Buffers, usually 30
|
|
/// </summary>
|
|
public uint NumBuffer;
|
|
/// <summary>
|
|
/// Type of memory to allocate for buffers
|
|
/// </summary>
|
|
public uint BufMemType;
|
|
/// <summary>
|
|
/// Maximum transfer, usually 0x7FFFFFFF
|
|
/// </summary>
|
|
public uint MaxTransfer;
|
|
/// <summary>
|
|
/// Address mask to block out certain memory, usually 0xFFFFFFFE
|
|
/// </summary>
|
|
public uint Mask;
|
|
/// <summary>
|
|
/// Boot priority
|
|
/// </summary>
|
|
public uint BootPriority;
|
|
/// <summary>
|
|
/// Partition type, and filesystem driver identification for AmigaDOS
|
|
/// </summary>
|
|
public uint DosType;
|
|
/// <summary>
|
|
/// Default baud rate for SER and AUX handlers
|
|
/// </summary>
|
|
public uint Baud;
|
|
/// <summary>
|
|
/// Flow control values for SER and AUX handlers
|
|
/// </summary>
|
|
public uint Control;
|
|
/// <summary>
|
|
/// Since Kickstart 2, how many boot blocks are to be loaded
|
|
/// </summary>
|
|
public uint BootBlocks;
|
|
}
|
|
|
|
struct PartitionEntry
|
|
{
|
|
/// <summary>
|
|
/// "PART"
|
|
/// </summary>
|
|
public uint Magic;
|
|
/// <summary>
|
|
/// Size in longs
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Checksum
|
|
/// </summary>
|
|
public int Checksum;
|
|
/// <summary>
|
|
/// SCSI target ID, 7 for non-SCSI
|
|
/// </summary>
|
|
public uint TargetId;
|
|
/// <summary>
|
|
/// Pointer to next PartitionEntry
|
|
/// </summary>
|
|
public uint NextPtr;
|
|
/// <summary>
|
|
/// Partition flags
|
|
/// </summary>
|
|
public uint Flags;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved1;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved2;
|
|
/// <summary>
|
|
/// Preferred flags for OpenDevice()
|
|
/// </summary>
|
|
public uint DevFlags;
|
|
/// <summary>
|
|
/// Length of drive name
|
|
/// </summary>
|
|
public uint DriveNameLen;
|
|
/// <summary>
|
|
/// Drive name, 31 bytes
|
|
/// </summary>
|
|
public string DriveName;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved3;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved4;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved5;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved6;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved7;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved8;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved9;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved10;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved11;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved12;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved13;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved14;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved15;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved16;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved17;
|
|
/// <summary>
|
|
/// DOSEnvVec, more information about partition
|
|
/// </summary>
|
|
public DosEnvironmentVector DosEnvVec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Device node, mostly useless, except for pointer to first LoadSegment block
|
|
/// </summary>
|
|
struct DeviceNode
|
|
{
|
|
/// <summary>
|
|
/// Device node type, =0
|
|
/// </summary>
|
|
public uint Type;
|
|
/// <summary>
|
|
/// DOS task field, =0
|
|
/// </summary>
|
|
public uint Task;
|
|
/// <summary>
|
|
/// Unused, =0
|
|
/// </summary>
|
|
public uint Locked;
|
|
/// <summary>
|
|
/// Filename handler to LoadSegment, =0
|
|
/// </summary>
|
|
public uint Handler;
|
|
/// <summary>
|
|
/// Stack size when starting task, =0
|
|
/// </summary>
|
|
public uint StackSize;
|
|
/// <summary>
|
|
/// Task priority, =0
|
|
/// </summary>
|
|
public uint Priority;
|
|
/// <summary>
|
|
/// Startup message, =0
|
|
/// </summary>
|
|
public uint Startup;
|
|
/// <summary>
|
|
/// Pointer to first LoadSegment block
|
|
/// </summary>
|
|
public uint SeglistPtr;
|
|
/// <summary>
|
|
/// BCPL globabl vector when starting task, =0xFFFFFFFF
|
|
/// </summary>
|
|
public uint GlobalVec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// File system header
|
|
/// </summary>
|
|
struct FileSystemHeader
|
|
{
|
|
/// <summary>
|
|
/// "FSHD"
|
|
/// </summary>
|
|
public uint Magic;
|
|
/// <summary>
|
|
/// Size in longs, 64
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Checksum
|
|
/// </summary>
|
|
public int Checksum;
|
|
/// <summary>
|
|
/// SCSI target ID, 7 for non-SCSI
|
|
/// </summary>
|
|
public uint TargetId;
|
|
/// <summary>
|
|
/// Pointer to next FileSystemHeader block
|
|
/// </summary>
|
|
public uint NextPtr;
|
|
/// <summary>
|
|
/// Flags, unknown
|
|
/// </summary>
|
|
public uint Flags;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved1;
|
|
/// <summary>
|
|
/// Reserved
|
|
/// </summary>
|
|
public uint Reserved2;
|
|
/// <summary>
|
|
/// Partition type, and filesystem driver identification for AmigaDOS
|
|
/// </summary>
|
|
public uint DosType;
|
|
/// <summary>
|
|
/// Filesystem version
|
|
/// Mask 0xFFFF0000, >>16, major version
|
|
/// Mask 0x0000FFFF, minor version
|
|
/// </summary>
|
|
public uint Version;
|
|
/// <summary>
|
|
/// Bits for DeviceNode fields that should be substituted into a standard device node
|
|
/// </summary>
|
|
public uint PatchFlags;
|
|
/// <summary>
|
|
/// Device node
|
|
/// </summary>
|
|
public DeviceNode Dnode;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Filesystem code
|
|
/// </summary>
|
|
struct LoadSegment
|
|
{
|
|
/// <summary>
|
|
/// "LSEG"
|
|
/// </summary>
|
|
public uint Magic;
|
|
/// <summary>
|
|
/// Size in longs
|
|
/// </summary>
|
|
public uint Size;
|
|
/// <summary>
|
|
/// Checksum
|
|
/// </summary>
|
|
public int Checksum;
|
|
/// <summary>
|
|
/// SCSI target ID, 7 for non-SCSI
|
|
/// </summary>
|
|
public uint TargetId;
|
|
/// <summary>
|
|
/// Pointer to next LoadSegment
|
|
/// </summary>
|
|
public uint NextPtr;
|
|
/// <summary>
|
|
/// Executable code, with relocation hunks, til end of sector
|
|
/// </summary>
|
|
public byte[] LoadData;
|
|
}
|
|
}
|
|
} |