1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-01 21:41:31 +00:00

added zeropage and stack to debugger

This commit is contained in:
Irmen de Jong 2019-09-21 15:57:14 +02:00
parent dfec693ba0
commit b8cea02ee0
7 changed files with 90 additions and 48 deletions

View File

@ -129,7 +129,7 @@ private class BitmapScreenPanel(val chargenData: ByteArray, val ram: MemoryCompo
}
}
class MainWindow(title: String, chargenData: ByteArray, val ram: MemoryComponent) : JFrame(title), KeyListener {
class MainC64Window(title: String, chargenData: ByteArray, val ram: MemoryComponent) : JFrame(title), KeyListener {
private val canvas = BitmapScreenPanel(chargenData, ram)
private val keyboardBuffer = ArrayDeque<KeyEvent>()
private var borderTop: JPanel
@ -192,6 +192,7 @@ class MainWindow(title: String, chargenData: ByteArray, val ram: MemoryComponent
addKeyListener(this)
pack()
setLocationRelativeTo(null)
location = Point(location.x/2, location.y)
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, mutableSetOf())
setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, mutableSetOf())
requestFocusInWindow()

View File

@ -15,7 +15,6 @@ import javax.swing.ImageIcon
* The virtual representation of the Commodore-64
*/
class C64Machine(title: String) : IVirtualMachine {
private val romsPath = Paths.get(expandUser("~/.vice/C64"))
private val chargenData = romsPath.resolve("chargen").toFile().readBytes()
private val basicData = romsPath.resolve("basic").toFile().readBytes()
@ -29,7 +28,7 @@ class C64Machine(title: String) : IVirtualMachine {
val kernalRom = Rom(0xe000, 0xffff).also { it.load(kernalData) }
private val debugWindow = DebugWindow(this)
private val hostDisplay = MainWindow(title, chargenData, ram)
private val hostDisplay = MainC64Window(title, chargenData, ram)
private var paused = false
init {
@ -58,6 +57,8 @@ class C64Machine(title: String) : IVirtualMachine {
}
override fun getZeroAndStackPages(): Array<UByte> = ram.getPages(0, 2)
override fun pause(paused: Boolean) {
this.paused = paused
}
@ -70,9 +71,11 @@ class C64Machine(title: String) : IVirtualMachine {
}
fun start() {
val timer = java.util.Timer("clock", true)
val startTime = System.currentTimeMillis()
timer.scheduleAtFixedRate(1, 1) {
javax.swing.Timer(10) {
debugWindow.updateCpu(cpu, bus)
}.start()
java.util.Timer("cpu-clock", true).scheduleAtFixedRate(1, 1) {
if(!paused) {
repeat(400) {
step()
@ -82,10 +85,6 @@ class C64Machine(title: String) : IVirtualMachine {
cpu.irq()
}
}
debugWindow.updateCpu(cpu, bus)
val duration = System.currentTimeMillis() - startTime
val speedKhz = cpu.totalCycles.toDouble() / duration
debugWindow.speedKhzTf.text = "%.1f".format(speedKhz)
}
}
}

View File

@ -149,7 +149,7 @@ private class BitmapScreenPanel : JPanel() {
class DebugWindow(private val vm: IVirtualMachine) : JFrame("debugger"), ActionListener {
private val cyclesTf = JTextField("00000000000000")
internal val speedKhzTf = JTextField("0000000")
private val speedKhzTf = JTextField("0000000")
private val regAtf = JTextField("000")
private val regXtf = JTextField("000")
private val regYtf = JTextField("000")
@ -158,14 +158,27 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("debugger"), ActionL
private val regPtf = JTextArea("NV-BDIZC\n000000000")
private val disassemTf = JTextField("00 00 00 lda (fffff),x")
private val pauseBt = JButton("Pause").also { it.actionCommand = "pause" }
private val zeropageTf = JTextArea(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled = false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
private val stackpageTf = JTextArea(8, 102).also {
it.border = BorderFactory.createEtchedBorder()
it.isEnabled=false
it.disabledTextColor = Color.DARK_GRAY
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
}
private val startTime = System.currentTimeMillis()
init {
contentPane.layout = GridBagLayout()
defaultCloseOperation = EXIT_ON_CLOSE
preferredSize = Dimension(350, 500)
val cpuPanel = JPanel(GridBagLayout())
cpuPanel.border = BorderFactory.createTitledBorder("CPU: ${vm.cpu.name}")
val gc = GridBagConstraints()
gc.insets = Insets(4, 4, 4, 4)
gc.insets = Insets(2, 2, 2, 2)
gc.anchor = GridBagConstraints.EAST
gc.gridx = 0
gc.gridy = 0
@ -178,42 +191,54 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("debugger"), ActionL
val regPClb = JLabel("PC")
val regPlb = JLabel("Status")
val disassemLb = JLabel("Instruction")
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, regPlb, disassemLb).forEach {
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, disassemLb, regPlb).forEach {
cpuPanel.add(it, gc)
gc.gridy++
}
gc.anchor = GridBagConstraints.WEST
gc.gridx = 1
gc.gridy = 0
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, regPtf, disassemTf).forEach {
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, disassemTf, regPtf).forEach {
it.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
it.isEditable = false
it.disabledTextColor = Color.DARK_GRAY
it.isEnabled = false
if(it is JTextField) {
it.columns = it.text.length
} else if(it is JTextArea) {
it.background = this.background
it.border = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY),
BorderFactory.createEmptyBorder(2,2,2,2))
}
cpuPanel.add(it, gc)
gc.gridy++
}
add(cpuPanel, BorderLayout.NORTH)
val buttonPanel = JPanel(FlowLayout())
buttonPanel.border = BorderFactory.createTitledBorder("Control")
val resetBt = JButton("Reset").also { it.actionCommand = "reset" }
val cycleBt = JButton("Step").also { it.actionCommand = "step" }
val stepBt = JButton("Step").also { it.actionCommand = "step" }
val irqBt = JButton("IRQ").also { it.actionCommand = "irq" }
val nmiBt = JButton("NMI").also { it.actionCommand = "nmi" }
val quitBt = JButton("Quit").also { it.actionCommand = "quit" }
listOf(resetBt, cycleBt, irqBt, nmiBt, pauseBt, quitBt).forEach {
listOf(resetBt, irqBt, nmiBt, pauseBt, stepBt, quitBt).forEach {
it.addActionListener(this)
buttonPanel.add(it)
}
add(buttonPanel, BorderLayout.CENTER)
val zeropagePanel = JPanel()
zeropagePanel.layout = BoxLayout(zeropagePanel, BoxLayout.Y_AXIS)
zeropagePanel.border = BorderFactory.createTitledBorder("Zeropage and Stack")
zeropagePanel.add(zeropageTf)
zeropagePanel.add(stackpageTf)
gc.gridx=0
gc.gridy=0
gc.fill=GridBagConstraints.BOTH
contentPane.add(cpuPanel, gc)
gc.gridy++
contentPane.add(zeropagePanel, gc)
gc.gridy++
contentPane.add(buttonPanel, gc)
pack()
}
@ -231,7 +256,7 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("debugger"), ActionL
"pause" -> {
vm.pause(true)
pauseBt.actionCommand = "continue"
pauseBt.text = "Cont."
pauseBt.text = "Continue"
}
"continue" -> {
vm.pause(false)
@ -256,6 +281,27 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("debugger"), ActionL
regSPtf.text = cpu.hexB(cpu.regSP)
val memory = bus.memoryComponentFor(cpu.regPC)
disassemTf.text = cpu.disassembleOneInstruction(memory.data, cpu.regPC, memory.startAddress).first.substringAfter(' ').trim()
val pages = vm.getZeroAndStackPages()
if(pages.isNotEmpty()) {
val zpLines = (0..0xff step 32).map { location ->
" ${'$'}${location.toString(16).padStart(2, '0')} " + (
(0..31).joinToString(" ") { lineoffset ->
pages[location + lineoffset].toString(16).padStart(2, '0')
})
}
val stackLines = (0x100..0x1ff step 32).map { location ->
"${'$'}${location.toString(16).padStart(2, '0')} " + (
(0..31).joinToString(" ") { lineoffset ->
pages[location + lineoffset].toString(16).padStart(2, '0')
})
}
zeropageTf.text = zpLines.joinToString ("\n")
stackpageTf.text = stackLines.joinToString ("\n")
}
val spentTime = System.currentTimeMillis() - startTime
val speedKhz = cpu.totalCycles.toDouble() / spentTime
speedKhzTf.text = "%.1f".format(speedKhz)
}
}
@ -323,9 +369,10 @@ class MainWindow(title: String) : JFrame(title), KeyListener, MouseInputListener
addKeyListener(this)
addMouseMotionListener(this)
addMouseListener(this)
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, mutableSetOf())
pack()
setLocationRelativeTo(null)
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, mutableSetOf())
location = Point(location.x/2, location.y)
requestFocusInWindow()
}

View File

@ -3,7 +3,6 @@ package razorvine.examplemachines
import kotlin.concurrent.scheduleAtFixedRate
import razorvine.ksim65.Bus
import razorvine.ksim65.Cpu6502
import razorvine.ksim65.IVirtualMachine
import razorvine.ksim65.Version
import razorvine.ksim65.components.*
import javax.swing.ImageIcon
@ -12,9 +11,9 @@ import javax.swing.ImageIcon
* A virtual computer constructed from the various virtual components,
* running the 6502 Enhanced Basic ROM.
*/
class EhBasicMachine(title: String): IVirtualMachine {
override val bus = Bus()
override val cpu = Cpu6502(false)
class EhBasicMachine(title: String) {
val bus = Bus()
val cpu = Cpu6502(false)
val ram = Ram(0x0000, 0xbfff)
val rom = Rom(0xc000, 0xffff).also { it.load(javaClass.getResourceAsStream("/ehbasic_C000.bin").readAllBytes()) }
@ -39,23 +38,15 @@ class EhBasicMachine(title: String): IVirtualMachine {
hostDisplay.start()
}
override fun pause(paused: Boolean) {
this.paused = paused
}
override fun step() {
// step a full single instruction
while (cpu.instrCycles > 0) bus.clock()
bus.clock()
while (cpu.instrCycles > 0) bus.clock()
}
fun start() {
val timer = java.util.Timer("clock", true)
timer.scheduleAtFixedRate(1, 1) {
val cpuTimer = java.util.Timer("cpu-clock", true)
cpuTimer.scheduleAtFixedRate(1, 1) {
if(!paused) {
repeat(500) {
step()
// step a full single instruction
while (cpu.instrCycles > 0) bus.clock()
bus.clock()
while (cpu.instrCycles > 0) bus.clock()
}
}
}

View File

@ -51,6 +51,8 @@ class VirtualMachine(title: String) : IVirtualMachine {
hostDisplay.start()
}
override fun getZeroAndStackPages(): Array<UByte> = ram.getPages(0, 2)
override fun pause(paused: Boolean) {
this.paused = paused
}
@ -63,17 +65,14 @@ class VirtualMachine(title: String) : IVirtualMachine {
}
fun start() {
val timer = java.util.Timer("clock", true)
val startTime = System.currentTimeMillis()
timer.scheduleAtFixedRate(1, 1) {
javax.swing.Timer(10) {
debugWindow.updateCpu(cpu, bus)
}.start()
java.util.Timer("cpu-clock", true).scheduleAtFixedRate(1, 1) {
if(!paused) {
repeat(50) {
step()
}
debugWindow.updateCpu(cpu, bus)
val duration = System.currentTimeMillis() - startTime
val speedKhz = cpu.totalCycles.toDouble() / duration
debugWindow.speedKhzTf.text = "%.1f".format(speedKhz)
}
}
}

View File

@ -1,8 +1,11 @@
package razorvine.ksim65
import razorvine.ksim65.components.UByte
interface IVirtualMachine {
fun step()
fun pause(paused: Boolean)
fun getZeroAndStackPages(): Array<UByte>
val cpu: Cpu6502
val bus: Bus

View File

@ -65,4 +65,6 @@ abstract class MemoryComponent(startAddress: Address, endAddress: Address) :
init {
require(startAddress and 0xff == 0 && endAddress and 0xff == 0xff) {"address range must span complete page(s)"}
}
fun getPages(page: Int, numPages: Int): Array<UByte> = data.copyOfRange(page*256, (page+numPages)*256)
}