diff --git a/DiscImageChef/PartPlugins/AppleMap.cs b/DiscImageChef/PartPlugins/AppleMap.cs index 343991365..7fce42dcd 100644 --- a/DiscImageChef/PartPlugins/AppleMap.cs +++ b/DiscImageChef/PartPlugins/AppleMap.cs @@ -96,34 +96,38 @@ namespace DiscImageChef.PartPlugins first_sector = 1; // Read first entry - byte[] APMEntry_sector = imagePlugin.ReadSector(first_sector); - APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00); - APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02); - APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04); - APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08); - APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C); - cString = new byte[32]; - Array.Copy(APMEntry_sector, 0x10, cString, 0, 32); - APMEntry.name = StringHandlers.CToString(cString); - cString = new byte[32]; - Array.Copy(APMEntry_sector, 0x30, cString, 0, 32); - APMEntry.type = StringHandlers.CToString(cString); - APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50); - APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54); - APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58); - APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C); - APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60); - APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64); - APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68); - APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C); - APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70); - APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74); - cString = new byte[16]; - Array.Copy(APMEntry_sector, 0x78, cString, 0, 16); - APMEntry.processor = StringHandlers.CToString(cString); + byte[] APMEntry_sector; + bool APMFromHDDOnCD = false; - if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) - return false; + if (sector_size == 2048) + { + APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector); + APMEntry = DecodeAPMEntry(APMEntry_sector); + + if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) + { + sector_size = 512; + APMFromHDDOnCD = true; + if (MainClass.isDebug) + Console.WriteLine("DEBUG (Apple Partition Map Plugin): PM sector size is 512 bytes, but device's 2048"); + } + else + { + APMEntry_sector = imagePlugin.ReadSector(first_sector); + APMEntry = DecodeAPMEntry(APMEntry_sector); + + if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) + return false; + } + } + else + { + APMEntry_sector = imagePlugin.ReadSector(first_sector); + APMEntry = DecodeAPMEntry(APMEntry_sector); + + if (APMEntry.signature != APM_ENTRY && APMEntry.signature != APM_OLDENT) + return false; + } if (APMEntry.entries <= 1) return false; @@ -133,31 +137,12 @@ namespace DiscImageChef.PartPlugins for (ulong i = 0; i < apm_entries; i++) // For each partition { APMEntry = new AppleMapPartitionEntry(); - APMEntry_sector = imagePlugin.ReadSector(first_sector + i); - APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00); - APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02); - APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04); - APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08); - APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C); - cString = new byte[32]; - Array.Copy(APMEntry_sector, 0x10, cString, 0, 32); - APMEntry.name = StringHandlers.CToString(cString); - cString = new byte[32]; - Array.Copy(APMEntry_sector, 0x30, cString, 0, 32); - APMEntry.type = StringHandlers.CToString(cString); - APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50); - APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54); - APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58); - APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C); - APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60); - APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64); - APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68); - APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C); - APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70); - APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74); - cString = new byte[16]; - Array.Copy(APMEntry_sector, 0x78, cString, 0, 16); - APMEntry.processor = StringHandlers.CToString(cString); + if(APMFromHDDOnCD) + APMEntry_sector = Read2048SectorAs512(imagePlugin, first_sector + i); + else + APMEntry_sector = imagePlugin.ReadSector(first_sector + i); + + APMEntry = DecodeAPMEntry(APMEntry_sector); if (APMEntry.signature == APM_ENTRY || APMEntry.signature == APM_OLDENT) // It should have partition entry signature { @@ -209,6 +194,52 @@ namespace DiscImageChef.PartPlugins return true; } + byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA) + { + UInt64 LBA2k = LBA / 4; + int Remainder = (int)(LBA % 4); + + byte[] buffer = imagePlugin.ReadSector(LBA2k); + byte[] sector = new byte[512]; + + Array.Copy(buffer, Remainder * 512, sector, 0, 512); + + return sector; + } + + AppleMapPartitionEntry DecodeAPMEntry(byte[] APMEntry_sector) + { + AppleMapPartitionEntry APMEntry = new AppleMapPartitionEntry(); + byte[] cString; + + APMEntry.signature = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x00); + APMEntry.reserved1 = BigEndianBitConverter.ToUInt16(APMEntry_sector, 0x02); + APMEntry.entries = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x04); + APMEntry.start = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x08); + APMEntry.sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x0C); + cString = new byte[32]; + Array.Copy(APMEntry_sector, 0x10, cString, 0, 32); + APMEntry.name = StringHandlers.CToString(cString); + cString = new byte[32]; + Array.Copy(APMEntry_sector, 0x30, cString, 0, 32); + APMEntry.type = StringHandlers.CToString(cString); + APMEntry.first_data_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x50); + APMEntry.data_sectors = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x54); + APMEntry.status = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x58); + APMEntry.first_boot_block = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x5C); + APMEntry.boot_size = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x60); + APMEntry.load_address = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x64); + APMEntry.reserved2 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x68); + APMEntry.entry_point = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x6C); + APMEntry.reserved3 = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x70); + APMEntry.checksum = BigEndianBitConverter.ToUInt32(APMEntry_sector, 0x74); + cString = new byte[16]; + Array.Copy(APMEntry_sector, 0x78, cString, 0, 16); + APMEntry.processor = StringHandlers.CToString(cString); + + return APMEntry; + } + public struct AppleMapBootEntry { // Signature ("ER") diff --git a/DiscImageChef/Plugins/AppleHFS.cs b/DiscImageChef/Plugins/AppleHFS.cs index c50fff857..c3c2028a4 100644 --- a/DiscImageChef/Plugins/AppleHFS.cs +++ b/DiscImageChef/Plugins/AppleHFS.cs @@ -63,14 +63,47 @@ namespace DiscImageChef.Plugins if ((2 + partitionOffset) >= imagePlugin.GetSectors()) return false; - byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); - UInt16 drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + byte[] mdb_sector; + UInt16 drSigWord; - if (drSigWord == HFS_MAGIC) + if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048) { - drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature + mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + { + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature + + return drSigWord != HFSP_MAGIC; + } + else + { + mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + { + if(MainClass.isDebug) + Console.WriteLine("DEBUG (HFS Plugin): HFS sector size is 512 bytes, but device's 2048"); + + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature + + return drSigWord != HFSP_MAGIC; + } + } + } + else + { + mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + { + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x7C); // Seek to embedded HFS+ signature - return drSigWord != HFSP_MAGIC; + return drSigWord != HFSP_MAGIC; + } } return false; } @@ -86,8 +119,46 @@ namespace DiscImageChef.Plugins byte[] pString; - byte[] bb_sector = imagePlugin.ReadSector(partitionOffset); // BB's first sector - byte[] mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); // MDB sector + byte[] bb_sector; + byte[] mdb_sector; + UInt16 drSigWord; + + bool APMFromHDDOnCD = false; + + if (imagePlugin.GetSectorSize() == 2352 || imagePlugin.GetSectorSize() == 2448 || imagePlugin.GetSectorSize() == 2048) + { + mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + { + bb_sector = imagePlugin.ReadSector(partitionOffset); + } + else + { + mdb_sector = Read2048SectorAs512(imagePlugin, 2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + { + bb_sector = Read2048SectorAs512(imagePlugin, partitionOffset); + APMFromHDDOnCD = true; + } + else + return; + } + } + else + { + mdb_sector = imagePlugin.ReadSector(2 + partitionOffset); + drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0); + + if (drSigWord == HFS_MAGIC) + bb_sector = imagePlugin.ReadSector(partitionOffset); + else + return; + } + MDB.drSigWord = BigEndianBitConverter.ToUInt16(mdb_sector, 0x000); if (MDB.drSigWord != HFS_MAGIC) return; @@ -181,6 +252,8 @@ namespace DiscImageChef.Plugins sb.AppendLine("Apple Hierarchical File System"); sb.AppendLine(); + if (APMFromHDDOnCD) + sb.AppendLine("HFS uses 512 bytes/sector while devices uses 2048 bytes/sector.").AppendLine(); sb.AppendLine("Master Directory Block:"); sb.AppendFormat("Creation date: {0}", DateHandlers.MacToDateTime(MDB.drCrDate)).AppendLine(); sb.AppendFormat("Last modification date: {0}", DateHandlers.MacToDateTime(MDB.drLsMod)).AppendLine(); @@ -291,6 +364,19 @@ namespace DiscImageChef.Plugins return; } + byte[] Read2048SectorAs512(ImagePlugins.ImagePlugin imagePlugin, UInt64 LBA) + { + UInt64 LBA2k = LBA / 4; + int Remainder = (int)(LBA % 4); + + byte[] buffer = imagePlugin.ReadSector(LBA2k); + byte[] sector = new byte[512]; + + Array.Copy(buffer, Remainder * 512, sector, 0, 512); + + return sector; + } + struct HFS_MasterDirectoryBlock // Should be sector 2 in volume { public UInt16 drSigWord;