All checks were successful
continuous-integration/drone/push Build is passing
still shit wrong idc
633 lines
18 KiB
Go
633 lines
18 KiB
Go
package chip8
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func slicesEqual(x, y []byte) bool {
|
|
if len(x) != len(y) {
|
|
return false
|
|
}
|
|
for i, xi := range x {
|
|
if xi != y[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// This test is kinda shit, there's so much stuff we ain't testing
|
|
// Maybe fix
|
|
func TestCreateCPU(t *testing.T) {
|
|
prog := []byte{1, 2, 3, 4}
|
|
newCPU := NewCHIP8(prog)
|
|
if !slicesEqual(newCPU.memory[0x200:0x204], prog) {
|
|
t.Errorf("CPU not initalized properly")
|
|
}
|
|
}
|
|
|
|
//0x00E0
|
|
func TestClearDisplay(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x00E0}
|
|
for i := range cpu.graphics {
|
|
cpu.graphics[i] = byte(i % 255)
|
|
}
|
|
cpu.zeroIndexOpcodes()
|
|
graphicsArray := cpu.GetGraphicsBuffer()
|
|
graphicsSlice := graphicsArray[:]
|
|
emptySlice := make([]byte, len(cpu.graphics))
|
|
if !slicesEqual(graphicsSlice, emptySlice) {
|
|
t.Errorf("Graphics buffer not cleared properly")
|
|
}
|
|
}
|
|
|
|
//0x00EE
|
|
func TestLeaveFunction(t *testing.T) {
|
|
cpu := Chip8{pc: 50, opcode: 0x00EE}
|
|
cpu.stack = append(cpu.stack, 1, 2, 3, 4, 5)
|
|
cpu.zeroIndexOpcodes()
|
|
if cpu.pc != 4 && len(cpu.stack) != 4 {
|
|
t.Errorf("TestLeaveFunction not in expected state")
|
|
}
|
|
}
|
|
|
|
//0x1NNN
|
|
func TestGoTo(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x3420}
|
|
cpu.goTo()
|
|
if cpu.pc != 0x420 {
|
|
t.Errorf("Test GoTo not working as expected")
|
|
}
|
|
}
|
|
|
|
//0x2NNN
|
|
func TestCallSubroutine(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x3420, pc: 43}
|
|
cpu.callSubroutine()
|
|
if (cpu.pc != 420) && (cpu.stack[0] != 43) && (len(cpu.stack) != 1) {
|
|
t.Errorf("CallSubroutine not working as expected")
|
|
}
|
|
}
|
|
|
|
//0x3XNN
|
|
func TestSkipIfRegisterEqual(t *testing.T) {
|
|
var tests = []struct {
|
|
register, regValue byte
|
|
compValue, want uint16
|
|
}{
|
|
{0, 2, 4, 0},
|
|
{0, 2, 2, 2},
|
|
{15, 2, 2, 2},
|
|
{15, 1, 12, 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("Reg:%d,RegVal:%d,Comp:%d", tt.register, tt.regValue, tt.compValue)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: tt.compValue + uint16(tt.register)<<8}
|
|
cpu.registers[tt.register] = tt.regValue
|
|
cpu.skipIfRegisterEqual()
|
|
if tt.want != cpu.pc {
|
|
t.Errorf("PC is %d, Wanted %d", cpu.pc, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x4XNN
|
|
func TestSkipIfRegisterNotEqual(t *testing.T) {
|
|
var tests = []struct {
|
|
register, regValue byte
|
|
compValue, want uint16
|
|
}{
|
|
{0, 2, 4, 2},
|
|
{0, 2, 2, 0},
|
|
{15, 2, 2, 0},
|
|
{15, 1, 12, 2},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("Reg:%d,RegVal:%d,Comp:%d", tt.register, tt.regValue, tt.compValue)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: tt.compValue + uint16(tt.register)<<8}
|
|
cpu.registers[tt.register] = tt.regValue
|
|
cpu.skipIfRegisterNotEqual()
|
|
if tt.want != cpu.pc {
|
|
t.Errorf("PC is %d, Wanted %d", cpu.pc, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x5XY0
|
|
func TestSkipIfRegistersEqual(t *testing.T) {
|
|
var tests = []struct {
|
|
reg1, reg2, val1, val2 byte
|
|
}{
|
|
{0, 2, 4, 2},
|
|
{0, 2, 2, 2},
|
|
{15, 1, 2, 0},
|
|
{15, 4, 12, 12},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("Reg1:%d,Reg2:%d,val1:%d,val2:%d", tt.reg1, tt.reg2, tt.val1, tt.val2)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: uint16(tt.reg1)<<8 + uint16(tt.reg2)<<4}
|
|
cpu.registers[tt.reg1] = tt.val1
|
|
cpu.registers[tt.reg2] = tt.val2
|
|
cpu.skipIfRegistersEqual()
|
|
if (2 != cpu.pc) && (tt.val1 == tt.val2) {
|
|
t.Errorf("PC is %d, Wanted %d", cpu.pc, 2)
|
|
} else if (0 != cpu.pc) && (tt.val1 != tt.val2) {
|
|
t.Errorf("PC is %d, Wanted %d", cpu.pc, 2)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x6XNN
|
|
func TestSetRegisterTo(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x0824}
|
|
cpu.setRegisterTo()
|
|
if cpu.registers[8] != 0x24 {
|
|
t.Errorf("Register 8 is %d wanted %d", cpu.registers[8], 0x24)
|
|
}
|
|
}
|
|
|
|
//0x7XNN
|
|
func TestRegisterPlusEqualsNN(t *testing.T) {
|
|
var tests = []struct {
|
|
register, initalVal, toAdd, expected byte
|
|
}{
|
|
{0, 2, 2, 4},
|
|
{0, 254, 3, 1},
|
|
{15, 2, 0, 2},
|
|
{15, 250, 6, 0},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("Register:%d,inital:%d,toAdd:%d,expected:%d", tt.register, tt.initalVal, tt.toAdd, tt.expected)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: uint16(tt.register)<<8 + uint16(tt.toAdd)}
|
|
cpu.registers[tt.register] = tt.initalVal
|
|
cpu.registerPlusEqualsNN()
|
|
if cpu.registers[tt.register] != tt.expected {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.register], tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// 0x8000
|
|
func TestLoadVxVy(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal byte
|
|
}{
|
|
{0, 2, 2, 4},
|
|
{0, 15, 3, 1},
|
|
{15, 2, 0, 2},
|
|
{15, 3, 6, 0},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d", tt.regX, tt.regY, tt.xVal, tt.yVal)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8000 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.yVal)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// 0x8001
|
|
func TestOrVxVy(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result byte
|
|
}{
|
|
{0, 2, 0xBB, 0xCC, 0xFF},
|
|
{0, 2, 0x00, 0x00, 0x00},
|
|
{0, 2, 0x0F, 0xF0, 0xFF},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8001 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8002
|
|
func TestAndVxVy(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result byte
|
|
}{
|
|
{0, 2, 0xCC, 0xDD, 0xCC},
|
|
{0, 2, 0x00, 0x00, 0x00},
|
|
{0, 2, 0x0F, 0xF0, 0x00},
|
|
{0, 2, 0x0F, 0xF1, 0x01},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8002 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8003
|
|
func TestXORVxVy(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result byte
|
|
}{
|
|
{0, 2, 0xDD, 0xEE, 0x33},
|
|
{0, 2, 0x00, 0x00, 0x00},
|
|
{0, 4, 0x0F, 0xF0, 0xFF},
|
|
{0, 2, 0xFF, 0xFF, 0x00},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8003 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8004
|
|
func TestAddVxVyCarry(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result, carry byte
|
|
}{
|
|
{0, 2, 0x44, 0xAA, 0xEE, 0},
|
|
{0, 2, 0xAA, 0xAA, 0x54, 1},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d,carry:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result, tt.carry)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8004 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.registers[0x0F] != tt.carry {
|
|
t.Errorf("Carry register is %d, wanted %d", cpu.registers[0x0F], tt.carry)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8005
|
|
func TestSubVxVyCarry(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result, carry byte
|
|
}{
|
|
{0, 2, 0xAA, 0x22, 0x88, 1},
|
|
{0, 2, 0x22, 0xDD, 0x45, 0},
|
|
{0, 2, 0x22, 0x22, 0x00, 1},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d,carry:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result, tt.carry)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8005 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.registers[0x0F] != tt.carry {
|
|
t.Errorf("Carry register is %d, wanted %d", cpu.registers[0x0F], tt.carry)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8006
|
|
func TestSHRVxVyCarry(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, expX, expY, regF byte
|
|
}{
|
|
{0, 2, 0x11, 0x44, 0x22, 0x44, 0},
|
|
{0, 2, 0x11, 0x45, 0x22, 0x45, 1},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expX:%d,expY:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.expX, tt.expY)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8006 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.expX {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.expX)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.registers[0x0F] != tt.regF {
|
|
t.Errorf("Carry register is %d, wanted %d", cpu.registers[0x0F], tt.regF)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x8007
|
|
func TestSUBNVxVyCarry(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, result, carry byte
|
|
}{
|
|
{0, 2, 0x22, 0xAA, 0x88, 1},
|
|
{0, 2, 0xDD, 0x22, 0x45, 0},
|
|
{0, 2, 0x22, 0x22, 0x00, 1},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expected:%d,carry:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.result, tt.carry)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x8007 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.result {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.result)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.registers[0x0F] != tt.carry {
|
|
t.Errorf("Carry register is %d, wanted %d", cpu.registers[0x0F], tt.carry)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x800E
|
|
func TestSHLVxVyCarry(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, expX, expY, regF byte
|
|
}{
|
|
{7, 8, 0x22, 0x44, 0x88, 0x44, 0},
|
|
{7, 8, 0x22, 0x45, 0x8A, 0x45, 0},
|
|
{7, 8, 0x22, 0xff, 0xFE, 0xFF, 1},
|
|
{7, 8, 0x22, 0x7F, 0xFE, 0x7F, 0},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,expX:%d,expY:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.expX, tt.expY)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x800E | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.bitOpsAndMath()
|
|
if cpu.registers[tt.regX] != tt.expX {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.expX)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.registers[0x0F] != tt.regF {
|
|
t.Errorf("Carry register is %d, wanted %d", cpu.registers[0x0F], tt.regF)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0x9XY0
|
|
func TestSkipNotEqual(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal byte
|
|
pc_val uint16
|
|
}{
|
|
{7, 8, 0x10, 0x10, 0},
|
|
{7, 8, 0x10, 0x20, 2},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("RegisterX:%d,RegisterY:%d,Xval:%d,Yval:%d,pc_val:%d", tt.regX, tt.regY, tt.xVal, tt.yVal, tt.pc_val)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0x9000 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4}
|
|
cpu.pc = 0
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.skipIfRegistersNotEqual()
|
|
if cpu.registers[tt.regX] != tt.xVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regX], tt.xVal)
|
|
}
|
|
if cpu.registers[tt.regY] != tt.yVal {
|
|
t.Errorf("Register is %d, wanted %d", cpu.registers[tt.regY], tt.yVal)
|
|
}
|
|
if cpu.pc != tt.pc_val {
|
|
t.Errorf("pc is %d, wanted %d", cpu.registers[0x0F], tt.pc_val)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0xANNN
|
|
func TestSetAddressRegister(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xA420}
|
|
cpu.setAddressRegister()
|
|
if cpu.addressRegister != 0x420 {
|
|
t.Errorf("Expected address register to be: %d, actual value %d", 0x420, cpu.addressRegister)
|
|
}
|
|
}
|
|
|
|
//0xBnnn
|
|
func TestJumpV0PlusNNN(t *testing.T) {
|
|
var tests = []struct {
|
|
regVal byte
|
|
addr, expPc uint16
|
|
}{
|
|
{0x44, 0x555, 0x599},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("TestJmpv0PlusNNN,regVal:%d,addr:%d,expected:%d", tt.regVal, tt.addr, tt.expPc)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xB000 | tt.addr}
|
|
cpu.registers[0] = tt.regVal
|
|
cpu.jumpToV0PlusAddress()
|
|
if cpu.pc != tt.expPc {
|
|
t.Errorf("Expected pc to be: %d, actual value %d", tt.expPc, cpu.pc)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0xCXNN
|
|
// do something for rand but this one's probably fine idk
|
|
|
|
//0xfx07
|
|
func TestSetRegisterToDelayTimer(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xF007 | uint16(7)<<8, delayTimer: 81}
|
|
cpu.registers[7] = 17
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.registers[7] != 81 {
|
|
t.Errorf("Expected register 7 to be %d, actually %d", 81, cpu.registers[7])
|
|
}
|
|
}
|
|
|
|
//0xfx15
|
|
func TestSetDelayTimer(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xF015 | uint16(7)<<8}
|
|
cpu.registers[7] = 161
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.delayTimer != 161 {
|
|
t.Errorf("Expected delay timer to be %d, actually %d", 161, cpu.delayTimer)
|
|
}
|
|
}
|
|
|
|
//0xfx18
|
|
func TestSetSoundTimer(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xF018 | uint16(7)<<8}
|
|
cpu.registers[7] = 161
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.beepTimer != 161 {
|
|
t.Errorf("Expected delay timer to be %d, actually %d", 161, cpu.beepTimer)
|
|
}
|
|
}
|
|
|
|
//0xFx1E
|
|
func TestAddIVx(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, xVal byte
|
|
iVal, res uint16
|
|
}{
|
|
{0xB, 0x33, 0x22, 0x55},
|
|
{0xA, 0xFF, 0x1, 0x100},
|
|
{0xC, 0x01, 0xFFF, 0},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("TestAddIVX,regX:%d,xVal:%d,iVal:%d,res:%d", tt.regX, tt.xVal, tt.iVal, tt.res)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xF01E | uint16(tt.regX)<<8, addressRegister: tt.iVal}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.addressRegister != tt.res {
|
|
t.Errorf("Expected address register to be %d actually %d", tt.res, cpu.addressRegister)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0xFx29
|
|
func TestLoadSprite(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, xVal byte
|
|
iVal uint16
|
|
}{
|
|
{0xB, 0x0, 0x0},
|
|
{0xA, 0x1, 0x5},
|
|
{0xC, 0x2, 0xA},
|
|
{0xC, 0xf, 0x4B},
|
|
}
|
|
for _, tt := range tests {
|
|
testname := fmt.Sprintf("TestLoadSprite,regX:%d,xVal:%d,iVal:%d", tt.regX, tt.xVal, tt.iVal)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xF029 | uint16(tt.regX)<<8}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.addressRegister != tt.iVal {
|
|
t.Errorf("Expected address register to be %d actually %d", tt.iVal, cpu.addressRegister)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
//0xFx33
|
|
func TestStoreBCD(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xFA33, addressRegister: 0x0AAA}
|
|
cpu.registers[0xA] = 123
|
|
cpu.fifteenIndexOpcodes()
|
|
if cpu.memory[0x0AAA] != 1 {
|
|
t.Errorf("Store BCD Failed")
|
|
}
|
|
if cpu.memory[0x0AAA+1] != 2 {
|
|
t.Errorf("Store BCD Failed")
|
|
}
|
|
if cpu.memory[0x0AAA+2] != 3 {
|
|
t.Errorf("Store BCD Failed")
|
|
}
|
|
}
|
|
|
|
//0xfx55
|
|
//0xfx65
|
|
// do the load store ones idk
|
|
|
|
//0xdxyn
|
|
func TestDraw(t *testing.T) {
|
|
var tests = []struct {
|
|
regX, regY, xVal, yVal, n, collision byte
|
|
addressRegister uint16
|
|
sprite []byte
|
|
set_bits [][]byte
|
|
}{
|
|
{0xA, 0xB, 10, 10, 2, 0, 0x0BBB,
|
|
[]byte{0x3C, 0xC3},
|
|
[][]byte{[]byte{12, 10}, []byte{13, 10}, []byte{14, 10}, []byte{15, 10}, []byte{10, 11}, []byte{11, 11}, []byte{16, 11}, []byte{17, 11}}},
|
|
{0xA, 0xB, 10, 10, 2, 1, 0x0BBB,
|
|
[]byte{0x20},
|
|
[][]byte{}},
|
|
}
|
|
for i, tt := range tests {
|
|
testname := fmt.Sprintf("DrawTest%d", i)
|
|
t.Run(testname, func(t *testing.T) {
|
|
cpu := Chip8{opcode: 0xD000 | uint16(tt.regX)<<8 | uint16(tt.regY)<<4 | uint16(tt.n)}
|
|
cpu.registers[tt.regX] = tt.xVal
|
|
cpu.registers[tt.regY] = tt.yVal
|
|
cpu.addressRegister = tt.addressRegister
|
|
for j, val := range tt.sprite {
|
|
cpu.memory[cpu.addressRegister+uint16(j)] = val
|
|
}
|
|
cpu.displaySprite()
|
|
if tt.collision == 1 {
|
|
cpu.displaySprite() // this is pretty fucking horrible but at this point i'm satisfied this function is correct so whatevs
|
|
}
|
|
if cpu.addressRegister != tt.addressRegister {
|
|
t.Errorf("Expected address register to be %d actually %d", tt.addressRegister, cpu.addressRegister)
|
|
}
|
|
if cpu.registers[0xF] != tt.collision {
|
|
t.Errorf("Expected reg[0xF] to be %d, %d", cpu.registers[0xF], tt.collision)
|
|
}
|
|
for _, val := range tt.set_bits {
|
|
if cpu.graphics[int(val[0])+(int(val[1])*64)] != 1 {
|
|
t.Errorf("Expected value at %d,%d to be set", val[0], val[1])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|