2017-07-27 06:28:52 +00:00
|
|
|
//
|
2017-08-01 06:02:49 +00:00
|
|
|
// AppleIIViewController.swift
|
2017-07-27 06:28:52 +00:00
|
|
|
// FruitMachine
|
|
|
|
//
|
2017-08-01 06:02:49 +00:00
|
|
|
// Created by Christopher Rohl on 8/1/17.
|
2017-07-27 06:28:52 +00:00
|
|
|
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
|
2017-08-12 05:38:57 +00:00
|
|
|
class EmulationNotifications {
|
|
|
|
static let StartEmulation = Notification.Name("StartEmulation")
|
|
|
|
static let StopEmulation = Notification.Name("StopEmulation")
|
|
|
|
}
|
|
|
|
|
2017-08-07 06:32:24 +00:00
|
|
|
class AppleIIViewController: NSViewController {
|
2017-08-04 02:53:36 +00:00
|
|
|
@IBOutlet weak var lbl_Drive1: NSTextField!
|
|
|
|
@IBOutlet weak var lbl_Drive2: NSTextField!
|
|
|
|
|
2017-07-27 23:22:13 +00:00
|
|
|
var debuggerWindowController: DebuggerWindowController!
|
2017-07-31 07:03:14 +00:00
|
|
|
var preferencesWindowController: PreferencesWindowController!
|
2017-07-27 23:22:13 +00:00
|
|
|
|
2017-07-29 06:56:06 +00:00
|
|
|
var isPaused = false
|
|
|
|
var frameTimer: Timer?
|
2017-08-01 06:02:49 +00:00
|
|
|
|
|
|
|
override func viewDidLoad() {
|
2017-07-27 06:28:52 +00:00
|
|
|
super.viewDidLoad()
|
2017-08-01 06:02:49 +00:00
|
|
|
// Do view setup here.
|
2017-07-31 07:03:14 +00:00
|
|
|
preferencesWindowController = PreferencesWindowController()
|
2017-08-12 05:38:57 +00:00
|
|
|
setModel()
|
|
|
|
|
2017-08-07 06:32:24 +00:00
|
|
|
self.view.addSubview(EmulatedSystemInstance!.emulatorView)
|
2017-07-27 06:28:52 +00:00
|
|
|
|
2017-08-07 00:16:25 +00:00
|
|
|
preferencesWindowController.setupDefaultsIfRequired()
|
2017-08-04 02:53:36 +00:00
|
|
|
setupDriveNotifications()
|
2017-08-12 05:38:57 +00:00
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.stopFrameTimer), name: EmulationNotifications.StopEmulation, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.startFrameTimer), name: EmulationNotifications.StartEmulation, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.breakpointHit), name: CPUNotifications.BreakpointHit, object: nil)
|
|
|
|
startFrameTimer()
|
|
|
|
}
|
|
|
|
|
|
|
|
func setModel() {
|
|
|
|
let model = UserDefaults.standard.string(forKey: "a2_Model")
|
|
|
|
if (model == "Apple ][ (Original") {
|
|
|
|
EmulatedSystemInstance = AppleII.sharedInstance
|
|
|
|
} else if(model == "Apple ][+") {
|
|
|
|
EmulatedSystemInstance = AppleIIPlus.sharedInstance
|
2017-08-13 04:20:45 +00:00
|
|
|
} else if(model == "Apple IIe") {
|
|
|
|
EmulatedSystemInstance = AppleIIe.sharedInstance
|
2017-08-12 05:38:57 +00:00
|
|
|
} else {
|
|
|
|
/* ??? */
|
|
|
|
EmulatedSystemInstance = AppleII.sharedInstance
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func breakpointHit() {
|
|
|
|
stopFrameTimer()
|
|
|
|
showDebugger(self)
|
2017-07-29 06:56:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@objc func runEmulation() {
|
2017-08-07 06:32:24 +00:00
|
|
|
EmulatedSystemInstance!.runFrame()
|
2017-07-30 02:48:37 +00:00
|
|
|
if(!CPU.sharedInstance.isRunning) {
|
|
|
|
self.frameTimer?.invalidate()
|
|
|
|
}
|
2017-07-29 06:56:06 +00:00
|
|
|
}
|
|
|
|
|
2017-08-12 05:38:57 +00:00
|
|
|
@objc func stopFrameTimer() {
|
|
|
|
self.frameTimer?.invalidate()
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func startFrameTimer() {
|
|
|
|
self.frameTimer = Timer.scheduledTimer(timeInterval: 1.0/60.0,
|
|
|
|
target: self,
|
|
|
|
selector: #selector(runEmulation),
|
|
|
|
userInfo: nil,
|
|
|
|
repeats: true)
|
2017-08-05 07:29:07 +00:00
|
|
|
}
|
|
|
|
|
2017-08-12 05:38:57 +00:00
|
|
|
@IBAction func showDebugger(_ sender: Any) {
|
|
|
|
stopFrameTimer()
|
2017-07-31 07:03:14 +00:00
|
|
|
let debuggerStoryboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "Debugger"), bundle: nil)
|
|
|
|
debuggerWindowController = debuggerStoryboard.instantiateInitialController() as! DebuggerWindowController
|
|
|
|
debuggerWindowController.showWindow(self)
|
|
|
|
}
|
2017-07-31 20:33:42 +00:00
|
|
|
|
|
|
|
@IBAction func showPreferences(_ sender: Any) {
|
2017-08-12 05:38:57 +00:00
|
|
|
stopFrameTimer()
|
2017-07-31 20:33:42 +00:00
|
|
|
preferencesWindowController.loadWindow()
|
2017-08-07 00:16:25 +00:00
|
|
|
preferencesWindowController.showWindow(self)
|
2017-08-12 05:38:57 +00:00
|
|
|
preferencesWindowController.setupPreferences()
|
2017-07-31 20:33:42 +00:00
|
|
|
}
|
2017-08-01 06:02:49 +00:00
|
|
|
|
2017-08-02 08:01:06 +00:00
|
|
|
@IBAction func doReset(_ sender: Any) {
|
2017-08-07 06:32:24 +00:00
|
|
|
EmulatedSystemInstance!.doReset()
|
2017-08-02 08:01:06 +00:00
|
|
|
}
|
|
|
|
|
2017-08-08 04:08:05 +00:00
|
|
|
@IBAction func doColdReset(_ sender: Any) {
|
2017-08-13 00:24:30 +00:00
|
|
|
setModel()
|
|
|
|
EmulatedSystemInstance!.setupPeripherals()
|
2017-08-08 04:08:05 +00:00
|
|
|
EmulatedSystemInstance!.doColdReset()
|
|
|
|
}
|
|
|
|
|
|
|
|
@IBAction func insertDiskIntoDrive1(_ sender: Any) {
|
|
|
|
let picker = NSOpenPanel()
|
|
|
|
|
|
|
|
picker.title = "Select a 5.25\" disk image"
|
|
|
|
picker.showsHiddenFiles = false
|
|
|
|
picker.canChooseFiles = true
|
|
|
|
picker.canChooseDirectories = false
|
|
|
|
picker.allowsMultipleSelection = false
|
|
|
|
picker.allowedFileTypes = ["do", "po"]
|
|
|
|
|
|
|
|
if(picker.runModal() == .OK) {
|
2017-08-13 00:24:30 +00:00
|
|
|
print("insertDiskIntoDrive1: \(EmulatedSystemInstance!.backplane[6]!)")
|
|
|
|
EmulatedSystemInstance!.attachImageToDiskDrive(drive: EmulatedSystemInstance!.backplane[6]!, image: picker.url!.path)
|
2017-08-08 04:08:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-01 21:40:01 +00:00
|
|
|
override func keyDown(with event: NSEvent) {
|
2017-08-03 04:31:12 +00:00
|
|
|
let leftArrowKeyCode = 123
|
|
|
|
let rightArrowKeyCode = 124
|
|
|
|
|
2017-08-01 21:40:01 +00:00
|
|
|
let c = returnChar(theEvent: event)
|
|
|
|
|
2017-08-03 04:31:12 +00:00
|
|
|
if(event.keyCode == leftArrowKeyCode) {
|
2017-08-07 06:32:24 +00:00
|
|
|
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((0x08 | 0x80) & 0x000000FF)
|
2017-08-03 04:31:12 +00:00
|
|
|
} else if(event.keyCode == rightArrowKeyCode) {
|
2017-08-07 06:32:24 +00:00
|
|
|
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((0x15 | 0x80) & 0x000000FF)
|
2017-08-03 04:31:12 +00:00
|
|
|
}
|
|
|
|
|
2017-08-01 21:40:01 +00:00
|
|
|
guard let ascii32 = c?.asciiValue else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-08-02 08:01:06 +00:00
|
|
|
//Set the keyboard input register accordingly. Set b7 so the OS knows there's a keypress waiting
|
2017-08-07 06:32:24 +00:00
|
|
|
EmulatedSystemInstance!.keyboardController.KEYBOARD = UInt8((ascii32 | 0x80) & 0x000000FF)
|
2017-08-01 21:40:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private func returnChar(theEvent: NSEvent) -> Character?{
|
|
|
|
let s: String = theEvent.characters!
|
|
|
|
for char in s{
|
|
|
|
return char
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-08-04 02:53:36 +00:00
|
|
|
func setupDriveNotifications() {
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive1MotorOn), name: DiskII.N_Drive1MotorOn, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive2MotorOn), name: DiskII.N_Drive2MotorOn, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive1MotorOff), name: DiskII.N_Drive1MotorOff, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive2MotorOff), name: DiskII.N_Drive2MotorOff, object: nil)
|
2017-08-04 07:20:17 +00:00
|
|
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive1TrackChanged), name: DiskII.N_Drive1TrackChanged, object: nil)
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(self.drive2TrackChanged), name: DiskII.N_Drive2TrackChanged, object: nil)
|
2017-08-05 07:29:07 +00:00
|
|
|
|
2017-08-04 02:53:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* drive lights */
|
2017-08-04 07:20:17 +00:00
|
|
|
@objc func drive1TrackChanged(notification: NSNotification) {
|
2017-08-07 00:16:25 +00:00
|
|
|
let num = notification.object as? (Int, Int)
|
|
|
|
lbl_Drive1.stringValue = "D1 T\(num!.0) S\(num!.1)"
|
2017-08-04 07:20:17 +00:00
|
|
|
}
|
|
|
|
@objc func drive2TrackChanged(notification: NSNotification) {
|
2017-08-07 00:16:25 +00:00
|
|
|
let num = notification.object as? (Int, Int)
|
|
|
|
lbl_Drive2.stringValue = "D1 T\(num!.0) S\(num!.1)"
|
2017-08-04 07:20:17 +00:00
|
|
|
}
|
|
|
|
|
2017-08-04 02:53:36 +00:00
|
|
|
@objc func drive1MotorOff(notification: NSNotification) {
|
|
|
|
lbl_Drive1.textColor = NSColor.textColor
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func drive2MotorOff(notification: NSNotification) {
|
|
|
|
lbl_Drive2.textColor = NSColor.textColor
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func drive1MotorOn(notification: NSNotification) {
|
|
|
|
lbl_Drive1.textColor = NSColor.red
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func drive2MotorOn(notification: NSNotification) {
|
|
|
|
lbl_Drive2.textColor = NSColor.red
|
|
|
|
}
|
|
|
|
|
2017-07-29 20:11:14 +00:00
|
|
|
}
|