From 70a6eab8ac536134f328baf74775de53ef3d8592 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 20 Apr 2015 04:29:23 +0100 Subject: [PATCH] Implemented support for Amiga RDB. --- DiscImageChef/ChangeLog | 6 + DiscImageChef/DiscImageChef.csproj | 1 + DiscImageChef/PartPlugins/RDB.cs | 1527 ++++++++++++++++++++++++++++ README.md | 1 + TODO | 1 - 5 files changed, 1535 insertions(+), 1 deletion(-) create mode 100644 DiscImageChef/PartPlugins/RDB.cs diff --git a/DiscImageChef/ChangeLog b/DiscImageChef/ChangeLog index 6d322f9de..08cafe915 100644 --- a/DiscImageChef/ChangeLog +++ b/DiscImageChef/ChangeLog @@ -1,3 +1,9 @@ +2015-04-20 Natalia Portillo + + * PartPlugins/RDB.cs: + * DiscImageChef.csproj: + Implemented support for Amiga RDB. + 2015-04-19 Natalia Portillo * Plugins/ProDOS.cs: diff --git a/DiscImageChef/DiscImageChef.csproj b/DiscImageChef/DiscImageChef.csproj index cde5d58d5..ff609baa5 100644 --- a/DiscImageChef/DiscImageChef.csproj +++ b/DiscImageChef/DiscImageChef.csproj @@ -110,6 +110,7 @@ + diff --git a/DiscImageChef/PartPlugins/RDB.cs b/DiscImageChef/PartPlugins/RDB.cs new file mode 100644 index 000000000..10a0b0f4c --- /dev/null +++ b/DiscImageChef/PartPlugins/RDB.cs @@ -0,0 +1,1527 @@ +/*************************************************************************** +The Disc Image Chef +---------------------------------------------------------------------------- + +Filename : RDB.cs +Version : 1.0 +Author(s) : Natalia Portillo + +Component : Partitioning scheme plugins + +Revision : $Revision$ +Last change by : $Author$ +Date : $Date$ + +--[ Description ] ---------------------------------------------------------- + +Manages Amiga partitions. + +--[ License ] -------------------------------------------------------------- + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +---------------------------------------------------------------------------- +Copyright (C) 2011-2014 Claunia.com +****************************************************************************/ +//$Id$ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DiscImageChef.PartPlugins +{ + public class AmigaRigidDiskBlock : PartPlugin + { + /// + /// RDB magic number "RDSK" + /// + const UInt32 RigidDiskBlockMagic = 0x5244534B; + /// + /// Bad block list magic number "BADB" + /// + const UInt32 BadBlockListMagic = 0x42414442; + /// + /// Partition entry magic number "PART" + /// + const UInt32 PartitionBlockMagic = 0x50415254; + /// + /// Filesystem header magic number "FSHD" + /// + const UInt32 FilesystemHeaderMagic = 0x46534844; + /// + /// LoadSeg block magic number "LSEG" + /// + const UInt32 LoadSegMagic = 0x4C534547; + + /// + /// Type ID for Amiga Original File System, "DOS\0" + /// + const UInt32 TypeIDOFS = 0x444F5300; + /// + /// Type ID for Amiga Fast File System, "DOS\1" + /// + const UInt32 TypeIDFFS = 0x444F5301; + /// + /// Type ID for Amiga Original File System with international characters, "DOS\2" + /// + const UInt32 TypeIDOFSi = 0x444F5302; + /// + /// Type ID for Amiga Fast File System with international characters, "DOS\3" + /// + const UInt32 TypeIDFFSi = 0x444F5303; + /// + /// Type ID for Amiga Original File System with directory cache, "DOS\4" + /// + const UInt32 TypeIDOFSc = 0x444F5304; + /// + /// Type ID for Amiga Fast File System with directory cache, "DOS\5" + /// + const UInt32 TypeIDFFSc = 0x444F5305; + /// + /// Type ID for Amiga Original File System with long filenames, "DOS\6" + /// + const UInt32 TypeIDOFS2 = 0x444F5306; + /// + /// Type ID for Amiga Fast File System with long filenames, "DOS\7" + /// + const UInt32 TypeIDFFS2 = 0x444F5307; + /// + /// Type ID for Amiga UNIX System V filesystem + /// + const UInt32 TypeIDAMIXSysV = 0x554E4900; + /// + /// Type ID for Amiga UNIX boot filesystem + /// + const UInt32 TypeIDAMIXBoot = 0x554E4901; + /// + /// Type ID for Amiga UNIX BSD filesystem + /// + const UInt32 TypeIDAMIXFFS = 0x554E4902; + /// + /// Type ID for Amiga UNIX Reserved partition (swap) + /// + const UInt32 TypeIDAMIXReserved = 0x72657376; + /// + /// Type ID for ProfessionalFileSystem, "PFS\1" + /// + const UInt32 TypeIDPFS = 0x50465301; + /// + /// Type ID for ProfessionalFileSystem, "muAF" + /// + const UInt32 TypeIDPFSm = 0x6D754146; + /// + /// Type ID for ProfessionalFileSystem, "AFS\1" + /// + const UInt32 TypeIDAFS = 0x41465301; + /// + /// Type ID for SmartFileSystem v1, "SFS\0" + /// + const UInt32 TypeIDSFS = 0x53465300; + /// + /// Type ID for SmartFileSystem v2, "SFS\2" + /// + const UInt32 TypeIDSFS2 = 0x53465302; + /// + /// Type ID for JXFS, "JXF\4" + /// + const UInt32 TypeIDJXFS = 0x4A584604; + /// + /// Type ID for FAT, as set by CrossDOS, "MSD\0" + /// + const UInt32 TypeIDCrossDOS = 0x4D534400; + /// + /// Type ID for HFS, as set by CrossMac, "MAC\0" + /// + const UInt32 TypeIDCrossMac = 0x4D414300; + /// + /// Type ID for 4.2UFS, for BFFS, "BFFS" + /// + const UInt32 TypeIDBFFS = 0x42464653; + /// + /// Type ID for Amiga Original File System with multi-user patches, "muF\0" + /// + const UInt32 TypeIDmuOFS = 0x6D754600; + /// + /// Type ID for Amiga Fast File System with multi-user patches, "muF\1" + /// + const UInt32 TypeIDmuFFS = 0x6D754601; + /// + /// Type ID for Amiga Original File System with international characters and multi-user patches, "muF\2" + /// + const UInt32 TypeIDmuOFSi = 0x6D754602; + /// + /// Type ID for Amiga Fast File System with international characters and multi-user patches, "muF\3" + /// + const UInt32 TypeIDmuFFSi = 0x6D754603; + /// + /// Type ID for Amiga Original File System with directory cache and multi-user patches, "muF\4" + /// + const UInt32 TypeIDmuOFSc = 0x6D754604; + /// + /// Type ID for Amiga Fast File System with directory cache and multi-user patches, "muF\5" + /// + const UInt32 TypeIDmuFFSc = 0x6D754605; + /// + /// Type ID for BSD unused, "BSD\0" + /// + const UInt32 TypeIDOldBSDUnused = 0x42534400; + /// + /// Type ID for BSD swap, "BSD\1" + /// + const UInt32 TypeIDOldBSDSwap = 0x42534401; + /// + /// Type ID for BSD 4.2 FFS, "BSD\7" + /// + const UInt32 TypeIDOldBSD42FFS = 0x42534407; + /// + /// Type ID for BSD 4.4 LFS, "BSD\9" + /// + const UInt32 TypeIDOldBSD44LFS = 0x42534409; + /// + /// Type ID for NetBSD unused root partition, "NBR\0" + /// + const UInt32 TypeIDNetBSDRootUnused = 0x4E425200; + /// + /// Type ID for NetBSD 4.2 FFS root partition, "NBR\7" + /// + const UInt32 TypeIDNetBSDRoot42FFS = 0x4E425207; + /// + /// Type ID for NetBSD 4.4 LFS root partition, "NBR\9" + /// + const UInt32 TypeIDNetBSDRoot44LFS = 0x4E425209; + /// + /// Type ID for NetBSD unused user partition, "NBR\0" + /// + const UInt32 TypeIDNetBSDUserUnused = 0x4E425500; + /// + /// Type ID for NetBSD 4.2 FFS user partition, "NBR\7" + /// + const UInt32 TypeIDNetBSDUser42FFS = 0x4E425507; + /// + /// Type ID for NetBSD 4.4 LFS user partition, "NBR\9" + /// + const UInt32 TypeIDNetBSDUser44LFS = 0x4E425509; + /// + /// Type ID for NetBSD swap partition + /// + const UInt32 TypeIDNetBSDSwap = 0x4E425300; + /// + /// Type ID for Linux filesystem partition, "LNX\0" + /// + const UInt32 TypeIDLinux = 0x4C4E5800; + /// + /// Type ID for Linux swap partition, "SWP\0" + /// + const UInt32 TypeIDLinuxSwap = 0x53575000; + /// + /// Type ID for RaidFrame partition, "RAID" + /// + const UInt32 TypeIDRaidFrame = 0x52414944; + /// + /// Type ID for RaidFrame partition, "RAI\0" + /// + const UInt32 TypeIDRaidFrame0 = 0x52414900; + + /// + /// No disks to be configured after this one + /// + const UInt32 FlagsNoDisks = 0x00000001; + /// + /// No LUNs to be configured after this one + /// + const UInt32 FlagsNoLUNs = 0x00000002; + /// + /// No target IDs to be configured after this one + /// + const UInt32 FlagsNoTargets = 0x00000004; + /// + /// Don't try to perform reselection with this drive + /// + const UInt32 FlagsNoReselection = 0x00000008; + /// + /// Disk identification is valid + /// + const UInt32 FlagsValidDiskID = 0x00000010; + /// + /// Controller identification is valid + /// + const UInt32 FlagsValidControllerID = 0x00000020; + /// + /// Drive supports synchronous SCSI mode + /// + const UInt32 FlagsSynchSCSI = 0x00000040; + + /// + /// Partition is bootable + /// + const UInt32 FlagsBootable = 0x00000001; + /// + /// Partition should not be mounted automatically + /// + const UInt32 FlagsNoAutomount = 0x00000002; + + public AmigaRigidDiskBlock(PluginBase Core) + { + Name = "Amiga Rigid Disk Block"; + PluginUUID = new Guid("8D72ED97-1854-4170-9CE4-6E8446FD9863"); + } + + /// + /// Amiga Rigid Disk Block, header for partitioning scheme + /// Can be in any sector from 0 to 15, inclusive + /// + struct RigidDiskBlock + { + /// + /// "RDSK" + /// + public UInt32 magic; + /// + /// Size in longs + /// + public UInt32 size; + /// + /// Checksum + /// + public Int32 checksum; + /// + /// SCSI target ID, 7 for non-SCSI + /// + public UInt32 targetID; + /// + /// Block size in bytes + /// + public UInt32 block_size; + /// + /// Flags + /// + public UInt32 flags; + /// + /// Pointer to first BadBlockList, 0xFFFFFFFF means last block in device + /// + public UInt32 badblock_ptr; + /// + /// Pointer to first PartitionEntry, 0xFFFFFFFF means last block in device + /// + public UInt32 partition_ptr; + /// + /// Pointer to first FileSystemHeader, 0xFFFFFFFF means last block in device + /// + public UInt32 fsheader_ptr; + /// + /// Optional drive specific init code + /// + public UInt32 driveinitcode; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved1; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved2; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved3; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved4; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved5; + /// + /// Reserved, should be 0xFFFFFFFF + /// + public UInt32 reserved6; + /// + /// Cylinders in drive + /// + public UInt32 cylinders; + /// + /// Sectors per track + /// + public UInt32 spt; + /// + /// Heads in drive + /// + public UInt32 heads; + /// + /// Drive interleave + /// + public UInt32 interleave; + /// + /// Cylinder for parking heads + /// + public UInt32 parking; + /// + /// Reserved, should be zero + /// + public UInt32 reserved7; + /// + /// Reserved, should be zero + /// + public UInt32 reserved8; + /// + /// Reserved, should be zero + /// + public UInt32 reserved9; + /// + /// Starting cylinder for write precompensation + /// + public UInt32 writeprecomp; + /// + /// Starting cylinder for reduced write current + /// + public UInt32 reducedwrite; + /// + /// Drive step rate + /// + public UInt32 steprate; + /// + /// Reserved, should be zero + /// + public UInt32 reserved10; + /// + /// Reserved, should be zero + /// + public UInt32 reserved11; + /// + /// Reserved, should be zero + /// + public UInt32 reserved12; + /// + /// Reserved, should be zero + /// + public UInt32 reserved13; + /// + /// Reserved, should be zero + /// + public UInt32 reserved14; + /// + /// Low block of RDB reserved blocks + /// + public UInt32 RDBBlockLow; + /// + /// High block of RDB reserved blocks + /// + public UInt32 RDBBlockHigh; + /// + /// Low cylinder for partitionable area + /// + public UInt32 LowCylinder; + /// + /// High cylinder for partitionable area + /// + public UInt32 HighCylinder; + /// + /// Blocks per cylinder + /// + public UInt32 CylBlocks; + /// + /// Seconds for head autoparking + /// + public UInt32 AutoParkSeconds; + /// + /// Highest block used by RDB + /// + public UInt32 HighRDSKBlock; + /// + /// Reserved, should be zero + /// + public UInt32 reserved15; + /// + /// Disk vendor, 8 bytes + /// + public string diskVendor; + /// + /// Disk product, 16 bytes + /// + public string diskProduct; + /// + /// Disk revision, 4 bytes + /// + public string diskRevision; + /// + /// Controller vendor, 8 bytes + /// + public string controllerVendor; + /// + /// Controller product, 16 bytes + /// + public string controllerProduct; + /// + /// Controller revision, 4 bytes + /// + public string controllerRevision; + /// + /// Reserved, should be zero + /// + public UInt32 reserved16; + /// + /// Reserved, should be zero + /// + public UInt32 reserved17; + /// + /// Reserved, should be zero + /// + public UInt32 reserved18; + /// + /// Reserved, should be zero + /// + public UInt32 reserved19; + /// + /// Reserved, should be zero + /// + public UInt32 reserved20; + /// + /// Reserved, should be zero + /// + public UInt32 reserved21; + /// + /// Reserved, should be zero + /// + public UInt32 reserved22; + /// + /// Reserved, should be zero + /// + public UInt32 reserved23; + /// + /// Reserved, should be zero + /// + public UInt32 reserved24; + /// + /// Reserved, should be zero + /// + public UInt32 reserved25; + } + + /// + /// Pair for spare blocks + /// + struct BadBlockEntry + { + /// + /// Bad block pointer + /// + public UInt32 badBlock; + /// + /// Replacement block pointer + /// + public UInt32 goodBlock; + } + + /// + /// List of bad blocks and spares + /// + struct BadBlockList + { + /// + /// "BADB" + /// + public UInt32 magic; + /// + /// Size in longs + /// + public UInt32 size; + /// + /// Checksum + /// + public Int32 checksum; + /// + /// SCSI target ID, 7 for non-SCSI + /// + public UInt32 targetID; + /// + /// Pointer for next BadBlockList + /// + public UInt32 next_ptr; + /// + /// Reserved + /// + public UInt32 reserved; + /// + /// Bad block entries, up to block filling, 8 bytes each + /// + public BadBlockEntry[] blockPairs; + } + + /// + /// DOSEnvVec, used by AmigaDOS + /// + struct DOSEnvironmentVector + { + /// + /// Size in longs, should be 16, minimum 11 + /// + public UInt32 size; + /// + /// Block size in longs + /// + public UInt32 block_size; + /// + /// Unknown, 0 + /// + public UInt32 sec_org; + /// + /// Heads in drive + /// + public UInt32 surfaces; + /// + /// Sectors per block + /// + public UInt32 spb; + /// + /// Blocks per track + /// + public UInt32 bpt; + /// + /// DOS reserved blocks at start of partition + /// + public UInt32 reservedblocks; + /// + /// DOS reserved blocks at end of partition + /// + public UInt32 prealloc; + /// + /// Interleave + /// + public UInt32 interleave; + /// + /// First cylinder of a partition, inclusive + /// + public UInt32 lowCylinder; + /// + /// Last cylinder of a partition, inclusive + /// + public UInt32 highCylinder; + /// + /// Buffers, usually 30 + /// + public UInt32 numBuffer; + /// + /// Type of memory to allocate for buffers + /// + public UInt32 bufMemType; + /// + /// Maximum transfer, usually 0x7FFFFFFF + /// + public UInt32 maxTransfer; + /// + /// Address mask to block out certain memory, usually 0xFFFFFFFE + /// + public UInt32 Mask; + /// + /// Boot priority + /// + public UInt32 bootPriority; + /// + /// Partition type, and filesystem driver identification for AmigaDOS + /// + public UInt32 dosType; + /// + /// Default baud rate for SER and AUX handlers + /// + public UInt32 baud; + /// + /// Flow control values for SER and AUX handlers + /// + public UInt32 control; + /// + /// Since Kickstart 2, how many boot blocks are to be loaded + /// + public UInt32 bootBlocks; + } + + struct PartitionEntry + { + /// + /// "PART" + /// + public UInt32 magic; + /// + /// Size in longs + /// + public UInt32 size; + /// + /// Checksum + /// + public Int32 checksum; + /// + /// SCSI target ID, 7 for non-SCSI + /// + public UInt32 targetID; + /// + /// Pointer to next PartitionEntry + /// + public UInt32 next_ptr; + /// + /// Partition flags + /// + public UInt32 flags; + /// + /// Reserved + /// + public UInt32 reserved1; + /// + /// Reserved + /// + public UInt32 reserved2; + /// + /// Preferred flags for OpenDevice() + /// + public UInt32 devFlags; + /// + /// Length of drive name + /// + public UInt32 driveNameLen; + /// + /// Drive name, 31 bytes + /// + public string driveName; + /// + /// Reserved + /// + public UInt32 reserved3; + /// + /// Reserved + /// + public UInt32 reserved4; + /// + /// Reserved + /// + public UInt32 reserved5; + /// + /// Reserved + /// + public UInt32 reserved6; + /// + /// Reserved + /// + public UInt32 reserved7; + /// + /// Reserved + /// + public UInt32 reserved8; + /// + /// Reserved + /// + public UInt32 reserved9; + /// + /// Reserved + /// + public UInt32 reserved10; + /// + /// Reserved + /// + public UInt32 reserved11; + /// + /// Reserved + /// + public UInt32 reserved12; + /// + /// Reserved + /// + public UInt32 reserved13; + /// + /// Reserved + /// + public UInt32 reserved14; + /// + /// Reserved + /// + public UInt32 reserved15; + /// + /// Reserved + /// + public UInt32 reserved16; + /// + /// Reserved + /// + public UInt32 reserved17; + /// + /// DOSEnvVec, more information about partition + /// + public DOSEnvironmentVector dosEnvVec; + } + + /// + /// Device node, mostly useless, except for pointer to first LoadSegment block + /// + struct DeviceNode + { + /// + /// Device node type, =0 + /// + public UInt32 type; + /// + /// DOS task field, =0 + /// + public UInt32 task; + /// + /// Unused, =0 + /// + public UInt32 locked; + /// + /// Filename handler to LoadSegment, =0 + /// + public UInt32 handler; + /// + /// Stack size when starting task, =0 + /// + public UInt32 stackSize; + /// + /// Task priority, =0 + /// + public UInt32 priority; + /// + /// Startup message, =0 + /// + public UInt32 startup; + /// + /// Pointer to first LoadSegment block + /// + public UInt32 seglist_ptr; + /// + /// BCPL globabl vector when starting task, =0xFFFFFFFF + /// + public UInt32 global_vec; + } + + /// + /// File system header + /// + struct FileSystemHeader + { + /// + /// "FSHD" + /// + public UInt32 magic; + /// + /// Size in longs, 64 + /// + public UInt32 size; + /// + /// Checksum + /// + public Int32 checksum; + /// + /// SCSI target ID, 7 for non-SCSI + /// + public UInt32 targetID; + /// + /// Pointer to next FileSystemHeader block + /// + public UInt32 next_ptr; + /// + /// Flags, unknown + /// + public UInt32 flags; + /// + /// Reserved + /// + public UInt32 reserved1; + /// + /// Reserved + /// + public UInt32 reserved2; + /// + /// Partition type, and filesystem driver identification for AmigaDOS + /// + public UInt32 dosType; + /// + /// Filesystem version + /// Mask 0xFFFF0000, >>16, major version + /// Mask 0x0000FFFF, minor version + /// + public UInt32 version; + /// + /// Bits for DeviceNode fields that should be substituted into a standard device node + /// + public UInt32 patchFlags; + /// + /// Device node + /// + public DeviceNode dnode; + } + + /// + /// Filesystem code + /// + struct LoadSegment + { + /// + /// "LSEG" + /// + public UInt32 magic; + /// + /// Size in longs + /// + public UInt32 size; + /// + /// Checksum + /// + public Int32 checksum; + /// + /// SCSI target ID, 7 for non-SCSI + /// + public UInt32 targetID; + /// + /// Pointer to next LoadSegment + /// + public UInt32 next_ptr; + /// + /// Executable code, with relocation hunks, til end of sector + /// + public byte[] loadData; + } + + public override bool GetInformation(ImagePlugins.ImagePlugin imagePlugin, out List partitions) + { + partitions = new List(); + BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian; + ulong RDBBlock = 0; + bool foundRDB = false; + + while (RDBBlock < 16 && !foundRDB) + { + if (imagePlugin.GetSectors() <= RDBBlock) + return false; + + byte[] tmpSector = imagePlugin.ReadSector(RDBBlock); + UInt32 magic = BigEndianBitConverter.ToUInt32(tmpSector, 0); + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Possible magic at block {0} is 0x{1:X8}", RDBBlock, magic); + + if (magic == RigidDiskBlockMagic) + { + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Found RDB magic at block {0}", RDBBlock); + + foundRDB = true; + break; + } + } + + if (!foundRDB) + return false; + + byte[] sector; + byte[] tmpString; + + RigidDiskBlock RDB = new RigidDiskBlock(); + + 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.block_size = BigEndianBitConverter.ToUInt32(sector, 0x10); + RDB.flags = BigEndianBitConverter.ToUInt32(sector, 0x04); + RDB.badblock_ptr = BigEndianBitConverter.ToUInt32(sector, 0x18); + RDB.partition_ptr = BigEndianBitConverter.ToUInt32(sector, 0x1C); + RDB.fsheader_ptr = 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); + + 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); + + if (MainClass.isDebug) + { + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.magic = 0x{0:X8}", RDB.magic); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.size = {0} longs, {1} bytes", RDB.size, RDB.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.checksum = 0x{0:X8}", RDB.checksum); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.targetID = {0}", RDB.targetID); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.block_size = {0}", RDB.block_size); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.badblock_ptr = {0}", RDB.badblock_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.partition_ptr = {0}", RDB.partition_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.fsheader_ptr = {0}", RDB.fsheader_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.driveinitcode = {0}", RDB.driveinitcode); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved1 = 0x{0:X8}", RDB.reserved1); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved2 = 0x{0:X8}", RDB.reserved2); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved3 = 0x{0:X8}", RDB.reserved3); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved4 = 0x{0:X8}", RDB.reserved4); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved5 = 0x{0:X8}", RDB.reserved5); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved6 = 0x{0:X8}", RDB.reserved6); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.cylinders = {0}", RDB.cylinders); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.spt = {0}", RDB.spt); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.heads = {0}", RDB.heads); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.interleave = {0}", RDB.interleave); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.parking = {0}", RDB.parking); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved7 = 0x{0:X8}", RDB.reserved7); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved8 = 0x{0:X8}", RDB.reserved8); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved9 = 0x{0:X8}", RDB.reserved9); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.writeprecomp = {0}", RDB.writeprecomp); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reducedwrite = {0}", RDB.reducedwrite); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.steprate = {0}", RDB.steprate); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved10 = 0x{0:X8}", RDB.reserved10); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved11 = 0x{0:X8}", RDB.reserved11); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved12 = 0x{0:X8}", RDB.reserved12); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved13 = 0x{0:X8}", RDB.reserved13); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved14 = 0x{0:X8}", RDB.reserved14); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.RDBBlockLow = {0}", RDB.RDBBlockLow); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.RDBBlockHigh = {0}", RDB.RDBBlockHigh); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.LowCylinder = {0}", RDB.LowCylinder); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.HighCylinder = {0}", RDB.HighCylinder); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.CylBlocks = {0}", RDB.CylBlocks); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.AutoParkSeconds = {0}", RDB.AutoParkSeconds); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.HighCylinder = {0}", RDB.HighCylinder); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved15 = 0x{0:X8}", RDB.reserved15); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.diskVendor = \"{0}\"", RDB.diskVendor); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.diskProduct = \"{0}\"", RDB.diskProduct); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.diskRevision = \"{0}\"", RDB.diskRevision); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.controllerVendor = \"{0}\"", RDB.controllerVendor); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.controllerProduct = \"{0}\"", RDB.controllerProduct); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.controllerRevision = \"{0}\"", RDB.controllerRevision); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved16 = 0x{0:X8}", RDB.reserved16); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved17 = 0x{0:X8}", RDB.reserved17); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved18 = 0x{0:X8}", RDB.reserved18); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved19 = 0x{0:X8}", RDB.reserved19); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved20 = 0x{0:X8}", RDB.reserved20); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved21 = 0x{0:X8}", RDB.reserved21); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved22 = 0x{0:X8}", RDB.reserved22); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved23 = 0x{0:X8}", RDB.reserved23); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved24 = 0x{0:X8}", RDB.reserved24); + Console.WriteLine("DEBUG (Amiga RDB plugin): RDB.reserved25 = 0x{0:X8}", RDB.reserved25); + } + + ulong nextBlock; + + // Reading BadBlock list + List BadBlockChain = new List(); + nextBlock = RDB.badblock_ptr; + while (nextBlock != 0xFFFFFFFF) + { + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Going to block {0} in search of a BadBlock block", nextBlock); + + sector = imagePlugin.ReadSector(nextBlock); + UInt32 magic = BigEndianBitConverter.ToUInt32(sector, 0); + + if (magic != BadBlockListMagic) + break; + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Found BadBlock block"); + + BadBlockList chainEntry = new BadBlockList(); + chainEntry.magic = BigEndianBitConverter.ToUInt32(sector, 0x00); + chainEntry.size = BigEndianBitConverter.ToUInt32(sector, 0x04); + chainEntry.checksum = BigEndianBitConverter.ToInt32(sector, 0x08); + chainEntry.targetID = BigEndianBitConverter.ToUInt32(sector, 0x0C); + chainEntry.next_ptr = BigEndianBitConverter.ToUInt32(sector, 0x10); + chainEntry.reserved = BigEndianBitConverter.ToUInt32(sector, 0x14); + + ulong entries = (chainEntry.size - 6) / 2; + chainEntry.blockPairs = new BadBlockEntry[entries]; + + if (MainClass.isDebug) + { + Console.WriteLine("DEBUG (Amiga RDB plugin): chainEntry.magic = 0x{0:X8}", chainEntry.magic); + Console.WriteLine("DEBUG (Amiga RDB plugin): chainEntry.size = {0} longs, {1} bytes", chainEntry.size, chainEntry.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): chainEntry.checksum = 0x{0:X8}", chainEntry.checksum); + Console.WriteLine("DEBUG (Amiga RDB plugin): chainEntry.targetID = {0}", chainEntry.targetID); + Console.WriteLine("DEBUG (Amiga RDB plugin): chainEntry.next_ptr = {0}", chainEntry.next_ptr); + Console.WriteLine("DEBUG (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)); + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (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.next_ptr; + } + + // Reading BadBlock list + List PartitionEntries = new List(); + nextBlock = RDB.partition_ptr; + while (nextBlock != 0xFFFFFFFF) + { + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Going to block {0} in search of a PartitionEntry block", nextBlock); + + sector = imagePlugin.ReadSector(nextBlock); + UInt32 magic = BigEndianBitConverter.ToUInt32(sector, 0); + + if (magic != PartitionBlockMagic) + break; + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Found PartitionEntry block"); + + PartitionEntry partEntry = new PartitionEntry(); + partEntry.dosEnvVec = new DOSEnvironmentVector(); + byte[] driveName = new byte[32]; + partEntry.magic = BigEndianBitConverter.ToUInt32(sector, 0x00); + partEntry.size = BigEndianBitConverter.ToUInt32(sector, 0x04); + partEntry.checksum = BigEndianBitConverter.ToInt32(sector, 0x08); + partEntry.targetID = BigEndianBitConverter.ToUInt32(sector, 0x0C); + partEntry.next_ptr = BigEndianBitConverter.ToUInt32(sector, 0x10); + partEntry.flags = BigEndianBitConverter.ToUInt32(sector, 0x14); + partEntry.reserved1 = BigEndianBitConverter.ToUInt32(sector, 0x18); + partEntry.reserved2 = BigEndianBitConverter.ToUInt32(sector, 0x1C); + partEntry.devFlags = BigEndianBitConverter.ToUInt32(sector, 0x20); + partEntry.driveNameLen = sector[0x24]; + Array.Copy(sector, 0x24, driveName, 0, 32); + partEntry.driveName = StringHandlers.PascalToString(driveName); + partEntry.reserved3 = BigEndianBitConverter.ToUInt32(sector, 0x44); + partEntry.reserved4 = BigEndianBitConverter.ToUInt32(sector, 0x48); + partEntry.reserved5 = BigEndianBitConverter.ToUInt32(sector, 0x4C); + partEntry.reserved6 = BigEndianBitConverter.ToUInt32(sector, 0x50); + partEntry.reserved7 = BigEndianBitConverter.ToUInt32(sector, 0x54); + partEntry.reserved8 = BigEndianBitConverter.ToUInt32(sector, 0x58); + partEntry.reserved9 = BigEndianBitConverter.ToUInt32(sector, 0x5C); + partEntry.reserved10 = BigEndianBitConverter.ToUInt32(sector, 0x60); + partEntry.reserved11 = BigEndianBitConverter.ToUInt32(sector, 0x64); + partEntry.reserved12 = BigEndianBitConverter.ToUInt32(sector, 0x68); + partEntry.reserved13 = BigEndianBitConverter.ToUInt32(sector, 0x6C); + partEntry.reserved14 = BigEndianBitConverter.ToUInt32(sector, 0x70); + partEntry.reserved15 = BigEndianBitConverter.ToUInt32(sector, 0x74); + partEntry.reserved16 = BigEndianBitConverter.ToUInt32(sector, 0x78); + partEntry.reserved17 = BigEndianBitConverter.ToUInt32(sector, 0x7C); + + partEntry.dosEnvVec.size = BigEndianBitConverter.ToUInt32(sector, 0x80); + partEntry.dosEnvVec.block_size = BigEndianBitConverter.ToUInt32(sector, 0x84); + partEntry.dosEnvVec.sec_org = BigEndianBitConverter.ToUInt32(sector, 0x88); + partEntry.dosEnvVec.surfaces = BigEndianBitConverter.ToUInt32(sector, 0x8C); + partEntry.dosEnvVec.spb = BigEndianBitConverter.ToUInt32(sector, 0x90); + partEntry.dosEnvVec.bpt = BigEndianBitConverter.ToUInt32(sector, 0x94); + partEntry.dosEnvVec.reservedblocks = BigEndianBitConverter.ToUInt32(sector, 0x98); + partEntry.dosEnvVec.prealloc = BigEndianBitConverter.ToUInt32(sector, 0x9C); + partEntry.dosEnvVec.interleave = BigEndianBitConverter.ToUInt32(sector, 0xA0); + partEntry.dosEnvVec.lowCylinder = BigEndianBitConverter.ToUInt32(sector, 0xA4); + partEntry.dosEnvVec.highCylinder = BigEndianBitConverter.ToUInt32(sector, 0xA8); + partEntry.dosEnvVec.numBuffer = BigEndianBitConverter.ToUInt32(sector, 0xAC); + partEntry.dosEnvVec.bufMemType = BigEndianBitConverter.ToUInt32(sector, 0xB0); + partEntry.dosEnvVec.maxTransfer = BigEndianBitConverter.ToUInt32(sector, 0xB4); + partEntry.dosEnvVec.Mask = BigEndianBitConverter.ToUInt32(sector, 0xB8); + partEntry.dosEnvVec.bootPriority = BigEndianBitConverter.ToUInt32(sector, 0xBC); + partEntry.dosEnvVec.dosType = BigEndianBitConverter.ToUInt32(sector, 0xC0); + partEntry.dosEnvVec.baud = BigEndianBitConverter.ToUInt32(sector, 0xC4); + partEntry.dosEnvVec.control = BigEndianBitConverter.ToUInt32(sector, 0xC8); + partEntry.dosEnvVec.bootBlocks = BigEndianBitConverter.ToUInt32(sector, 0xCC); + + if (MainClass.isDebug) + { + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.magic = 0x{0:X8}", partEntry.magic); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.size = {0} longs, {1} bytes", partEntry.size, partEntry.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.checksum = 0x{0:X8}", partEntry.checksum); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.targetID = {0}", partEntry.targetID); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.next_ptr = {0}", partEntry.next_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.flags = 0x{0:X8}", partEntry.flags); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved1 = 0x{0:X8}", partEntry.reserved1); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved2 = 0x{0:X8}", partEntry.reserved2); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.devFlags = 0x{0:X8}", partEntry.devFlags); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.driveNameLen = {0}", partEntry.driveNameLen); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.driveName = \"{0}\"", partEntry.driveName); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved3 = 0x{0:X8}", partEntry.reserved3); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved4 = 0x{0:X8}", partEntry.reserved4); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved5 = 0x{0:X8}", partEntry.reserved5); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved6 = 0x{0:X8}", partEntry.reserved6); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved7 = 0x{0:X8}", partEntry.reserved7); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved8 = 0x{0:X8}", partEntry.reserved8); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved9 = 0x{0:X8}", partEntry.reserved9); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved10 = 0x{0:X8}", partEntry.reserved10); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved11 = 0x{0:X8}", partEntry.reserved11); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved12 = 0x{0:X8}", partEntry.reserved12); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved13 = 0x{0:X8}", partEntry.reserved13); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved14 = 0x{0:X8}", partEntry.reserved14); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved15 = 0x{0:X8}", partEntry.reserved15); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved16 = 0x{0:X8}", partEntry.reserved16); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.reserved17 = 0x{0:X8}", partEntry.reserved17); + + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.size = {0} longs, {1} bytes", partEntry.dosEnvVec.size, partEntry.dosEnvVec.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.block_size = {0} longs, {1} bytes", partEntry.dosEnvVec.block_size, partEntry.dosEnvVec.block_size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.sec_org = 0x{0:X8}", partEntry.dosEnvVec.sec_org); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.surfaces = {0}", partEntry.dosEnvVec.surfaces); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.spb = {0}", partEntry.dosEnvVec.spb); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.bpt = {0}", partEntry.dosEnvVec.bpt); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.reservedblocks = {0}", partEntry.dosEnvVec.reservedblocks); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.prealloc = {0}", partEntry.dosEnvVec.prealloc); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.interleave = {0}", partEntry.dosEnvVec.interleave); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.lowCylinder = {0}", partEntry.dosEnvVec.lowCylinder); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.highCylinder = {0}", partEntry.dosEnvVec.highCylinder); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.numBuffer = {0}", partEntry.dosEnvVec.numBuffer); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.bufMemType = {0}", partEntry.dosEnvVec.bufMemType); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.maxTransfer = {0}", partEntry.dosEnvVec.maxTransfer); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.Mask = 0x{0:X8}", partEntry.dosEnvVec.Mask); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.bootPriority = {0}", partEntry.dosEnvVec.bootPriority); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.dosType = {0}", AmigaDOSTypeToString(partEntry.dosEnvVec.dosType, true)); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.baud = {0}", partEntry.dosEnvVec.baud); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.control = 0x{0:X8}", partEntry.dosEnvVec.control); + Console.WriteLine("DEBUG (Amiga RDB plugin): partEntry.dosEnvVec.bootBlocks = {0}", partEntry.dosEnvVec.bootBlocks); + + } + + PartitionEntries.Add(partEntry); + nextBlock = partEntry.next_ptr; + } + + // Reading BadBlock list + List FSHDEntries = new List(); + List SegmentEntries = new List(); + nextBlock = RDB.fsheader_ptr; + while (nextBlock != 0xFFFFFFFF) + { + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Going to block {0} in search of a FileSystemHeader block", nextBlock); + + sector = imagePlugin.ReadSector(nextBlock); + UInt32 magic = BigEndianBitConverter.ToUInt32(sector, 0); + + if (magic != FilesystemHeaderMagic) + break; + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Found FileSystemHeader block"); + + FileSystemHeader FSHD = new FileSystemHeader(); + FSHD.dnode = new DeviceNode(); + + FSHD.magic = BigEndianBitConverter.ToUInt32(sector, 0x00); + FSHD.size = BigEndianBitConverter.ToUInt32(sector, 0x04); + FSHD.checksum = BigEndianBitConverter.ToInt32(sector, 0x08); + FSHD.targetID = BigEndianBitConverter.ToUInt32(sector, 0x0C); + FSHD.next_ptr = BigEndianBitConverter.ToUInt32(sector, 0x10); + FSHD.flags = BigEndianBitConverter.ToUInt32(sector, 0x14); + FSHD.reserved1 = BigEndianBitConverter.ToUInt32(sector, 0x18); + FSHD.reserved2 = BigEndianBitConverter.ToUInt32(sector, 0x1C); + FSHD.dosType = BigEndianBitConverter.ToUInt32(sector, 0x20); + FSHD.version = BigEndianBitConverter.ToUInt32(sector, 0x24); + FSHD.patchFlags = BigEndianBitConverter.ToUInt32(sector, 0x28); + + FSHD.dnode.type = BigEndianBitConverter.ToUInt32(sector, 0x2C); + FSHD.dnode.task = BigEndianBitConverter.ToUInt32(sector, 0x30); + FSHD.dnode.locked = BigEndianBitConverter.ToUInt32(sector, 0x34); + FSHD.dnode.handler = BigEndianBitConverter.ToUInt32(sector, 0x38); + FSHD.dnode.stackSize = BigEndianBitConverter.ToUInt32(sector, 0x3C); + FSHD.dnode.priority = BigEndianBitConverter.ToUInt32(sector, 0x40); + FSHD.dnode.startup = BigEndianBitConverter.ToUInt32(sector, 0x44); + FSHD.dnode.seglist_ptr = BigEndianBitConverter.ToUInt32(sector, 0x48); + FSHD.dnode.global_vec = BigEndianBitConverter.ToUInt32(sector, 0x4C); + + if (MainClass.isDebug) + { + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.magic = 0x{0:X8}", FSHD.magic); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.size = {0} longs, {1} bytes", FSHD.size, FSHD.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.checksum = 0x{0:X8}", FSHD.checksum); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.targetID = {0}", FSHD.targetID); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.next_ptr = {0}", FSHD.next_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.flags = 0x{0:X8}", FSHD.flags); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.reserved1 = 0x{0:X8}", FSHD.reserved1); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.reserved2 = 0x{0:X8}", FSHD.reserved2); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dosType = {0}", AmigaDOSTypeToString(FSHD.dosType)); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.version = {0:D2}.{1:D2} (0x{2:X8})", (FSHD.version & 0xFFFF0000) >> 16, FSHD.version & 0xFFFF, FSHD.version); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.patchFlags = 0x{0:X8}", FSHD.patchFlags); + + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.type = {0}", FSHD.dnode.type); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.task = {0}", FSHD.dnode.task); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.locked = {0}", FSHD.dnode.locked); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.handler = {0}", FSHD.dnode.handler); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.stackSize = {0}", FSHD.dnode.stackSize); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.priority = {0}", FSHD.dnode.priority); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.startup = {0}", FSHD.dnode.startup); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.seglist_ptr = {0}", FSHD.dnode.seglist_ptr); + Console.WriteLine("DEBUG (Amiga RDB plugin): FSHD.dnode.global_vec = 0x{0:X8}", FSHD.dnode.global_vec); + } + + nextBlock = FSHD.dnode.seglist_ptr; + bool thereAreLoadSegments = false; + Checksums.SHA1Context sha1Ctx = new Checksums.SHA1Context(); + sha1Ctx.Init(); + while (nextBlock != 0xFFFFFFFF) + { + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Going to block {0} in search of a LoadSegment block", nextBlock); + + sector = imagePlugin.ReadSector(nextBlock); + UInt32 magicSeg = BigEndianBitConverter.ToUInt32(sector, 0); + + if (magicSeg != LoadSegMagic) + break; + + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): Found LoadSegment block"); + + thereAreLoadSegments = true; + LoadSegment loadSeg = new LoadSegment(); + loadSeg.magic = BigEndianBitConverter.ToUInt32(sector, 0x00); + loadSeg.size = BigEndianBitConverter.ToUInt32(sector, 0x04); + loadSeg.checksum = BigEndianBitConverter.ToInt32(sector, 0x08); + loadSeg.targetID = BigEndianBitConverter.ToUInt32(sector, 0x0C); + loadSeg.next_ptr = BigEndianBitConverter.ToUInt32(sector, 0x10); + loadSeg.loadData = new byte[(loadSeg.size - 5) * 4]; + Array.Copy(sector, 0x14, loadSeg.loadData, 0, (loadSeg.size - 5) * 4); + + if (MainClass.isDebug) + { + Console.WriteLine("DEBUG (Amiga RDB plugin): loadSeg.magic = 0x{0:X8}", loadSeg.magic); + Console.WriteLine("DEBUG (Amiga RDB plugin): loadSeg.size = {0} longs, {1} bytes", loadSeg.size, loadSeg.size * 4); + Console.WriteLine("DEBUG (Amiga RDB plugin): loadSeg.checksum = 0x{0:X8}", loadSeg.checksum); + Console.WriteLine("DEBUG (Amiga RDB plugin): loadSeg.targetID = {0}", loadSeg.targetID); + Console.WriteLine("DEBUG (Amiga RDB plugin): loadSeg.next_ptr = {0}", loadSeg.next_ptr); + } + + SegmentEntries.Add(loadSeg); + nextBlock = loadSeg.next_ptr; + + sha1Ctx.Update(loadSeg.loadData); + } + if (thereAreLoadSegments) + { + string loadSegSHA1 = sha1Ctx.End(); + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Amiga RDB plugin): LoadSegment data SHA1: {0}", loadSegSHA1); + } + + FSHDEntries.Add(FSHD); + nextBlock = FSHD.next_ptr; + } + + ulong sequence = 0; + foreach (PartitionEntry RDBEntry in PartitionEntries) + { + Partition entry = new Partition(); + + entry.PartitionDescription = AmigaDOSTypeToDescriptionString(RDBEntry.dosEnvVec.dosType); + entry.PartitionName = RDBEntry.driveName; + entry.PartitionSequence = sequence; + entry.PartitionSectors = (RDBEntry.dosEnvVec.highCylinder + 1 - RDBEntry.dosEnvVec.lowCylinder) * RDBEntry.dosEnvVec.surfaces * RDBEntry.dosEnvVec.bpt; + entry.PartitionStartSector = RDBEntry.dosEnvVec.lowCylinder * RDBEntry.dosEnvVec.surfaces * RDBEntry.dosEnvVec.bpt; + entry.PartitionStart = entry.PartitionStartSector * RDB.block_size; + entry.PartitionLength = entry.PartitionSectors * RDB.block_size; + entry.PartitionType = AmigaDOSTypeToString(RDBEntry.dosEnvVec.dosType); + + partitions.Add(entry); + sequence++; + } + + return true; + } + + static string AmigaDOSTypeToDescriptionString(UInt32 AmigaDOSType) + { + switch (AmigaDOSType) + { + + case TypeIDOFS: + return "Amiga Original File System"; + case TypeIDFFS: + return "Amiga Fast File System"; + case TypeIDOFSi: + return "Amiga Original File System with international characters"; + case TypeIDFFSi: + return "Amiga Fast File System with international characters"; + case TypeIDOFSc: + return "Amiga Original File System with directory cache"; + case TypeIDFFSc: + return "Amiga Fast File System with directory cache"; + case TypeIDOFS2: + return "Amiga Original File System with long filenames"; + case TypeIDFFS2: + return "Amiga Fast File System with long filenames"; + case TypeIDAMIXSysV: + return "Amiga UNIX System V filesystem"; + case TypeIDAMIXBoot: + return "Amiga UNIX boot filesystem"; + case TypeIDAMIXFFS: + return "Amiga UNIX BSD filesystem"; + case TypeIDAMIXReserved: + return "Amiga UNIX Reserved partition (swap)"; + case TypeIDPFS: + case TypeIDPFSm: + case TypeIDAFS: + return "ProfessionalFileSystem"; + case TypeIDSFS: + return "SmartFileSystem v1"; + case TypeIDSFS2: + return "SmartFileSystem v2"; + case TypeIDJXFS: + return "JXFS"; + case TypeIDCrossDOS: + return "FAT, as set by CrossDOS"; + case TypeIDCrossMac: + return "HFS, as set by CrossMac"; + case TypeIDBFFS: + return "4.2UFS, for BFFS"; + case TypeIDmuOFS: + return "Amiga Original File System with multi-user patches"; + case TypeIDmuFFS: + return "Amiga Fast File System with multi-user patches"; + case TypeIDmuOFSi: + return "Amiga Original File System with international characters and multi-user patches"; + case TypeIDmuFFSi: + return "Amiga Fast File System with international characters and multi-user patches"; + case TypeIDmuOFSc: + return "Amiga Original File System with directory cache and multi-user patches"; + case TypeIDmuFFSc: + return "Amiga Fast File System with directory cache and multi-user patches"; + case TypeIDOldBSDUnused: + return "BSD unused"; + case TypeIDOldBSDSwap: + return "BSD swap"; + case TypeIDOldBSD42FFS: + return "BSD 4.2 FFS"; + case TypeIDOldBSD44LFS: + return "BSD 4.4 LFS"; + case TypeIDNetBSDRootUnused: + return "NetBSD unused root partition"; + case TypeIDNetBSDRoot42FFS: + return "NetBSD 4.2 FFS root partition"; + case TypeIDNetBSDRoot44LFS: + return "NetBSD 4.4 LFS root partition"; + case TypeIDNetBSDUserUnused: + return "NetBSD unused user partition"; + case TypeIDNetBSDUser42FFS: + return "NetBSD 4.2 FFS user partition"; + case TypeIDNetBSDUser44LFS: + return "NetBSD 4.4 LFS user partition"; + case TypeIDNetBSDSwap: + return "NetBSD swap partition"; + case TypeIDLinux: + return "Linux filesystem partition"; + case TypeIDLinuxSwap: + return "Linux swap partition"; + case TypeIDRaidFrame: + case TypeIDRaidFrame0: + return "RaidFrame partition"; + + default: + { + if ((AmigaDOSType & TypeIDOFS) == TypeIDOFS) + return String.Format("Unknown Amiga DOS filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDAMIXSysV) == TypeIDAMIXSysV) + return String.Format("Unknown Amiga UNIX filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & 0x50465300) == 0x50465300 || + (AmigaDOSType & 0x41465300) == 0x41465300) + return String.Format("Unknown ProfessionalFileSystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDSFS) == TypeIDSFS) + return String.Format("Unknown SmartFileSystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDmuOFS) == TypeIDmuOFS) + return String.Format("Unknown Amiga DOS multi-user filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDOldBSDUnused) == TypeIDOldBSDUnused) + return String.Format("Unknown BSD filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDNetBSDRootUnused) == TypeIDNetBSDRootUnused) + return String.Format("Unknown NetBSD root filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDNetBSDUserUnused) == TypeIDNetBSDUserUnused) + return String.Format("Unknown NetBSD user filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDNetBSDSwap) == TypeIDNetBSDSwap) + return String.Format("Unknown NetBSD swap filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + if ((AmigaDOSType & TypeIDLinux) == TypeIDLinux || + (AmigaDOSType & TypeIDLinuxSwap) == TypeIDLinuxSwap) + return String.Format("Unknown Linux filesystem type {0}", AmigaDOSTypeToString(AmigaDOSType)); + + return String.Format("Unknown partition type {0}", AmigaDOSTypeToString(AmigaDOSType)); + } + } + } + + static string AmigaDOSTypeToString(UInt32 AmigaDOSType) + { + return AmigaDOSTypeToString(AmigaDOSType, true); + } + + static string AmigaDOSTypeToString(UInt32 AmigaDOSType, bool quoted) + { + byte[] textPart = new byte[3]; + string textPartString; + + textPart[0] = (byte)((AmigaDOSType & 0xFF000000) >> 24); + textPart[1] = (byte)((AmigaDOSType & 0x00FF0000) >> 16); + textPart[2] = (byte)((AmigaDOSType & 0x0000FF00) >> 8); + + textPartString = Encoding.ASCII.GetString(textPart); + + return quoted ? String.Format("\"{0}\\{1}\"", textPartString, AmigaDOSType & 0xFF) : String.Format("{0}\\{1}", textPartString, AmigaDOSType & 0xFF); + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 20f484226..a5fec8aa6 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Supported partitioning schemes * UNIX VTOC inside MBR * Apple Partition Map * NeXT disklabel +* Amiga Rigid Disk Block (RDB) Supported file systems ====================== diff --git a/TODO b/TODO index 512b88892..470003129 100644 --- a/TODO +++ b/TODO @@ -47,7 +47,6 @@ Filesystem plugins: Partitioning scheme plugins: --- Add support for Acorn partitions ---- Add support for Amiga's RDB --- Add support for Atari partitions --- Add support for AIX partitions --- Add support for EFI GPT