From 9bc97a70223bd38a0f963aa27b2b7c887f8ace58 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Fri, 21 Jul 2017 03:25:48 -0400 Subject: [PATCH] more opcodes --- FruitMachine.xcodeproj/project.pbxproj | 5 + FruitMachine/M6502/CPUInstructions.swift | 54 ++++- FruitMachine/M6502/CPUState.swift | 52 ++++- FruitMachine/M6502/IntegerExtensions.swift | 15 ++ FruitMachine/M6502/MemoryInterface.swift | 12 ++ FruitMachine/M6502/Opcodes.swift | 240 +++++++++++++++------ FruitMachine/ViewController.swift | 10 +- 7 files changed, 318 insertions(+), 70 deletions(-) create mode 100644 FruitMachine/M6502/IntegerExtensions.swift diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 32f7053..f53124a 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* 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 */; }; 2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; }; @@ -18,6 +19,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerExtensions.swift; sourceTree = ""; }; 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 = ""; }; 2AD458CF1F205EB700F05121 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -79,6 +81,7 @@ 2AD458E21F20661300F05121 /* CPUInstructions.swift */, 2AD458E41F2070DF00F05121 /* Opcodes.swift */, 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */, + 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */, ); path = M6502; sourceTree = ""; @@ -156,6 +159,7 @@ 2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */, 2AD458D01F205EB700F05121 /* ViewController.swift in Sources */, 2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */, + 2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */, 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */, 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */, 2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */, @@ -329,6 +333,7 @@ 2AD458DC1F205EB700F05121 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/FruitMachine/M6502/CPUInstructions.swift b/FruitMachine/M6502/CPUInstructions.swift index 13f71f6..bf290d3 100644 --- a/FruitMachine/M6502/CPUInstructions.swift +++ b/FruitMachine/M6502/CPUInstructions.swift @@ -41,11 +41,59 @@ class CPUInstruction: NSObject { } } +//indexed_indirect = LDA ($00,X) +//indirect_indexed = LDA ($00),Y + let InstructionTable: [UInt8:CPUInstruction] = [ - 0xA5: CPUInstruction.init(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA), + + //LD instructions 0xA9: CPUInstruction.init(mnemonic: "LDA", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDA), - 0xAD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA), + 0xA5: CPUInstruction.init(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA), 0xB5: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDA), - 0xB9: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA), + 0xAD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA), 0xBD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDA), + 0xB9: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA), + 0xA1: CPUInstruction.init(mnemonic: "LDA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.LDA), + 0xB1: CPUInstruction.init(mnemonic: "LDA", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.LDA), + + 0xA2: CPUInstruction.init(mnemonic: "LDX", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDX), + 0xA6: CPUInstruction.init(mnemonic: "LDX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDX), + 0xB6: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.LDX), + 0xAE: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDX), + 0xBE: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDX), + + 0xA0: CPUInstruction.init(mnemonic: "LDY", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDY), + 0xA4: CPUInstruction.init(mnemonic: "LDY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDY), + 0xB4: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDY), + 0xAC: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDY), + 0xBC: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDY), + + //Register functions + 0x88: CPUInstruction.init(mnemonic: "DEY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEY), + 0x8A: CPUInstruction.init(mnemonic: "TXA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXA), + 0x98: CPUInstruction.init(mnemonic: "TYA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TYA), + 0xA8: CPUInstruction.init(mnemonic: "TAY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAY), + 0xAA: CPUInstruction.init(mnemonic: "TAX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAX), + 0xC8: CPUInstruction.init(mnemonic: "INY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INY), + 0xCA: CPUInstruction.init(mnemonic: "DEX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEX), + 0xE8: CPUInstruction.init(mnemonic: "INX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INX), + + //Processor flag instructions + 0x18: CPUInstruction.init(mnemonic: "CLC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLC), + 0x38: CPUInstruction.init(mnemonic: "SEC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEC), + 0x58: CPUInstruction.init(mnemonic: "CLI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLI), + 0x78: CPUInstruction.init(mnemonic: "SEI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEI), + 0xB8: CPUInstruction.init(mnemonic: "CLV", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLV), + 0xD8: CPUInstruction.init(mnemonic: "CLD", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLD), + 0xF8: CPUInstruction.init(mnemonic: "SED", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SED), + + //Stack instructions + 0x9A: CPUInstruction.init(mnemonic: "TXS", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXS), + 0xBA: CPUInstruction.init(mnemonic: "TSX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TSX), + 0x48: CPUInstruction.init(mnemonic: "PHA", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHA), + 0x68: CPUInstruction.init(mnemonic: "PLA", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLA), + 0x08: CPUInstruction.init(mnemonic: "PHP", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHP), + 0x28: CPUInstruction.init(mnemonic: "PLP", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLP), + + 0xEA: CPUInstruction.init(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP), ] diff --git a/FruitMachine/M6502/CPUState.swift b/FruitMachine/M6502/CPUState.swift index 5e63dd4..6e33ff2 100644 --- a/FruitMachine/M6502/CPUState.swift +++ b/FruitMachine/M6502/CPUState.swift @@ -31,6 +31,34 @@ struct StatusRegister { zero = (state & 0x02 == 0x02) carry = (state & 0x01 == 0x01) } + + func asByte() -> UInt8 { + var val: UInt8 = 0x00 + + if(negative) { + val |= 0x80 + } + if(overflow) { + val |= 0x40 + } + if(brk) { + val |= 0x10 + } + if(decimal) { + val |= 0x08 + } + if(irq_disable) { + val |= 0x04 + } + if(zero) { + val |= 0x02 + } + if(carry) { + val |= 0x01 + } + + return val + } } class CPUState: NSObject { @@ -67,6 +95,23 @@ class CPUState: NSObject { page_boundary_crossed = false } + func getOperandByte() -> UInt8 { + //Returns the operand byte after the current instruction byte. + return memoryInterface.readByte(offset: program_counter + 1) + } + + func getOperandWord() -> UInt16 { + var word: UInt16 + let low = memoryInterface.readByte(offset: program_counter + 1) + let high = memoryInterface.readByte(offset: program_counter + 2) + + word = UInt16(high) + word = word << 8 + word |= UInt16(low) + + return word + } + func executeNextInstruction() throws { instruction_register = memoryInterface.memory[Int(program_counter)] let operation = InstructionTable[instruction_register] @@ -81,13 +126,16 @@ class CPUState: NSObject { self.cycles += 1 self.page_boundary_crossed = false } + + self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes) } - func setNegativeFlag() { + func updateNegativeFlag() { status_register.negative = (accumulator & 0x80 == 0x80) } - func setZeroFlag() { + func updateZeroFlag() { status_register.zero = (accumulator == 0) } + } diff --git a/FruitMachine/M6502/IntegerExtensions.swift b/FruitMachine/M6502/IntegerExtensions.swift new file mode 100644 index 0000000..13bfdda --- /dev/null +++ b/FruitMachine/M6502/IntegerExtensions.swift @@ -0,0 +1,15 @@ +// +// IntegerExtensions.swift +// FruitMachine +// +// Created by Christopher Rohl on 7/20/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +extension UInt16 { + static func + (left: UInt16, right: UInt8) -> UInt16 { + return left + right + } +} diff --git a/FruitMachine/M6502/MemoryInterface.swift b/FruitMachine/M6502/MemoryInterface.swift index 1ff0820..0abe27a 100644 --- a/FruitMachine/M6502/MemoryInterface.swift +++ b/FruitMachine/M6502/MemoryInterface.swift @@ -14,4 +14,16 @@ class MemoryInterface: NSObject { override init() { memory = [UInt8](repeating: 0x00, count: 65536) } + + func readByte(offset: UInt16) -> UInt8 { + return memory[Int(offset)] + } + + func writeByte(offset: UInt16, value: UInt8) { + memory[Int(offset)] = value + } + + func readWord(offset: UInt16) -> UInt16 { + return UInt16(memory[Int(offset)] | (memory[Int(offset+1)] << 8)) + } } diff --git a/FruitMachine/M6502/Opcodes.swift b/FruitMachine/M6502/Opcodes.swift index 3f27cd0..a102b1d 100644 --- a/FruitMachine/M6502/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes.swift @@ -8,72 +8,188 @@ import Cocoa -/* Addressing mode helper functions */ -func PC_PLUS_1(state: CPUState) -> UInt16 { - return state.program_counter + 1 +func getOperand(state: CPUState, mode: AddressingMode) -> UInt8 { + switch (mode) { + + case .immediate: + return state.getOperandByte() + + case .zeropage: + return state.memoryInterface.readByte(offset: UInt16(0x0000 + state.getOperandByte())) + case .zeropage_indexed_x: + return state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_x) & 0x00FF) + case .zeropage_indexed_y: + return state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_y) & 0x00FF) + + case .absolute: + let word: UInt16 = state.getOperandWord() + return state.memoryInterface.readByte(offset: word) + case .absolute_indexed_x: + return state.memoryInterface.readByte(offset: state.getOperandWord() + UInt16(state.index_x)) + case .absolute_indexed_y: + return state.memoryInterface.readByte(offset: state.getOperandWord() + UInt16(state.index_y)) + + 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)) + state.accumulator = state.memoryInterface.readByte(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) + state.accumulator = state.memoryInterface.readByte(offset: pointer) + + case .indirect: + //JMP is the only instruction that does this - handle it specially since it's a UInt16 + break + + default: + print("Called getOperand on an instruction in addressing mode \(mode)") + return 0 + } + + return 0 //never gets here } -func OPERAND_IMMEDIATE(state: CPUState) -> UInt8 { - //Operand = PC+1 - return MEMORY_READ_UINT8(state: state, address: state.program_counter + 1) -} - -func OPERAND_ZEROPAGE_INDEXED_X(state: CPUState) -> UInt8 { - //Operand = (PC+1) + X - return MEMORY_READ_UINT8(state: state, address: (state.program_counter + 1) + UInt16(state.index_x)) -} - -func OPERAND_ZEROPAGE_INDEXED_Y(state: CPUState) -> UInt8 { - //Operand = (PC+1) + Y - return MEMORY_READ_UINT8(state: state, address: (state.program_counter + 1) + UInt16(state.index_y)) -} - -func OPERAND_ABSOLUTE(state: CPUState) -> UInt16 { - //Operand = L:(PC+1) H:(PC+2) - let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1) - let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2) - return UInt16(high << 8 | low) -} - -func OPERAND_ABSOLUTE_INDEXED_X(state: CPUState) -> UInt16 { - //Operand = L:(PC+1)+X H:(PC+2)+X - let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1 + UInt16(state.index_x)) - let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2 + UInt16(state.index_x)) - return UInt16(high << 8 | low) -} - -func OPERAND_ABSOLUTE_INDEXED_Y(state: CPUState) -> UInt16 { - //Operand = L:(PC+1)+Y H:(PC+2)+Y - let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1 + UInt16(state.index_y)) - let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2 + UInt16(state.index_y)) - return UInt16(high << 8 | low) -} - -func MEMORY_READ_UINT8(state: CPUState, address: UInt16) -> UInt8 { - return state.memoryInterface.memory[Int(address)] -} +/* */ class Opcodes: NSObject { + static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void { - - switch addressingMode { - case .immediate: - state.accumulator = OPERAND_IMMEDIATE(state: state) - case .zeropage: - state.accumulator = OPERAND_ZEROPAGE_INDEXED_X(state: state) - case .zeropage_indexed_x: - state.accumulator = MEMORY_READ_UINT8(state: state, address: UInt16(0x0000 + OPERAND_ZEROPAGE_INDEXED_X(state: state))) - case .absolute: - state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE(state: state)) - case .absolute_indexed_x: - state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE_INDEXED_X(state: state)) - case .absolute_indexed_y: - state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE_INDEXED_Y(state: state)) - default: - print("Unhandled addressing mode \(addressingMode) for LDA") - } - - state.setZeroFlag(); - state.setNegativeFlag(); + state.accumulator = getOperand(state: state, mode: addressingMode) + + state.updateZeroFlag() + state.updateNegativeFlag() } + + static func LDX(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_x = getOperand(state: state, mode: addressingMode) + + state.updateZeroFlag() + state.updateNegativeFlag() + } + + static func LDY(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_y = getOperand(state: state, mode: addressingMode) + + state.updateZeroFlag() + state.updateNegativeFlag() + } + + //Register instructions + static func TAX(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_x = state.accumulator + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func TXA(state: CPUState, addressingMode: AddressingMode) -> Void { + state.accumulator = state.index_x + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func DEX(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_x = state.index_x &- 1 + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func INX(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_x = state.index_x &+ 1 + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func TAY(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_y = state.accumulator + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func TYA(state: CPUState, addressingMode: AddressingMode) -> Void { + state.accumulator = state.index_y + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func DEY(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_y = state.index_x &- 1 + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + static func INY(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_y = state.index_x &+ 1 + + state.updateZeroFlag(); + state.updateNegativeFlag(); + } + + //Processor flag instructions + static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.carry = false + } + + static func SEC(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.carry = true + } + + static func CLI(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.irq_disable = false + } + + static func SEI(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.irq_disable = true + } + + static func CLV(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.overflow = false + } + + static func CLD(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.decimal = false + } + + static func SED(state: CPUState, addressingMode: AddressingMode) -> Void { + state.status_register.carry = true + } + + //Stack instructions + static func TXS(state: CPUState, addressingMode: AddressingMode) -> Void { + state.stack_pointer = state.index_x + } + + static func TSX(state: CPUState, addressingMode: AddressingMode) -> Void { + state.index_x = state.stack_pointer + } + + static func PHA(state: CPUState, addressingMode: AddressingMode) -> Void { + state.memoryInterface.writeByte(offset: 0x0100 | UInt16(state.stack_pointer), value: state.accumulator) + state.stack_pointer = state.stack_pointer &- 1 + } + + static func PLA(state: CPUState, addressingMode: AddressingMode) -> Void { + state.stack_pointer = state.stack_pointer &+ 1 + state.accumulator = state.memoryInterface.readByte(offset: 0x0100 | UInt16(state.stack_pointer)) + } + + static func PHP(state: CPUState, addressingMode: AddressingMode) -> Void { + state.memoryInterface.writeByte(offset: 0x0100 | UInt16(state.stack_pointer), value: state.status_register.asByte()) + state.stack_pointer = state.stack_pointer &- 1 + } + + static func PLP(state: CPUState, addressingMode: AddressingMode) -> Void { + state.stack_pointer = state.stack_pointer &+ 1 + state.status_register.setState(state: state.memoryInterface.readByte(offset: 0x0100 | UInt16(state.stack_pointer))) + } + + static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {} } diff --git a/FruitMachine/ViewController.swift b/FruitMachine/ViewController.swift index 1cf55c8..3352dd5 100644 --- a/FruitMachine/ViewController.swift +++ b/FruitMachine/ViewController.swift @@ -15,11 +15,15 @@ class ViewController: NSViewController { super.viewDidLoad() CPU.memoryInterface.memory[0] = 0xAD - CPU.memoryInterface.memory[1] = 0x00 - CPU.memoryInterface.memory[2] = 0x00 - + + CPU.memoryInterface.memory[1] = 0x34 + CPU.memoryInterface.memory[2] = 0x12 + + CPU.memoryInterface.memory[0x1234] = 0xAA + do { try CPU.executeNextInstruction() + try CPU.executeNextInstruction() } catch CPUExceptions.invalidInstruction { print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX") } catch {