From a10296d11856517e55c9bf787d7d09b0fcb7e72a Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Tue, 25 Jul 2017 03:56:31 -0400 Subject: [PATCH] working on passing the klaus tests - works up to the JSR test --- FruitMachine/Base.lproj/Main.storyboard | 1 - FruitMachine/DebuggerCommands.swift | 40 ++++++++++++++-- FruitMachine/DebuggerViewController.swift | 53 ++++------------------ FruitMachine/M6502/CPU.swift | 10 +++- FruitMachine/M6502/Disassembly.swift | 49 ++++++++++++++++++++ FruitMachine/M6502/IntegerExtensions.swift | 6 +++ FruitMachine/M6502/Opcodes.swift | 42 ++++++++++------- 7 files changed, 132 insertions(+), 69 deletions(-) diff --git a/FruitMachine/Base.lproj/Main.storyboard b/FruitMachine/Base.lproj/Main.storyboard index 08b9b8b..3dfc83f 100644 --- a/FruitMachine/Base.lproj/Main.storyboard +++ b/FruitMachine/Base.lproj/Main.storyboard @@ -1035,7 +1035,6 @@ - diff --git a/FruitMachine/DebuggerCommands.swift b/FruitMachine/DebuggerCommands.swift index 85f33b0..0cec85f 100644 --- a/FruitMachine/DebuggerCommands.swift +++ b/FruitMachine/DebuggerCommands.swift @@ -24,9 +24,18 @@ extension DebuggerViewController { { debugConsolePrint(str: DebuggerCommands.bpdel(state: cpuInstance, parameters: parameters), newline: true) } - else if(commandSplit[0] == "bpadd") + else if(commandSplit[0] == "bpset") { - debugConsolePrint(str: DebuggerCommands.bpadd(state: cpuInstance, parameters: parameters), newline: true) + debugConsolePrint(str: DebuggerCommands.bpset(state: cpuInstance, parameters: parameters), newline: true) + } + else if(commandSplit[0] == "bpclear") + { + debugConsolePrint(str: DebuggerCommands.bpclear(state: cpuInstance, parameters: parameters), newline: true) + } + + else if(commandSplit[0] == "memread") + { + debugConsolePrint(str: DebuggerCommands.memread(state: cpuInstance, parameters: parameters), newline: true) } else { @@ -46,7 +55,7 @@ class DebuggerCommands: NSObject { return output } - static func bpadd(state: CPU, parameters: [String]) -> String { + static func bpset(state: CPU, parameters: [String]) -> String { var output = "" let val = UInt16(parameters[0]) @@ -78,7 +87,30 @@ class DebuggerCommands: NSObject { } else { - output += "Usage: bpdel . Use bplist to find breakpoint numbers." + output += "Usage: bpdel \r\n Use bplist to find breakpoint numbers." + } + + return output + } + + static func bpclear(state: CPU, parameters: [String]) -> String { + var output = "" + + state.breakpoints.removeAll() + output += "All breakpoints deleted." + + return output + } + + static func memread(state: CPU, parameters: [String]) -> String { + var output = "" + let val = UInt16(parameters[0], radix: 16) + + if(val != nil) { + output += "$\(val!.asHexString()) == $\(state.memoryInterface.readByte(offset: val!).asHexString())" + } + else { + output += "Usage: memread " } return output diff --git a/FruitMachine/DebuggerViewController.swift b/FruitMachine/DebuggerViewController.swift index 997fe63..d4cc4e0 100644 --- a/FruitMachine/DebuggerViewController.swift +++ b/FruitMachine/DebuggerViewController.swift @@ -46,7 +46,7 @@ class DebuggerViewController: NSViewController { text_CPU_SR.stringValue = String(format:"%02X", cpuInstance.stack_pointer) text_CPU_Flags.stringValue = String(cpuInstance.status_register.asString()) - disassembly = cpuInstance.disassemble(fromAddress: 0, length: 10000) + disassembly = cpuInstance.disassemble(fromAddress: 0, length: 40000) highlightCurrentInstruction() } @@ -60,10 +60,10 @@ class DebuggerViewController: NSViewController { cpuInstance.performReset() cpuInstance.program_counter = 0x400 //entry point for the test program updateCPUStatusFields() - disassembly = cpuInstance.disassemble(fromAddress: 0, length: 10000) + disassembly = cpuInstance.disassemble(fromAddress: 0, length: 40000) debuggerTableView.reloadData() - cpuInstance.breakpoints.append(0x0528) + cpuInstance.breakpoints.append(0x94B) //failing at 0x36AC - JSR test. some stack problem // Do any additional setup after loading the view. } @@ -89,7 +89,7 @@ class DebuggerViewController: NSViewController { isRunning = true cpuInstance.cycles = 0 - cpuInstance.cyclesInBatch = 1000 + cpuInstance.cyclesInBatch = 50000 while(!cpuInstance.checkOutOfCycles() && isRunning) { cpuStep() @@ -126,7 +126,7 @@ class DebuggerViewController: NSViewController { @IBAction func btn_CPU_Restart(_ sender: Any) { cpuInstance.performReset() cpuInstance.program_counter = 0x400 - debugConsolePrint(str: "CPU restarted from $0400", newline: true) + debugConsolePrint(str: "CPU restarted from \(cpuInstance.program_counter)", newline: true) } @@ -158,7 +158,7 @@ extension DebuggerViewController: NSTableViewDelegate { let operation = disassembly[row] if(tableColumn == tableView.tableColumns[0]) { - cellText = String(format: "%04X", operation.address) + cellText = operation.getAddressString() cellIdentifier = CellIdentifiers.AddressCell } @@ -166,50 +166,13 @@ extension DebuggerViewController: NSTableViewDelegate { 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[1]) - case .implied: - cellText = String(format: "%@", operation.instruction!.mnemonic) - case .relative: - var destination: UInt16 = operation.address - if((operation.data[1] & 0x80) == 0x80) { - destination = destination + 1 - UInt16(~operation.data[1]) - } else { - destination = destination + 2 + UInt16(operation.data[1]) - } - cellText = String(format: "%@ #$%04X", operation.instruction!.mnemonic, destination) - case .absolute: - 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[1]) - case .indirect: - 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[2], operation.data[1]) - case .absolute_indexed_y: - 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[1]) - case .zeropage_indexed_y: - cellText = String(format: "%@ $%02X,Y", operation.instruction!.mnemonic, operation.data[1]) - case .indexed_indirect: - cellText = String(format: "%@ ($%02X,X)", operation.instruction!.mnemonic, operation.data[1]) - case .indirect_indexed: - cellText = String(format: "%@ ($%02X),Y", operation.instruction!.mnemonic, operation.data[1]) - } + cellText = operation.getInstructionString() } cellIdentifier = CellIdentifiers.DataCell } if(tableColumn == tableView.tableColumns[2]) { - cellText = "" - for byte in operation.data { - cellText += String(format: "%02X ", byte) - } - + cellText = operation.getDataString() cellIdentifier = CellIdentifiers.BytesCell } diff --git a/FruitMachine/M6502/CPU.swift b/FruitMachine/M6502/CPU.swift index 0b3e747..1d2b100 100644 --- a/FruitMachine/M6502/CPU.swift +++ b/FruitMachine/M6502/CPU.swift @@ -37,7 +37,7 @@ struct StatusRegister { str += "-" } - str += "-" //0x20 is unassigned + str += "|" //0x20 is unassigned if(brk) { str += "B" @@ -63,6 +63,12 @@ struct StatusRegister { str += "-" } + if(carry) { + str += "C" + } else { + str += "-" + } + return str } @@ -206,7 +212,7 @@ class CPU: NSObject { self.branch_was_taken = false } - if(operation!.mnemonic != "JMP") { + if(operation!.mnemonic != "JMP" && operation!.mnemonic != "JSR") { self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes) } } diff --git a/FruitMachine/M6502/Disassembly.swift b/FruitMachine/M6502/Disassembly.swift index 278423c..d92369e 100644 --- a/FruitMachine/M6502/Disassembly.swift +++ b/FruitMachine/M6502/Disassembly.swift @@ -18,6 +18,55 @@ class Disassembly: NSObject { self.address = address self.data = data } + + func getAddressString() -> String { + return String(format: "%04X", address) + } + + func getInstructionString() -> String { + switch(instruction!.addressingMode) { + case .accumulator: + return String(format: "%@ A", instruction!.mnemonic) + case .immediate: + return String(format: "%@ #$%02X", instruction!.mnemonic, data[1]) + case .implied: + return String(format: "%@", instruction!.mnemonic) + case .relative: + var destination: UInt16 = address + if((data[1] & 0x80) == 0x80) { + destination = destination + 1 - UInt16(~data[1]) + } else { + destination = destination + 2 + UInt16(data[1]) + } + return String(format: "%@ #$%04X", instruction!.mnemonic, destination) + case .absolute: + return String(format: "%@ $%02X%02X", instruction!.mnemonic, data[2], data[1]) + case .zeropage: + return String(format: "%@ $%02X", instruction!.mnemonic, data[1]) + case .indirect: + return String(format: "%@ ($%02X%02X)", instruction!.mnemonic, data[2], data[1]) + case .absolute_indexed_x: + return String(format: "%@ $%02X%02X,X", instruction!.mnemonic, data[2], data[1]) + case .absolute_indexed_y: + return String(format: "%@ $%02X%02X,Y", instruction!.mnemonic, data[2], data[1]) + case .zeropage_indexed_x: + return String(format: "%@ $%02X,X", instruction!.mnemonic, data[1]) + case .zeropage_indexed_y: + return String(format: "%@ $%02X,Y", instruction!.mnemonic, data[1]) + case .indexed_indirect: + return String(format: "%@ ($%02X,X)", instruction!.mnemonic, data[1]) + case .indirect_indexed: + return String(format: "%@ ($%02X),Y", instruction!.mnemonic, data[1]) + } + } + + func getDataString() -> String { + var dataStr = "" + for byte in data { + dataStr += String(format: "%02X ", byte) + } + return dataStr + } } extension CPU { diff --git a/FruitMachine/M6502/IntegerExtensions.swift b/FruitMachine/M6502/IntegerExtensions.swift index 516a2c5..8063a58 100644 --- a/FruitMachine/M6502/IntegerExtensions.swift +++ b/FruitMachine/M6502/IntegerExtensions.swift @@ -17,3 +17,9 @@ extension UInt16 { return String(format: "%04X", self) } } + +extension UInt8 { + func asHexString() -> String { + return String(format: "%02X", self) + } +} diff --git a/FruitMachine/M6502/Opcodes.swift b/FruitMachine/M6502/Opcodes.swift index 54aec8c..da71af5 100644 --- a/FruitMachine/M6502/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes.swift @@ -369,27 +369,30 @@ class Opcodes: NSObject { //CMP static func CMP(state: CPU, addressingMode: AddressingMode) -> Void { - let data = state.accumulator - state.getOperandByte() //CMP is a subtract that doesn't affect memory + let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) + let t = state.accumulator &- mem //CMP is a subtract that doesn't affect memory - state.updateZeroFlag(value: data) - state.updateNegativeFlag(value: data) - state.status_register.carry = (data >= 0) + state.status_register.zero = (t == 0) ? true : false + state.status_register.negative = (t & 0x80) == 0x80 ? true : false + state.status_register.carry = (state.accumulator >= mem) } static func CPX(state: CPU, addressingMode: AddressingMode) -> Void { - let data = state.index_x - state.getOperandByte() //CMP is a subtract that doesn't affect memory + let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) + let t = state.index_x &- mem //CMP is a subtract that doesn't affect memory - state.updateZeroFlag(value: data) - state.updateNegativeFlag(value: data) - state.status_register.carry = (data >= 0) + state.status_register.zero = (t == 0) ? true : false + state.status_register.negative = (t & 0x80) == 0x80 ? true : false + state.status_register.carry = (state.index_x >= mem) } static func CPY(state: CPU, addressingMode: AddressingMode) -> Void { - let data = state.index_y - state.getOperandByte() //CMP is a subtract that doesn't affect memory + let mem = getOperandByteForAddressingMode(state: state, mode: addressingMode) + let t = state.index_y &- mem //CMP is a subtract that doesn't affect memory - state.updateZeroFlag(value: data) - state.updateNegativeFlag(value: data) - state.status_register.carry = (data >= 0) + state.status_register.zero = (t == 0) ? true : false + state.status_register.negative = (t & 0x80) == 0x80 ? true : false + state.status_register.carry = (state.index_y >= mem) } //Boolean operators @@ -556,8 +559,7 @@ class Opcodes: NSObject { } static func PHA(state: CPU, addressingMode: AddressingMode) -> Void { - state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.accumulator) - state.stack_pointer = state.stack_pointer &- 1 + state.pushByte(data: state.accumulator) } static func PLA(state: CPU, addressingMode: AddressingMode) -> Void { @@ -569,13 +571,17 @@ class Opcodes: NSObject { } static func PHP(state: CPU, addressingMode: AddressingMode) -> Void { - state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: state.status_register.asByte()) + var sr = state.status_register + sr.brk = true //PHP pushes B as true + + state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), value: sr.asByte()) state.stack_pointer = state.stack_pointer &- 1 } 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())) + state.status_register.brk = false //PLP sets B to 0 } static func BPL(state: CPU, addressingMode: AddressingMode) -> Void { @@ -643,12 +649,14 @@ class Opcodes: NSObject { static func RTI(state: CPU, addressingMode: AddressingMode) -> Void { state.status_register.fromByte(state: state.popByte()) state.program_counter = state.popWord() + state.status_register.brk = false //RTI sets B to 0 } static func BRK(state: CPU, addressingMode: AddressingMode) -> Void { - state.status_register.brk = true + var sr = state.status_register + sr.brk = true //BRK pushes B as true state.pushWord(data: state.program_counter) - state.pushByte(data: state.status_register.asByte()) + state.pushByte(data: sr.asByte()) state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE) }