diff --git a/pkg/chip8/chip8.go b/pkg/chip8/chip8.go index 59b6982..d7ef11b 100644 --- a/pkg/chip8/chip8.go +++ b/pkg/chip8/chip8.go @@ -9,19 +9,19 @@ type Chip8 struct { beep_timer uint16 draw_required bool delay_timer uint16 - graphics [graphicsBufferSize]uint8 - keys [16]uint8 - memory [4096]uint8 + graphics [graphicsBufferSize]byte + keys [16]byte + memory [4096]byte opcode uint16 pc uint16 - registers [16]uint8 // an array - has a fixed length - stack []uint16 // a slice - basically a c++ vector + registers [16]byte // an array - has a fixed length + stack []uint16 // a slice - basically a c++ vector } // we can't have const arrays in go // This is a good a solution as any -func getLetters() []uint8 { - return []uint8{ +func getLetters() []byte { + return []byte{ 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 0x20, 0x60, 0x20, 0x20, 0x70, // 1 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 @@ -40,7 +40,7 @@ func getLetters() []uint8 { 0xF0, 0x80, 0xF0, 0x80, 0x80} // F } -func NewCHIP8(prog []uint8) *Chip8 { +func NewCHIP8(prog []byte) *Chip8 { cpu := Chip8{pc: 0x200} memory_slice := cpu.memory[:80] copy(memory_slice, getLetters()) @@ -53,13 +53,13 @@ func NewCHIP8(prog []uint8) *Chip8 { return &cpu } -func (cpu *Chip8) GetGraphicsBuffer() [graphicsBufferSize]uint8 { +func (cpu *Chip8) GetGraphicsBuffer() [graphicsBufferSize]byte { return cpu.graphics } func (cpu *Chip8) clearDisplay() { // fuck it the gc can do the hard work for us - cpu.graphics = [64 * 32]uint8{} + cpu.graphics = [64 * 32]byte{} cpu.draw_required = true } @@ -82,14 +82,14 @@ func (cpu *Chip8) callSubroutine() { func (cpu *Chip8) skipIfRegisterEqual() { r := (cpu.opcode) >> 8 & 0x0F - if cpu.registers[r] == uint8(cpu.opcode&0xFF) { + if cpu.registers[r] == byte(cpu.opcode&0xFF) { cpu.pc += 2 } } func (cpu *Chip8) skipIfRegisterNotEqual() { r := (cpu.opcode) >> 8 & 0x0F - if cpu.registers[r] != uint8(cpu.opcode&0xFF) { + if cpu.registers[r] != byte(cpu.opcode&0xFF) { cpu.pc += 2 } } @@ -103,14 +103,62 @@ func (cpu *Chip8) skipIfRegistersEqual() { func (cpu *Chip8) setRegisterTo() { r := (cpu.opcode >> 8) & 0x0F - cpu.registers[r] = uint8(cpu.opcode & 0xFF) + cpu.registers[r] = byte(cpu.opcode & 0xFF) } 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 + } +} + func main() { fmt.Printf("Hello world!\n") - prog := []uint8{1, 2, 3, 4} + prog := []byte{1, 2, 3, 4} new_cpu := NewCHIP8(prog) fmt.Printf("%d\n", new_cpu.opcode) } diff --git a/pkg/chip8/chip8_test.go b/pkg/chip8/chip8_test.go index 2af7c7f..623caef 100644 --- a/pkg/chip8/chip8_test.go +++ b/pkg/chip8/chip8_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func slicesEqual(x, y []uint8) bool { +func slicesEqual(x, y []byte) bool { if len(x) != len(y) { return false } @@ -20,7 +20,7 @@ func slicesEqual(x, y []uint8) bool { // This test is kinda shit, there's so much stuff we ain't testing // Maybe fix func TestCreateCPU(t *testing.T) { - prog := []uint8{1, 2, 3, 4} + prog := []byte{1, 2, 3, 4} new_cpu := NewCHIP8(prog) if !slicesEqual(new_cpu.memory[200:204], prog) { t.Errorf("CPU not initalized properly") @@ -30,12 +30,12 @@ func TestCreateCPU(t *testing.T) { func TestClearDisplay(t *testing.T) { cpu := Chip8{} for i := range cpu.graphics { - cpu.graphics[i] = uint8(i % 255) + cpu.graphics[i] = byte(i % 255) } cpu.clearDisplay() graphics_array := cpu.GetGraphicsBuffer() graphics_slice := graphics_array[:] - empty_slice := make([]uint8, len(cpu.graphics)) + empty_slice := make([]byte, len(cpu.graphics)) if !slicesEqual(graphics_slice, empty_slice) { t.Errorf("Graphics buffer not cleared properly") } @@ -68,7 +68,7 @@ func TestCallSubroutine(t *testing.T) { func TestSkipIfRegisterEqual(t *testing.T) { var tests = []struct { - register, regValue uint8 + register, regValue byte compValue, want uint16 }{ {0, 2, 4, 0}, @@ -92,7 +92,7 @@ func TestSkipIfRegisterEqual(t *testing.T) { func TestSkipIfRegisterNotEqual(t *testing.T) { var tests = []struct { - register, regValue uint8 + register, regValue byte compValue, want uint16 }{ {0, 2, 4, 2}, @@ -116,7 +116,7 @@ func TestSkipIfRegisterNotEqual(t *testing.T) { func TestSkipIfRegistersEqual(t *testing.T) { var tests = []struct { - reg1, reg2, val1, val2 uint8 + reg1, reg2, val1, val2 byte }{ {0, 2, 4, 2}, {0, 2, 2, 2},