adding a basic debug console and fixing issues with branch instructions

This commit is contained in:
Luigi Thirty 2017-07-24 23:25:55 -04:00
parent a0d28938b7
commit 3c04503525
8 changed files with 285 additions and 42 deletions

View File

@ -16,6 +16,7 @@
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */; };
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E21F20661300F05121 /* CPUInstructions.swift */; };
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E41F2070DF00F05121 /* Opcodes.swift */; };
2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.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 */
@ -33,6 +34,7 @@
2AD458E01F2064CB00F05121 /* MemoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryInterface.swift; sourceTree = "<group>"; };
2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = "<group>"; };
2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = "<group>"; };
2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerCommands.swift; sourceTree = "<group>"; };
2AE5BA031F23DE4400FAA343 /* Disassembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disassembly.swift; sourceTree = "<group>"; };
2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressConversions.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -70,6 +72,7 @@
2AD458DD1F205F0D00F05121 /* M6502 */,
2AD458CD1F205EB700F05121 /* AppDelegate.swift */,
2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */,
2AD6D5831F26E6BF008F3CF5 /* DebuggerCommands.swift */,
2AD458D11F205EB700F05121 /* Assets.xcassets */,
2AD458D31F205EB700F05121 /* Main.storyboard */,
2AD458D61F205EB700F05121 /* Info.plist */,
@ -166,6 +169,7 @@
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */,
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */,
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */,
2AD6D5841F26E6BF008F3CF5 /* DebuggerCommands.swift in Sources */,
2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */,
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */,

View File

@ -707,11 +707,11 @@
<objects>
<viewController id="XfG-lQ-9wD" customClass="DebuggerViewController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="450" height="400"/>
<rect key="frame" x="0.0" y="0.0" width="450" height="550"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-VZ-R2W">
<rect key="frame" x="18" y="363" width="18" height="17"/>
<rect key="frame" x="18" y="513" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="A" id="teN-CC-Ijg">
<font key="font" metaFont="system"/>
@ -720,7 +720,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WjO-ue-iRg">
<rect key="frame" x="42" y="360" width="96" height="22"/>
<rect key="frame" x="42" y="510" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="tFR-bO-ncf">
<font key="font" metaFont="fixedUser" size="11"/>
@ -729,7 +729,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PyS-Mu-bnf">
<rect key="frame" x="18" y="333" width="18" height="17"/>
<rect key="frame" x="18" y="483" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="X" id="YEp-wn-anc">
<font key="font" metaFont="system"/>
@ -738,7 +738,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nOs-8C-MbH">
<rect key="frame" x="42" y="330" width="96" height="22"/>
<rect key="frame" x="42" y="480" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="rbk-9r-h0r">
<font key="font" metaFont="fixedUser" size="11"/>
@ -747,7 +747,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DmJ-LS-i50">
<rect key="frame" x="18" y="303" width="18" height="17"/>
<rect key="frame" x="18" y="453" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Y" id="Or5-cX-RQb">
<font key="font" metaFont="system"/>
@ -756,7 +756,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eqA-qk-YQy">
<rect key="frame" x="42" y="300" width="96" height="22"/>
<rect key="frame" x="42" y="450" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="TpP-00-jRa">
<font key="font" metaFont="fixedUser" size="11"/>
@ -765,7 +765,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X2P-rm-4XW">
<rect key="frame" x="18" y="275" width="18" height="17"/>
<rect key="frame" x="18" y="425" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="PC" id="okQ-uV-ovH">
<font key="font" metaFont="system"/>
@ -774,7 +774,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XbV-5m-dd0">
<rect key="frame" x="42" y="270" width="96" height="22"/>
<rect key="frame" x="42" y="420" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="tiL-Qj-d0G">
<font key="font" metaFont="fixedUser" size="11"/>
@ -783,7 +783,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iZJ-VB-xRU">
<rect key="frame" x="18" y="245" width="18" height="17"/>
<rect key="frame" x="18" y="395" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="SR" id="2XF-Q8-qZg">
<font key="font" metaFont="system"/>
@ -792,7 +792,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5TT-BA-Iw1">
<rect key="frame" x="42" y="240" width="96" height="22"/>
<rect key="frame" x="42" y="390" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="wzs-zZ-PQs">
<font key="font" metaFont="fixedUser" size="11"/>
@ -801,7 +801,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6li-po-zVA">
<rect key="frame" x="18" y="215" width="18" height="17"/>
<rect key="frame" x="18" y="365" width="18" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="F" id="qfi-b1-PI7">
<font key="font" metaFont="system"/>
@ -810,7 +810,7 @@
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ecN-Ge-1hE">
<rect key="frame" x="42" y="210" width="96" height="22"/>
<rect key="frame" x="42" y="360" width="96" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4dD-B8-JHv">
<font key="font" metaFont="fixedUser" size="11"/>
@ -819,7 +819,7 @@
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HdY-Jc-lNK">
<rect key="frame" x="36" y="46" width="108" height="32"/>
<rect key="frame" x="36" y="196" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Step" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="kSv-aI-p6H">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -830,7 +830,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oRf-MK-DEX">
<rect key="frame" x="36" y="13" width="108" height="32"/>
<rect key="frame" x="36" y="163" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Run" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="e8U-eN-C1K">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -841,7 +841,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="94S-pW-GeW">
<rect key="frame" x="36" y="79" width="108" height="32"/>
<rect key="frame" x="36" y="229" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Break" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pg2-w8-mzE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -852,7 +852,7 @@
</connections>
</button>
<scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D58-pD-kHB">
<rect key="frame" x="146" y="20" width="284" height="362"/>
<rect key="frame" x="146" y="170" width="284" height="362"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" ambiguous="YES" id="bpK-Jl-YbG">
<rect key="frame" x="1" y="0.0" width="282" height="361"/>
@ -969,7 +969,7 @@
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="jEY-yd-b3r">
<rect key="frame" x="1" y="346" width="442" height="15"/>
<rect key="frame" x="1" y="-15" width="0.0" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="xl3-SC-c8c">
@ -981,9 +981,61 @@
<autoresizingMask key="autoresizingMask"/>
</tableHeaderView>
</scrollView>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gOM-wQ-387">
<rect key="frame" x="42" y="20" width="388" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" state="on" borderStyle="bezel" title="debuggerInput" drawsBackground="YES" usesSingleLineMode="YES" id="Tgu-VW-lrU">
<font key="font" metaFont="fixedUser" size="11"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="debuggerInput_submit:" target="XfG-lQ-9wD" id="YfD-Ke-ibS"/>
<outlet property="delegate" destination="XfG-lQ-9wD" id="j9U-3F-uJ0"/>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ki7-hi-cZ9">
<rect key="frame" x="36" y="262" width="108" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Restart" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="z0u-6V-7iW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btn_CPU_Restart:" target="XfG-lQ-9wD" id="B2O-Nw-A6U"/>
</connections>
</button>
<scrollView wantsLayer="YES" fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ytp-2q-EO1">
<rect key="frame" x="42" y="50" width="388" height="112"/>
<autoresizingMask key="autoresizingMask"/>
<clipView key="contentView" ambiguous="YES" id="8jz-1j-CtB">
<rect key="frame" x="1" y="1" width="371" height="110"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" usesRuler="YES" textCompletion="NO" id="3gF-hp-68k">
<rect key="frame" x="0.0" y="-1" width="371" height="110"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<size key="minSize" width="371" height="110"/>
<size key="maxSize" width="463" height="10000000"/>
<color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="6LY-CO-tGe">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="bS2-z2-W2K">
<rect key="frame" x="372" y="1" width="15" height="110"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<connections>
<outlet property="btn_CPU_restart" destination="ki7-hi-cZ9" id="PD7-dk-eNE"/>
<outlet property="debuggerTableView" destination="MuT-J3-VZ6" id="TMx-Do-29u"/>
<outlet property="text_CPU_A" destination="WjO-ue-iRg" id="kaI-Bh-Efs"/>
<outlet property="text_CPU_Flags" destination="ecN-Ge-1hE" id="dDw-IG-xNd"/>
@ -991,6 +1043,8 @@
<outlet property="text_CPU_SR" destination="5TT-BA-Iw1" id="Bnh-oz-AnZ"/>
<outlet property="text_CPU_X" destination="nOs-8C-MbH" id="71D-al-r5q"/>
<outlet property="text_CPU_Y" destination="eqA-qk-YQy" id="c88-2h-DES"/>
<outlet property="text_debugger_input" destination="gOM-wQ-387" id="2XS-fM-VQn"/>
<outlet property="text_debugger_output" destination="3gF-hp-68k" id="esg-CB-lFg"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>

View File

@ -0,0 +1,25 @@
//
// DebugConsole.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/24/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
class DebugConsole: NSObject {
func interpretCommand(command: String) {
let commandSplit = command.split(separator: " ")
if(commandSplit[0] == "bplist") {
}
}
}
class DebugCommands: NSObject {
static func bplist() -> String {
}
}

View File

@ -0,0 +1,86 @@
//
// DebuggerCommands.swift
// FruitMachine
//
// Created by Christopher Rohl on 7/24/17.
// Copyright © 2017 Christopher Rohl. All rights reserved.
//
import Cocoa
extension DebuggerViewController {
func interpretCommand(command: String) {
debugConsolePrint(str: "> \(command)", newline: true)
let commandSplit = command.components(separatedBy: " ")
var parameters: [String] = commandSplit
parameters.remove(at: 0)
if(commandSplit[0] == "bplist")
{
debugConsolePrint(str: DebuggerCommands.bplist(state: cpuInstance, parameters: parameters), newline: true)
}
else if(commandSplit[0] == "bpdel")
{
debugConsolePrint(str: DebuggerCommands.bpdel(state: cpuInstance, parameters: parameters), newline: true)
}
else if(commandSplit[0] == "bpadd")
{
debugConsolePrint(str: DebuggerCommands.bpadd(state: cpuInstance, parameters: parameters), newline: true)
}
else
{
debugConsolePrint(str: "Unrecognized command", newline: true)
}
text_debugger_output.scrollToEndOfDocument(self)
}
}
class DebuggerCommands: NSObject {
static func bplist(state: CPU, parameters: [String]) -> String {
var output = ""
for (index, bp) in state.breakpoints.enumerated() {
output += "Breakpoint \(index): $\(bp.asHexString())\r\n"
}
return output
}
static func bpadd(state: CPU, parameters: [String]) -> String {
var output = ""
let val = UInt16(parameters[0])
if(val != nil) {
state.breakpoints.append(val!)
output += "Breakpoint added at $\(val!.asHexString())."
}
else {
output += "Usage: bpadd <address>"
}
return output
}
static func bpdel(state: CPU, parameters: [String]) -> String {
var output = ""
let val = Int(parameters[0])
if(val != nil)
{
if (val! >= 0 && val! < state.breakpoints.count) {
state.breakpoints.remove(at: val!)
output += "Breakpoint \(val!) deleted."
}
else
{
output += "Breakpoint \(val!) does not exist."
}
}
else
{
output += "Usage: bpdel <breakpoint-number>. Use bplist to find breakpoint numbers."
}
return output
}
}

View File

@ -16,6 +16,9 @@ class DebuggerViewController: NSViewController {
@IBOutlet weak var text_CPU_SR: NSTextField!
@IBOutlet weak var text_CPU_Flags: NSTextField!
@IBOutlet weak var text_debugger_output: NSTextView!
@IBOutlet weak var text_debugger_input: NSTextField!
@IBOutlet weak var debuggerTableView: NSTableView!
var cpuInstance = CPU.sharedInstance
@ -43,10 +46,8 @@ class DebuggerViewController: NSViewController {
text_CPU_SR.stringValue = String(format:"%02X", cpuInstance.stack_pointer)
text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString())
if(!highlightCurrentInstruction()) {
disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 256)
highlightCurrentInstruction()
}
disassembly = cpuInstance.disassemble(fromAddress: 0, length: 10000)
highlightCurrentInstruction()
}
override func viewDidLoad() {
@ -59,9 +60,11 @@ class DebuggerViewController: NSViewController {
cpuInstance.performReset()
cpuInstance.program_counter = 0x400 //entry point for the test program
updateCPUStatusFields()
disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 10000)
disassembly = cpuInstance.disassemble(fromAddress: 0, length: 10000)
debuggerTableView.reloadData()
cpuInstance.breakpoints.append(0x0528)
// Do any additional setup after loading the view.
}
@ -75,7 +78,8 @@ class DebuggerViewController: NSViewController {
do {
try cpuInstance.executeNextInstruction()
} catch CPUExceptions.invalidInstruction {
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
isRunning = false
} catch {
print(error)
}
@ -83,20 +87,26 @@ class DebuggerViewController: NSViewController {
func cpuRun() {
isRunning = true
let queue = DispatchQueue(label: "com.luigithirty.m6502.instructions")
let main = DispatchQueue.main
queue.async {
while(self.isRunning == true)
{
queue.asyncAfter(deadline: .now() + .seconds(1), execute: {
self.cpuStep()
main.sync {
self.updateCPUStatusFields()
}
})
cpuInstance.cycles = 0
cpuInstance.cyclesInBatch = 1000
while(!cpuInstance.checkOutOfCycles() && isRunning) {
cpuStep()
if (cpuInstance.breakpoints.contains(cpuInstance.program_counter)) {
isRunning = false
updateCPUStatusFields()
debugConsolePrint(str: "Breakpoint reached at $\(cpuInstance.program_counter.asHexString())", newline: true)
}
}
}
func queueCPUStep(queue: DispatchQueue) {
queue.async {
self.cpuStep()
}
}
@IBAction func btn_CPUStep(_ sender: Any) {
@ -112,8 +122,26 @@ class DebuggerViewController: NSViewController {
@IBAction func btn_CPURun(_ sender: Any) {
cpuRun()
}
@IBAction func btn_CPU_Restart(_ sender: Any) {
cpuInstance.performReset()
cpuInstance.program_counter = 0x400
debugConsolePrint(str: "CPU restarted from $0400", newline: true)
}
@IBAction func debuggerInput_submit(_ sender: NSTextField) {
interpretCommand(command: sender.stringValue)
sender.stringValue = ""
}
func debugConsolePrint(str: String, newline: Bool) {
text_debugger_output.appendText(line: str)
if(newline) {
text_debugger_output.appendText(line:"\r\n")
}
}
}
extension DebuggerViewController: NSTableViewDelegate {
@ -150,7 +178,7 @@ extension DebuggerViewController: NSTableViewDelegate {
if((operation.data[1] & 0x80) == 0x80) {
destination = destination + 1 - UInt16(~operation.data[1])
} else {
destination = destination + UInt16(operation.data[1])
destination = destination + 2 + UInt16(operation.data[1])
}
cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, destination)
case .absolute:
@ -204,3 +232,21 @@ extension DebuggerViewController: NSTableViewDataSource {
return disassembly[atIndex]
}
}
extension NSTextView {
func appendText(line: String) {
let attrDict = [NSAttributedStringKey.font: NSFont.userFixedPitchFont(ofSize: 11)]
let astring = NSAttributedString(string: "\(line)", attributes: attrDict)
self.textStorage?.append(astring)
let loc = self.string.lengthOfBytes(using: String.Encoding.utf8)
let range = NSRange(location: loc, length: 0)
self.scrollRangeToVisible(range)
}
}
func xlog(logView:NSTextView?, line:String) {
if let view = logView {
view.appendText(line: line)
}
}

View File

@ -113,6 +113,7 @@ class CPU: NSObject {
static var sharedInstance = CPU()
var cycles: Int
var cyclesInBatch: Int
var instruction_register: UInt8
@ -128,8 +129,11 @@ class CPU: NSObject {
var memoryInterface: MemoryInterface
var breakpoints: [UInt16]
override init() {
cycles = 0
cyclesInBatch = 0
instruction_register = 0
@ -146,6 +150,8 @@ class CPU: NSObject {
//Branches incur a 1-cycle penalty if taken plus the page boundary penalty if necessary.
branch_was_taken = false
breakpoints = [UInt16]()
}
func getOperandByte() -> UInt8 {
@ -205,6 +211,14 @@ class CPU: NSObject {
}
}
func checkOutOfCycles() -> Bool {
if(cycles > cyclesInBatch) {
return true
} else {
return false
}
}
func performReset() {
program_counter = memoryInterface.readWord(offset: RESET_VECTOR)
stack_pointer = 0xFF

View File

@ -12,4 +12,8 @@ extension UInt16 {
static func + (left: UInt16, right: UInt8) -> UInt16 {
return left + UInt16(right)
}
func asHexString() -> String {
return String(format: "%04X", self)
}
}

View File

@ -29,7 +29,7 @@ extension CPU {
func pushWord(data: UInt16) -> Void {
let low = UInt8(data & 0x00FF)
let high = UInt8(data & 0xFF00)
let high = UInt8((data & 0xFF00) >> 8)
pushByte(data: low)
pushByte(data: high)
@ -52,8 +52,18 @@ extension CPU {
}
}
program_counter = UInt16(Int(program_counter) + Int(distance))
if(distance > 0) {
program_counter = UInt16(Int(program_counter) + Int(distance))
} else {
program_counter = UInt16(Int(program_counter) + Int(distance))
}
branch_was_taken = true
if(distance == -2) {
print("Infinite loop at $\(program_counter.asHexString()). Halting execution.")
cyclesInBatch = 0
}
}
}
@ -116,7 +126,7 @@ func getOperandWordForAddressingMode(state: CPU, mode: AddressingMode) -> UInt16
let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp)) + UInt16(state.index_y)
return state.memoryInterface.readWord(offset: pointer)
default:
print("Called getOperand: UInt16 on an instruction that expects a UInt8")
print("Called getOperand: UInt16 on an instruction that expects a UInt8. Address: \(state.program_counter.asHexString())")
return 0
}
@ -231,7 +241,7 @@ class Opcodes: NSObject {
return
}
}
static func STY(state: CPU, addressingMode: AddressingMode) -> Void {
let address: UInt16
@ -294,14 +304,14 @@ class Opcodes: NSObject {
}
static func DEY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = state.index_x &- 1
state.index_y = state.index_y &- 1
state.updateZeroFlag(value: state.index_y);
state.updateNegativeFlag(value: state.index_y);
}
static func INY(state: CPU, addressingMode: AddressingMode) -> Void {
state.index_y = state.index_x &+ 1
state.index_y = state.index_y &+ 1
state.updateZeroFlag(value: state.index_y);
state.updateNegativeFlag(value: state.index_y);