From f6e0467fe10543b0763233d723881d474047eeb2 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Tue, 1 Aug 2017 02:02:49 -0400 Subject: [PATCH] how hard can bolting Apple II onto this be? --- FruitMachine.xcodeproj/project.pbxproj | 98 ++++++++++++++++--- FruitMachine/AppleI/AppleI.swift | 26 ++--- FruitMachine/AppleI/AppleIBitmapDisplay.swift | 4 +- ...creenView.swift => AppleIScreenView.swift} | 2 +- FruitMachine/AppleI/PIAOverrides.swift | 62 ++++++++++++ .../AppleI/Video/A1CharacterGenerator.swift | 71 ++++++++++++++ .../AppleI/Video/CharacterGenerator.swift | 75 -------------- FruitMachine/AppleI/Video/PIAOverrides.swift | 58 ----------- FruitMachine/AppleI/Video/Terminal.swift | 96 +++++++++--------- FruitMachine/AppleII/AppleII.swift | 67 +++++++++++++ .../AppleII/Video/A2CharacterGenerator.swift | 70 +++++++++++++ .../AppleII/Video/ScreenDelegate.swift | 19 ++++ FruitMachine/AppleII/Video/ScreenView.swift | 37 +++++++ FruitMachine/AppleIIViewController.swift | 52 ++++++++++ ...oller.swift => AppleIViewController.swift} | 2 +- FruitMachine/Common/EmulatedSystem.swift | 18 ++++ .../{AppleI => Common/Peripherals}/PIA.swift | 0 .../Video/BitmapPixels.swift | 0 FruitMachine/Common/Video/Glyph.swift | 17 ++++ FruitMachine/FruitMachine.storyboard | 4 +- 20 files changed, 566 insertions(+), 212 deletions(-) rename FruitMachine/AppleI/{AppleScreenView.swift => AppleIScreenView.swift} (95%) create mode 100644 FruitMachine/AppleI/PIAOverrides.swift create mode 100644 FruitMachine/AppleI/Video/A1CharacterGenerator.swift delete mode 100644 FruitMachine/AppleI/Video/CharacterGenerator.swift delete mode 100644 FruitMachine/AppleI/Video/PIAOverrides.swift create mode 100644 FruitMachine/AppleII/AppleII.swift create mode 100644 FruitMachine/AppleII/Video/A2CharacterGenerator.swift create mode 100644 FruitMachine/AppleII/Video/ScreenDelegate.swift create mode 100644 FruitMachine/AppleII/Video/ScreenView.swift create mode 100644 FruitMachine/AppleIIViewController.swift rename FruitMachine/{MainViewController.swift => AppleIViewController.swift} (97%) create mode 100644 FruitMachine/Common/EmulatedSystem.swift rename FruitMachine/{AppleI => Common/Peripherals}/PIA.swift (100%) rename FruitMachine/{AppleI => Common}/Video/BitmapPixels.swift (100%) create mode 100644 FruitMachine/Common/Video/Glyph.swift diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 9b97ff8..cc6052d 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -9,16 +9,23 @@ /* Begin PBXBuildFile section */ 2A2126841F2A9FA300E43DC1 /* DebuggerWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */; }; 2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */; }; - 2A5BC5191F29A28D008C03BE /* AppleScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */; }; + 2A5BC5191F29A28D008C03BE /* AppleIScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC5181F29A28D008C03BE /* AppleIScreenView.swift */; }; 2A5BC51C1F29A2EB008C03BE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A5BC51B1F29A2EB008C03BE /* QuartzCore.framework */; }; 2A5BC51E1F29A4C3008C03BE /* AppleIBitmapDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5BC51D1F29A4C3008C03BE /* AppleIBitmapDisplay.swift */; }; + 2A5C5BBC1F304C3A00ED351D /* A2CharacterGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */; }; + 2A5C5BBE1F304D4B00ED351D /* Glyph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C5BBD1F304D4B00ED351D /* Glyph.swift */; }; 2A60851E1F2AFAE900E05B64 /* PIA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A60851D1F2AFAE900E05B64 /* PIA.swift */; }; + 2A6DC7E91F3045280066FE0D /* AppleIIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7E81F3045280066FE0D /* AppleIIViewController.swift */; }; + 2A6DC7EB1F3045C90066FE0D /* EmulatedSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */; }; + 2A6DC7ED1F30492C0066FE0D /* ScreenDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */; }; + 2A6DC7F01F30495D0066FE0D /* ScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */; }; 2A7665781F2F05F600135518 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A7665761F2F05F600135518 /* PreferencesWindowController.swift */; }; 2A7665791F2F05F600135518 /* PreferencesWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A7665771F2F05F600135518 /* PreferencesWindow.xib */; }; 2A91852A1F2EA84D00A9E5BE /* BitmapPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */; }; 2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5F71F2A8889002B350F /* AppleI.swift */; }; 2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */; }; 2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */; }; + 2AB6CACD1F3041A200DECAC0 /* AppleII.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB6CACC1F3041A200DECAC0 /* AppleII.swift */; }; 2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CD1F205EB700F05121 /* AppDelegate.swift */; }; 2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */; }; 2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; }; @@ -31,9 +38,9 @@ 2AE42E081F2850F400C4900E /* ReadOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E071F2850F400C4900E /* ReadOverride.swift */; }; 2AE42E0A1F28521E00C4900E /* WriteOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E091F28521E00C4900E /* WriteOverride.swift */; }; 2AE42E0C1F28522D00C4900E /* MemoryOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E0B1F28522D00C4900E /* MemoryOverride.swift */; }; - 2AE42E3A1F28628300C4900E /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E381F28628300C4900E /* MainViewController.swift */; }; + 2AE42E3A1F28628300C4900E /* AppleIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E381F28628300C4900E /* AppleIViewController.swift */; }; 2AE42E401F28638100C4900E /* FruitMachine.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AE42E3F1F28638100C4900E /* FruitMachine.storyboard */; }; - 2AE42E431F28665300C4900E /* CharacterGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E421F28665300C4900E /* CharacterGenerator.swift */; }; + 2AE42E431F28665300C4900E /* A1CharacterGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE42E421F28665300C4900E /* A1CharacterGenerator.swift */; }; 2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */; }; 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */; }; /* End PBXBuildFile section */ @@ -41,16 +48,23 @@ /* Begin PBXFileReference section */ 2A2126831F2A9FA300E43DC1 /* DebuggerWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerWindowController.swift; sourceTree = ""; }; 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerExtensions.swift; sourceTree = ""; }; - 2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleScreenView.swift; sourceTree = ""; }; + 2A5BC5181F29A28D008C03BE /* AppleIScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIScreenView.swift; sourceTree = ""; }; 2A5BC51B1F29A2EB008C03BE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 2A5BC51D1F29A4C3008C03BE /* AppleIBitmapDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIBitmapDisplay.swift; sourceTree = ""; }; + 2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = A2CharacterGenerator.swift; sourceTree = ""; }; + 2A5C5BBD1F304D4B00ED351D /* Glyph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Glyph.swift; sourceTree = ""; }; 2A60851D1F2AFAE900E05B64 /* PIA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIA.swift; sourceTree = ""; }; + 2A6DC7E81F3045280066FE0D /* AppleIIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIIViewController.swift; sourceTree = ""; }; + 2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmulatedSystem.swift; sourceTree = ""; }; + 2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenDelegate.swift; sourceTree = ""; }; + 2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenView.swift; sourceTree = ""; }; 2A7665761F2F05F600135518 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = ""; }; 2A7665771F2F05F600135518 /* PreferencesWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PreferencesWindow.xib; sourceTree = ""; }; 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitmapPixels.swift; sourceTree = ""; }; 2AA8B5F71F2A8889002B350F /* AppleI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleI.swift; sourceTree = ""; }; 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Terminal.swift; sourceTree = ""; }; 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PIAOverrides.swift; sourceTree = ""; }; + 2AB6CACC1F3041A200DECAC0 /* AppleII.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleII.swift; sourceTree = ""; }; 2AD458CA1F205EB700F05121 /* FruitMachine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FruitMachine.app; sourceTree = BUILT_PRODUCTS_DIR; }; 2AD458CD1F205EB700F05121 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerViewController.swift; sourceTree = ""; }; @@ -66,9 +80,9 @@ 2AE42E071F2850F400C4900E /* ReadOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadOverride.swift; sourceTree = ""; }; 2AE42E091F28521E00C4900E /* WriteOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteOverride.swift; sourceTree = ""; }; 2AE42E0B1F28522D00C4900E /* MemoryOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryOverride.swift; sourceTree = ""; }; - 2AE42E381F28628300C4900E /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + 2AE42E381F28628300C4900E /* AppleIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleIViewController.swift; sourceTree = ""; }; 2AE42E3F1F28638100C4900E /* FruitMachine.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = FruitMachine.storyboard; sourceTree = ""; }; - 2AE42E421F28665300C4900E /* CharacterGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterGenerator.swift; sourceTree = ""; }; + 2AE42E421F28665300C4900E /* A1CharacterGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = A1CharacterGenerator.swift; sourceTree = ""; }; 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disassembly.swift; sourceTree = ""; }; 2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressConversions.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -93,18 +107,64 @@ name = Frameworks; sourceTree = ""; }; + 2A6DC7E51F3043DB0066FE0D /* Common */ = { + isa = PBXGroup; + children = ( + 2A6DC7E71F3044080066FE0D /* Peripherals */, + 2A6DC7E61F3043E10066FE0D /* Video */, + 2A6DC7EA1F3045C90066FE0D /* EmulatedSystem.swift */, + ); + path = Common; + sourceTree = ""; + }; + 2A6DC7E61F3043E10066FE0D /* Video */ = { + isa = PBXGroup; + children = ( + 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */, + 2A5C5BBD1F304D4B00ED351D /* Glyph.swift */, + ); + path = Video; + sourceTree = ""; + }; + 2A6DC7E71F3044080066FE0D /* Peripherals */ = { + isa = PBXGroup; + children = ( + 2A60851D1F2AFAE900E05B64 /* PIA.swift */, + ); + path = Peripherals; + sourceTree = ""; + }; + 2A6DC7EE1F30492E0066FE0D /* Video */ = { + isa = PBXGroup; + children = ( + 2A5C5BBB1F304C3A00ED351D /* A2CharacterGenerator.swift */, + 2A6DC7EC1F30492C0066FE0D /* ScreenDelegate.swift */, + 2A6DC7EF1F30495D0066FE0D /* ScreenView.swift */, + ); + path = Video; + sourceTree = ""; + }; 2AA8B5F61F2A8844002B350F /* AppleI */ = { isa = PBXGroup; children = ( 2AE42E411F28663600C4900E /* Video */, - 2A5BC5181F29A28D008C03BE /* AppleScreenView.swift */, + 2A5BC5181F29A28D008C03BE /* AppleIScreenView.swift */, 2A5BC51D1F29A4C3008C03BE /* AppleIBitmapDisplay.swift */, 2AA8B5F71F2A8889002B350F /* AppleI.swift */, - 2A60851D1F2AFAE900E05B64 /* PIA.swift */, + 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */, ); path = AppleI; sourceTree = ""; }; + 2AB6CAC71F30407200DECAC0 /* AppleII */ = { + isa = PBXGroup; + children = ( + 2A6DC7EE1F30492E0066FE0D /* Video */, + 2AB6CACC1F3041A200DECAC0 /* AppleII.swift */, + ); + path = AppleII; + sourceTree = ""; + }; 2AD458C11F205EB700F05121 = { isa = PBXGroup; children = ( @@ -125,10 +185,13 @@ 2AD458CC1F205EB700F05121 /* FruitMachine */ = { isa = PBXGroup; children = ( + 2A6DC7E51F3043DB0066FE0D /* Common */, 2AA8B5F61F2A8844002B350F /* AppleI */, + 2AB6CAC71F30407200DECAC0 /* AppleII */, 2AD458DD1F205F0D00F05121 /* M6502 */, 2AD458CD1F205EB700F05121 /* AppDelegate.swift */, - 2AE42E381F28628300C4900E /* MainViewController.swift */, + 2AE42E381F28628300C4900E /* AppleIViewController.swift */, + 2A6DC7E81F3045280066FE0D /* AppleIIViewController.swift */, 2AE42E3F1F28638100C4900E /* FruitMachine.storyboard */, 2A7665761F2F05F600135518 /* PreferencesWindowController.swift */, 2A7665771F2F05F600135518 /* PreferencesWindow.xib */, @@ -195,9 +258,7 @@ 2AE42E411F28663600C4900E /* Video */ = { isa = PBXGroup; children = ( - 2A9185291F2EA84D00A9E5BE /* BitmapPixels.swift */, - 2AE42E421F28665300C4900E /* CharacterGenerator.swift */, - 2AA8B5FD1F2A942C002B350F /* PIAOverrides.swift */, + 2AE42E421F28665300C4900E /* A1CharacterGenerator.swift */, 2AA8B5FB1F2A8EAD002B350F /* Terminal.swift */, ); path = Video; @@ -276,29 +337,36 @@ buildActionMask = 2147483647; files = ( 2A60851E1F2AFAE900E05B64 /* PIA.swift in Sources */, + 2A5C5BBE1F304D4B00ED351D /* Glyph.swift in Sources */, 2A2126841F2A9FA300E43DC1 /* DebuggerWindowController.swift in Sources */, 2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */, + 2A5C5BBC1F304C3A00ED351D /* A2CharacterGenerator.swift in Sources */, 2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */, 2A7665781F2F05F600135518 /* PreferencesWindowController.swift in Sources */, 2AA8B5FC1F2A8EAD002B350F /* Terminal.swift in Sources */, 2A5BC51E1F29A4C3008C03BE /* AppleIBitmapDisplay.swift in Sources */, 2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */, 2A91852A1F2EA84D00A9E5BE /* BitmapPixels.swift in Sources */, - 2AE42E431F28665300C4900E /* CharacterGenerator.swift in Sources */, + 2AE42E431F28665300C4900E /* A1CharacterGenerator.swift in Sources */, + 2A6DC7F01F30495D0066FE0D /* ScreenView.swift in Sources */, 2AE42E0C1F28522D00C4900E /* MemoryOverride.swift in Sources */, 2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */, 2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */, 2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */, - 2AE42E3A1F28628300C4900E /* MainViewController.swift in Sources */, + 2A6DC7EB1F3045C90066FE0D /* EmulatedSystem.swift in Sources */, + 2AE42E3A1F28628300C4900E /* AppleIViewController.swift in Sources */, 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */, 2AE42E081F2850F400C4900E /* ReadOverride.swift in Sources */, 2AA8B5FE1F2A942C002B350F /* PIAOverrides.swift in Sources */, + 2AB6CACD1F3041A200DECAC0 /* AppleII.swift in Sources */, 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */, 2AE42E0A1F28521E00C4900E /* WriteOverride.swift in Sources */, - 2A5BC5191F29A28D008C03BE /* AppleScreenView.swift in Sources */, + 2A6DC7ED1F30492C0066FE0D /* ScreenDelegate.swift in Sources */, + 2A5BC5191F29A28D008C03BE /* AppleIScreenView.swift in Sources */, 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */, 2AA8B5F81F2A8889002B350F /* AppleI.swift in Sources */, 2AD458DF1F205F4500F05121 /* CPU.swift in Sources */, + 2A6DC7E91F3045280066FE0D /* AppleIIViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FruitMachine/AppleI/AppleI.swift b/FruitMachine/AppleI/AppleI.swift index ddc9f6b..dcae11b 100644 --- a/FruitMachine/AppleI/AppleI.swift +++ b/FruitMachine/AppleI/AppleI.swift @@ -8,10 +8,14 @@ import Cocoa -class AppleI: NSObject { - static let sharedInstance = AppleI() +class AppleI: NSObject, EmulatedSystem { + var CPU_FREQUENCY: Double + var FRAMES_PER_SECOND: Double + var CYCLES_PER_BATCH: Int - let cg = CharacterGenerator(romPath: "/Users/luigi/apple1/apple1.vid"); + static let sharedInstance = AppleI(cpuFrequency: 1000000.0, fps: 60.0) + + let cg = A1CharacterGenerator(romPath: "/Users/luigi/apple1/apple1.vid"); let terminal = Terminal() let pia: [String:PIA] = [ @@ -20,14 +24,13 @@ class AppleI: NSObject { ] let emulatorViewDelegate = AppleIBitmapDisplay() - let emulatorView = AppleScreenView(frame: NSMakeRect(0, 0, 640, 384)) + let emulatorView = AppleIScreenView(frame: NSMakeRect(0, 0, 640, 384)) let emuScreenLayer = CALayer() - static let CPU_FREQUENCY = 1000000 - static let FRAMES_PER_SECOND = 60 - static let CYCLES_PER_BATCH = CPU_FREQUENCY / FRAMES_PER_SECOND - - override init() { + required init(cpuFrequency: Double, fps: Double) { + CPU_FREQUENCY = cpuFrequency + FRAMES_PER_SECOND = fps + CYCLES_PER_BATCH = Int(cpuFrequency / fps) super.init() emuScreenLayer.shouldRasterize = true @@ -35,7 +38,7 @@ class AppleI: NSObject { emuScreenLayer.frame = emulatorView.bounds emulatorView.wantsLayer = true - + emuScreenLayer.setNeedsDisplay() emulatorView.layer?.addSublayer(emuScreenLayer) @@ -44,7 +47,6 @@ class AppleI: NSObject { CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00, length: 0x100) CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/basic.bin", offset: 0xE000, length: 0x1000) CPU.sharedInstance.performReset() - } func installOverrides() { @@ -59,7 +61,7 @@ class AppleI: NSObject { func runFrame() { CPU.sharedInstance.cycles = 0 - CPU.sharedInstance.cyclesInBatch = AppleI.CYCLES_PER_BATCH + CPU.sharedInstance.cyclesInBatch = AppleI.sharedInstance.CYCLES_PER_BATCH CPU.sharedInstance.runCyclesBatch() //update the video display diff --git a/FruitMachine/AppleI/AppleIBitmapDisplay.swift b/FruitMachine/AppleI/AppleIBitmapDisplay.swift index a10277f..9c0cf29 100644 --- a/FruitMachine/AppleI/AppleIBitmapDisplay.swift +++ b/FruitMachine/AppleI/AppleIBitmapDisplay.swift @@ -46,7 +46,7 @@ class AppleIBitmapDisplay: NSObject, CALayerDelegate { //Calculate the offset to reach the desired position. let baseOffset = scanlineOffsets[Int(pixelPosition.y)] + Int(pixelPosition.x) - for charY in 0.. CGPoint { - return getPixelOffset(charCellX: charCellIndex % Terminal.CELLS_WIDTH, charCellY: charCellIndex / Terminal.CELLS_WIDTH) + return getPixelOffset(charCellX: charCellIndex % AppleI.Terminal.CELLS_WIDTH, charCellY: charCellIndex / AppleI.Terminal.CELLS_WIDTH) } /* Draw the screen. */ diff --git a/FruitMachine/AppleI/AppleScreenView.swift b/FruitMachine/AppleI/AppleIScreenView.swift similarity index 95% rename from FruitMachine/AppleI/AppleScreenView.swift rename to FruitMachine/AppleI/AppleIScreenView.swift index 3b74d1b..be1891d 100644 --- a/FruitMachine/AppleI/AppleScreenView.swift +++ b/FruitMachine/AppleI/AppleIScreenView.swift @@ -8,7 +8,7 @@ import Cocoa -class AppleScreenView: NSView { +class AppleIScreenView: NSView { override var acceptsFirstResponder: Bool { return true diff --git a/FruitMachine/AppleI/PIAOverrides.swift b/FruitMachine/AppleI/PIAOverrides.swift new file mode 100644 index 0000000..9217a53 --- /dev/null +++ b/FruitMachine/AppleI/PIAOverrides.swift @@ -0,0 +1,62 @@ +// +// Overrides.swift +// FruitMachine +// +// Created by Christopher Rohl on 7/27/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +extension AppleI { + + class PIAOverrides: NSObject { + static let writeDSP = WriteOverride(start: 0xD012, end: 0xD012, writeAnyway: false, action: PIAOverrides.actionWriteDSP) + static func actionWriteDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? { + + let pia = AppleI.sharedInstance.pia["display"]! + + if(pia.getMode() == .Output) { + //Writing to DSP sets DSP.7 + AppleI.sharedInstance.pia["display"]!.data = byte! | 0x80 + + //Output our character to the terminal + AppleI.sharedInstance.terminal.putCharacter(charIndex: byte!) + + AppleI.sharedInstance.pia["display"]!.data = byte! & ~(0x80) + } + return nil + } + + static let writeDSPCR = WriteOverride(start: 0xD013, end: 0xD013, writeAnyway: false, action: PIAOverrides.actionWriteDSPCR) + static func actionWriteDSPCR(terminal: AnyObject, byte: UInt8?) -> UInt8? { + AppleI.sharedInstance.pia["display"]?.control = byte! + return nil + } + + static let readDSP = ReadOverride(start: 0xD012, end: 0xD012, readAnyway: false, action: PIAOverrides.actionReadDSP) + static func actionReadDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? { + + //DSP.7 is unset when the character is accepted by the terminal + return AppleI.sharedInstance.pia["display"]!.data + } + /* */ + + static let readKBDCR = ReadOverride(start: 0xD011, end: 0xD011, readAnyway: false, action: PIAOverrides.actionReadKBDCR) + static func actionReadKBDCR(terminal: AnyObject, byte: UInt8?) -> UInt8? { + return AppleI.sharedInstance.pia["keyboard"]!.control + } + + /* */ + static let readKBD = ReadOverride(start: 0xD010, end: 0xD010, readAnyway: false, action: PIAOverrides.actionReadKBD) + static func actionReadKBD(terminal: AnyObject, byte: UInt8?) -> UInt8? { + //Reading KBD clears KBDCR.7 + AppleI.sharedInstance.pia["keyboard"]!.control = AppleI.sharedInstance.pia["keyboard"]!.control & ~(0x80) + + //KBD.7 is tied to +5V + return AppleI.sharedInstance.pia["keyboard"]!.data | 0x80 + } + + } + +} diff --git a/FruitMachine/AppleI/Video/A1CharacterGenerator.swift b/FruitMachine/AppleI/Video/A1CharacterGenerator.swift new file mode 100644 index 0000000..293da6a --- /dev/null +++ b/FruitMachine/AppleI/Video/A1CharacterGenerator.swift @@ -0,0 +1,71 @@ +// +// CharacterGenerator.swift +// FruitMachine +// +// Created by Christopher Rohl on 7/26/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +//The character generator ROM contains 64 8x5 glyphs. + +extension AppleI { + + class A1CharacterGenerator: NSObject { + static let CHAR_WIDTH = 5 + static let CHAR_HEIGHT = 8 + + var ROM: [UInt8] + var glyphs: [Glyph] + + init(romPath: String) { + ROM = [UInt8](repeating: 0xCC, count: 512) + glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsBE555.PixelData]()), count: 64) + + super.init() + loadROM(path: romPath) + + for index in 0..<64 { + glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index))) + } + } + + private func loadROM(path: String) { + do { + let fileContent: NSData = try NSData(contentsOfFile: path) + fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 512)) + } catch { + print(error) + } + } + + private func getCharacterPixels(charIndex: UInt8) -> [BitmapPixelsBE555.PixelData] { + var pixelArray = [UInt8](repeating: 0x00, count: A1CharacterGenerator.CHAR_HEIGHT) + + /* Instead of ignoring ASCII bit b6, we ignore bit b5. At the same time ASCII bit b6 must be inverted before it is fed to the character ROM. This way the entire character range from $40 to $7F will end up in the range $00 to $1F (twice of course). Now lower case characters are automatically translated into their corresponding upper case bit maps. + */ + + //Don't convert the character indexes if we're populating the glyphs array. + for scanlineIndex in 0.. 0 ? BitmapPixelsBE555.White : BitmapPixelsBE555.Black) + } + } + + return glyphPixels + } + + func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 { + return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1) + } + + } + +} diff --git a/FruitMachine/AppleI/Video/CharacterGenerator.swift b/FruitMachine/AppleI/Video/CharacterGenerator.swift deleted file mode 100644 index 1618bcd..0000000 --- a/FruitMachine/AppleI/Video/CharacterGenerator.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// CharacterGenerator.swift -// FruitMachine -// -// Created by Christopher Rohl on 7/26/17. -// Copyright © 2017 Christopher Rohl. All rights reserved. -// - -import Cocoa - -//The character generator ROM contains 64 8x5 glyphs. - -struct Glyph { - var pixels: [BitmapPixelsBE555.PixelData] = [BitmapPixelsBE555.PixelData]() - - init(inPixels: [BitmapPixelsBE555.PixelData]) { - pixels = inPixels - } -} - -class CharacterGenerator: NSObject { - static let CHAR_WIDTH = 5 - static let CHAR_HEIGHT = 8 - - var ROM: [UInt8] - var glyphs: [Glyph] - - init(romPath: String) { - ROM = [UInt8](repeating: 0xCC, count: 512) - glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsBE555.PixelData]()), count: 64) - - super.init() - loadROM(path: romPath) - - for index in 0..<64 { - glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index))) - } - } - - private func loadROM(path: String) { - do { - let fileContent: NSData = try NSData(contentsOfFile: path) - fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 512)) - } catch { - print(error) - } - } - - private func getCharacterPixels(charIndex: UInt8) -> [BitmapPixelsBE555.PixelData] { - var pixelArray = [UInt8](repeating: 0x00, count: CharacterGenerator.CHAR_HEIGHT) - - /* Instead of ignoring ASCII bit b6, we ignore bit b5. At the same time ASCII bit b6 must be inverted before it is fed to the character ROM. This way the entire character range from $40 to $7F will end up in the range $00 to $1F (twice of course). Now lower case characters are automatically translated into their corresponding upper case bit maps. - */ - - //Don't convert the character indexes if we're populating the glyphs array. - for scanlineIndex in 0.. 0 ? BitmapPixelsBE555.White : BitmapPixelsBE555.Black) - } - } - - return glyphPixels - } - - func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 { - return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1) - } - -} diff --git a/FruitMachine/AppleI/Video/PIAOverrides.swift b/FruitMachine/AppleI/Video/PIAOverrides.swift deleted file mode 100644 index 8c0356a..0000000 --- a/FruitMachine/AppleI/Video/PIAOverrides.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// Overrides.swift -// FruitMachine -// -// Created by Christopher Rohl on 7/27/17. -// Copyright © 2017 Christopher Rohl. All rights reserved. -// - -import Cocoa - -class PIAOverrides: NSObject { - static let writeDSP = WriteOverride(start: 0xD012, end: 0xD012, writeAnyway: false, action: PIAOverrides.actionWriteDSP) - static func actionWriteDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? { - - let pia = AppleI.sharedInstance.pia["display"]! - - if(pia.getMode() == .Output) { - //Writing to DSP sets DSP.7 - AppleI.sharedInstance.pia["display"]!.data = byte! | 0x80 - - //Output our character to the terminal - AppleI.sharedInstance.terminal.putCharacter(charIndex: byte!) - - AppleI.sharedInstance.pia["display"]!.data = byte! & ~(0x80) - } - return nil - } - - static let writeDSPCR = WriteOverride(start: 0xD013, end: 0xD013, writeAnyway: false, action: PIAOverrides.actionWriteDSPCR) - static func actionWriteDSPCR(terminal: AnyObject, byte: UInt8?) -> UInt8? { - AppleI.sharedInstance.pia["display"]?.control = byte! - return nil - } - - static let readDSP = ReadOverride(start: 0xD012, end: 0xD012, readAnyway: false, action: PIAOverrides.actionReadDSP) - static func actionReadDSP(terminal: AnyObject, byte: UInt8?) -> UInt8? { - - //DSP.7 is unset when the character is accepted by the terminal - return AppleI.sharedInstance.pia["display"]!.data - } - /* */ - - static let readKBDCR = ReadOverride(start: 0xD011, end: 0xD011, readAnyway: false, action: PIAOverrides.actionReadKBDCR) - static func actionReadKBDCR(terminal: AnyObject, byte: UInt8?) -> UInt8? { - return AppleI.sharedInstance.pia["keyboard"]!.control - } - - /* */ - static let readKBD = ReadOverride(start: 0xD010, end: 0xD010, readAnyway: false, action: PIAOverrides.actionReadKBD) - static func actionReadKBD(terminal: AnyObject, byte: UInt8?) -> UInt8? { - //Reading KBD clears KBDCR.7 - AppleI.sharedInstance.pia["keyboard"]!.control = AppleI.sharedInstance.pia["keyboard"]!.control & ~(0x80) - - //KBD.7 is tied to +5V - return AppleI.sharedInstance.pia["keyboard"]!.data | 0x80 - } - -} diff --git a/FruitMachine/AppleI/Video/Terminal.swift b/FruitMachine/AppleI/Video/Terminal.swift index a5de04c..62a407a 100644 --- a/FruitMachine/AppleI/Video/Terminal.swift +++ b/FruitMachine/AppleI/Video/Terminal.swift @@ -8,42 +8,54 @@ import Cocoa -struct Cell { - var x: Int - var y: Int -} +extension AppleI { -class Terminal: NSObject { - static let CELLS_WIDTH = 40 - static let CELLS_HEIGHT = 24 - static let CELLS_COUNT = CELLS_WIDTH * CELLS_HEIGHT - - var cursorPosition: Cell - var characters: [UInt8] - - override init() { - cursorPosition = Cell(x: 0, y: 0) - characters = [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH * Terminal.CELLS_HEIGHT) + struct Cell { + var x: Int + var y: Int } - - func cellToIndex(cell: Cell) -> Int { - return (cell.y * Terminal.CELLS_WIDTH) + (cell.x % Terminal.CELLS_WIDTH) - } - - func putCharacter(charIndex: UInt8) { - if(charIndex == 0x8D) - { - carriageReturn() + + class Terminal: NSObject { + static let CELLS_WIDTH = 40 + static let CELLS_HEIGHT = 24 + static let CELLS_COUNT = CELLS_WIDTH * CELLS_HEIGHT + + var cursorPosition: Cell + var characters: [UInt8] + + override init() { + cursorPosition = Cell(x: 0, y: 0) + characters = [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH * Terminal.CELLS_HEIGHT) } - else { - characters[cellToIndex(cell: cursorPosition)] = charIndex - advanceCursor() + + func cellToIndex(cell: Cell) -> Int { + return (cell.y * Terminal.CELLS_WIDTH) + (cell.x % Terminal.CELLS_WIDTH) } - } - - func advanceCursor() { - cursorPosition.x += 1 - if(cursorPosition.x == Terminal.CELLS_WIDTH) { + + func putCharacter(charIndex: UInt8) { + if(charIndex == 0x8D) + { + carriageReturn() + } + else { + characters[cellToIndex(cell: cursorPosition)] = charIndex + advanceCursor() + } + } + + func advanceCursor() { + cursorPosition.x += 1 + if(cursorPosition.x == Terminal.CELLS_WIDTH) { + cursorPosition.x = 0 + cursorPosition.y += 1 + if(cursorPosition.y >= Terminal.CELLS_HEIGHT) { + cursorPosition.y = Terminal.CELLS_HEIGHT - 1 + scrollUp(lines: 1) + } + } + } + + func carriageReturn() { cursorPosition.x = 0 cursorPosition.y += 1 if(cursorPosition.y >= Terminal.CELLS_HEIGHT) { @@ -51,20 +63,12 @@ class Terminal: NSObject { scrollUp(lines: 1) } } - } - - func carriageReturn() { - cursorPosition.x = 0 - cursorPosition.y += 1 - if(cursorPosition.y >= Terminal.CELLS_HEIGHT) { - cursorPosition.y = Terminal.CELLS_HEIGHT - 1 - scrollUp(lines: 1) + + func scrollUp(lines: Int) { + let scrolled = characters[Terminal.CELLS_WIDTH ..< Terminal.CELLS_COUNT] + characters = [UInt8](scrolled) + characters.append(contentsOf: [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH)) } } - - func scrollUp(lines: Int) { - let scrolled = characters[Terminal.CELLS_WIDTH ..< Terminal.CELLS_COUNT] - characters = [UInt8](scrolled) - characters.append(contentsOf: [UInt8](repeating: 0x00, count: Terminal.CELLS_WIDTH)) - } + } diff --git a/FruitMachine/AppleII/AppleII.swift b/FruitMachine/AppleII/AppleII.swift new file mode 100644 index 0000000..b88866e --- /dev/null +++ b/FruitMachine/AppleII/AppleII.swift @@ -0,0 +1,67 @@ +// +// AppleII.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +class AppleII: NSObject, EmulatedSystem { + static let sharedInstance = AppleII(cpuFrequency: (14.31818 / 7 / 2) * 1000000, fps: 60.0) + + var CPU_FREQUENCY: Double + var FRAMES_PER_SECOND: Double + var CYCLES_PER_BATCH: Int + + let emulatorViewDelegate = AppleII.ScreenDelegate() + let emulatorView = AppleII.ScreenView(frame: NSMakeRect(0, 0, 640, 384)) + let emuScreenLayer = CALayer() + + required init(cpuFrequency: Double, fps: Double) { + CPU_FREQUENCY = cpuFrequency + FRAMES_PER_SECOND = fps + CYCLES_PER_BATCH = Int(cpuFrequency / fps) + super.init() + + loadROMs() + + /* + emuScreenLayer.shouldRasterize = true + emuScreenLayer.delegate = emulatorViewDelegate + emuScreenLayer.frame = emulatorView.bounds + + emulatorView.wantsLayer = true + + emuScreenLayer.setNeedsDisplay() + emulatorView.layer?.addSublayer(emuScreenLayer) + + installOverrides() + + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/apple1.rom", offset: 0xFF00, length: 0x100) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple1/basic.bin", offset: 0xE000, length: 0x1000) + CPU.sharedInstance.performReset() + */ + } + + func loadROMs() { + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0001-00.e0", offset: 0xE000, length: 0x800) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0002-00.e8", offset: 0xE800, length: 0x800) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0003-00.f0", offset: 0xF000, length: 0x800) + CPU.sharedInstance.memoryInterface.loadBinary(path: "/Users/luigi/apple2/341-0004-00.f8", offset: 0xF800, length: 0x800) + } + + func installOverrides() { + //TODO + } + + func runFrame() { + CPU.sharedInstance.cycles = 0 + CPU.sharedInstance.cyclesInBatch = CYCLES_PER_BATCH + CPU.sharedInstance.runCyclesBatch() + + //TODO + } + +} diff --git a/FruitMachine/AppleII/Video/A2CharacterGenerator.swift b/FruitMachine/AppleII/Video/A2CharacterGenerator.swift new file mode 100644 index 0000000..d0314d9 --- /dev/null +++ b/FruitMachine/AppleII/Video/A2CharacterGenerator.swift @@ -0,0 +1,70 @@ +// +// CharacterGenerator.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +extension AppleII { + + //The Apple II character generator is a clone of the Signetics 2513 from the Apple I. + + class A2CharacterGenerator: NSObject { + static let CHAR_WIDTH = 5 + static let CHAR_HEIGHT = 8 + + var ROM: [UInt8] + var glyphs: [Glyph] + + init(romPath: String) { + ROM = [UInt8](repeating: 0xCC, count: 0x800) + glyphs = [Glyph](repeating: Glyph(inPixels: [BitmapPixelsBE555.PixelData]()), count: 64) + + super.init() + loadROM(path: romPath) + + for index in 0..<64 { + glyphs[index] = Glyph(inPixels: getCharacterPixels(charIndex: UInt8(index))) + } + } + + private func getCharacterPixels(charIndex: UInt8) -> [BitmapPixelsBE555.PixelData] { + var pixelArray = [UInt8](repeating: 0x00, count: A2CharacterGenerator.CHAR_HEIGHT) + + /* Instead of ignoring ASCII bit b6, we ignore bit b5. At the same time ASCII bit b6 must be inverted before it is fed to the character ROM. This way the entire character range from $40 to $7F will end up in the range $00 to $1F (twice of course). Now lower case characters are automatically translated into their corresponding upper case bit maps. + */ + + //Don't convert the character indexes if we're populating the glyphs array. + for scanlineIndex in 0.. 0 ? BitmapPixelsBE555.White : BitmapPixelsBE555.Black) + } + } + + return glyphPixels + } + + func asciiToAppleCharIndex(ascii: UInt8) -> UInt8 { + return (ascii & 0x1f) | (((ascii ^ 0x40) & 0x40) >> 1) + } + + private func loadROM(path: String) { + do { + let fileContent: NSData = try NSData(contentsOfFile: path) + fileContent.getBytes(&ROM, range: NSRange(location: 0, length: 0x800)) + } catch { + print(error) + } + } + } + +} diff --git a/FruitMachine/AppleII/Video/ScreenDelegate.swift b/FruitMachine/AppleII/Video/ScreenDelegate.swift new file mode 100644 index 0000000..a5bd40e --- /dev/null +++ b/FruitMachine/AppleII/Video/ScreenDelegate.swift @@ -0,0 +1,19 @@ +// +// ScreenDelegate.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +extension AppleII { + + class ScreenDelegate: NSObject, CALayerDelegate { + static let PIXEL_WIDTH = 280 + static let PIXEL_HEIGHT = 192 + + } + +} diff --git a/FruitMachine/AppleII/Video/ScreenView.swift b/FruitMachine/AppleII/Video/ScreenView.swift new file mode 100644 index 0000000..1df41c5 --- /dev/null +++ b/FruitMachine/AppleII/Video/ScreenView.swift @@ -0,0 +1,37 @@ +// +// ScreenView.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +extension AppleII { + + class ScreenView: NSView { + + override var acceptsFirstResponder: Bool { + return true + } + + override func becomeFirstResponder() -> Bool { + return true + } + + override func resignFirstResponder() -> Bool { + return true + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + // Drawing code here. + + //layer?.sublayers![0].setNeedsDisplay() + //layer?.sublayers![0].display() + } + + } + +} diff --git a/FruitMachine/AppleIIViewController.swift b/FruitMachine/AppleIIViewController.swift new file mode 100644 index 0000000..7cce5b2 --- /dev/null +++ b/FruitMachine/AppleIIViewController.swift @@ -0,0 +1,52 @@ +// +// AppleIIViewController.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +class AppleIIViewController: NSViewController { + + let computer = AppleII.sharedInstance + var debuggerWindowController: DebuggerWindowController! + var preferencesWindowController: PreferencesWindowController! + + var isPaused = false + var frameTimer: Timer? + + override func viewDidLoad() { + super.viewDidLoad() + // Do view setup here. + + preferencesWindowController = PreferencesWindowController() + + self.view.addSubview(computer.emulatorView) + + self.frameTimer = Timer.scheduledTimer(timeInterval: 1/60, + target: self, + selector: #selector(runEmulation), + userInfo: nil, + repeats: true) + } + + @objc func runEmulation() { + computer.runFrame() + if(!CPU.sharedInstance.isRunning) { + self.frameTimer?.invalidate() + } + } + + @IBAction func showDebugger(_ sender: Any) { + let debuggerStoryboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Debugger"), bundle: nil) + debuggerWindowController = debuggerStoryboard.instantiateInitialController() as! DebuggerWindowController + debuggerWindowController.showWindow(self) + } + + @IBAction func showPreferences(_ sender: Any) { + preferencesWindowController.loadWindow() + } + +} diff --git a/FruitMachine/MainViewController.swift b/FruitMachine/AppleIViewController.swift similarity index 97% rename from FruitMachine/MainViewController.swift rename to FruitMachine/AppleIViewController.swift index 55159fb..544aaa4 100644 --- a/FruitMachine/MainViewController.swift +++ b/FruitMachine/AppleIViewController.swift @@ -9,7 +9,7 @@ import Cocoa import CoreGraphics -class MainViewController: NSViewController { +class AppleIViewController: NSViewController { let computer = AppleI.sharedInstance var debuggerWindowController: DebuggerWindowController! diff --git a/FruitMachine/Common/EmulatedSystem.swift b/FruitMachine/Common/EmulatedSystem.swift new file mode 100644 index 0000000..9513863 --- /dev/null +++ b/FruitMachine/Common/EmulatedSystem.swift @@ -0,0 +1,18 @@ +// +// EmulatedSystem.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +protocol EmulatedSystem { + var CPU_FREQUENCY: Double { get } + var FRAMES_PER_SECOND: Double { get } + var CYCLES_PER_BATCH: Int { get } + + init(cpuFrequency: Double, fps: Double) + func installOverrides() +} diff --git a/FruitMachine/AppleI/PIA.swift b/FruitMachine/Common/Peripherals/PIA.swift similarity index 100% rename from FruitMachine/AppleI/PIA.swift rename to FruitMachine/Common/Peripherals/PIA.swift diff --git a/FruitMachine/AppleI/Video/BitmapPixels.swift b/FruitMachine/Common/Video/BitmapPixels.swift similarity index 100% rename from FruitMachine/AppleI/Video/BitmapPixels.swift rename to FruitMachine/Common/Video/BitmapPixels.swift diff --git a/FruitMachine/Common/Video/Glyph.swift b/FruitMachine/Common/Video/Glyph.swift new file mode 100644 index 0000000..cb43072 --- /dev/null +++ b/FruitMachine/Common/Video/Glyph.swift @@ -0,0 +1,17 @@ +// +// Glyph.swift +// FruitMachine +// +// Created by Christopher Rohl on 8/1/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +struct Glyph { + var pixels: [BitmapPixelsBE555.PixelData] = [BitmapPixelsBE555.PixelData]() + + init(inPixels: [BitmapPixelsBE555.PixelData]) { + pixels = inPixels + } +} diff --git a/FruitMachine/FruitMachine.storyboard b/FruitMachine/FruitMachine.storyboard index 7b6d113..1a4f89a 100644 --- a/FruitMachine/FruitMachine.storyboard +++ b/FruitMachine/FruitMachine.storyboard @@ -224,10 +224,10 @@ - + - +