diff --git a/Delta/Settings/Cores/MelonDSCoreSettingsViewController.swift b/Delta/Settings/Cores/MelonDSCoreSettingsViewController.swift index 8686fda..9556557 100644 --- a/Delta/Settings/Cores/MelonDSCoreSettingsViewController.swift +++ b/Delta/Settings/Cores/MelonDSCoreSettingsViewController.swift @@ -32,6 +32,7 @@ private extension MelonDSCoreSettingsViewController { case unknownSize(URL) case incorrectHash(URL, hash: String, expectedHash: String) + case unsupportedHash(URL, hash: String) @available(iOS 13, *) case incorrectSize(URL, size: Int, validSizes: Set>>) @@ -50,7 +51,10 @@ private extension MelonDSCoreSettingsViewController return String(format: NSLocalizedString("%@’s size could not be determined.", comment: ""), fileURL.lastPathComponent) case .incorrectHash(let fileURL, let md5Hash, let expectedHash): - return String(format: NSLocalizedString("%@‘s hash does not match the expected hash.\n\nHash:\n%@\n\nExpected:\n%@.", comment: ""), fileURL.lastPathComponent, md5Hash, expectedHash) + return String(format: NSLocalizedString("%@‘s checksum does not match the expected checksum.\n\nChecksum:\n%@\n\nExpected:\n%@", comment: ""), fileURL.lastPathComponent, md5Hash, expectedHash) + + case .unsupportedHash(let fileURL, let md5Hash): + return String(format: NSLocalizedString("%@ is not compatible with this version of Delta.\n\nChecksum:\n%@", comment: ""), fileURL.lastPathComponent, md5Hash) case .incorrectSize(let fileURL, let size, let validSizes): let actualSize = BIOSError.byteFormatter.string(fromByteCount: Int64(size)) @@ -435,15 +439,21 @@ extension MelonDSCoreSettingsViewController: UIDocumentPickerDelegate let measurement = Measurement(value: Double(fileSize), unit: .bytes) guard bios.validFileSizes.contains(where: { $0.contains(measurement) }) else { throw BIOSError.incorrectSize(fileURL, size: fileSize, validSizes: bios.validFileSizes) } - if let expectedMD5Hash = bios.expectedMD5Hash + if bios.expectedMD5Hash != nil || !bios.unsupportedMD5Hashes.isEmpty { - // If there's an expected hash, make sure it matches. + // Only calculate hash if we need to. let data = try Data(contentsOf: fileURL) let md5Hash = Insecure.MD5.hash(data: data) let hashString = md5Hash.compactMap { String(format: "%02x", $0) }.joined() - guard hashString == expectedMD5Hash else { throw BIOSError.incorrectHash(fileURL, hash: hashString, expectedHash: expectedMD5Hash) } + + if let expectedMD5Hash = bios.expectedMD5Hash + { + guard hashString == expectedMD5Hash else { throw BIOSError.incorrectHash(fileURL, hash: hashString, expectedHash: expectedMD5Hash) } + } + + guard !bios.unsupportedMD5Hashes.contains(hashString) else { throw BIOSError.unsupportedHash(fileURL, hash: hashString) } } } diff --git a/Delta/Settings/Cores/SystemBIOS.swift b/Delta/Settings/Cores/SystemBIOS.swift index 5a847cf..19e965b 100644 --- a/Delta/Settings/Cores/SystemBIOS.swift +++ b/Delta/Settings/Cores/SystemBIOS.swift @@ -16,6 +16,7 @@ protocol SystemBIOS var filename: String { get } var expectedMD5Hash: String? { get } + var unsupportedMD5Hashes: Set { get } // RangeSet would be preferable, but it's not in Swift stdlib yet. @available(iOS 13, *) @@ -27,6 +28,14 @@ extension SystemBIOS var filename: String { return self.fileURL.lastPathComponent } + + var expectedMD5Hash: String? { + return nil + } + + var unsupportedMD5Hashes: Set { + return [] + } } enum DSBIOS: SystemBIOS, CaseIterable @@ -88,13 +97,25 @@ enum DSiBIOS: SystemBIOS, CaseIterable } } - var expectedMD5Hash: String? { + var unsupportedMD5Hashes: Set { switch self { - case .bios7: return "559dae4ea78eb9d67702c56c1d791e81" - case .bios9: return "87b665fce118f76251271c3732532777" - case .firmware: return nil - case .nand: return nil + case .bios7: + return [ + "c8b9fe70f1ef5cab8e55540cd1c13dc8", // BIOSDSI7.ROM + "3fbb3f39bd9a96e5d743f138bd4b9907", // BIOSDSI9.ROM + "87b665fce118f76251271c3732532777", // bios9i.bin + ] + + case .bios9: + return [ + "c8b9fe70f1ef5cab8e55540cd1c13dc8", // BIOSDSI7.ROM + "3fbb3f39bd9a96e5d743f138bd4b9907", // BIOSDSI9.ROM + "559dae4ea78eb9d67702c56c1d791e81", // bios7i.bin + ] + + case .firmware: return [] + case .nand: return [] } }