mirror of
https://github.com/Luigi30/FruitMachine-Swift.git
synced 2025-02-16 23:31:01 +00:00
started on the disassembler
This commit is contained in:
parent
87d5584eee
commit
f3bbb0413e
@ -9,20 +9,21 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */; };
|
||||
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CD1F205EB700F05121 /* AppDelegate.swift */; };
|
||||
2AD458D01F205EB700F05121 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* ViewController.swift */; };
|
||||
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */; };
|
||||
2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; };
|
||||
2AD458D51F205EB700F05121 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D31F205EB700F05121 /* Main.storyboard */; };
|
||||
2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458DE1F205F4500F05121 /* CPUState.swift */; };
|
||||
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 */; };
|
||||
2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerExtensions.swift; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
2AD458CF1F205EB700F05121 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggerViewController.swift; sourceTree = "<group>"; };
|
||||
2AD458D11F205EB700F05121 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
2AD458D41F205EB700F05121 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
2AD458D61F205EB700F05121 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@ -31,6 +32,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>"; };
|
||||
2AE5BA031F23DE4400FAA343 /* Disassembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disassembly.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -65,7 +67,7 @@
|
||||
children = (
|
||||
2AD458DD1F205F0D00F05121 /* M6502 */,
|
||||
2AD458CD1F205EB700F05121 /* AppDelegate.swift */,
|
||||
2AD458CF1F205EB700F05121 /* ViewController.swift */,
|
||||
2AD458CF1F205EB700F05121 /* DebuggerViewController.swift */,
|
||||
2AD458D11F205EB700F05121 /* Assets.xcassets */,
|
||||
2AD458D31F205EB700F05121 /* Main.storyboard */,
|
||||
2AD458D61F205EB700F05121 /* Info.plist */,
|
||||
@ -79,6 +81,7 @@
|
||||
children = (
|
||||
2AD458DE1F205F4500F05121 /* CPUState.swift */,
|
||||
2AD458E21F20661300F05121 /* CPUInstructions.swift */,
|
||||
2AE5BA031F23DE4400FAA343 /* Disassembly.swift */,
|
||||
2AD458E41F2070DF00F05121 /* Opcodes.swift */,
|
||||
2AD458E01F2064CB00F05121 /* MemoryInterface.swift */,
|
||||
2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */,
|
||||
@ -157,9 +160,10 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */,
|
||||
2AD458D01F205EB700F05121 /* ViewController.swift in Sources */,
|
||||
2AD458D01F205EB700F05121 /* DebuggerViewController.swift in Sources */,
|
||||
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */,
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */,
|
||||
2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */,
|
||||
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
|
||||
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */,
|
||||
2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */,
|
||||
|
@ -685,7 +685,7 @@
|
||||
<scene sceneID="R2V-B0-nI4">
|
||||
<objects>
|
||||
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
|
||||
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
|
||||
<window key="window" title="Debugger" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
|
||||
@ -702,10 +702,10 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="75" y="250"/>
|
||||
</scene>
|
||||
<!--View Controller-->
|
||||
<!--Debugger View Controller-->
|
||||
<scene sceneID="hIz-AP-VOD">
|
||||
<objects>
|
||||
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModule="FruitMachine" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<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="480" height="270"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@ -767,7 +767,7 @@
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X2P-rm-4XW">
|
||||
<rect key="frame" x="18" y="145" width="18" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="IP" id="okQ-uV-ovH">
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="PC" id="okQ-uV-ovH">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
@ -782,6 +782,15 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iZJ-VB-xRU">
|
||||
<rect key="frame" x="18" y="115" 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"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5TT-BA-Iw1">
|
||||
<rect key="frame" x="42" y="110" width="96" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
@ -802,18 +811,107 @@
|
||||
<action selector="btn_CPUStep:" target="XfG-lQ-9wD" id="sht-OT-bFK"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iZJ-VB-xRU">
|
||||
<rect key="frame" x="18" y="115" width="18" height="17"/>
|
||||
<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="314" height="232"/>
|
||||
<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"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<clipView key="contentView" ambiguous="YES" id="bpK-Jl-YbG">
|
||||
<rect key="frame" x="1" y="0.0" width="312" height="231"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="Ep4-FK-mkU" viewBased="YES" id="MuT-J3-VZ6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="312" height="208"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="AddressCellID" width="116" minWidth="40" maxWidth="1000" id="hX8-rd-9WQ">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Address">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="Paw-o4-m30">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="CfD-bj-I9h">
|
||||
<rect key="frame" x="1" y="1" width="116" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gF6-Xd-zbg">
|
||||
<rect key="frame" x="0.0" y="0.0" width="116" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="rhk-Nf-Hah">
|
||||
<font key="font" size="11" name="Menlo-Regular"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="textField" destination="gF6-Xd-zbg" id="lep-1z-ZAt"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
<tableColumn identifier="DataCellID" width="190" minWidth="40" maxWidth="1000" id="Ma5-Fz-J7v">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Disassembly">
|
||||
<font key="font" metaFont="smallSystem"/>
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="pvJ-AI-di6">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="ZF1-Mn-oL5">
|
||||
<rect key="frame" x="120" y="1" width="190" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gen-Zj-0O4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="190" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="lxl-6b-xYm">
|
||||
<font key="font" metaFont="fixedUser" size="11"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<connections>
|
||||
<outlet property="textField" destination="gen-Zj-0O4" id="t04-GH-nId"/>
|
||||
</connections>
|
||||
</tableCellView>
|
||||
</prototypeCellViews>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
</tableView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="jEY-yd-b3r">
|
||||
<rect key="frame" x="1" y="119" width="223" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="xl3-SC-c8c">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<tableHeaderView key="headerView" id="Ep4-FK-mkU">
|
||||
<rect key="frame" x="0.0" y="0.0" width="312" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableHeaderView>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<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_IP" destination="XbV-5m-dd0" id="IoJ-th-0Ve"/>
|
||||
<outlet property="text_CPU_SR" destination="5TT-BA-Iw1" id="Bnh-oz-AnZ"/>
|
||||
|
139
FruitMachine/DebuggerViewController.swift
Normal file
139
FruitMachine/DebuggerViewController.swift
Normal file
@ -0,0 +1,139 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 7/19/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class DebuggerViewController: NSViewController {
|
||||
@IBOutlet weak var text_CPU_A: NSTextField!
|
||||
@IBOutlet weak var text_CPU_X: NSTextField!
|
||||
@IBOutlet weak var text_CPU_Y: NSTextField!
|
||||
@IBOutlet weak var text_CPU_IP: NSTextField!
|
||||
@IBOutlet weak var text_CPU_SR: NSTextField!
|
||||
|
||||
@IBOutlet weak var debuggerTableView: NSTableView!
|
||||
|
||||
let CPU = CPUState.sharedInstance
|
||||
var disassembly: [Disassembly] = [Disassembly]()
|
||||
|
||||
func updateCPUStatusFields() {
|
||||
text_CPU_A.stringValue = String(format:"%02X", CPU.accumulator)
|
||||
text_CPU_X.stringValue = String(format:"%02X", CPU.index_x)
|
||||
text_CPU_Y.stringValue = String(format:"%02X", CPU.index_y)
|
||||
text_CPU_IP.stringValue = String(format:"%04X", CPU.program_counter)
|
||||
text_CPU_SR.stringValue = String(format:"%02X", CPU.stack_pointer)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
debuggerTableView.delegate = self
|
||||
debuggerTableView.dataSource = self
|
||||
|
||||
CPU.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin")
|
||||
updateCPUStatusFields()
|
||||
disassembly = CPU.disassemble(fromAddress: 0x0000, length: 16)
|
||||
debuggerTableView.reloadData()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override var representedObject: Any? {
|
||||
didSet {
|
||||
// Update the view, if already loaded.
|
||||
}
|
||||
}
|
||||
|
||||
func cpuStep() {
|
||||
do {
|
||||
try CPU.executeNextInstruction()
|
||||
updateCPUStatusFields()
|
||||
} catch CPUExceptions.invalidInstruction {
|
||||
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func btn_CPUStep(_ sender: Any) {
|
||||
cpuStep()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DebuggerViewController: NSTableViewDelegate {
|
||||
|
||||
fileprivate enum CellIdentifiers {
|
||||
static let AddressCell = "AddressCellID"
|
||||
static let DataCell = "DataCellID"
|
||||
}
|
||||
|
||||
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||
var cellText: String = ""
|
||||
var cellIdentifier: String = ""
|
||||
let operation = disassembly[row]
|
||||
|
||||
if(tableColumn == tableView.tableColumns[0]) {
|
||||
cellText = String(format: "%04X", operation.address)
|
||||
cellIdentifier = CellIdentifiers.AddressCell
|
||||
}
|
||||
|
||||
if(tableColumn == tableView.tableColumns[1]) {
|
||||
if(operation.instruction == nil) {
|
||||
cellText = "ILLEGAL"
|
||||
} else {
|
||||
switch(operation.instruction!.addressingMode) {
|
||||
case .accumulator:
|
||||
cellText = String(format: "%@ A", operation.instruction!.mnemonic)
|
||||
case .immediate:
|
||||
cellText = String(format: "%@ #%02X", operation.instruction!.mnemonic, operation.data[0])
|
||||
case .implied:
|
||||
cellText = String(format: "%@", operation.instruction!.mnemonic)
|
||||
case .relative:
|
||||
cellText = String(format: "%@ #%04X", operation.instruction!.mnemonic, UInt16(operation.data[0]) + operation.address)
|
||||
case .absolute:
|
||||
cellText = String(format: "%@ #%02X%02X", operation.instruction!.mnemonic, operation.data[1], operation.data[0])
|
||||
case .zeropage:
|
||||
cellText = String(format: "%@ $%02X", operation.instruction!.mnemonic, operation.data[0])
|
||||
case .indirect:
|
||||
cellText = String(format: "%@ ($%02X%02X)", operation.instruction!.mnemonic, operation.data[1], operation.data[0])
|
||||
case .absolute_indexed_x:
|
||||
cellText = String(format: "%@ #%02X%02X,X", operation.instruction!.mnemonic, operation.data[1], operation.data[0])
|
||||
case .absolute_indexed_y:
|
||||
cellText = String(format: "%@ #%02X%02X,Y", operation.instruction!.mnemonic, operation.data[1], operation.data[0])
|
||||
case .zeropage_indexed_x:
|
||||
cellText = String(format: "%@ $%02X,X", operation.instruction!.mnemonic, operation.data[0])
|
||||
case .zeropage_indexed_y:
|
||||
cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[0])
|
||||
case .indexed_indirect:
|
||||
cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[0])
|
||||
case .indirect_indexed:
|
||||
cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[0])
|
||||
}
|
||||
}
|
||||
cellIdentifier = CellIdentifiers.DataCell
|
||||
}
|
||||
|
||||
if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView {
|
||||
cell.textField?.stringValue = cellText
|
||||
return cell
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DebuggerViewController: NSTableViewDataSource {
|
||||
func numberOfRows(in tableView: NSTableView) -> Int {
|
||||
return disassembly.count
|
||||
}
|
||||
|
||||
func getItem(atIndex: Int) -> Disassembly {
|
||||
return disassembly[atIndex]
|
||||
}
|
||||
}
|
@ -83,6 +83,15 @@ let InstructionTable: [UInt8:CPUInstruction] = [
|
||||
0xAC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDY),
|
||||
0xBC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDY),
|
||||
|
||||
//ST functions
|
||||
0x85: CPUInstruction(mnemonic: "STA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STA),
|
||||
0x95: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.STA),
|
||||
0x8D: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STA),
|
||||
0x9D: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.STA),
|
||||
0x99: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.STA),
|
||||
0x81: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.STA),
|
||||
0x91: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.STA),
|
||||
|
||||
//Register functions
|
||||
0x88: CPUInstruction(mnemonic: "DEY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEY),
|
||||
0x8A: CPUInstruction(mnemonic: "TXA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXA),
|
||||
|
@ -95,6 +95,32 @@ class CPUState: NSObject {
|
||||
page_boundary_crossed = false
|
||||
}
|
||||
|
||||
func disassemble(fromAddress: UInt16, length: UInt16) -> [Disassembly] {
|
||||
var disassembly: [Disassembly] = [Disassembly]()
|
||||
|
||||
var currentAddress: UInt16 = fromAddress
|
||||
let endAddress: UInt16 = fromAddress + length
|
||||
|
||||
while(currentAddress < endAddress) {
|
||||
let instruction = memoryInterface.readByte(offset: currentAddress)
|
||||
let operation = InstructionTable[instruction]
|
||||
var data = [UInt8]()
|
||||
|
||||
if(operation != nil) {
|
||||
for index in 1...operation!.bytes {
|
||||
data.append(memoryInterface.readByte(offset:currentAddress + UInt16(index)))
|
||||
}
|
||||
|
||||
disassembly.append(Disassembly(instruction: operation, address: currentAddress, data: data))
|
||||
currentAddress = currentAddress + UInt16(operation!.bytes)
|
||||
} else {
|
||||
currentAddress = currentAddress + 1
|
||||
}
|
||||
}
|
||||
|
||||
return disassembly
|
||||
}
|
||||
|
||||
func getOperandByte() -> UInt8 {
|
||||
//Returns the operand byte after the current instruction byte.
|
||||
return memoryInterface.readByte(offset: program_counter + 1)
|
||||
@ -111,6 +137,22 @@ class CPUState: NSObject {
|
||||
|
||||
return word
|
||||
}
|
||||
|
||||
func getInstructionBytes(atAddress: UInt16) -> [UInt8] {
|
||||
var bytes = [UInt8]()
|
||||
|
||||
let instruction = memoryInterface.readByte(offset: atAddress)
|
||||
let operation = InstructionTable[instruction]
|
||||
|
||||
if(operation != nil){
|
||||
for offset in 0...operation!.bytes {
|
||||
bytes.append(memoryInterface.readByte(offset: atAddress + UInt16(offset)))
|
||||
}
|
||||
}
|
||||
|
||||
return bytes
|
||||
|
||||
}
|
||||
|
||||
func executeNextInstruction() throws {
|
||||
instruction_register = memoryInterface.readByte(offset: program_counter)
|
||||
|
21
FruitMachine/M6502/Disassembly.swift
Normal file
21
FruitMachine/M6502/Disassembly.swift
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// Disassembly.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 7/22/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class Disassembly: NSObject {
|
||||
let instruction: CPUInstruction?
|
||||
let address: UInt16
|
||||
let data: [UInt8]
|
||||
|
||||
init(instruction: CPUInstruction?, address: UInt16, data: [UInt8]) {
|
||||
self.instruction = instruction
|
||||
self.address = address
|
||||
self.data = data
|
||||
}
|
||||
}
|
@ -65,6 +65,15 @@ func getOperandWordForAddressingMode(state: CPUState, mode: AddressingMode) -> U
|
||||
return state.getOperandWord() + state.index_y
|
||||
case .indirect:
|
||||
return state.memoryInterface.readWord(offset: state.getOperandWord())
|
||||
case .indexed_indirect:
|
||||
let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_x))
|
||||
//read from (ZP)
|
||||
let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp))
|
||||
return state.memoryInterface.readWord(offset: pointer)
|
||||
case .indirect_indexed:
|
||||
let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.getOperandByte()))
|
||||
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")
|
||||
return 0
|
||||
@ -97,6 +106,24 @@ class Opcodes: NSObject {
|
||||
state.updateNegativeFlag(value: state.index_y)
|
||||
}
|
||||
|
||||
static func STA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
let address: UInt16
|
||||
|
||||
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) {
|
||||
address = zpAsUInt16(address: state.getOperandByte())
|
||||
state.memoryInterface.writeByte(offset: address, value: state.accumulator)
|
||||
|
||||
}
|
||||
else if (addressingMode == .absolute || addressingMode == .absolute_indexed_x || addressingMode == .absolute_indexed_y || addressingMode == .indexed_indirect || addressingMode == .indirect_indexed) {
|
||||
address = state.getOperandWord()
|
||||
state.memoryInterface.writeByte(offset: address, value: state.accumulator)
|
||||
}
|
||||
else {
|
||||
print("Illegal addressing mode for STA")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//Register instructions
|
||||
static func TAX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = state.accumulator
|
||||
|
@ -1,59 +0,0 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 7/19/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ViewController: NSViewController {
|
||||
@IBOutlet weak var text_CPU_A: NSTextField!
|
||||
@IBOutlet weak var text_CPU_X: NSTextField!
|
||||
@IBOutlet weak var text_CPU_Y: NSTextField!
|
||||
@IBOutlet weak var text_CPU_IP: NSTextField!
|
||||
@IBOutlet weak var text_CPU_SR: NSTextField!
|
||||
|
||||
let CPU = CPUState.sharedInstance
|
||||
|
||||
func updateCPUStatusFields() {
|
||||
text_CPU_A.stringValue = String(format:"%02X", CPU.accumulator)
|
||||
text_CPU_X.stringValue = String(format:"%02X", CPU.index_x)
|
||||
text_CPU_Y.stringValue = String(format:"%02X", CPU.index_y)
|
||||
text_CPU_IP.stringValue = String(format:"%04X", CPU.instruction_register)
|
||||
text_CPU_SR.stringValue = String(format:"%02X", CPU.instruction_register)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
CPU.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin")
|
||||
updateCPUStatusFields()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override var representedObject: Any? {
|
||||
didSet {
|
||||
// Update the view, if already loaded.
|
||||
}
|
||||
}
|
||||
|
||||
func cpuStep() {
|
||||
do {
|
||||
try CPU.executeNextInstruction()
|
||||
updateCPUStatusFields()
|
||||
} catch CPUExceptions.invalidInstruction {
|
||||
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func btn_CPUStep(_ sender: Any) {
|
||||
cpuStep()
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user