tons more unit tests
continuous-integration/drone/push Build is passing Details

still shit wrong
idc
This commit is contained in:
Sid 2020-10-24 17:41:55 +01:00
parent 1f526b5331
commit d6e1b989e2
2 changed files with 499 additions and 16 deletions

View File

@ -49,7 +49,6 @@ func NewCHIP8(prog []byte) *Chip8 {
memory_slice := cpu.memory[:80]
copy(memory_slice, getLetters())
memory_slice = cpu.memory[0x200:]
fmt.Printf("%d\n", prog[0])
copy(memory_slice, prog)
// Do some extra checking to ensure the right
@ -176,38 +175,43 @@ func (cpu *Chip8) bitOpsAndMath() {
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 {
if cpu.registers[regX] > 0xFF-cpu.registers[regY] {
cpu.registers[0x0F] = 1
} else {
cpu.registers[0x0F] = 0
}
cpu.registers[regX] = res & 0xFF
cpu.registers[regX] += +cpu.registers[regY]
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 {
if cpu.registers[regY] < 0xFF-cpu.registers[regX] {
cpu.registers[0x0F] = 1
} else {
cpu.registers[0x0F] = 0
}
cpu.registers[regX] = res & 0xFF
cpu.registers[regX] -= cpu.registers[regY]
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
// Need to account for quirks - look how that js one does it
cpu.registers[0x0F] = cpu.registers[regY] & 0x01
cpu.registers[regX] = cpu.registers[regY] >> 1
case 7:
// 8XY57
// 8XY7
// Set register x to X=Y-X (Set VF to 1 when there's a carry and 0 if not)
res := cpu.registers[regY] - cpu.registers[regX]
if res < 0 {
cpu.registers[0x0F] = 0
if cpu.registers[regX] < 0xFF-cpu.registers[regY] {
cpu.registers[0x0F] = 1
} else {
cpu.registers[0x0f] = 1
cpu.registers[0x0f] = 0
}
cpu.registers[regX] = res & 0xFF
cpu.registers[regX] = cpu.registers[regY] - cpu.registers[regX]
case 0xE:
// BXYE
// Store msb of reg X in reg F and then shift reg X >> 1
// Need to account for quirks - look how that js one does it
// Need to account for quircks - look how that js one does it
cpu.registers[0x0F] = (cpu.registers[regY] >> 7) & 0x01
cpu.registers[regX] = cpu.registers[regY] << 1
}
}
@ -222,6 +226,9 @@ func (cpu *Chip8) setAddressRegister() {
// ANNN
// Sets the address register to NNN
cpu.addressRegister = cpu.opcode & 0x0FFF
fmt.Printf("---set----\n")
fmt.Printf("%x\n", cpu.opcode)
fmt.Printf("addr set to %d\n", cpu.addressRegister)
}
func (cpu *Chip8) jumpToV0PlusAddress() {
@ -243,12 +250,20 @@ func (cpu *Chip8) displaySprite() {
cpu.registers[0x0F] = 0
x := int(cpu.registers[(cpu.opcode>>8)&0x0F])
y := int(cpu.registers[(cpu.opcode>>4)&0x0F])
for row := 0; row < int(cpu.opcode&0xF); row++ {
pixel := cpu.memory[int(cpu.addressRegister)+row]
for column := 0; column < 8; column++ {
if pixel&(0x80>>column) != 0 {
graphicsPosition := x + column + ((y + row) * 64)
if graphicsPosition > 2048 {
fmt.Printf("OH FUCK\n")
fmt.Printf("graphpos: %d\n", graphicsPosition)
fmt.Printf("x: %d\n", x)
fmt.Printf("y: %d\n", y)
fmt.Printf("row: %d\n", row)
fmt.Printf("addreg: %d\n", cpu.addressRegister)
graphicsPosition = graphicsPosition % 64 * 32
}
if cpu.graphics[graphicsPosition] == 1 {
cpu.registers[0xF] = 1
}
@ -318,10 +333,16 @@ func (cpu *Chip8) fifteenIndexOpcodes() {
cpu.registers[0x0F] = 0
}
cpu.addressRegister = uint16((int(cpu.addressRegister) + int(cpu.registers[reg])) & 0xFFF)
fmt.Printf("---set----\n")
fmt.Printf("%x\n", cpu.opcode)
fmt.Printf("addr set to %d\n", cpu.addressRegister)
case 0x29:
// FX29
// Sets address register to location of char stored in VX
cpu.addressRegister = uint16(cpu.registers[reg]) * 5
fmt.Printf("---set----\n")
fmt.Printf("%x\n", cpu.opcode)
fmt.Printf("addr set to %d\n", cpu.addressRegister)
case 0x33:
// FX33
// Stores BCD representation of VX
@ -351,6 +372,7 @@ func (cpu *Chip8) UpdateKeys(newKeys [16]byte) {
func (cpu *Chip8) PerformCycle() {
cpu.opcode = (uint16(cpu.memory[cpu.pc]) << 8) + uint16(cpu.memory[cpu.pc+1])
cpu.pc += 2
fmt.Printf("%x\n", cpu.opcode)
switch cpu.opcode >> 12 {
case 0:
cpu.zeroIndexOpcodes()

View File

@ -27,6 +27,7 @@ func TestCreateCPU(t *testing.T) {
}
}
//0x00E0
func TestClearDisplay(t *testing.T) {
cpu := Chip8{opcode: 0x00E0}
for i := range cpu.graphics {
@ -41,6 +42,7 @@ func TestClearDisplay(t *testing.T) {
}
}
//0x00EE
func TestLeaveFunction(t *testing.T) {
cpu := Chip8{pc: 50, opcode: 0x00EE}
cpu.stack = append(cpu.stack, 1, 2, 3, 4, 5)
@ -50,6 +52,7 @@ func TestLeaveFunction(t *testing.T) {
}
}
//0x1NNN
func TestGoTo(t *testing.T) {
cpu := Chip8{opcode: 0x3420}
cpu.goTo()
@ -58,6 +61,7 @@ func TestGoTo(t *testing.T) {
}
}
//0x2NNN
func TestCallSubroutine(t *testing.T) {
cpu := Chip8{opcode: 0x3420, pc: 43}
cpu.callSubroutine()
@ -66,6 +70,7 @@ func TestCallSubroutine(t *testing.T) {
}
}
//0x3XNN
func TestSkipIfRegisterEqual(t *testing.T) {
var tests = []struct {
register, regValue byte
@ -90,6 +95,7 @@ func TestSkipIfRegisterEqual(t *testing.T) {
}
}
//0x4XNN
func TestSkipIfRegisterNotEqual(t *testing.T) {
var tests = []struct {
register, regValue byte
@ -114,6 +120,7 @@ func TestSkipIfRegisterNotEqual(t *testing.T) {
}
}
//0x5XY0
func TestSkipIfRegistersEqual(t *testing.T) {
var tests = []struct {
reg1, reg2, val1, val2 byte
@ -140,6 +147,7 @@ func TestSkipIfRegistersEqual(t *testing.T) {
}
}
//0x6XNN
func TestSetRegisterTo(t *testing.T) {
cpu := Chip8{opcode: 0x0824}
cpu.setRegisterTo()
@ -148,6 +156,7 @@ func TestSetRegisterTo(t *testing.T) {
}
}
//0x7XNN
func TestRegisterPlusEqualsNN(t *testing.T) {
var tests = []struct {
register, initalVal, toAdd, expected byte
@ -169,3 +178,455 @@ func TestRegisterPlusEqualsNN(t *testing.T) {
})
}
}
// 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])
}
}
})
}
}