diff options
| author | James Barnett <noreply@jamesbarnett.xyz> | 2018-07-21 19:46:20 +0100 |
|---|---|---|
| committer | James Barnett <noreply@jamesbarnett.xyz> | 2018-07-21 19:46:20 +0100 |
| commit | c6a953d722b1fdc27a9db6f78f00c52fe43a7222 (patch) | |
| tree | 6efab06c40d0bd3c26876ca2b40f2f0f20b2def2 /src | |
| parent | 2861f2db6f918c48019c1ac3f91bf6a407452493 (diff) | |
| download | KGB-c6a953d722b1fdc27a9db6f78f00c52fe43a7222.tar.xz KGB-c6a953d722b1fdc27a9db6f78f00c52fe43a7222.zip | |
Add ability to step through CPU execution of boot rom
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/kotlin/cpu/Cpu.kt | 61 | ||||
| -rw-r--r-- | src/main/kotlin/gui/CpuRegisterWindow.kt | 2 | ||||
| -rw-r--r-- | src/main/kotlin/gui/RunControlWindow.kt | 46 | ||||
| -rw-r--r-- | src/main/kotlin/gui/WindowContainer.kt | 6 | ||||
| -rw-r--r-- | src/main/kotlin/ram/Ram.kt | 7 | ||||
| -rw-r--r-- | src/main/resources/roms/boot-rom.gb | bin | 0 -> 256 bytes |
6 files changed, 121 insertions, 1 deletions
diff --git a/src/main/kotlin/cpu/Cpu.kt b/src/main/kotlin/cpu/Cpu.kt index 91150c4..f474dbb 100644 --- a/src/main/kotlin/cpu/Cpu.kt +++ b/src/main/kotlin/cpu/Cpu.kt @@ -2,12 +2,16 @@ package cpu import cpu.opcodes.* import ram.Ram +import kotlin.concurrent.thread class Cpu { val registers = Registers() val ram = Ram() + var currentOp: Operation? = null + var nextOp: Operation? = null + var standardOpcodes: Map<Int, Operation> var extendedOpcodes: Map<Int, Operation> init { @@ -33,4 +37,61 @@ class Cpu { } + fun loadRom(rom: ByteArray) { + ram.load(rom) + } + + fun executeNextInstruction() { + + val (op, opArgs) = getNextOp() + op.command.invoke(registers, ram, opArgs) + + currentOp = op + nextOp = peekNextOp() + } + + fun run() { + thread { + while(true) { + executeNextInstruction() + } + } + + } + + private fun getNextOp(): Pair<Operation, IntArray> { + + var addr = registers.PC + val startByte = ram.readByte(addr) + val op: Operation + + op = if(startByte == 0xCB) { + extendedOpcodes[ram.readByte(++addr)]!! + } else { + standardOpcodes[startByte]!! + } + + val opLength = op.length + val opArgs = IntArray(opLength) + + IntRange(0, opLength -1).forEach {i -> + opArgs[i] = ram.readByte(++addr) + } + + registers.PC = ++addr + + return Pair(op, opArgs) + } + + + private fun peekNextOp(): Operation { + + val startByte = ram.readByte(registers.PC) + return if(startByte == 0xCB) { + extendedOpcodes[ram.readByte(registers.PC + 1)]!! + } else { + standardOpcodes[startByte]!! + } + } + }
\ No newline at end of file diff --git a/src/main/kotlin/gui/CpuRegisterWindow.kt b/src/main/kotlin/gui/CpuRegisterWindow.kt index 0de7ad6..618d298 100644 --- a/src/main/kotlin/gui/CpuRegisterWindow.kt +++ b/src/main/kotlin/gui/CpuRegisterWindow.kt @@ -7,7 +7,7 @@ import imgui.ImGui fun paintCpuRegisterWindow(registers: Registers) { with(ImGui) { - setNextWindowSize(Vec2(200, 300), Cond.FirstUseEver) + setNextWindowSize(Vec2(200, 250), Cond.FirstUseEver) setNextWindowPos(Vec2(20, 150), Cond.FirstUseEver) begin("CPU state") diff --git a/src/main/kotlin/gui/RunControlWindow.kt b/src/main/kotlin/gui/RunControlWindow.kt new file mode 100644 index 0000000..8ffc764 --- /dev/null +++ b/src/main/kotlin/gui/RunControlWindow.kt @@ -0,0 +1,46 @@ +package gui + +import cpu.Cpu +import glm_.vec2.Vec2 +import imgui.Cond +import imgui.ImGui + +fun paintRunControlWindow(cpu: Cpu) { + with(ImGui) { + + setNextWindowPos(Vec2(20, 410), Cond.FirstUseEver) + begin("Run control") + + text("Current op:") + separator() + if(cpu.currentOp != null) { + text(cpu.currentOp!!.name) + } + else { + text("None") + } + + newLine() + + text("Next op:") + separator() + if(cpu.nextOp != null) { + text(cpu.nextOp!!.name) + } + else { + text("None") + } + + newLine() + + text("Control:") + separator() + + + if(button("Step")) { + cpu.executeNextInstruction() + } + + end() + } +}
\ No newline at end of file diff --git a/src/main/kotlin/gui/WindowContainer.kt b/src/main/kotlin/gui/WindowContainer.kt index 5e101b7..4d58c18 100644 --- a/src/main/kotlin/gui/WindowContainer.kt +++ b/src/main/kotlin/gui/WindowContainer.kt @@ -10,6 +10,7 @@ import imgui.impl.LwjglGL3 import org.lwjgl.opengl.GL11 import uno.glfw.GlfwWindow import uno.glfw.glfw +import java.io.File class WindowContainer { @@ -18,6 +19,10 @@ class WindowContainer { init { glfw.init("3.2") cpu = Cpu() + val file = File("src/main/resources/roms/boot-rom.gb") + val rom = file.readBytes() + cpu.loadRom(rom) + //cpu.run() } val window = GlfwWindow(1280, 720, "KGB - KotlinGameBoy").apply { @@ -52,6 +57,7 @@ class WindowContainer { paintDebugWindow() paintEmulationOutputWindow() paintCpuRegisterWindow(cpu.registers) + paintRunControlWindow(cpu) } gln.glViewport(window.framebufferSize) diff --git a/src/main/kotlin/ram/Ram.kt b/src/main/kotlin/ram/Ram.kt index 93336a7..7614040 100644 --- a/src/main/kotlin/ram/Ram.kt +++ b/src/main/kotlin/ram/Ram.kt @@ -13,4 +13,11 @@ class Ram { ram[address] = data } + fun load(rom: ByteArray) { + + rom.forEachIndexed{i, b -> + ram[i] = b.toInt() and 0xFF + } + } + }
\ No newline at end of file diff --git a/src/main/resources/roms/boot-rom.gb b/src/main/resources/roms/boot-rom.gb Binary files differnew file mode 100644 index 0000000..afa0ee4 --- /dev/null +++ b/src/main/resources/roms/boot-rom.gb |