still shit wrong idc
This commit is contained in:
		
							parent
							
								
									1f526b5331
								
							
						
					
					
						commit
						d6e1b989e2
					
				| @ -49,7 +49,6 @@ func NewCHIP8(prog []byte) *Chip8 { | |||||||
| 	memory_slice := cpu.memory[:80] | 	memory_slice := cpu.memory[:80] | ||||||
| 	copy(memory_slice, getLetters()) | 	copy(memory_slice, getLetters()) | ||||||
| 	memory_slice = cpu.memory[0x200:] | 	memory_slice = cpu.memory[0x200:] | ||||||
| 	fmt.Printf("%d\n", prog[0]) |  | ||||||
| 	copy(memory_slice, prog) | 	copy(memory_slice, prog) | ||||||
| 
 | 
 | ||||||
| 	// Do some extra checking to ensure the right | 	// Do some extra checking to ensure the right | ||||||
| @ -176,38 +175,43 @@ func (cpu *Chip8) bitOpsAndMath() { | |||||||
| 	case 4: | 	case 4: | ||||||
| 		// 8XY4 | 		// 8XY4 | ||||||
| 		// Set register x to X+=Y (Set VF to 1 when there's a carry and 0 if not) | 		// 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 cpu.registers[regX] > 0xFF-cpu.registers[regY] { | ||||||
| 		if res > 0xFF { |  | ||||||
| 			cpu.registers[0x0F] = 1 | 			cpu.registers[0x0F] = 1 | ||||||
| 		} else { | 		} else { | ||||||
| 			cpu.registers[0x0F] = 0 | 			cpu.registers[0x0F] = 0 | ||||||
| 		} | 		} | ||||||
| 		cpu.registers[regX] = res & 0xFF | 		cpu.registers[regX] += +cpu.registers[regY] | ||||||
| 	case 5: | 	case 5: | ||||||
| 		// 8XY5 | 		// 8XY5 | ||||||
| 		// Set register x to X-=Y (Set VF to 1 when there's a carry and 0 if not) | 		// 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 cpu.registers[regY] < 0xFF-cpu.registers[regX] { | ||||||
| 		if res > 0xFF { |  | ||||||
| 			cpu.registers[0x0F] = 1 | 			cpu.registers[0x0F] = 1 | ||||||
| 		} else { | 		} else { | ||||||
| 			cpu.registers[0x0F] = 0 | 			cpu.registers[0x0F] = 0 | ||||||
| 		} | 		} | ||||||
| 		cpu.registers[regX] = res & 0xFF | 		cpu.registers[regX] -= cpu.registers[regY] | ||||||
| 	case 6: | 	case 6: | ||||||
| 		// BXY6 | 		// BXY6 | ||||||
| 		// Store lsb of reg X in reg F and then shift reg X >> 1 | 		// Store lsb of reg X in reg F and then shift reg X >> 1 | ||||||
| 		cpu.registers[0x0F] = cpu.registers[regX] & 0x01 | 		// Need to account for quirks - look how that js one does it | ||||||
| 		cpu.registers[regX] >>= 1 | 		cpu.registers[0x0F] = cpu.registers[regY] & 0x01 | ||||||
|  | 		cpu.registers[regX] = cpu.registers[regY] >> 1 | ||||||
| 	case 7: | 	case 7: | ||||||
| 		// 8XY57 | 		// 8XY7 | ||||||
| 		// Set register x to X=Y-X (Set VF to 1 when there's a carry and 0 if not) | 		// 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 cpu.registers[regX] < 0xFF-cpu.registers[regY] { | ||||||
| 		if res < 0 { | 			cpu.registers[0x0F] = 1 | ||||||
| 			cpu.registers[0x0F] = 0 |  | ||||||
| 		} else { | 		} 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 | 	// ANNN | ||||||
| 	// Sets the address register to NNN | 	// Sets the address register to NNN | ||||||
| 	cpu.addressRegister = cpu.opcode & 0x0FFF | 	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() { | func (cpu *Chip8) jumpToV0PlusAddress() { | ||||||
| @ -243,12 +250,20 @@ func (cpu *Chip8) displaySprite() { | |||||||
| 	cpu.registers[0x0F] = 0 | 	cpu.registers[0x0F] = 0 | ||||||
| 	x := int(cpu.registers[(cpu.opcode>>8)&0x0F]) | 	x := int(cpu.registers[(cpu.opcode>>8)&0x0F]) | ||||||
| 	y := int(cpu.registers[(cpu.opcode>>4)&0x0F]) | 	y := int(cpu.registers[(cpu.opcode>>4)&0x0F]) | ||||||
| 
 |  | ||||||
| 	for row := 0; row < int(cpu.opcode&0xF); row++ { | 	for row := 0; row < int(cpu.opcode&0xF); row++ { | ||||||
| 		pixel := cpu.memory[int(cpu.addressRegister)+row] | 		pixel := cpu.memory[int(cpu.addressRegister)+row] | ||||||
| 		for column := 0; column < 8; column++ { | 		for column := 0; column < 8; column++ { | ||||||
| 			if pixel&(0x80>>column) != 0 { | 			if pixel&(0x80>>column) != 0 { | ||||||
| 				graphicsPosition := x + column + ((y + row) * 64) | 				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 { | 				if cpu.graphics[graphicsPosition] == 1 { | ||||||
| 					cpu.registers[0xF] = 1 | 					cpu.registers[0xF] = 1 | ||||||
| 				} | 				} | ||||||
| @ -318,10 +333,16 @@ func (cpu *Chip8) fifteenIndexOpcodes() { | |||||||
| 			cpu.registers[0x0F] = 0 | 			cpu.registers[0x0F] = 0 | ||||||
| 		} | 		} | ||||||
| 		cpu.addressRegister = uint16((int(cpu.addressRegister) + int(cpu.registers[reg])) & 0xFFF) | 		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: | 	case 0x29: | ||||||
| 		// FX29 | 		// FX29 | ||||||
| 		// Sets address register to location of char stored in VX | 		// Sets address register to location of char stored in VX | ||||||
| 		cpu.addressRegister = uint16(cpu.registers[reg]) * 5 | 		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: | 	case 0x33: | ||||||
| 		// FX33 | 		// FX33 | ||||||
| 		// Stores BCD representation of VX | 		// Stores BCD representation of VX | ||||||
| @ -351,6 +372,7 @@ func (cpu *Chip8) UpdateKeys(newKeys [16]byte) { | |||||||
| func (cpu *Chip8) PerformCycle() { | func (cpu *Chip8) PerformCycle() { | ||||||
| 	cpu.opcode = (uint16(cpu.memory[cpu.pc]) << 8) + uint16(cpu.memory[cpu.pc+1]) | 	cpu.opcode = (uint16(cpu.memory[cpu.pc]) << 8) + uint16(cpu.memory[cpu.pc+1]) | ||||||
| 	cpu.pc += 2 | 	cpu.pc += 2 | ||||||
|  | 	fmt.Printf("%x\n", cpu.opcode) | ||||||
| 	switch cpu.opcode >> 12 { | 	switch cpu.opcode >> 12 { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		cpu.zeroIndexOpcodes() | 		cpu.zeroIndexOpcodes() | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ func TestCreateCPU(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x00E0 | ||||||
| func TestClearDisplay(t *testing.T) { | func TestClearDisplay(t *testing.T) { | ||||||
| 	cpu := Chip8{opcode: 0x00E0} | 	cpu := Chip8{opcode: 0x00E0} | ||||||
| 	for i := range cpu.graphics { | 	for i := range cpu.graphics { | ||||||
| @ -41,6 +42,7 @@ func TestClearDisplay(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x00EE | ||||||
| func TestLeaveFunction(t *testing.T) { | func TestLeaveFunction(t *testing.T) { | ||||||
| 	cpu := Chip8{pc: 50, opcode: 0x00EE} | 	cpu := Chip8{pc: 50, opcode: 0x00EE} | ||||||
| 	cpu.stack = append(cpu.stack, 1, 2, 3, 4, 5) | 	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) { | func TestGoTo(t *testing.T) { | ||||||
| 	cpu := Chip8{opcode: 0x3420} | 	cpu := Chip8{opcode: 0x3420} | ||||||
| 	cpu.goTo() | 	cpu.goTo() | ||||||
| @ -58,6 +61,7 @@ func TestGoTo(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x2NNN | ||||||
| func TestCallSubroutine(t *testing.T) { | func TestCallSubroutine(t *testing.T) { | ||||||
| 	cpu := Chip8{opcode: 0x3420, pc: 43} | 	cpu := Chip8{opcode: 0x3420, pc: 43} | ||||||
| 	cpu.callSubroutine() | 	cpu.callSubroutine() | ||||||
| @ -66,6 +70,7 @@ func TestCallSubroutine(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x3XNN | ||||||
| func TestSkipIfRegisterEqual(t *testing.T) { | func TestSkipIfRegisterEqual(t *testing.T) { | ||||||
| 	var tests = []struct { | 	var tests = []struct { | ||||||
| 		register, regValue byte | 		register, regValue byte | ||||||
| @ -90,6 +95,7 @@ func TestSkipIfRegisterEqual(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x4XNN | ||||||
| func TestSkipIfRegisterNotEqual(t *testing.T) { | func TestSkipIfRegisterNotEqual(t *testing.T) { | ||||||
| 	var tests = []struct { | 	var tests = []struct { | ||||||
| 		register, regValue byte | 		register, regValue byte | ||||||
| @ -114,6 +120,7 @@ func TestSkipIfRegisterNotEqual(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x5XY0 | ||||||
| func TestSkipIfRegistersEqual(t *testing.T) { | func TestSkipIfRegistersEqual(t *testing.T) { | ||||||
| 	var tests = []struct { | 	var tests = []struct { | ||||||
| 		reg1, reg2, val1, val2 byte | 		reg1, reg2, val1, val2 byte | ||||||
| @ -140,6 +147,7 @@ func TestSkipIfRegistersEqual(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x6XNN | ||||||
| func TestSetRegisterTo(t *testing.T) { | func TestSetRegisterTo(t *testing.T) { | ||||||
| 	cpu := Chip8{opcode: 0x0824} | 	cpu := Chip8{opcode: 0x0824} | ||||||
| 	cpu.setRegisterTo() | 	cpu.setRegisterTo() | ||||||
| @ -148,6 +156,7 @@ func TestSetRegisterTo(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | //0x7XNN | ||||||
| func TestRegisterPlusEqualsNN(t *testing.T) { | func TestRegisterPlusEqualsNN(t *testing.T) { | ||||||
| 	var tests = []struct { | 	var tests = []struct { | ||||||
| 		register, initalVal, toAdd, expected byte | 		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]) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user