public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset) { partitions = new List <Partition>(); ulong sbSector; // RISC OS always checks for the partition on 0. Afaik no emulator chains it. if (sectorOffset != 0) { return(false); } if (imagePlugin.Info.SectorSize > ADFS_SB_POS) { sbSector = 0; } else { sbSector = ADFS_SB_POS / imagePlugin.Info.SectorSize; } byte[] sector = imagePlugin.ReadSector(sbSector); if (sector.Length < 512) { return(false); } IntPtr bbPtr = Marshal.AllocHGlobal(512); Marshal.Copy(sector, 0, bbPtr, 512); AcornBootBlock bootBlock = (AcornBootBlock)Marshal.PtrToStructure(bbPtr, typeof(AcornBootBlock)); Marshal.FreeHGlobal(bbPtr); int checksum = 0; for (int i = 0; i < 0x1FF; i++) { checksum = (checksum & 0xFF) + (checksum >> 8) + sector[i]; } int heads = bootBlock.discRecord.heads + ((bootBlock.discRecord.lowsector >> 6) & 1); int secCyl = bootBlock.discRecord.spt * heads; int mapSector = bootBlock.startCylinder * secCyl; if ((ulong)mapSector >= imagePlugin.Info.Sectors) { return(false); } byte[] map = imagePlugin.ReadSector((ulong)mapSector); ulong counter = 0; if (checksum == bootBlock.checksum) { Partition part = new Partition { Size = (ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size, Length = ((ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size) / imagePlugin.Info.SectorSize, Type = "ADFS", Name = StringHandlers.CToString(bootBlock.discRecord.disc_name, Encoding.GetEncoding("iso-8859-1")) }; if (part.Size > 0) { partitions.Add(part); counter++; } } switch (bootBlock.flags & TYPE_MASK) { case TYPE_LINUX: { IntPtr tablePtr = Marshal.AllocHGlobal(512); Marshal.Copy(map, 0, tablePtr, 512); LinuxTable table = (LinuxTable)Marshal.PtrToStructure(tablePtr, typeof(LinuxTable)); Marshal.FreeHGlobal(tablePtr); foreach (LinuxEntry entry in table.entries) { Partition part = new Partition { Start = (ulong)(mapSector + entry.start), Size = entry.size, Length = (ulong)(entry.size * sector.Length), Sequence = counter, Scheme = Name }; part.Offset = part.Start * (ulong)sector.Length; if (entry.magic != LINUX_MAGIC && entry.magic != SWAP_MAGIC) { continue; } partitions.Add(part); counter++; } break; } case TYPE_RISCIX_MFM: case TYPE_RISCIX_SCSI: { IntPtr tablePtr = Marshal.AllocHGlobal(512); Marshal.Copy(map, 0, tablePtr, 512); RiscIxTable table = (RiscIxTable)Marshal.PtrToStructure(tablePtr, typeof(RiscIxTable)); Marshal.FreeHGlobal(tablePtr); if (table.magic == RISCIX_MAGIC) { foreach (RiscIxEntry entry in table.partitions) { Partition part = new Partition { Start = (ulong)(mapSector + entry.start), Size = entry.length, Length = (ulong)(entry.length * sector.Length), Name = StringHandlers.CToString(entry.name, Encoding.GetEncoding("iso-8859-1")), Sequence = counter, Scheme = Name }; part.Offset = part.Start * (ulong)sector.Length; if (entry.length <= 0) { continue; } partitions.Add(part); counter++; } } break; } } return(partitions.Count != 0); }
public bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset) { partitions = new List<Partition>(); ulong sbSector; // RISC OS always checks for the partition on 0. Afaik no emulator chains it. if(sectorOffset != 0) return false; if(imagePlugin.Info.SectorSize > ADFS_SB_POS) sbSector = 0; else sbSector = ADFS_SB_POS / imagePlugin.Info.SectorSize; byte[] sector = imagePlugin.ReadSector(sbSector); if(sector.Length < 512) return false; AcornBootBlock bootBlock = Marshal.ByteArrayToStructureLittleEndian<AcornBootBlock>(sector); int checksum = 0; for(int i = 0; i < 0x1FF; i++) checksum = (checksum & 0xFF) + (checksum >> 8) + sector[i]; int heads = bootBlock.discRecord.heads + ((bootBlock.discRecord.lowsector >> 6) & 1); int secCyl = bootBlock.discRecord.spt * heads; int mapSector = bootBlock.startCylinder * secCyl; if((ulong)mapSector >= imagePlugin.Info.Sectors) return false; byte[] map = imagePlugin.ReadSector((ulong)mapSector); ulong counter = 0; if(checksum == bootBlock.checksum) { Partition part = new Partition { Size = (ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size, Length = ((ulong)bootBlock.discRecord.disc_size_high * 0x100000000 + bootBlock.discRecord.disc_size) / imagePlugin.Info.SectorSize, Type = "ADFS", Name = StringHandlers.CToString(bootBlock.discRecord.disc_name, Encoding.GetEncoding("iso-8859-1")) }; if(part.Size > 0) { partitions.Add(part); counter++; } } switch(bootBlock.flags & TYPE_MASK) { case TYPE_LINUX: { LinuxTable table = Marshal.ByteArrayToStructureLittleEndian<LinuxTable>(map); foreach(LinuxEntry entry in table.entries) { Partition part = new Partition { Start = (ulong)(mapSector + entry.start), Size = entry.size, Length = (ulong)(entry.size * sector.Length), Sequence = counter, Scheme = Name }; part.Offset = part.Start * (ulong)sector.Length; if(entry.magic != LINUX_MAGIC && entry.magic != SWAP_MAGIC) continue; partitions.Add(part); counter++; } break; } case TYPE_RISCIX_MFM: case TYPE_RISCIX_SCSI: { RiscIxTable table = Marshal.ByteArrayToStructureLittleEndian<RiscIxTable>(map); if(table.magic == RISCIX_MAGIC) foreach(RiscIxEntry entry in table.partitions) { Partition part = new Partition { Start = (ulong)(mapSector + entry.start), Size = entry.length, Length = (ulong)(entry.length * sector.Length), Name = StringHandlers.CToString(entry.name, Encoding.GetEncoding("iso-8859-1")), Sequence = counter, Scheme = Name }; part.Offset = part.Start * (ulong)sector.Length; if(entry.length <= 0) continue; partitions.Add(part); counter++; } break; } } return partitions.Count != 0; }