1
0
Fork 0
mirror of https://github.com/ethauvin/chip-8.git synced 2025-04-24 08:27:10 -07:00
chip-8/README.md
Cedric Beust 9e97df2ab6
Fix links
2020-08-22 16:21:48 -07:00

3 KiB

Chipsk-8

A Chip-8 emulator written in Kotlin

How to run

$ ./gradlew run

The emulator will load with Space Invaders by default (press 5 to start the game, then 4/5/6 to move around and shoot). Open a new rom by clicking on the "Open rom..." button.

You can pause the emulator at any time (key 'p'), which will update the disassembly window to show the next instructions about to be executed. You can also adjust the clock speed to make the emulator go slower or faster.

Architecture

The game creates a Computer object which is made of a Display, Keyboard, FrameBuffer and Cpu.

Cpu

The CPU reads a new instruction (the next two bytes extracted at the program counter location) at a fixed rate which defines the clock speed. Two timers are needed: one for the CPU and one for the device timer register, called DT, which needs to tick at 60 Hz according to the spec. Since there is no specific definition for the CPU clock, I used the timing diagram from the document to set it at around 500Hz:

// CPU clock: around 500 Hz by default
cpuFuture = executor.scheduleAtFixedRate(cpuTick, 0, 1_000_000L / cpuClockHz, TimeUnit.MICROSECONDS)

// Delay Timer: 60 Hz by spec
timerFuture = executor.scheduleAtFixedRate(timerTick, 0, 16L, TimeUnit.MILLISECONDS)

The next two bytes are then masked and turned into instructions. All the op codes can be found in the [Ops.kt](https://github.com/cbeust/chip8/blob/master/src/main/kotlin/com/beust/chip8/Ops.kt) file. Here is an example:

/**
 * 7xkk
 * Set Vx = Vx + kk
 */
class Add(c: Computer, n: Nibbles): Op(c, n) {
    override fun run() { cpu.V[x] = unsigned(cpu.V[x] + kk) }
    override fun toString() = "ADD V$x, $kk"
}

Display

The Display is a simple interface which allows multiple strategies to render the frame buffer:

interface Display {
    val pane: Pane
    fun draw(frameBuffer: IntArray)
    fun clear(frameBuffer: IntArray)
}

For example, here is a text based renderer:

The emulator window will resize gracefully:

You can also easily alter other aspects of the renderer: