Chip-8_Go/pkg/chip8/chip8.go

165 lines
4.0 KiB
Go
Raw Normal View History

2020-10-10 21:29:53 +01:00
package chip8
import "fmt"
const graphicsBufferSize = 64 * 32
type Chip8 struct {
address_register uint16
beep_timer uint16
draw_required bool
delay_timer uint16
graphics [graphicsBufferSize]byte
keys [16]byte
memory [4096]byte
2020-10-10 21:29:53 +01:00
opcode uint16
pc uint16
registers [16]byte // an array - has a fixed length
stack []uint16 // a slice - basically a c++ vector
2020-10-10 21:29:53 +01:00
}
// we can't have const arrays in go
// This is a good a solution as any
func getLetters() []byte {
return []byte{
2020-10-10 21:29:53 +01:00
0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
0x20, 0x60, 0x20, 0x20, 0x70, // 1
0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
0x90, 0x90, 0xF0, 0x10, 0x10, // 4
0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
0xF0, 0x10, 0x20, 0x40, 0x40, // 7
0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
0xF0, 0x90, 0xF0, 0x90, 0x90, // A
0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
0xF0, 0x80, 0x80, 0x80, 0xF0, // C
0xE0, 0x90, 0x90, 0x90, 0xE0, // D
0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
0xF0, 0x80, 0xF0, 0x80, 0x80} // F
}
func NewCHIP8(prog []byte) *Chip8 {
2020-10-10 21:29:53 +01:00
cpu := Chip8{pc: 0x200}
memory_slice := cpu.memory[:80]
copy(memory_slice, getLetters())
memory_slice = cpu.memory[200:]
copy(memory_slice, prog)
// Do some extra checking to ensure the right
// Stuff is copied
return &cpu
}
func (cpu *Chip8) GetGraphicsBuffer() [graphicsBufferSize]byte {
2020-10-10 21:29:53 +01:00
return cpu.graphics
}
func (cpu *Chip8) clearDisplay() {
// fuck it the gc can do the hard work for us
cpu.graphics = [64 * 32]byte{}
2020-10-10 21:29:53 +01:00
cpu.draw_required = true
}
// what if there's nothing in the stack?
// return something sensible
func (cpu *Chip8) leaveFunction() {
cpu.pc = cpu.stack[len(cpu.stack)-1]
cpu.stack[len(cpu.stack)-1] = 0
cpu.stack = cpu.stack[:len(cpu.stack)-1]
}
func (cpu *Chip8) goTo() {
cpu.pc = cpu.opcode & 0x0FFF
}
func (cpu *Chip8) callSubroutine() {
cpu.stack = append(cpu.stack, cpu.pc)
cpu.pc = cpu.opcode & 0x0FFF
}
func (cpu *Chip8) skipIfRegisterEqual() {
r := (cpu.opcode) >> 8 & 0x0F
if cpu.registers[r] == byte(cpu.opcode&0xFF) {
2020-10-10 21:29:53 +01:00
cpu.pc += 2
}
}
func (cpu *Chip8) skipIfRegisterNotEqual() {
r := (cpu.opcode) >> 8 & 0x0F
if cpu.registers[r] != byte(cpu.opcode&0xFF) {
2020-10-10 21:29:53 +01:00
cpu.pc += 2
}
}
func (cpu *Chip8) skipIfRegistersEqual() {
x, y := (cpu.opcode>>8)&0x0F, (cpu.opcode>>4)&0x0F
if cpu.registers[x] == cpu.registers[y] {
cpu.pc += 2
}
}
2020-10-10 22:29:35 +01:00
func (cpu *Chip8) setRegisterTo() {
2020-10-10 21:29:53 +01:00
r := (cpu.opcode >> 8) & 0x0F
cpu.registers[r] = byte(cpu.opcode & 0xFF)
2020-10-10 21:29:53 +01:00
}
func (cpu *Chip8) RegisterPlusEqualsNN() {} // QUESTION HERE - WHAT DO IF IT WOULD WRAP ROUND?
func (cpu *Chip8) BitOpsAndMath() {
instruction := cpu.opcode & 0x0F
regX, regY := cpu.opcode>>8&0x0F, cpu.opcode>>4&0x0F
switch instruction {
case 0:
// 8XY0
// Assign value of register Y to register X
cpu.registers[regX] = cpu.registers[regY]
case 1:
// 8XY1
// Set register X to x|Y
cpu.registers[regX] = cpu.registers[regX] | cpu.registers[regY]
case 2:
// 8XY2
// Set register x to X&Y
cpu.registers[regX] = cpu.registers[regX] & cpu.registers[regY]
case 3:
// 8XY3
// Set register x to X^Y
cpu.registers[regX] = cpu.registers[regX] ^ cpu.registers[regY]
case 4:
// 8XY4
// Set register x to X+=Y (Set VF to 1 when there's a carry and 0 if not)
res := cpu.registers[regX] + cpu.registers[regY]
if res > 0xFF {
cpu.registers[0x0F] = 1
} else {
cpu.registers[0x0F] = 0
}
cpu.registers[regX] = res & 0xFF
case 5:
// 8XY5
// Set register x to X-=Y (Set VF to 1 when there's a carry and 0 if not)
res := cpu.registers[regX] - cpu.registers[regY]
if res > 0xFF {
cpu.registers[0x0F] = 1
} else {
cpu.registers[0x0F] = 0
}
cpu.registers[regX] = res & 0xFF
case 6:
// BXY6
// Store lsb of reg X in reg F and then shift reg X >> 1
cpu.registers[0x0F] = cpu.registers[regX] & 0x01
cpu.registers[regX] >>= 1
}
}
2020-10-10 21:29:53 +01:00
func main() {
fmt.Printf("Hello world!\n")
prog := []byte{1, 2, 3, 4}
2020-10-10 21:29:53 +01:00
new_cpu := NewCHIP8(prog)
fmt.Printf("%d\n", new_cpu.opcode)
}