From 87d5584eeee9e61264dfd02f49b04f5bdf60263c Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Sat, 22 Jul 2017 03:11:14 -0400 Subject: [PATCH] working --- FruitMachine/Base.lproj/Main.storyboard | 125 +++++++++++++++++++++-- FruitMachine/M6502/CPUInstructions.swift | 11 ++ FruitMachine/M6502/MemoryInterface.swift | 4 +- FruitMachine/M6502/Opcodes.swift | 68 ++++++++++-- FruitMachine/ViewController.swift | 37 +++++-- 5 files changed, 224 insertions(+), 21 deletions(-) diff --git a/FruitMachine/Base.lproj/Main.storyboard b/FruitMachine/Base.lproj/Main.storyboard index d295059..b34d67e 100644 --- a/FruitMachine/Base.lproj/Main.storyboard +++ b/FruitMachine/Base.lproj/Main.storyboard @@ -1,7 +1,9 @@ - - + + - + + + @@ -673,7 +675,7 @@ - + @@ -688,7 +690,7 @@ - + @@ -703,13 +705,124 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FruitMachine/M6502/CPUInstructions.swift b/FruitMachine/M6502/CPUInstructions.swift index a3ce30c..5c4ccea 100644 --- a/FruitMachine/M6502/CPUInstructions.swift +++ b/FruitMachine/M6502/CPUInstructions.swift @@ -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), diff --git a/FruitMachine/M6502/MemoryInterface.swift b/FruitMachine/M6502/MemoryInterface.swift index 50eeaea..b899198 100644 --- a/FruitMachine/M6502/MemoryInterface.swift +++ b/FruitMachine/M6502/MemoryInterface.swift @@ -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) { diff --git a/FruitMachine/M6502/Opcodes.swift b/FruitMachine/M6502/Opcodes.swift index 185693e..0fae35d 100644 --- a/FruitMachine/M6502/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes.swift @@ -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 {} } diff --git a/FruitMachine/ViewController.swift b/FruitMachine/ViewController.swift index 14d9201..b762103 100644 --- a/FruitMachine/ViewController.swift +++ b/FruitMachine/ViewController.swift @@ -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() + } }