2019-04-25 22:05:33 +01:00
|
|
|
// /***************************************************************************
|
2020-02-27 12:31:25 +00:00
|
|
|
// Aaru Data Preservation Suite
|
2019-04-25 22:05:33 +01:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : BPB.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Microsoft FAT filesystem plugin.
|
|
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// This library is free software; you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Lesser General Public License as
|
|
|
|
|
// published by the Free Software Foundation; either version 2.1 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This library is distributed in the hope that it will be useful, but
|
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2024-05-01 04:17:32 +01:00
|
|
|
// Copyright © 2011-2024 Natalia Portillo
|
2019-04-25 22:05:33 +01:00
|
|
|
// ****************************************************************************/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
2020-02-27 00:33:26 +00:00
|
|
|
using Aaru.CommonTypes;
|
|
|
|
|
using Aaru.CommonTypes.Enums;
|
|
|
|
|
using Aaru.CommonTypes.Interfaces;
|
|
|
|
|
using Aaru.Console;
|
|
|
|
|
using Aaru.Helpers;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
namespace Aaru.Filesystems;
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
public sealed partial class FAT
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
static BpbKind DetectBpbKind(byte[] bpbSector, IMediaImage imagePlugin, Partition partition,
|
|
|
|
|
out BiosParameterBlockEbpb fakeBpb, out HumanParameterBlock humanBpb,
|
2022-03-07 07:36:44 +00:00
|
|
|
out AtariParameterBlock atariBpb, out byte minBootNearJump, out bool andosOemCorrect,
|
|
|
|
|
out bool bootable)
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb = new BiosParameterBlockEbpb();
|
|
|
|
|
minBootNearJump = 0;
|
|
|
|
|
andosOemCorrect = false;
|
|
|
|
|
bootable = false;
|
|
|
|
|
|
|
|
|
|
humanBpb = Marshal.ByteArrayToStructureBigEndian<HumanParameterBlock>(bpbSector);
|
|
|
|
|
atariBpb = Marshal.ByteArrayToStructureLittleEndian<AtariParameterBlock>(bpbSector);
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
ulong expectedClusters = humanBpb.bpc > 0 ? partition.Size / humanBpb.bpc : 0;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// Check clusters for Human68k are correct
|
2023-10-03 23:22:08 +01:00
|
|
|
bool humanClustersCorrect = humanBpb.clusters == 0
|
|
|
|
|
? humanBpb.big_clusters == expectedClusters
|
|
|
|
|
: humanBpb.clusters == expectedClusters;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// Check OEM for Human68k is correct
|
2023-10-04 17:34:40 +01:00
|
|
|
bool humanOemCorrect = bpbSector[2] >= 0x20 &&
|
|
|
|
|
bpbSector[3] >= 0x20 &&
|
|
|
|
|
bpbSector[4] >= 0x20 &&
|
|
|
|
|
bpbSector[5] >= 0x20 &&
|
|
|
|
|
bpbSector[6] >= 0x20 &&
|
|
|
|
|
bpbSector[7] >= 0x20 &&
|
|
|
|
|
bpbSector[8] >= 0x20 &&
|
|
|
|
|
bpbSector[9] >= 0x20 &&
|
|
|
|
|
bpbSector[10] >= 0x20 &&
|
|
|
|
|
bpbSector[11] >= 0x20 &&
|
|
|
|
|
bpbSector[12] >= 0x20 &&
|
|
|
|
|
bpbSector[13] >= 0x20 &&
|
|
|
|
|
bpbSector[14] >= 0x20 &&
|
|
|
|
|
bpbSector[15] >= 0x20 &&
|
|
|
|
|
bpbSector[16] >= 0x20 &&
|
2022-03-06 13:29:38 +00:00
|
|
|
bpbSector[17] >= 0x20;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// Check correct branch for Human68k
|
|
|
|
|
bool humanBranchCorrect = bpbSector[0] == 0x60 && bpbSector[1] >= 0x1C && bpbSector[1] < 0xFE;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, "humanClustersCorrect = {0}", humanClustersCorrect);
|
2023-10-03 23:22:08 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, "humanOemCorrect = {0}", humanOemCorrect);
|
|
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, "humanBranchCorrect = {0}", humanBranchCorrect);
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// If all Human68k checks are correct, it is a Human68k FAT16
|
|
|
|
|
bool useHumanBpb = humanClustersCorrect && humanOemCorrect && humanBranchCorrect && expectedClusters > 0;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useHumanBpb)
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_Human68k_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
fakeBpb.jump = humanBpb.jump;
|
|
|
|
|
fakeBpb.oem_name = humanBpb.oem_name;
|
|
|
|
|
fakeBpb.bps = (ushort)imagePlugin.Info.SectorSize;
|
|
|
|
|
fakeBpb.spc = (byte)(humanBpb.bpc / fakeBpb.bps);
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = humanBpb.root_ent;
|
|
|
|
|
fakeBpb.media = humanBpb.media;
|
|
|
|
|
fakeBpb.spfat = (ushort)(humanBpb.cpfat * fakeBpb.spc);
|
|
|
|
|
fakeBpb.boot_code = humanBpb.boot_code;
|
|
|
|
|
fakeBpb.sectors = humanBpb.clusters;
|
|
|
|
|
fakeBpb.big_sectors = humanBpb.big_clusters;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Human;
|
|
|
|
|
}
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
var msxBpb = new MsxParameterBlock();
|
|
|
|
|
var dos2Bpb = new BiosParameterBlock2();
|
|
|
|
|
var dos30Bpb = new BiosParameterBlock30();
|
|
|
|
|
var dos32Bpb = new BiosParameterBlock32();
|
|
|
|
|
var dos33Bpb = new BiosParameterBlock33();
|
|
|
|
|
var shortEbpb = new BiosParameterBlockShortEbpb();
|
|
|
|
|
var ebpb = new BiosParameterBlockEbpb();
|
|
|
|
|
var apricotBpb = new ApricotLabel();
|
|
|
|
|
|
2023-10-03 23:22:08 +01:00
|
|
|
var useAtariBpb = false;
|
|
|
|
|
var useMsxBpb = false;
|
|
|
|
|
var useDos2Bpb = false;
|
|
|
|
|
var useDos3Bpb = false;
|
|
|
|
|
var useDos32Bpb = false;
|
|
|
|
|
var useDos33Bpb = false;
|
|
|
|
|
var userShortExtendedBpb = false;
|
|
|
|
|
var useExtendedBpb = false;
|
|
|
|
|
var useApricotBpb = false;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
if(imagePlugin.Info.SectorSize >= 256)
|
|
|
|
|
{
|
|
|
|
|
msxBpb = Marshal.ByteArrayToStructureLittleEndian<MsxParameterBlock>(bpbSector);
|
|
|
|
|
dos2Bpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlock2>(bpbSector);
|
|
|
|
|
dos30Bpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlock30>(bpbSector);
|
|
|
|
|
dos32Bpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlock32>(bpbSector);
|
|
|
|
|
dos33Bpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlock33>(bpbSector);
|
|
|
|
|
shortEbpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlockShortEbpb>(bpbSector);
|
|
|
|
|
ebpb = Marshal.ByteArrayToStructureLittleEndian<BiosParameterBlockEbpb>(bpbSector);
|
|
|
|
|
|
|
|
|
|
Fat32ParameterBlockShort shortFat32Bpb =
|
|
|
|
|
Marshal.ByteArrayToStructureLittleEndian<Fat32ParameterBlockShort>(bpbSector);
|
|
|
|
|
|
|
|
|
|
Fat32ParameterBlock fat32Bpb = Marshal.ByteArrayToStructureLittleEndian<Fat32ParameterBlock>(bpbSector);
|
|
|
|
|
apricotBpb = Marshal.ByteArrayToStructureLittleEndian<ApricotLabel>(bpbSector);
|
|
|
|
|
|
|
|
|
|
int bitsInBpsMsx = CountBits.Count(msxBpb.bps);
|
|
|
|
|
int bitsInBpsDos33 = CountBits.Count(dos33Bpb.bps);
|
|
|
|
|
int bitsInBpsDos40 = CountBits.Count(ebpb.bps);
|
|
|
|
|
int bitsInBpsFat32Short = CountBits.Count(shortFat32Bpb.bps);
|
|
|
|
|
int bitsInBpsFat32 = CountBits.Count(fat32Bpb.bps);
|
|
|
|
|
int bitsInBpsApricot = CountBits.Count(apricotBpb.mainBPB.bps);
|
|
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcMsx = msxBpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcDos33 = dos33Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcDos40 = ebpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcFat32Short = shortFat32Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcFat32 = fat32Bpb.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-03-16 11:47:00 +00:00
|
|
|
bool correctSpcApricot = apricotBpb.mainBPB.spc is 1 or 2 or 4 or 8 or 16 or 32 or 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
// This is to support FAT partitions on hybrid ISO/USB images
|
2022-12-15 22:21:07 +00:00
|
|
|
if(imagePlugin.Info.MetadataMediaType == MetadataMediaType.OpticalDisc)
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
atariBpb.sectors /= 4;
|
|
|
|
|
msxBpb.sectors /= 4;
|
|
|
|
|
dos2Bpb.sectors /= 4;
|
|
|
|
|
dos30Bpb.sectors /= 4;
|
|
|
|
|
dos32Bpb.sectors /= 4;
|
|
|
|
|
dos33Bpb.sectors /= 4;
|
|
|
|
|
dos33Bpb.big_sectors /= 4;
|
|
|
|
|
shortEbpb.sectors /= 4;
|
|
|
|
|
shortEbpb.big_sectors /= 4;
|
|
|
|
|
ebpb.sectors /= 4;
|
|
|
|
|
ebpb.big_sectors /= 4;
|
|
|
|
|
shortFat32Bpb.sectors /= 4;
|
|
|
|
|
shortFat32Bpb.big_sectors /= 4;
|
|
|
|
|
shortFat32Bpb.huge_sectors /= 4;
|
|
|
|
|
fat32Bpb.sectors /= 4;
|
|
|
|
|
fat32Bpb.big_sectors /= 4;
|
|
|
|
|
apricotBpb.mainBPB.sectors /= 4;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
|
2023-10-04 17:34:40 +01:00
|
|
|
andosOemCorrect = dos33Bpb.oem_name[0] < 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[1] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[2] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[3] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[4] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[5] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[6] >= 0x20 &&
|
|
|
|
|
dos33Bpb.oem_name[7] >= 0x20;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
if(bitsInBpsFat32 == 1 &&
|
|
|
|
|
correctSpcFat32 &&
|
|
|
|
|
fat32Bpb.fats_no <= 2 &&
|
|
|
|
|
fat32Bpb is { spfat: 0, signature: 0x29 } &&
|
2022-03-06 13:29:38 +00:00
|
|
|
Encoding.ASCII.GetString(fat32Bpb.fs_type) == "FAT32 ")
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_FAT32_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
minBootNearJump = 0x58;
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return BpbKind.LongFat32;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-11-15 15:58:43 +00:00
|
|
|
if(bitsInBpsFat32Short == 1 &&
|
|
|
|
|
correctSpcFat32Short &&
|
|
|
|
|
shortFat32Bpb is { fats_no: <= 2, sectors: 0 } and { spfat: 0, signature: 0x28 })
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_short_FAT32_BPB);
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
minBootNearJump = 0x57;
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return BpbKind.ShortFat32;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(bitsInBpsMsx == 1 &&
|
|
|
|
|
correctSpcMsx &&
|
2022-11-15 15:58:43 +00:00
|
|
|
msxBpb is { fats_no: <= 2, root_ent: > 0 } &&
|
2022-03-06 13:29:38 +00:00
|
|
|
msxBpb.sectors <= partition.End - partition.Start + 1 &&
|
|
|
|
|
msxBpb.spfat > 0 &&
|
|
|
|
|
Encoding.ASCII.GetString(msxBpb.vol_id) == "VOL_ID")
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_MSX_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useMsxBpb = true;
|
|
|
|
|
}
|
2022-11-15 15:58:43 +00:00
|
|
|
else if(bitsInBpsApricot == 1 &&
|
|
|
|
|
correctSpcApricot &&
|
|
|
|
|
apricotBpb.mainBPB is { fats_no: <= 2, root_ent: > 0 } &&
|
|
|
|
|
apricotBpb.mainBPB.sectors <= partition.End - partition.Start + 1 &&
|
|
|
|
|
apricotBpb.mainBPB.spfat > 0 &&
|
|
|
|
|
apricotBpb.partitionCount == 0)
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_Apricot_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useApricotBpb = true;
|
|
|
|
|
}
|
2022-11-15 15:58:43 +00:00
|
|
|
else if(bitsInBpsDos40 == 1 &&
|
|
|
|
|
correctSpcDos40 &&
|
|
|
|
|
ebpb.fats_no <= 2 &&
|
|
|
|
|
ebpb is { root_ent: > 0, spfat: > 0 } &&
|
2022-03-16 11:47:00 +00:00
|
|
|
(ebpb.signature is 0x28 or 0x29 || andosOemCorrect))
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
if(ebpb.sectors == 0)
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(ebpb.big_sectors <= partition.End - partition.Start + 1)
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2019-04-25 22:05:33 +01:00
|
|
|
if(ebpb.signature == 0x29 || andosOemCorrect)
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_4_0_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
useExtendedBpb = true;
|
|
|
|
|
minBootNearJump = 0x3C;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_4_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
userShortExtendedBpb = true;
|
|
|
|
|
minBootNearJump = 0x29;
|
|
|
|
|
}
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
else if(ebpb.sectors <= partition.End - partition.Start + 1)
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(ebpb.signature == 0x29 || andosOemCorrect)
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_4_0_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useExtendedBpb = true;
|
|
|
|
|
minBootNearJump = 0x3C;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_4_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
userShortExtendedBpb = true;
|
|
|
|
|
minBootNearJump = 0x29;
|
|
|
|
|
}
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
|
|
|
|
else if(bitsInBpsDos33 == 1 &&
|
|
|
|
|
correctSpcDos33 &&
|
|
|
|
|
dos33Bpb.rsectors < partition.End - partition.Start &&
|
|
|
|
|
dos33Bpb.fats_no <= 2 &&
|
2022-11-15 15:58:43 +00:00
|
|
|
dos33Bpb is { root_ent: > 0, spfat: > 0 })
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(dos33Bpb.sectors == 0 &&
|
|
|
|
|
dos33Bpb.hsectors <= partition.Start &&
|
|
|
|
|
dos33Bpb.big_sectors > 0 &&
|
|
|
|
|
dos33Bpb.big_sectors <= partition.End - partition.Start + 1)
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_3_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useDos33Bpb = true;
|
|
|
|
|
minBootNearJump = 0x22;
|
|
|
|
|
}
|
|
|
|
|
else if(dos33Bpb.big_sectors == 0 &&
|
|
|
|
|
dos33Bpb.hsectors <= partition.Start &&
|
|
|
|
|
dos33Bpb.sectors > 0 &&
|
|
|
|
|
dos33Bpb.sectors <= partition.End - partition.Start + 1)
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(atariBpb.jump[0] == 0x60 ||
|
2023-10-04 17:34:40 +01:00
|
|
|
atariBpb.jump[0] == 0xE9 &&
|
|
|
|
|
atariBpb.jump[1] == 0x00 &&
|
2023-10-03 23:22:08 +01:00
|
|
|
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT " ||
|
2022-03-16 11:47:00 +00:00
|
|
|
partition.Type is "GEM" or "BGM")
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_Atari_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useAtariBpb = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_3_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
useDos33Bpb = true;
|
|
|
|
|
minBootNearJump = 0x22;
|
|
|
|
|
}
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(dos32Bpb.hsectors <= partition.Start &&
|
|
|
|
|
dos32Bpb.hsectors + dos32Bpb.sectors == dos32Bpb.total_sectors)
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_2_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useDos32Bpb = true;
|
|
|
|
|
minBootNearJump = 0x1E;
|
|
|
|
|
}
|
2023-10-04 17:34:40 +01:00
|
|
|
else if(dos30Bpb.sptrk is > 0 and < 64 && dos30Bpb.heads is > 0 and < 256)
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2020-02-29 18:03:35 +00:00
|
|
|
if(atariBpb.jump[0] == 0x60 ||
|
2023-10-04 17:34:40 +01:00
|
|
|
atariBpb.jump[0] == 0xE9 &&
|
|
|
|
|
atariBpb.jump[1] == 0x00 &&
|
2023-10-03 23:22:08 +01:00
|
|
|
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT ")
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_Atari_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
useAtariBpb = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_3_0_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useDos3Bpb = true;
|
|
|
|
|
minBootNearJump = 0x1C;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
else
|
|
|
|
|
{
|
2022-03-06 13:29:38 +00:00
|
|
|
if(atariBpb.jump[0] == 0x60 ||
|
2023-10-04 17:34:40 +01:00
|
|
|
atariBpb.jump[0] == 0xE9 &&
|
|
|
|
|
atariBpb.jump[1] == 0x00 &&
|
2023-10-03 23:22:08 +01:00
|
|
|
Encoding.ASCII.GetString(dos33Bpb.oem_name) != "NEXT ")
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_Atari_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useAtariBpb = true;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DOS_2_0_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
useDos2Bpb = true;
|
|
|
|
|
minBootNearJump = 0x16;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// DEC Rainbow, lacks a BPB but has a very concrete structure...
|
2022-11-15 15:58:43 +00:00
|
|
|
if(imagePlugin.Info is { Sectors: 800, SectorSize: 512 } &&
|
|
|
|
|
!useAtariBpb &&
|
|
|
|
|
!useMsxBpb &&
|
|
|
|
|
!useDos2Bpb &&
|
|
|
|
|
!useDos3Bpb &&
|
|
|
|
|
!useDos32Bpb &&
|
|
|
|
|
!useDos33Bpb &&
|
|
|
|
|
!userShortExtendedBpb &&
|
|
|
|
|
!useExtendedBpb &&
|
2022-03-06 13:29:38 +00:00
|
|
|
!useApricotBpb)
|
|
|
|
|
{
|
|
|
|
|
// DEC Rainbow boots up with a Z80, first byte should be DI (disable interrupts)
|
|
|
|
|
byte z80Di = bpbSector[0];
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// First FAT1 sector resides at LBA 0x14
|
|
|
|
|
imagePlugin.ReadSector(0x14, out byte[] fat1Sector0);
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// First FAT2 sector resides at LBA 0x1A
|
|
|
|
|
imagePlugin.ReadSector(0x1A, out byte[] fat2Sector0);
|
|
|
|
|
bool equalFatIds = fat1Sector0[0] == fat2Sector0[0] && fat1Sector0[1] == fat2Sector0[1];
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// Volume is software interleaved 2:1
|
|
|
|
|
var rootMs = new MemoryStream();
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2023-10-04 17:34:40 +01:00
|
|
|
foreach(ulong rootSector in new ulong[]
|
2024-05-01 04:05:22 +01:00
|
|
|
{
|
|
|
|
|
0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20
|
|
|
|
|
})
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
imagePlugin.ReadSector(rootSector, out byte[] tmp);
|
|
|
|
|
rootMs.Write(tmp, 0, tmp.Length);
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
byte[] rootDir = rootMs.ToArray();
|
2023-10-03 23:22:08 +01:00
|
|
|
var validRootDir = true;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// Iterate all root directory
|
2023-10-03 23:22:08 +01:00
|
|
|
for(var e = 0; e < 96 * 32; e += 32)
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 23:22:08 +01:00
|
|
|
for(var c = 0; c < 11; c++)
|
|
|
|
|
{
|
2023-10-04 07:39:22 +01:00
|
|
|
if((rootDir[c + e] >= 0x20 || rootDir[c + e] == 0x00 || rootDir[c + e] == 0x05) &&
|
|
|
|
|
rootDir[c + e] != 0xFF &&
|
|
|
|
|
rootDir[c + e] != 0x2E)
|
|
|
|
|
continue;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2023-10-04 07:39:22 +01:00
|
|
|
validRootDir = false;
|
|
|
|
|
|
|
|
|
|
break;
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2024-05-01 04:05:22 +01:00
|
|
|
if(!validRootDir) break;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(z80Di == 0xF3 &&
|
|
|
|
|
equalFatIds &&
|
|
|
|
|
(fat1Sector0[0] & 0xF0) == 0xF0 &&
|
|
|
|
|
fat1Sector0[1] == 0xFF &&
|
|
|
|
|
validRootDir)
|
2019-04-25 22:05:33 +01:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_DEC_Rainbow_hardcoded_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 512;
|
|
|
|
|
fakeBpb.spc = 1;
|
|
|
|
|
fakeBpb.rsectors = 20;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 96;
|
|
|
|
|
fakeBpb.sectors = 800;
|
|
|
|
|
fakeBpb.media = 0xFA;
|
|
|
|
|
fakeBpb.sptrk = 10;
|
|
|
|
|
fakeBpb.heads = 1;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 3;
|
|
|
|
|
bootable = true;
|
|
|
|
|
fakeBpb.boot_code = bpbSector;
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return BpbKind.DecRainbow;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!useAtariBpb &&
|
|
|
|
|
!useMsxBpb &&
|
|
|
|
|
!useDos2Bpb &&
|
|
|
|
|
!useDos3Bpb &&
|
|
|
|
|
!useDos32Bpb &&
|
|
|
|
|
!useDos33Bpb &&
|
|
|
|
|
!useHumanBpb &&
|
|
|
|
|
!userShortExtendedBpb &&
|
|
|
|
|
!useExtendedBpb &&
|
2023-10-05 02:35:03 +01:00
|
|
|
!useApricotBpb)
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
|
|
|
|
imagePlugin.ReadSector(1 + partition.Start, out byte[] fatSector);
|
|
|
|
|
|
|
|
|
|
switch(fatSector[0])
|
|
|
|
|
{
|
|
|
|
|
case 0xE5:
|
2022-11-15 15:58:43 +00:00
|
|
|
if(imagePlugin.Info is { Sectors: 2002, SectorSize: 128 })
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 128;
|
|
|
|
|
fakeBpb.spc = 4;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 64;
|
|
|
|
|
fakeBpb.sectors = 2002;
|
|
|
|
|
fakeBpb.media = 0xE5;
|
|
|
|
|
fakeBpb.sptrk = 26;
|
|
|
|
|
fakeBpb.heads = 1;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 0xFD:
|
2022-11-13 19:38:03 +00:00
|
|
|
switch(imagePlugin.Info.Sectors)
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2022-11-13 19:38:03 +00:00
|
|
|
case 4004 when imagePlugin.Info.SectorSize == 128:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2022-11-13 19:38:03 +00:00
|
|
|
fakeBpb.bps = 128;
|
|
|
|
|
fakeBpb.spc = 4;
|
|
|
|
|
fakeBpb.rsectors = 4;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 68;
|
|
|
|
|
fakeBpb.sectors = 4004;
|
|
|
|
|
fakeBpb.media = 0xFD;
|
|
|
|
|
fakeBpb.sptrk = 26;
|
|
|
|
|
fakeBpb.heads = 2;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 6;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 2002 when imagePlugin.Info.SectorSize == 128:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2022-11-13 19:38:03 +00:00
|
|
|
fakeBpb.bps = 128;
|
|
|
|
|
fakeBpb.spc = 4;
|
|
|
|
|
fakeBpb.rsectors = 4;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 68;
|
|
|
|
|
fakeBpb.sectors = 2002;
|
|
|
|
|
fakeBpb.media = 0xFD;
|
|
|
|
|
fakeBpb.sptrk = 26;
|
|
|
|
|
fakeBpb.heads = 1;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 6;
|
|
|
|
|
|
|
|
|
|
break;
|
2022-03-06 13:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 0xFE:
|
|
|
|
|
switch(imagePlugin.Info.Sectors)
|
|
|
|
|
{
|
|
|
|
|
case 320 when imagePlugin.Info.SectorSize == 512:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB_for_5_25_SSDD);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 512;
|
|
|
|
|
fakeBpb.spc = 1;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 64;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.sectors = 320;
|
|
|
|
|
fakeBpb.media = 0xFE;
|
|
|
|
|
fakeBpb.sptrk = 8;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.heads = 1;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 1;
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
case 2002 when imagePlugin.Info.SectorSize == 128:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.bps = 128;
|
|
|
|
|
fakeBpb.spc = 4;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.rsectors = 1;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 68;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.sectors = 2002;
|
|
|
|
|
fakeBpb.media = 0xFE;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.sptrk = 26;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.heads = 1;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 6;
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 1232 when imagePlugin.Info.SectorSize == 1024:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 1024;
|
|
|
|
|
fakeBpb.spc = 1;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 192;
|
|
|
|
|
fakeBpb.sectors = 1232;
|
|
|
|
|
fakeBpb.media = 0xFE;
|
|
|
|
|
fakeBpb.sptrk = 8;
|
|
|
|
|
fakeBpb.heads = 2;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 2;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 616 when imagePlugin.Info.SectorSize == 1024:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 1024;
|
|
|
|
|
fakeBpb.spc = 1;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 6192;
|
|
|
|
|
fakeBpb.sectors = 616;
|
|
|
|
|
fakeBpb.media = 0xFE;
|
|
|
|
|
fakeBpb.sptrk = 8;
|
|
|
|
|
fakeBpb.heads = 2;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 720 when imagePlugin.Info.SectorSize == 128:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB);
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.bps = 128;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.spc = 2;
|
|
|
|
|
fakeBpb.rsectors = 54;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.fats_no = 2;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.root_ent = 64;
|
|
|
|
|
fakeBpb.sectors = 720;
|
|
|
|
|
fakeBpb.media = 0xFE;
|
|
|
|
|
fakeBpb.sptrk = 18;
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.heads = 1;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.spfat = 4;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
case 640 when imagePlugin.Info.SectorSize == 512:
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB_for_5_25_DSDD);
|
2019-04-25 22:05:33 +01:00
|
|
|
fakeBpb.bps = 512;
|
|
|
|
|
fakeBpb.spc = 2;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 112;
|
|
|
|
|
fakeBpb.sectors = 640;
|
|
|
|
|
fakeBpb.media = 0xFF;
|
|
|
|
|
fakeBpb.sptrk = 8;
|
|
|
|
|
fakeBpb.heads = 2;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 1;
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
|
|
|
|
case 0xFF:
|
2022-11-15 15:58:43 +00:00
|
|
|
if(imagePlugin.Info is { Sectors: 640, SectorSize: 512 })
|
2022-03-06 13:29:38 +00:00
|
|
|
{
|
2023-10-03 17:47:32 +01:00
|
|
|
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Using_hardcoded_BPB_for_5_25_DSDD);
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.bps = 512;
|
|
|
|
|
fakeBpb.spc = 2;
|
|
|
|
|
fakeBpb.rsectors = 1;
|
|
|
|
|
fakeBpb.fats_no = 2;
|
|
|
|
|
fakeBpb.root_ent = 112;
|
|
|
|
|
fakeBpb.sectors = 640;
|
|
|
|
|
fakeBpb.media = 0xFF;
|
|
|
|
|
fakeBpb.sptrk = 8;
|
|
|
|
|
fakeBpb.heads = 2;
|
|
|
|
|
fakeBpb.hsectors = 0;
|
|
|
|
|
fakeBpb.spfat = 1;
|
|
|
|
|
}
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
break;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
// This assumes a bootable sector will jump somewhere or disable interrupts in x86 code
|
2023-10-04 17:34:40 +01:00
|
|
|
bootable |= bpbSector[0] == 0xFA ||
|
|
|
|
|
bpbSector[0] == 0xEB && bpbSector[1] <= 0x7F ||
|
|
|
|
|
bpbSector[0] == 0xE9 && BitConverter.ToUInt16(bpbSector, 1) <= 0x1FC;
|
2020-02-29 18:03:35 +00:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
fakeBpb.boot_code = bpbSector;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return BpbKind.Hardcoded;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useExtendedBpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb = ebpb;
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
return BpbKind.Extended;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(userShortExtendedBpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = shortEbpb.jump;
|
|
|
|
|
fakeBpb.oem_name = shortEbpb.oem_name;
|
|
|
|
|
fakeBpb.bps = shortEbpb.bps;
|
|
|
|
|
fakeBpb.spc = shortEbpb.spc;
|
|
|
|
|
fakeBpb.rsectors = shortEbpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = shortEbpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = shortEbpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = shortEbpb.sectors;
|
|
|
|
|
fakeBpb.media = shortEbpb.media;
|
|
|
|
|
fakeBpb.spfat = shortEbpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = shortEbpb.sptrk;
|
|
|
|
|
fakeBpb.heads = shortEbpb.heads;
|
|
|
|
|
fakeBpb.hsectors = shortEbpb.hsectors;
|
|
|
|
|
fakeBpb.big_sectors = shortEbpb.big_sectors;
|
|
|
|
|
fakeBpb.drive_no = shortEbpb.drive_no;
|
|
|
|
|
fakeBpb.flags = shortEbpb.flags;
|
|
|
|
|
fakeBpb.signature = shortEbpb.signature;
|
|
|
|
|
fakeBpb.serial_no = shortEbpb.serial_no;
|
|
|
|
|
fakeBpb.boot_code = shortEbpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = shortEbpb.boot_signature;
|
|
|
|
|
|
|
|
|
|
return BpbKind.ShortExtended;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useDos33Bpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = dos33Bpb.jump;
|
|
|
|
|
fakeBpb.oem_name = dos33Bpb.oem_name;
|
|
|
|
|
fakeBpb.bps = dos33Bpb.bps;
|
|
|
|
|
fakeBpb.spc = dos33Bpb.spc;
|
|
|
|
|
fakeBpb.rsectors = dos33Bpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = dos33Bpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = dos33Bpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = dos33Bpb.sectors;
|
|
|
|
|
fakeBpb.media = dos33Bpb.media;
|
|
|
|
|
fakeBpb.spfat = dos33Bpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = dos33Bpb.sptrk;
|
|
|
|
|
fakeBpb.heads = dos33Bpb.heads;
|
|
|
|
|
fakeBpb.hsectors = dos33Bpb.hsectors;
|
|
|
|
|
fakeBpb.big_sectors = dos33Bpb.big_sectors;
|
|
|
|
|
fakeBpb.boot_code = dos33Bpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = dos33Bpb.boot_signature;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Dos33;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useDos32Bpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = dos32Bpb.jump;
|
|
|
|
|
fakeBpb.oem_name = dos32Bpb.oem_name;
|
|
|
|
|
fakeBpb.bps = dos32Bpb.bps;
|
|
|
|
|
fakeBpb.spc = dos32Bpb.spc;
|
|
|
|
|
fakeBpb.rsectors = dos32Bpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = dos32Bpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = dos32Bpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = dos32Bpb.sectors;
|
|
|
|
|
fakeBpb.media = dos32Bpb.media;
|
|
|
|
|
fakeBpb.spfat = dos32Bpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = dos32Bpb.sptrk;
|
|
|
|
|
fakeBpb.heads = dos32Bpb.heads;
|
|
|
|
|
fakeBpb.hsectors = dos32Bpb.hsectors;
|
|
|
|
|
fakeBpb.boot_code = dos32Bpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = dos32Bpb.boot_signature;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Dos32;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useDos3Bpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = dos30Bpb.jump;
|
|
|
|
|
fakeBpb.oem_name = dos30Bpb.oem_name;
|
|
|
|
|
fakeBpb.bps = dos30Bpb.bps;
|
|
|
|
|
fakeBpb.spc = dos30Bpb.spc;
|
|
|
|
|
fakeBpb.rsectors = dos30Bpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = dos30Bpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = dos30Bpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = dos30Bpb.sectors;
|
|
|
|
|
fakeBpb.media = dos30Bpb.media;
|
|
|
|
|
fakeBpb.spfat = dos30Bpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = dos30Bpb.sptrk;
|
|
|
|
|
fakeBpb.heads = dos30Bpb.heads;
|
|
|
|
|
fakeBpb.hsectors = dos30Bpb.hsectors;
|
|
|
|
|
fakeBpb.boot_code = dos30Bpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = dos30Bpb.boot_signature;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Dos3;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useDos2Bpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = dos2Bpb.jump;
|
|
|
|
|
fakeBpb.oem_name = dos2Bpb.oem_name;
|
|
|
|
|
fakeBpb.bps = dos2Bpb.bps;
|
|
|
|
|
fakeBpb.spc = dos2Bpb.spc;
|
|
|
|
|
fakeBpb.rsectors = dos2Bpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = dos2Bpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = dos2Bpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = dos2Bpb.sectors;
|
|
|
|
|
fakeBpb.media = dos2Bpb.media;
|
|
|
|
|
fakeBpb.spfat = dos2Bpb.spfat;
|
|
|
|
|
fakeBpb.boot_code = dos2Bpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = dos2Bpb.boot_signature;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Dos2;
|
|
|
|
|
}
|
2019-04-25 22:05:33 +01:00
|
|
|
|
2022-03-06 13:29:38 +00:00
|
|
|
if(useMsxBpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = msxBpb.jump;
|
|
|
|
|
fakeBpb.oem_name = msxBpb.oem_name;
|
|
|
|
|
fakeBpb.bps = msxBpb.bps;
|
|
|
|
|
fakeBpb.spc = msxBpb.spc;
|
|
|
|
|
fakeBpb.rsectors = msxBpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = msxBpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = msxBpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = msxBpb.sectors;
|
|
|
|
|
fakeBpb.media = msxBpb.media;
|
|
|
|
|
fakeBpb.spfat = msxBpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = msxBpb.sptrk;
|
|
|
|
|
fakeBpb.heads = msxBpb.heads;
|
|
|
|
|
fakeBpb.hsectors = msxBpb.hsectors;
|
|
|
|
|
fakeBpb.boot_code = msxBpb.boot_code;
|
|
|
|
|
fakeBpb.boot_signature = msxBpb.boot_signature;
|
|
|
|
|
fakeBpb.serial_no = msxBpb.serial_no;
|
|
|
|
|
|
|
|
|
|
// TODO: Is there any way to check this?
|
|
|
|
|
bootable = true;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Msx;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
2022-03-06 13:29:38 +00:00
|
|
|
|
|
|
|
|
if(useAtariBpb)
|
|
|
|
|
{
|
|
|
|
|
fakeBpb.jump = atariBpb.jump;
|
|
|
|
|
fakeBpb.oem_name = atariBpb.oem_name;
|
|
|
|
|
fakeBpb.bps = atariBpb.bps;
|
|
|
|
|
fakeBpb.spc = atariBpb.spc;
|
|
|
|
|
fakeBpb.rsectors = atariBpb.rsectors;
|
|
|
|
|
fakeBpb.fats_no = atariBpb.fats_no;
|
|
|
|
|
fakeBpb.root_ent = atariBpb.root_ent;
|
|
|
|
|
fakeBpb.sectors = atariBpb.sectors;
|
|
|
|
|
fakeBpb.media = atariBpb.media;
|
|
|
|
|
fakeBpb.spfat = atariBpb.spfat;
|
|
|
|
|
fakeBpb.sptrk = atariBpb.sptrk;
|
|
|
|
|
fakeBpb.heads = atariBpb.heads;
|
|
|
|
|
fakeBpb.boot_code = atariBpb.boot_code;
|
|
|
|
|
|
|
|
|
|
return BpbKind.Atari;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 04:05:22 +01:00
|
|
|
if(!useApricotBpb) return BpbKind.None;
|
2022-11-13 21:14:18 +00:00
|
|
|
|
|
|
|
|
fakeBpb.bps = apricotBpb.mainBPB.bps;
|
|
|
|
|
fakeBpb.spc = apricotBpb.mainBPB.spc;
|
|
|
|
|
fakeBpb.rsectors = apricotBpb.mainBPB.rsectors;
|
|
|
|
|
fakeBpb.fats_no = apricotBpb.mainBPB.fats_no;
|
|
|
|
|
fakeBpb.root_ent = apricotBpb.mainBPB.root_ent;
|
|
|
|
|
fakeBpb.sectors = apricotBpb.mainBPB.sectors;
|
|
|
|
|
fakeBpb.media = apricotBpb.mainBPB.media;
|
|
|
|
|
fakeBpb.spfat = apricotBpb.mainBPB.spfat;
|
|
|
|
|
fakeBpb.sptrk = apricotBpb.spt;
|
|
|
|
|
bootable = apricotBpb.bootType > 0;
|
|
|
|
|
|
2023-10-04 17:34:40 +01:00
|
|
|
if(apricotBpb.bootLocation > 0 && apricotBpb.bootLocation + apricotBpb.bootSize < imagePlugin.Info.Sectors)
|
2023-10-03 23:22:08 +01:00
|
|
|
{
|
2022-11-13 21:14:18 +00:00
|
|
|
imagePlugin.ReadSectors(apricotBpb.bootLocation,
|
|
|
|
|
(uint)(apricotBpb.sectorSize * apricotBpb.bootSize) / imagePlugin.Info.SectorSize,
|
|
|
|
|
out fakeBpb.boot_code);
|
2023-10-03 23:22:08 +01:00
|
|
|
}
|
2022-11-13 21:14:18 +00:00
|
|
|
|
|
|
|
|
return BpbKind.Apricot;
|
2019-04-25 22:05:33 +01:00
|
|
|
}
|
|
|
|
|
}
|