diff --git a/.gitmodules b/.gitmodules index 20f6bd2..9131605 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "External/Harmony"] path = External/Harmony url = https://github.com/rileytestut/Harmony.git +[submodule "Cores/NESDeltaCore"] + path = Cores/NESDeltaCore + url = git@github.com:rileytestut/NESDeltaCore.git \ No newline at end of file diff --git a/Cores/NESDeltaCore b/Cores/NESDeltaCore new file mode 160000 index 0000000..d83e51d --- /dev/null +++ b/Cores/NESDeltaCore @@ -0,0 +1 @@ +Subproject commit d83e51d06020045adc4403b9d77e604cf46e34f5 diff --git a/Delta.xcodeproj/project.pbxproj b/Delta.xcodeproj/project.pbxproj index 7071f1d..cb06da3 100644 --- a/Delta.xcodeproj/project.pbxproj +++ b/Delta.xcodeproj/project.pbxproj @@ -113,6 +113,8 @@ BF8DDD241F4F6C880088A21B /* InputCalloutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */; }; BF95E2771E4977BF0030E7AD /* GameMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF95E2761E4977BF0030E7AD /* GameMetadata.swift */; }; BF95E2791E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF95E2781E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift */; }; + BF98C9822204D9AB006B95AC /* NESDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF98C9812204D9A1006B95AC /* NESDeltaCore.framework */; }; + BF98C9832204D9AB006B95AC /* NESDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF98C9812204D9A1006B95AC /* NESDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; BF99A5971DC2F9C400468E9E /* ControllerSkinTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF99A5961DC2F9C400468E9E /* ControllerSkinTableViewCell.swift */; }; BF99C6941D0A9AA600BA92BC /* SNESDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; }; BF99C6951D0A9AA600BA92BC /* SNESDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFC134E01AAD82460087AD7B /* SNESDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -164,6 +166,7 @@ BFF0742D1E9DC17500ACDF4A /* GBCDeltaCore.framework in Embed Frameworks */, BFEC732E1AAECC4A00650035 /* Roxas.framework in Embed Frameworks */, BF0418151D01E93400E85BCF /* GBADeltaCore.framework in Embed Frameworks */, + BF98C9832204D9AB006B95AC /* NESDeltaCore.framework in Embed Frameworks */, BF99C6951D0A9AA600BA92BC /* SNESDeltaCore.framework in Embed Frameworks */, BF072011219A3A9D00F05DA4 /* ZIPFoundation.framework in Embed Frameworks */, ); @@ -276,6 +279,7 @@ BF8DDD231F4F6C880088A21B /* InputCalloutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputCalloutView.swift; sourceTree = ""; }; BF95E2761E4977BF0030E7AD /* GameMetadata.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameMetadata.swift; sourceTree = ""; }; BF95E2781E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesDatabaseBrowserViewController.swift; sourceTree = ""; }; + BF98C9812204D9A1006B95AC /* NESDeltaCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = NESDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BF99A5961DC2F9C400468E9E /* ControllerSkinTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControllerSkinTableViewCell.swift; sourceTree = ""; }; BF9F4FCE1AAD7B87004C9500 /* DeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BFAA1FEC1B8AA4FA00495943 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; @@ -319,6 +323,7 @@ BFEC732D1AAECC4A00650035 /* Roxas.framework in Frameworks */, BF48F75B219A1F8A00BC2FC1 /* Harmony_Drive.framework in Frameworks */, BF99C6941D0A9AA600BA92BC /* SNESDeltaCore.framework in Frameworks */, + BF98C9822204D9AB006B95AC /* NESDeltaCore.framework in Frameworks */, BF0418141D01E93400E85BCF /* GBADeltaCore.framework in Frameworks */, BF072010219A3A9D00F05DA4 /* ZIPFoundation.framework in Frameworks */, BFF0742C1E9DC17500ACDF4A /* GBCDeltaCore.framework in Frameworks */, @@ -612,6 +617,7 @@ BF9F4FCD1AAD7B25004C9500 /* Frameworks */ = { isa = PBXGroup; children = ( + BF98C9812204D9A1006B95AC /* NESDeltaCore.framework */, BF07200E219A3A9500F05DA4 /* ZIPFoundation.framework */, BF48F754219A1EEB00BC2FC1 /* Harmony.framework */, BF48F75A219A1F8300BC2FC1 /* Harmony_Drive.framework */, diff --git a/Delta.xcodeproj/xcshareddata/xcschemes/Delta.xcscheme b/Delta.xcodeproj/xcshareddata/xcschemes/Delta.xcscheme index 8750c29..dd0b06f 100644 --- a/Delta.xcodeproj/xcshareddata/xcschemes/Delta.xcscheme +++ b/Delta.xcodeproj/xcshareddata/xcschemes/Delta.xcscheme @@ -42,10 +42,10 @@ buildForAnalyzing = "YES"> + BlueprintIdentifier = "BF3C12F220438F3F0079A4B5" + BuildableName = "NESDeltaCore.framework" + BlueprintName = "NESDeltaCore" + ReferencedContainer = "container:Cores/NESDeltaCore/NESDeltaCore.xcodeproj"> + BlueprintIdentifier = "BF9F4FDB1AAD8070004C9500" + BuildableName = "SNESDeltaCore.framework" + BlueprintName = "SNESDeltaCore" + ReferencedContainer = "container:Cores/SNESDeltaCore/SNESDeltaCore.xcodeproj"> - - - - + BlueprintIdentifier = "BFE8E9C91D010AF7009D623D" + BuildableName = "GBADeltaCore.framework" + BlueprintName = "GBADeltaCore" + ReferencedContainer = "container:Cores/GBADeltaCore/GBADeltaCore.xcodeproj"> + + + location = "group:Cores/GBCDeltaCore/GBCDeltaCore.xcodeproj"> + location = "group:Cores/GBADeltaCore/GBADeltaCore.xcodeproj"> diff --git a/Delta/AppDelegate.swift b/Delta/AppDelegate.swift index 4ad9156..81b47ad 100644 --- a/Delta/AppDelegate.swift +++ b/Delta/AppDelegate.swift @@ -26,7 +26,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate Settings.registerDefaults() - System.supportedSystems.forEach { Delta.register($0.deltaCore) } + System.allCases.forEach { Delta.register($0.deltaCore) } self.configureAppearance() diff --git a/Delta/Base.lproj/Settings.storyboard b/Delta/Base.lproj/Settings.storyboard index b3670ac..e051d36 100644 --- a/Delta/Base.lproj/Settings.storyboard +++ b/Delta/Base.lproj/Settings.storyboard @@ -178,12 +178,29 @@ + + + + + + + + + + + - + diff --git a/Delta/Database/DatabaseManager.swift b/Delta/Database/DatabaseManager.swift index 7c5054e..e10248d 100644 --- a/Delta/Database/DatabaseManager.swift +++ b/Delta/Database/DatabaseManager.swift @@ -143,7 +143,7 @@ private extension DatabaseManager self.performBackgroundTask { (context) in - for system in System.supportedSystems + for system in System.allCases { guard let deltaControllerSkin = DeltaCore.ControllerSkin.standardControllerSkin(for: system.gameType) else { continue } diff --git a/Delta/Extensions/DeltaCoreProtocol+Delta.swift b/Delta/Extensions/DeltaCoreProtocol+Delta.swift index a11418a..d6a1bf0 100644 --- a/Delta/Extensions/DeltaCoreProtocol+Delta.swift +++ b/Delta/Extensions/DeltaCoreProtocol+Delta.swift @@ -15,9 +15,10 @@ extension DeltaCoreProtocol switch system { + case .nes: return 1...4 case .snes: return 1...4 - case .gba: return 1...3 case .gbc: return 1...4 + case .gba: return 1...3 } } } diff --git a/Delta/Extensions/Input+Display.swift b/Delta/Extensions/Input+Display.swift index 6629abb..c35c32f 100644 --- a/Delta/Extensions/Input+Display.swift +++ b/Delta/Extensions/Input+Display.swift @@ -35,6 +35,28 @@ extension Input case .rightTrigger: return 500 default: break } + + case .controller(.keyboard): + let input = KeyboardGameController.Input(input: self)! + + if input == .escape + { + // The iPad Smart Keyboard doesn't have an escape key, so return lower priority + // to ensure it only appears if there is no other key mapped to the same input. + return 100 + } + + // We prefer to display keys with special characters (e.g. arrow keys, shift) over regular keys. + // If the input's localizedName == it's string value, we can assume it's a normal key, and return a lower priority. + // Otherwise, it has a special display character, and so we return a higher priority. + if input.localizedName == input.stringValue.uppercased() + { + return 500 + } + else + { + return 1000 + } default: break } diff --git a/Delta/Game Selection/GamesViewController.swift b/Delta/Game Selection/GamesViewController.swift index 3eecdc3..873a1c7 100644 --- a/Delta/Game Selection/GamesViewController.swift +++ b/Delta/Game Selection/GamesViewController.swift @@ -311,7 +311,7 @@ extension GamesViewController: ImportControllerDelegate { @IBAction private func importFiles() { - var documentTypes = Set(System.supportedSystems.map { $0.gameType.rawValue }) + var documentTypes = Set(System.allCases.map { $0.gameType.rawValue }) documentTypes.insert(kUTTypeZipArchive as String) // Add GBA4iOS's exported UTIs in case user has GBA4iOS installed (which may override Delta's UTI declarations) diff --git a/Delta/Settings/Controllers/ControllerInputsViewController.swift b/Delta/Settings/Controllers/ControllerInputsViewController.swift index 6a1a137..90436d9 100644 --- a/Delta/Settings/Controllers/ControllerInputsViewController.swift +++ b/Delta/Settings/Controllers/ControllerInputsViewController.swift @@ -21,7 +21,7 @@ class ControllerInputsViewController: UIViewController } } - var system: System = .snes { + var system: System = System.allCases[0] { didSet { guard self.system != oldValue else { return } self.updateSystem() @@ -167,7 +167,7 @@ private extension ControllerInputsViewController let popoverMenuController = PopoverMenuController(popoverViewController: navigationController) self.navigationItem.popoverMenuController = popoverMenuController - let items = System.supportedSystems.map { [unowned self, weak popoverMenuController, weak listMenuViewController] system -> MenuItem in + let items = System.allCases.map { [unowned self, weak popoverMenuController, weak listMenuViewController] system -> MenuItem in let item = MenuItem(text: system.localizedShortName, image: #imageLiteral(resourceName: "CheatCodes")) { [weak popoverMenuController, weak listMenuViewController] item in listMenuViewController?.items.forEach { $0.isSelected = ($0 == item) } popoverMenuController?.isActive = false diff --git a/Delta/Settings/Controllers/ControllersSettingsViewController.swift b/Delta/Settings/Controllers/ControllersSettingsViewController.swift index 031cd93..b1f703b 100644 --- a/Delta/Settings/Controllers/ControllersSettingsViewController.swift +++ b/Delta/Settings/Controllers/ControllersSettingsViewController.swift @@ -106,7 +106,6 @@ extension ControllersSettingsViewController case "controllerInputsSegue": let controllerInputsViewController = (segue.destination as! UINavigationController).topViewController as! ControllerInputsViewController controllerInputsViewController.gameController = self.gameController - controllerInputsViewController.system = .snes default: break } diff --git a/Delta/Settings/Settings.swift b/Delta/Settings/Settings.swift index 048ba2d..72f1584 100644 --- a/Delta/Settings/Settings.swift +++ b/Delta/Settings/Settings.swift @@ -198,9 +198,10 @@ private extension Settings switch system { + case .nes: systemName = "nes" case .snes: systemName = "snes" - case .gba: systemName = "gba" case .gbc: systemName = "gbc" + case .gba: systemName = "gba" } let orientation: String diff --git a/Delta/Settings/SettingsViewController.swift b/Delta/Settings/SettingsViewController.swift index 3927d46..ccb782e 100644 --- a/Delta/Settings/SettingsViewController.swift +++ b/Delta/Settings/SettingsViewController.swift @@ -28,14 +28,7 @@ private extension SettingsViewController case controllers = "controllersSegue" case controllerSkins = "controllerSkinsSegue" } - - enum ControllerSkinsRow: Int - { - case snes - case gba - case gbc - } - + enum SyncingRow: Int, CaseIterable { case service @@ -125,13 +118,8 @@ class SettingsViewController: UITableViewController case Segue.controllerSkins: let systemControllerSkinsViewController = segue.destination as! SystemControllerSkinsViewController - let row = ControllerSkinsRow(rawValue: indexPath.row)! - switch row - { - case .snes: systemControllerSkinsViewController.system = .snes - case .gba: systemControllerSkinsViewController.system = .gba - case .gbc: systemControllerSkinsViewController.system = .gbc - } + let system = System.allCases[indexPath.row] + systemControllerSkinsViewController.system = system } } } @@ -244,7 +232,7 @@ extension SettingsViewController switch section { case .controllers: return 1 // Temporarily hide other controller indexes until controller logic is finalized - case .controllerSkins: return System.supportedSystems.count + case .controllerSkins: return System.allCases.count default: if isSectionHidden(section) { @@ -279,7 +267,7 @@ extension SettingsViewController cell.detailTextLabel?.text = nil } - case .controllerSkins: cell.textLabel?.text = System.supportedSystems[indexPath.row].localizedName + case .controllerSkins: cell.textLabel?.text = System.allCases[indexPath.row].localizedName case .syncing: switch SyncingRow.allCases[indexPath.row] { diff --git a/Delta/Systems/System.swift b/Delta/Systems/System.swift index 3cb147a..ea55b13 100644 --- a/Delta/Systems/System.swift +++ b/Delta/Systems/System.swift @@ -11,30 +11,14 @@ import DeltaCore import SNESDeltaCore import GBADeltaCore import GBCDeltaCore +import NESDeltaCore -extension GameType -{ - init?(fileExtension: String) - { - switch fileExtension.lowercased() - { - case "smc", "sfc", "fig": self = .snes - case "gba": self = .gba - case "gbc", "gb": self = .gbc - default: return nil - } - } -} - -enum System +enum System: CaseIterable { + case nes case snes - case gba case gbc - - static var supportedSystems: [System] { - return [.snes, .gba, .gbc] - } + case gba } extension System @@ -42,27 +26,30 @@ extension System var localizedName: String { switch self { + case .nes: return NSLocalizedString("Nintendo", comment: "") case .snes: return NSLocalizedString("Super Nintendo", comment: "") - case .gba: return NSLocalizedString("Game Boy Advance", comment: "") case .gbc: return NSLocalizedString("Game Boy Color", comment: "") + case .gba: return NSLocalizedString("Game Boy Advance", comment: "") } } var localizedShortName: String { switch self { + case .nes: return NSLocalizedString("NES", comment: "") case .snes: return NSLocalizedString("SNES", comment: "") - case .gba: return NSLocalizedString("GBA", comment: "") case .gbc: return NSLocalizedString("GBC", comment: "") + case .gba: return NSLocalizedString("GBA", comment: "") } } var year: Int { switch self { + case .nes: return 1985 case .snes: return 1990 - case .gba: return 2001 case .gbc: return 1998 + case .gba: return 2001 } } } @@ -72,21 +59,20 @@ extension System var deltaCore: DeltaCoreProtocol { switch self { + case .nes: return NES.core case .snes: return SNES.core - case .gba: return GBA.core case .gbc: return GBC.core + case .gba: return GBA.core } } -} - -extension System -{ + var gameType: GameType { switch self { + case .nes: return .nes case .snes: return .snes - case .gba: return .gba case .gbc: return .gbc + case .gba: return .gba } } @@ -94,9 +80,25 @@ extension System { switch gameType { + case GameType.nes: self = .nes case GameType.snes: self = .snes - case GameType.gba: self = .gba case GameType.gbc: self = .gbc + case GameType.gba: self = .gba + default: return nil + } + } +} + +extension GameType +{ + init?(fileExtension: String) + { + switch fileExtension.lowercased() + { + case "nes": self = .nes + case "smc", "sfc", "fig": self = .snes + case "gbc", "gb": self = .gbc + case "gba": self = .gba default: return nil } }