This commit is contained in:
Luigi Thirty 2017-07-22 03:11:14 -04:00
parent e1a6a0c1b3
commit 87d5584eee
5 changed files with 224 additions and 21 deletions

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13156.6" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11134"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13156.6"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
@ -673,7 +675,7 @@
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider="target"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="FruitMachine" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
@ -688,7 +690,7 @@
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
@ -703,13 +705,124 @@
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<viewController id="XfG-lQ-9wD" customClass="ViewController" 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"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9cE-VZ-R2W">
<rect key="frame" x="18" y="233" 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"/>
<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="WjO-ue-iRg">
<rect key="frame" x="42" y="230" 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="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PyS-Mu-bnf">
<rect key="frame" x="18" y="203" 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"/>
<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="nOs-8C-MbH">
<rect key="frame" x="42" y="200" 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="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DmJ-LS-i50">
<rect key="frame" x="18" y="173" 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"/>
<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="eqA-qk-YQy">
<rect key="frame" x="42" y="170" 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="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<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">
<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="XbV-5m-dd0">
<rect key="frame" x="42" y="140" 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="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" 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"/>
<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="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="HdY-Jc-lNK">
<rect key="frame" x="50" y="13" width="81" 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"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<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"/>
<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>
</subviews>
</view>
<connections>
<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"/>
<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"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<userDefaultsController representsSharedInstance="YES" id="C79-Oc-seX"/>
</objects>
<point key="canvasLocation" x="75" y="655"/>
</scene>

View File

@ -46,6 +46,17 @@ class CPUInstruction: NSObject {
let InstructionTable: [UInt8:CPUInstruction] = [
//INC/DEC
0xC6: CPUInstruction(mnemonic: "DEC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.DEC),
0xD6: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.DEC),
0xCE: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.DEC),
0xDE: CPUInstruction(mnemonic: "DEC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.DEC),
0xE6: CPUInstruction(mnemonic: "INC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.INC),
0xF6: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.INC),
0xEE: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.INC),
0xFE: CPUInstruction(mnemonic: "INC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.INC),
//JMP
0x4C: CPUInstruction(mnemonic: "JMP", cycles: 3, bytes: 3, addressingMode: .absolute, action: Opcodes.JMP),
0x6C: CPUInstruction(mnemonic: "JMP", cycles: 5, bytes: 3, addressingMode: .indirect, action: Opcodes.JMP),

View File

@ -25,7 +25,9 @@ class MemoryInterface: NSObject {
}
func readWord(offset: UInt16) -> UInt16 {
return UInt16(memory[Int(offset)] | (memory[Int(offset+1)] << 8))
let low: UInt8 = memory[Int(offset)]
let high: UInt8 = memory[Int(offset+1)]
return (UInt16(high) << 8) | UInt16(low)
}
func loadBinary(path: String) {

View File

@ -12,7 +12,11 @@ func stackPointerAsUInt16(state: CPUState) -> UInt16 {
return 0x0100 | UInt16(state.stack_pointer);
}
func getOperand(state: CPUState, mode: AddressingMode) -> UInt8 {
func zpAsUInt16(address: UInt8) -> UInt16 {
return 0x0000 | UInt16(address)
}
func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 {
switch (mode) {
case .immediate:
@ -48,7 +52,7 @@ func getOperand(state: CPUState, mode: AddressingMode) -> UInt8 {
}
}
func getOperand(state: CPUState, mode: AddressingMode) -> UInt16 {
func getOperandWordForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt16 {
//Function that will provide a 16-bit operand to instructions.
//All instructions have 2 data bytes, little-endian.
@ -73,21 +77,21 @@ func getOperand(state: CPUState, mode: AddressingMode) -> UInt16 {
class Opcodes: NSObject {
static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void {
state.accumulator = getOperand(state: state, mode: addressingMode)
state.accumulator = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.accumulator)
state.updateNegativeFlag(value: state.accumulator)
}
static func LDX(state: CPUState, addressingMode: AddressingMode) -> Void {
state.index_x = getOperand(state: state, mode: addressingMode)
state.index_x = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.index_x)
state.updateNegativeFlag(value: state.index_x)
}
static func LDY(state: CPUState, addressingMode: AddressingMode) -> Void {
state.index_y = getOperand(state: state, mode: addressingMode)
state.index_y = getOperandByteForAddressingMode(state: state, mode: addressingMode)
state.updateZeroFlag(value: state.index_y)
state.updateNegativeFlag(value: state.index_y)
@ -150,6 +154,56 @@ class Opcodes: NSObject {
state.updateNegativeFlag(value: state.index_y);
}
static func INC(state: CPUState, addressingMode: AddressingMode) -> Void {
let address: UInt16
var val: UInt8
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) {
address = zpAsUInt16(address: state.getOperandByte())
val = state.memoryInterface.readByte(offset: address)
}
else if (addressingMode == .absolute || addressingMode == .absolute_indexed_x) {
address = state.getOperandWord()
val = state.memoryInterface.readByte(offset: address)
}
else {
print("Illegal addressing mode for INC")
return
}
val = val &+ 1
state.memoryInterface.writeByte(offset: address, value: val)
state.updateZeroFlag(value: val);
state.updateNegativeFlag(value: val);
}
static func DEC(state: CPUState, addressingMode: AddressingMode) -> Void {
let address: UInt16
var val: UInt8
if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) {
address = zpAsUInt16(address: state.getOperandByte())
val = state.memoryInterface.readByte(offset: address)
}
else if (addressingMode == .absolute || addressingMode == .absolute_indexed_x) {
address = state.getOperandWord()
val = state.memoryInterface.readByte(offset: address)
}
else {
print("Illegal addressing mode for INC")
return
}
val = val &- 1
state.memoryInterface.writeByte(offset: address, value: val)
state.updateZeroFlag(value: val);
state.updateNegativeFlag(value: val);
}
//Processor flag instructions
static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void {
state.status_register.carry = false
@ -214,9 +268,11 @@ class Opcodes: NSObject {
state.status_register.fromByte(state: state.memoryInterface.readByte(offset: stackPointerAsUInt16(state: state)))
}
//Misc
static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void {
state.program_counter = getOperand(state: state, mode: addressingMode)
state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode)
}
static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {}
}

View File

@ -9,21 +9,28 @@
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 {
try CPU.executeNextInstruction()
try CPU.executeNextInstruction()
} catch CPUExceptions.invalidInstruction {
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
} catch {
print(error)
}
// Do any additional setup after loading the view.
}
@ -33,6 +40,20 @@ class ViewController: NSViewController {
}
}
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()
}
}