From a0d28938b72bc41b43aae6c784f1da91daa04a36 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Mon, 24 Jul 2017 03:29:12 -0400 Subject: [PATCH] debugging! --- FruitMachine.xcodeproj/project.pbxproj | 8 +- FruitMachine/Base.lproj/Main.storyboard | 292 ++++++++++-------- FruitMachine/DebuggerViewController.swift | 97 ++++-- .../M6502/{CPUState.swift => CPU.swift} | 35 +-- FruitMachine/M6502/CPUInstructions.swift | 5 +- FruitMachine/M6502/Disassembly.swift | 28 ++ FruitMachine/M6502/Opcodes.swift | 147 +++++---- 7 files changed, 366 insertions(+), 246 deletions(-) rename FruitMachine/M6502/{CPUState.swift => CPU.swift} (82%) diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 19396ed..de4da2f 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ 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 */; }; + 2AD458DF1F205F4500F05121 /* CPU.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458DE1F205F4500F05121 /* CPU.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 */; }; @@ -29,7 +29,7 @@ 2AD458D41F205EB700F05121 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 2AD458D61F205EB700F05121 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 2AD458D71F205EB700F05121 /* FruitMachine.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FruitMachine.entitlements; sourceTree = ""; }; - 2AD458DE1F205F4500F05121 /* CPUState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUState.swift; sourceTree = ""; }; + 2AD458DE1F205F4500F05121 /* CPU.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPU.swift; sourceTree = ""; }; 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryInterface.swift; sourceTree = ""; }; 2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = ""; }; 2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = ""; }; @@ -81,7 +81,7 @@ 2AD458DD1F205F0D00F05121 /* M6502 */ = { isa = PBXGroup; children = ( - 2AD458DE1F205F4500F05121 /* CPUState.swift */, + 2AD458DE1F205F4500F05121 /* CPU.swift */, 2AD458E21F20661300F05121 /* CPUInstructions.swift */, 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */, 2AD458E41F2070DF00F05121 /* Opcodes.swift */, @@ -170,7 +170,7 @@ 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */, 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */, 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */, - 2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */, + 2AD458DF1F205F4500F05121 /* CPU.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FruitMachine/Base.lproj/Main.storyboard b/FruitMachine/Base.lproj/Main.storyboard index 915ca2b..07316cb 100644 --- a/FruitMachine/Base.lproj/Main.storyboard +++ b/FruitMachine/Base.lproj/Main.storyboard @@ -679,7 +679,7 @@ - + @@ -688,7 +688,7 @@ - + @@ -700,14 +700,14 @@ - + - + @@ -800,125 +800,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -937,6 +818,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -952,7 +996,7 @@ - + diff --git a/FruitMachine/DebuggerViewController.swift b/FruitMachine/DebuggerViewController.swift index e7d0bb6..f019f74 100644 --- a/FruitMachine/DebuggerViewController.swift +++ b/FruitMachine/DebuggerViewController.swift @@ -18,13 +18,17 @@ class DebuggerViewController: NSViewController { @IBOutlet weak var debuggerTableView: NSTableView! - let CPU = CPUState.sharedInstance + var cpuInstance = CPU.sharedInstance + var isRunning = false + var disassembly: [Disassembly] = [Disassembly]() func highlightCurrentInstruction() -> Bool { for (index, instruction) in disassembly.enumerated() { - if(instruction.address == CPU.program_counter) { + if(instruction.address == cpuInstance.program_counter) { debuggerTableView.selectRowIndexes(NSIndexSet(index: index) as IndexSet, byExtendingSelection: false) + debuggerTableView.scrollRowToVisible(index+10) + debuggerTableView.scrollRowToVisible(index-5) return true //instruction found } } @@ -32,15 +36,15 @@ class DebuggerViewController: NSViewController { } 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) - text_CPU_Flags.stringValue = String(CPU.status_register.asString()) + text_CPU_A.stringValue = String(format:"%02X", cpuInstance.accumulator) + text_CPU_X.stringValue = String(format:"%02X", cpuInstance.index_x) + text_CPU_Y.stringValue = String(format:"%02X", cpuInstance.index_y) + text_CPU_IP.stringValue = String(format:"%04X", cpuInstance.program_counter) + text_CPU_SR.stringValue = String(format:"%02X", cpuInstance.stack_pointer) + text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString()) if(!highlightCurrentInstruction()) { - disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 256) + disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 256) highlightCurrentInstruction() } } @@ -51,11 +55,11 @@ class DebuggerViewController: NSViewController { debuggerTableView.delegate = self debuggerTableView.dataSource = self - CPU.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin") - CPU.performReset() - CPU.program_counter = 0x400 //entry point for the test program + cpuInstance.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin") + cpuInstance.performReset() + cpuInstance.program_counter = 0x400 //entry point for the test program updateCPUStatusFields() - disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 10000) + disassembly = cpuInstance.disassemble(fromAddress: cpuInstance.program_counter, length: 10000) debuggerTableView.reloadData() // Do any additional setup after loading the view. @@ -69,8 +73,7 @@ class DebuggerViewController: NSViewController { func cpuStep() { do { - try CPU.executeNextInstruction() - updateCPUStatusFields() + try cpuInstance.executeNextInstruction() } catch CPUExceptions.invalidInstruction { print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX") } catch { @@ -78,13 +81,39 @@ 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() + } + }) + } + } + } + @IBAction func btn_CPUStep(_ sender: Any) { cpuStep() + updateCPUStatusFields() } @IBAction func btn_Break(_ sender: Any) { + isRunning = false _ = 0 } + + @IBAction func btn_CPURun(_ sender: Any) { + cpuRun() + } + + } extension DebuggerViewController: NSTableViewDelegate { @@ -92,6 +121,7 @@ extension DebuggerViewController: NSTableViewDelegate { fileprivate enum CellIdentifiers { static let AddressCell = "AddressCellID" static let DataCell = "DataCellID" + static let BytesCell = "BytesCellID" } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { @@ -112,34 +142,49 @@ extension DebuggerViewController: NSTableViewDelegate { case .accumulator: cellText = String(format: "%@ A", operation.instruction!.mnemonic) case .immediate: - cellText = String(format: "%@ #$%02X", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ #$%02X", operation.instruction!.mnemonic, operation.data[1]) case .implied: cellText = String(format: "%@", operation.instruction!.mnemonic) case .relative: - cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, UInt16(operation.data[0]) + operation.address) + var destination: UInt16 = operation.address + if((operation.data[1] & 0x80) == 0x80) { + destination = destination + 1 - UInt16(~operation.data[1]) + } else { + destination = destination + UInt16(operation.data[1]) + } + cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, destination) case .absolute: - cellText = String(format: "%@ $%02X%02X", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) + cellText = String(format: "%@ $%02X%02X", operation.instruction!.mnemonic, operation.data[2], operation.data[1]) case .zeropage: - cellText = String(format: "%@ $%02X", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ $%02X", operation.instruction!.mnemonic, operation.data[1]) case .indirect: - cellText = String(format: "%@ ($%02X%02X)", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) + cellText = String(format: "%@ ($%02X%02X)", operation.instruction!.mnemonic, operation.data[2], operation.data[1]) case .absolute_indexed_x: - cellText = String(format: "%@ $%02X%02X,X", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) + cellText = String(format: "%@ $%02X%02X,X", operation.instruction!.mnemonic, operation.data[2], operation.data[1]) case .absolute_indexed_y: - cellText = String(format: "%@ $%02X%02X,Y", operation.instruction!.mnemonic, operation.data[1], operation.data[0]) + cellText = String(format: "%@ $%02X%02X,Y", operation.instruction!.mnemonic, operation.data[2], operation.data[1]) case .zeropage_indexed_x: - cellText = String(format: "%@ $%02X,X", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ $%02X,X", operation.instruction!.mnemonic, operation.data[1]) case .zeropage_indexed_y: - cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[1]) case .indexed_indirect: - cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[1]) case .indirect_indexed: - cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[0]) + cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[1]) } } cellIdentifier = CellIdentifiers.DataCell } + if(tableColumn == tableView.tableColumns[2]) { + cellText = "" + for byte in operation.data { + cellText += String(format: "%02X ", byte) + } + + cellIdentifier = CellIdentifiers.BytesCell + } + if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView { cell.textField?.stringValue = cellText return cell diff --git a/FruitMachine/M6502/CPUState.swift b/FruitMachine/M6502/CPU.swift similarity index 82% rename from FruitMachine/M6502/CPUState.swift rename to FruitMachine/M6502/CPU.swift index e1777a4..225816d 100644 --- a/FruitMachine/M6502/CPUState.swift +++ b/FruitMachine/M6502/CPU.swift @@ -105,12 +105,12 @@ struct StatusRegister { } } -class CPUState: NSObject { +class CPU: NSObject { let NMI_VECTOR: UInt16 = 0xFFFA let RESET_VECTOR: UInt16 = 0xFFFC let IRQ_VECTOR: UInt16 = 0xFFFE - static var sharedInstance = CPUState() + static var sharedInstance = CPU() var cycles: Int @@ -124,11 +124,10 @@ class CPUState: NSObject { var status_register: StatusRegister var page_boundary_crossed: Bool + var branch_was_taken: Bool var memoryInterface: MemoryInterface - var branch_was_taken: Bool - override init() { cycles = 0 @@ -149,32 +148,6 @@ class CPUState: NSObject { } - 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) @@ -215,7 +188,7 @@ class CPUState: NSObject { throw CPUExceptions.invalidInstruction } - operation!.action(CPUState.sharedInstance, operation!.addressingMode) + operation!.action(CPU.sharedInstance, operation!.addressingMode) self.cycles += operation!.cycles if(self.page_boundary_crossed) { diff --git a/FruitMachine/M6502/CPUInstructions.swift b/FruitMachine/M6502/CPUInstructions.swift index 7ef976a..7188fd6 100644 --- a/FruitMachine/M6502/CPUInstructions.swift +++ b/FruitMachine/M6502/CPUInstructions.swift @@ -30,9 +30,9 @@ class CPUInstruction: NSObject { let bytes: Int //How many bytes long is this instruction? let addressingMode: AddressingMode //The addressing mode of this instruction. - let action: (CPUState, AddressingMode) -> Void //A closure that describes this function's action. + let action: (CPU, AddressingMode) -> Void //A closure that describes this function's action. - init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: AddressingMode, action: @escaping (CPUState, AddressingMode) -> Void) { + init(mnemonic: String, cycles: Int, bytes: Int, addressingMode: AddressingMode, action: @escaping (CPU, AddressingMode) -> Void) { self.mnemonic = mnemonic self.cycles = cycles self.bytes = bytes @@ -222,6 +222,7 @@ let InstructionTable: [UInt8:CPUInstruction] = [ 0xF0: CPUInstruction(mnemonic: "BEQ", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BEQ), 0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR), + 0x40: CPUInstruction(mnemonic: "RTI", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTI), 0x60: CPUInstruction(mnemonic: "RTS", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTS), 0x00: CPUInstruction(mnemonic: "BRK", cycles: 7, bytes: 1, addressingMode: .implied, action: Opcodes.BRK), diff --git a/FruitMachine/M6502/Disassembly.swift b/FruitMachine/M6502/Disassembly.swift index d6d1ccd..278423c 100644 --- a/FruitMachine/M6502/Disassembly.swift +++ b/FruitMachine/M6502/Disassembly.swift @@ -19,3 +19,31 @@ class Disassembly: NSObject { self.data = data } } + +extension CPU { + 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-1))) + } + + disassembly.append(Disassembly(instruction: operation, address: currentAddress, data: data)) + currentAddress = currentAddress + UInt16(operation!.bytes) + } else { + currentAddress = currentAddress + 1 + } + } + + return disassembly + } +} diff --git a/FruitMachine/M6502/Opcodes.swift b/FruitMachine/M6502/Opcodes.swift index 67bbe2d..738b762 100644 --- a/FruitMachine/M6502/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes.swift @@ -8,7 +8,7 @@ import Cocoa -extension CPUState { +extension CPU { func popByte() -> UInt8 { stack_pointer = stack_pointer &+ 1 @@ -57,7 +57,7 @@ extension CPUState { } } -func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 { +func getOperandByteForAddressingMode(state: CPU, mode: AddressingMode) -> UInt8 { switch (mode) { case .immediate: @@ -93,7 +93,7 @@ func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> U } } -func getOperandWordForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt16 { +func getOperandWordForAddressingMode(state: CPU, mode: AddressingMode) -> UInt16 { //Function that will provide a 16-bit operand to instructions. //All instructions have 2 data bytes, little-endian. @@ -132,9 +132,7 @@ func hex2bcd(hex: UInt8) -> UInt8 { class Opcodes: NSObject { - static func ADC(state: CPUState, addressingMode: AddressingMode) -> Void { - let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)) - + static func _Add(state: CPU, operand: UInt8) { var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0))) let t8: UInt8 = UInt8(t16 & 0xFF) @@ -151,28 +149,54 @@ class Opcodes: NSObject { state.accumulator = (UInt8(t16 & 0xFF)) } - static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func ADC(state: CPU, addressingMode: AddressingMode) -> Void { + _Add(state: state, operand: UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))) + /* + let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)) + + var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0))) + let t8: UInt8 = UInt8(t16 & 0xFF) + + state.status_register.overflow = (~(state.accumulator ^ operand) & (state.accumulator ^ t8) & 0x80) == 0x80 + state.status_register.zero = (t8 == 0) + state.status_register.negative = (t8 & 0x80) == 0x80 + + if(state.status_register.decimal) { + t16 = UInt16(hex2bcd(hex: state.accumulator) + hex2bcd(hex: operand) + (state.status_register.carry ? UInt8(1) : UInt8(0))) + } else { + state.status_register.carry = (t16 > 255) + } + + state.accumulator = (UInt8(t16 & 0xFF)) + */ + } + + static func SBC(state: CPU, addressingMode: AddressingMode) -> Void { + _Add(state: state, operand: ~(UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode)))) + } + + static func LDA(state: CPU, addressingMode: AddressingMode) -> Void { 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 { + static func LDX(state: CPU, addressingMode: AddressingMode) -> Void { 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 { + static func LDY(state: CPU, addressingMode: AddressingMode) -> Void { state.index_y = getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.index_y) state.updateNegativeFlag(value: state.index_y) } - static func STA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func STA(state: CPU, addressingMode: AddressingMode) -> Void { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { @@ -190,7 +214,7 @@ class Opcodes: NSObject { } } - static func STX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func STX(state: CPU, addressingMode: AddressingMode) -> Void { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_y) { @@ -208,7 +232,7 @@ class Opcodes: NSObject { } } - static func STY(state: CPUState, addressingMode: AddressingMode) -> Void { + static func STY(state: CPU, addressingMode: AddressingMode) -> Void { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { @@ -227,63 +251,63 @@ class Opcodes: NSObject { } //Register instructions - static func TAX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TAX(state: CPU, addressingMode: AddressingMode) -> Void { state.index_x = state.accumulator state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func TXA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TXA(state: CPU, addressingMode: AddressingMode) -> Void { state.accumulator = state.index_x state.updateZeroFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator); } - static func DEX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func DEX(state: CPU, addressingMode: AddressingMode) -> Void { state.index_x = state.index_x &- 1 state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func INX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func INX(state: CPU, addressingMode: AddressingMode) -> Void { state.index_x = state.index_x &+ 1 state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func TAY(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TAY(state: CPU, addressingMode: AddressingMode) -> Void { state.index_y = state.accumulator state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func TYA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TYA(state: CPU, addressingMode: AddressingMode) -> Void { state.accumulator = state.index_y state.updateZeroFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator); } - static func DEY(state: CPUState, addressingMode: AddressingMode) -> Void { + static func DEY(state: CPU, addressingMode: AddressingMode) -> Void { state.index_y = state.index_x &- 1 state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func INY(state: CPUState, addressingMode: AddressingMode) -> Void { + static func INY(state: CPU, addressingMode: AddressingMode) -> Void { state.index_y = state.index_x &+ 1 state.updateZeroFlag(value: state.index_y); state.updateNegativeFlag(value: state.index_y); } - static func INC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func INC(state: CPU, addressingMode: AddressingMode) -> Void { let address: UInt16 var val: UInt8 @@ -308,7 +332,7 @@ class Opcodes: NSObject { state.updateNegativeFlag(value: val); } - static func DEC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func DEC(state: CPU, addressingMode: AddressingMode) -> Void { let address: UInt16 var val: UInt8 @@ -334,7 +358,7 @@ class Opcodes: NSObject { } //CMP - static func CMP(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CMP(state: CPU, addressingMode: AddressingMode) -> Void { let data = state.accumulator - state.getOperandByte() //CMP is a subtract that doesn't affect memory state.updateZeroFlag(value: data) @@ -342,7 +366,7 @@ class Opcodes: NSObject { state.status_register.carry = (data >= 0) } - static func CPX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CPX(state: CPU, addressingMode: AddressingMode) -> Void { let data = state.index_x - state.getOperandByte() //CMP is a subtract that doesn't affect memory state.updateZeroFlag(value: data) @@ -350,7 +374,7 @@ class Opcodes: NSObject { state.status_register.carry = (data >= 0) } - static func CPY(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CPY(state: CPU, addressingMode: AddressingMode) -> Void { let data = state.index_y - state.getOperandByte() //CMP is a subtract that doesn't affect memory state.updateZeroFlag(value: data) @@ -359,21 +383,21 @@ class Opcodes: NSObject { } //Boolean operators - static func EOR(state: CPUState, addressingMode: AddressingMode) -> Void { + static func EOR(state: CPU, addressingMode: AddressingMode) -> Void { state.accumulator = state.accumulator ^ getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator) } - static func AND(state: CPUState, addressingMode: AddressingMode) -> Void { + static func AND(state: CPU, addressingMode: AddressingMode) -> Void { state.accumulator = state.accumulator & getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) state.updateNegativeFlag(value: state.accumulator) } - static func ORA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func ORA(state: CPU, addressingMode: AddressingMode) -> Void { state.accumulator = state.accumulator | getOperandByteForAddressingMode(state: state, mode: addressingMode) state.updateZeroFlag(value: state.accumulator) @@ -381,7 +405,7 @@ class Opcodes: NSObject { } //Bitwise operators - static func BIT(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BIT(state: CPU, addressingMode: AddressingMode) -> Void { let operand = getOperandByteForAddressingMode(state: state, mode: addressingMode) let data = state.accumulator & operand @@ -390,7 +414,7 @@ class Opcodes: NSObject { state.status_register.overflow = (state.accumulator & UInt8(0x40)) == 0x40 } - static func ASL(state: CPUState, addressingMode: AddressingMode) -> Void { + static func ASL(state: CPU, addressingMode: AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .implied) { @@ -410,7 +434,7 @@ class Opcodes: NSObject { } } - static func LSR(state: CPUState, addressingMode: AddressingMode) -> Void { + static func LSR(state: CPU, addressingMode: AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .implied) { @@ -430,7 +454,7 @@ class Opcodes: NSObject { } } - static func ROL(state: CPUState, addressingMode: AddressingMode) -> Void { + static func ROL(state: CPU, addressingMode: AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .implied) { @@ -456,7 +480,7 @@ class Opcodes: NSObject { } } - static func ROR(state: CPUState, addressingMode: AddressingMode) -> Void { + static func ROR(state: CPU, addressingMode: AddressingMode) -> Void { let operand: UInt8 if(addressingMode == .implied) { @@ -481,52 +505,52 @@ class Opcodes: NSObject { } //Processor flag instructions - static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CLC(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.carry = false } - static func SEC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func SEC(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.carry = true } - static func CLI(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CLI(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.irq_disable = false } - static func SEI(state: CPUState, addressingMode: AddressingMode) -> Void { + static func SEI(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.irq_disable = true } - static func CLV(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CLV(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.overflow = false } - static func CLD(state: CPUState, addressingMode: AddressingMode) -> Void { + static func CLD(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.decimal = false } - static func SED(state: CPUState, addressingMode: AddressingMode) -> Void { + static func SED(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.carry = true } //Stack instructions - static func TXS(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TXS(state: CPU, addressingMode: AddressingMode) -> Void { state.stack_pointer = state.index_x } - static func TSX(state: CPUState, addressingMode: AddressingMode) -> Void { + static func TSX(state: CPU, addressingMode: AddressingMode) -> Void { state.index_x = state.stack_pointer state.updateZeroFlag(value: state.index_x); state.updateNegativeFlag(value: state.index_x); } - static func PHA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func PHA(state: CPU, addressingMode: AddressingMode) -> Void { state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.accumulator) state.stack_pointer = state.stack_pointer &- 1 } - static func PLA(state: CPUState, addressingMode: AddressingMode) -> Void { + static func PLA(state: CPU, addressingMode: AddressingMode) -> Void { state.stack_pointer = state.stack_pointer &+ 1 state.accumulator = state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()) @@ -534,84 +558,89 @@ class Opcodes: NSObject { state.updateNegativeFlag(value: state.accumulator); } - static func PHP(state: CPUState, addressingMode: AddressingMode) -> Void { + static func PHP(state: CPU, addressingMode: AddressingMode) -> Void { state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.status_register.asByte()) state.stack_pointer = state.stack_pointer &- 1 } - static func PLP(state: CPUState, addressingMode: AddressingMode) -> Void { + static func PLP(state: CPU, addressingMode: AddressingMode) -> Void { state.stack_pointer = state.stack_pointer &+ 1 state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16())) } - static func BPL(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BPL(state: CPU, addressingMode: AddressingMode) -> Void { if(!state.status_register.negative) { state.doBranch() } } - static func BMI(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BMI(state: CPU, addressingMode: AddressingMode) -> Void { if(state.status_register.negative) { state.doBranch() } } - static func BVC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BVC(state: CPU, addressingMode: AddressingMode) -> Void { if(!state.status_register.overflow) { state.doBranch() } } - static func BVS(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BVS(state: CPU, addressingMode: AddressingMode) -> Void { if(state.status_register.overflow) { state.doBranch() } } - static func BCC(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BCC(state: CPU, addressingMode: AddressingMode) -> Void { if(!state.status_register.carry) { state.doBranch() } } - static func BCS(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BCS(state: CPU, addressingMode: AddressingMode) -> Void { if(state.status_register.carry) { state.doBranch() } } - static func BNE(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BNE(state: CPU, addressingMode: AddressingMode) -> Void { if(!state.status_register.zero) { state.doBranch() } } - static func BEQ(state: CPUState, addressingMode: AddressingMode) -> Void { + static func BEQ(state: CPU, addressingMode: AddressingMode) -> Void { if(state.status_register.zero) { state.doBranch() } } //Misc - static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void { + static func JMP(state: CPU, addressingMode: AddressingMode) -> Void { state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode) } - static func JSR(state: CPUState, addressingMode: AddressingMode) -> Void { + static func JSR(state: CPU, addressingMode: AddressingMode) -> Void { state.pushWord(data: state.program_counter - 1) state.program_counter = state.getOperandWord() } - static func RTS(state: CPUState, addressingMode: AddressingMode) -> Void { + static func RTS(state: CPU, addressingMode: AddressingMode) -> Void { state.program_counter = state.popWord() + 1 } - static func BRK(state: CPUState, addressingMode: AddressingMode) -> Void { + static func RTI(state: CPU, addressingMode: AddressingMode) -> Void { + state.status_register.fromByte(state: state.popByte()) + state.program_counter = state.popWord() + } + + static func BRK(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.brk = true state.pushWord(data: state.program_counter) state.pushByte(data: state.status_register.asByte()) state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE) } - static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {} + static func NOP(state: CPU, addressingMode: AddressingMode) -> Void {} }