Steve2/A2Mac/DebuggerWindowController.swift
2024-01-06 07:11:52 -08:00

300 lines
7.8 KiB
Swift

//
// ToolBarController.swift
// Steve ][
//
// Created by Tamas Rudnai on 6/30/20.
// Copyright © 2019, 2020 Tamas Rudnai. All rights reserved.
//
// This file is part of Steve ][ -- The Apple ][ Emulator.
//
// Steve ][ is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Steve ][ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Steve ][. If not, see <https://www.gnu.org/licenses/>.
//
import Cocoa
class DebuggerWindowController: NSWindowController, NSWindowDelegate {
static var shared : DebuggerWindowController? = nil
required init?(coder: NSCoder) {
super.init(coder: coder)
DebuggerWindowController.shared = self
m6502_dbg_init()
}
override func windowDidLoad() {
let isWindowFullscreen = window?.styleMask.contains(.fullSizeContentView) ?? false
if isWindowFullscreen {
window?.toggleFullScreen(self)
}
NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
return self.keyHandler(with: $0)
// return nil // $0
}
}
var isKey : Bool = false
func windowDidBecomeKey(_ notification: Notification) {
// NSLog("windowDidBecomeKey")
isKey = true
ViewController.shared?.keyEventsOff()
}
func windowDidResignKey(_ notification: Notification) {
// NSLog("windowDidResignKey")
isKey = false
ViewController.shared?.keyEventsOn()
}
func windowWillClose(_ notification: Notification) {
m6502_dbg_off()
DebuggerWindowController.shared = nil
}
// TODO: Probably there is a better way to achieve this
// fill non-break spaces to provide uniform button width
let offLabel = "Off \u{A0}\u{A0}\u{A0}\u{A0}\u{A0}\u{A0}\u{A0}\u{A0}\u{A0}"
let pauseLabel = "Pause\u{A0}\u{A0}\u{A0}\u{A0}\u{A0}"
let resumeLabel = "Continue"
@IBOutlet weak var PauseToolbarItem: NSToolbarItem!
@IBOutlet weak var PauseButton: NSButton!
func PauseButtonUpdate(needUpdateMainToolbar: Bool = true) {
DispatchQueue.main.async {
switch cpuState {
case cpuState_halted:
if let PauseButton = self.PauseButton {
PauseButton.state = .off
}
if let PauseToolbarItem = self.PauseToolbarItem {
PauseToolbarItem.isEnabled = true;
PauseToolbarItem.label = self.resumeLabel
}
case cpuState_running:
if let PauseButton = self.PauseButton {
PauseButton.state = .on
}
if let PauseToolbarItem = self.PauseToolbarItem {
PauseToolbarItem.isEnabled = true;
PauseToolbarItem.label = self.pauseLabel
}
default:
if let PauseToolbarItem = self.PauseToolbarItem {
PauseToolbarItem.isEnabled = false;
PauseToolbarItem.label = self.offLabel
}
if let PauseButton = self.PauseButton {
PauseButton.state = .off
}
break
}
}
if needUpdateMainToolbar {
ToolBarController.current?.PauseButtonUpdate(needUpdateDebugToolbar: false)
}
}
func Continue() {
PauseButtonUpdate()
m6502.debugger.SP = 0xFF
m6502.debugger.wMask = 0
m6502.debugger.mask.hlt = 1;
m6502.debugger.mask.brk = 1;
m6502.debugger.mask.inv = 1;
m6502.debugger.on = true
m6502.interrupt = NO_INT
// because of memory debugger first we need to step over one instruction
// otherwise it would not step over that instruction
m6502_Step_dbg()
// now we cn resume to run
ViewController.shared?.Resume()
}
func Pause() {
PauseButtonUpdate()
ViewController.shared?.Pause(0)
m6502.debugger.on = false
}
@IBAction func ContinuePauseButton(_ sender: Any) {
switch cpuState {
case cpuState_halted:
Continue()
case cpuState_running:
Pause()
default:
break
}
}
// AppleScript Keycodes
let leftArrowKey = 123
let rightArrowKey = 124
let upArrowKey = 126
let downArrowKey = 125
let F4FunctionKey = 118
let F5FunctionKey = 96
let F6FunctionKey = 97
let F7FunctionKey = 98
let F8FunctionKey = 100
func keyHandler(with event: NSEvent) -> NSEvent? {
let keyCode = Int(event.keyCode)
print("keyDown DWC:", keyCode)
switch keyCode {
case leftArrowKey:
break
case rightArrowKey:
break
case downArrowKey:
break
case upArrowKey:
if isKey {
print("upArrowKeyDn in Debugger")
break
}
print("upArrowKeyDn outside of Debugger")
case F4FunctionKey:
Continue()
case F5FunctionKey:
Pause()
case F6FunctionKey:
Step_Over(event)
case F7FunctionKey:
Step_In(event)
case F8FunctionKey:
Step_Out(event)
default:
// print("keycode: %d", keyCode)
return event
}
return nil
}
let JSR_instr_code : UInt8 = 0x20
@IBAction func Step_Over(_ sender: Any) {
if MEM[Int(m6502.PC)] == JSR_instr_code {
m6502.debugger.SP = m6502.SP > 1 ? m6502.SP : 0
m6502.debugger.wMask = 0
m6502.debugger.mask.out = 1
m6502.debugger.mask.hlt = 1
m6502.debugger.mask.brk = 1
m6502.debugger.mask.inv = 1
m6502.debugger.on = true
m6502.interrupt = NO_INT
// because of memory debugger first we need to step over one instruction
// otherwise it would not step over that instruction
m6502_Step_dbg()
// now we cn resume to run
ViewController.shared?.Resume()
}
else {
// not a JSR call, only do a single step
Step_In(sender)
}
}
@IBAction func Step_In(_ sender: Any) {
m6502_Step_dbg()
// TODO: This should be in Debugger!
if let debuggerViewController = DebuggerViewController.shared {
debuggerViewController.remove_highlight(view: debuggerViewController.Disass_Display, line: debuggerViewController.highlighted_line_number)
debuggerViewController.Update()
}
// TODO: Update Screen and speaker etc
ViewController.shared?.Update()
}
@IBAction func Step_Out(_ sender: Any) {
PauseButtonUpdate()
m6502.debugger.SP = m6502.SP < 0xFE ? m6502.SP + 1 : 0xFF
m6502.debugger.wMask = 0
m6502.debugger.mask.out = 1
m6502.debugger.mask.hlt = 1;
m6502.debugger.mask.brk = 1;
m6502.debugger.mask.inv = 1;
m6502.debugger.on = true
m6502.interrupt = NO_INT
// because of memory debugger first we need to step over one instruction
// otherwise it would not step over that instruction
m6502_Step_dbg()
// now we cn resume to run
ViewController.shared?.Resume()
}
@IBAction func SetBreakPoint(_ sender: Any) {
}
@IBAction func DisableBreakPoint(_ sender: Any) {
}
}