def test_set_x_to_delay_timer(self): opcode = Opcode(0xF207) operation = SetXToDelayTimer() self.cpu.delay_timer = 0xA operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.general_purpose_registers[opcode.x], self.cpu.delay_timer)
def _test_skip(self, word, operation): opcode = Opcode(word) operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.program_counter, Cpu.PROGRAM_START_ADDRESS) self.cpu.general_purpose_registers[1] = 1 operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.program_counter, Cpu.PROGRAM_START_ADDRESS + Cpu.WORD_SIZE_IN_BYTES)
def test_load_character_addresses(self): operation = LoadCharacterAddress() for number in range(16): opcode = Opcode(0xF029) self.cpu.general_purpose_registers[opcode.x] = number operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.index_register, number * Font.CHAR_SIZE_IN_BYTES)
def test_shift_x_right(self): opcode = Opcode(0x810E) operation = ShiftXRight() self.cpu.general_purpose_registers[opcode.x] = 2 operation.execute(opcode, self.cpu) self.assertEqual( self.cpu.general_purpose_registers[ Cpu.ARITHMETIC_FLAG_REGISTER_ADDRESS], 0) self.assertEqual(self.cpu.general_purpose_registers[opcode.x], 1)
def test_clear_display(self): opcode = Opcode(0x00E0) operation = ClearDisplay() operation.execute(opcode, self.cpu) for x in range(64): for y in range(32): self.assertEqual(self.cpu.frame_buffer[x][y], False)
def test_call_function(self): opcode = Opcode(0x2ABC) operation = CallFunction() operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.program_counter, 0xABC) self.assertEqual(len(self.cpu.stack), 1) self.assertEqual(self.cpu.stack[0], 512)
def _test_arithmetic(self, word, operation, x, y, expected_result, expected_flag_value): opcode = Opcode(word) self.cpu.general_purpose_registers[opcode.x] = x self.cpu.general_purpose_registers[opcode.y] = y operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.general_purpose_registers[opcode.x], expected_result) self.assertEqual( self.cpu.general_purpose_registers[ Cpu.ARITHMETIC_FLAG_REGISTER_ADDRESS], expected_flag_value)
def test_skip_if_key_not_down(self): opcode = Opcode(0xE4A1) self.cpu.general_purpose_registers[opcode.x] = 0xF operation = SkipIfKeyNotPressed() self.cpu.key_down(0xF) operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.program_counter, self.cpu.PROGRAM_START_ADDRESS) self.cpu.key_up(0xF) operation.execute(opcode, self.cpu) self.assertEqual( self.cpu.program_counter, self.cpu.PROGRAM_START_ADDRESS + self.cpu.WORD_SIZE_IN_BYTES)
def test_draw_collision(self): opcode = Opcode(0xD113) x = self.cpu.general_purpose_registers[opcode.x] y = self.cpu.general_purpose_registers[opcode.y] self.cpu.ram[self.cpu.index_register] = 0b1111 operation = DrawSprite() operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.general_purpose_registers[self.cpu.ARITHMETIC_FLAG_REGISTER_ADDRESS], 0) self.cpu.ram[self.cpu.index_register] = 0b0110 operation.execute(opcode, self.cpu) self._test_buffer_pixels_match_pattern(x, y, 0b1001) self.assertEqual(self.cpu.general_purpose_registers[self.cpu.ARITHMETIC_FLAG_REGISTER_ADDRESS], 1)
def test_wait_for_key_press(self): opcode = Opcode(0xF10A) operation = WaitForKeyPress() program_address = self.cpu.program_counter operation.execute(opcode, self.cpu) self.cpu.move_to_next_instruction() self.assertEqual(self.cpu.general_purpose_registers[opcode.x], 0x0) self.assertEqual(self.cpu.program_counter, program_address) self.cpu.key_down(0xE) operation.execute(opcode, self.cpu) self.cpu.move_to_next_instruction() self.assertEqual(self.cpu.general_purpose_registers[opcode.x], 0xE) self.assertGreater(self.cpu.program_counter, program_address) self.assertEqual(self.cpu.program_counter - program_address, self.cpu.WORD_SIZE_IN_BYTES)
def test_draw_sprite(self): opcode = Opcode(0xD013) self.cpu.general_purpose_registers[opcode.x] = 0 self.cpu.general_purpose_registers[opcode.y] = 1 self.cpu.ram[self.cpu.index_register] = 0b1 self.cpu.ram[self.cpu.index_register + 1] = 0b11 self.cpu.ram[self.cpu.index_register + 2] = 0b111 operation = DrawSprite() operation.execute(opcode, self.cpu) x = self.cpu.general_purpose_registers[opcode.x] y = self.cpu.general_purpose_registers[opcode.y] self._test_buffer_pixels_match_pattern(x, y, 0b1) self._test_buffer_pixels_match_pattern(x, y+1, 0b11) self._test_buffer_pixels_match_pattern(x, y+2, 0b111) self._test_buffer_pixels_match_pattern(x, y+3, 0b0)
def find_operation(self, word): "This method takes a 16 bit value representing an opcode and returns the related operation" opcode = Opcode(word) # make a key of a + n + n so that 0xA123 becomes 0xA23 twelve_bit_key = int((opcode.a << 8) + opcode.nn) if twelve_bit_key in self._operations: return self._operations[twelve_bit_key] # make a key of a + n so that 0xA123 becomes 0xA3 eight_bit_key = int((opcode.a << 4) + opcode.n) if eight_bit_key in self._operations: return self._operations[eight_bit_key] four_bit_key = opcode.a if four_bit_key in self._operations: return self._operations[four_bit_key] raise KeyError( f"Opcode {word:#06x} not present in list of valid operations")
def setUp(self): self.opcode = Opcode(0xABCD) self.operation_mapper = OperationMapper()
def setUp(self): self.opcode = Opcode(0xABCD)
def _test_bitwise_operation(self, word, operation, expected_value): opcode = Opcode(word) operation.execute(opcode, self.cpu) self.assertEqual(self.cpu.general_purpose_registers[opcode.x], expected_value)