コード例 #1
0
def test_00e0_calls_vram_clear_screen():
    """00E0 causes VM to call screen clear on video ram"""
    vm = VM()
    vm.video_ram = Mock(VideoRam)

    load_and_execute_instruction(vm, 0x00E0)
    assert vm.video_ram.clear_screen.called_once()
コード例 #2
0
def test_1nnn_jumps_to_address(memory_location):
    """1nnn sets program counter to nnn"""
    vm = VM()

    assert vm.program_counter == DEFAULT_EXECUTION_START
    load_and_execute_instruction(vm, 0x1000, nnn=memory_location)
    assert vm.program_counter == memory_location
    assert vm.stack_size == 0
コード例 #3
0
    def test_8xy0_same_value_for_x_and_y_leaves_reg_unchanged(self, reg_index):
        """8xy0 does not alter the value when x & y are the same"""
        vm = VM()

        vm.v_registers[reg_index] = 5
        load_and_execute_instruction(vm, 0x8000, x=reg_index, y=reg_index)

        assert vm.v_registers[reg_index] == 5
コード例 #4
0
    def test_data_past_ram_end_raises_indexerror(self, ram_size, location):
        vm = VM(memory_size=ram_size)

        # 1 after end of RAM
        data_len = 1 + ram_size - location

        with pytest.raises(IndexError):
            vm.load_to_memory(b"a" * data_len, location)
コード例 #5
0
    def test_releasing_keys_works(self):
        vm = VM()

        for key in range(0, 16):
            vm.press(key)

        for key in range(0, 16):
            vm.release(key)
            assert not vm.pressed(key)
コード例 #6
0
    def test_6xy0_skips_next_if_vx_not_equal_vy(self, x, y):
        vm = VM()
        vm.v_registers[x] = 0
        vm.v_registers[y] = 1

        load_and_execute_instruction(vm, 0x9000, x=x, y=y)

        assert vm.program_counter ==\
               DEFAULT_EXECUTION_START + (2 * INSTRUCTION_LENGTH)
コード例 #7
0
    def test_8xy2_leaves_other_registers_alone(self, x, y):
        """8xy2 leaves registers other than VX and VY alone"""

        vm = VM()
        vm.v_registers[x] = 0b10101010
        vm.v_registers[y] = 0b01010101

        load_and_execute_instruction(vm, 0x8002, x=x, y=y)

        assert other_registers_untouched(vm, (x, y))
コード例 #8
0
    def test_8xye_sets_vf_to_most_significant_digit_of_vy(self, x, y, a, b):
        """8xyE sets VF to most significant digit of VY"""
        vm = VM()

        vm.v_registers[x] = a
        vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x800E, x=x, y=y)

        assert vm.v_registers[0xF] == bool(b & 0b10000000)
コード例 #9
0
 def test_4xkk_does_not_skip_next_instruction_if_vx_eq_kk(
         self, vx: int, vx_and_kk_value: int, exec_start: int):
     vm = VM(execution_start=exec_start)
     vm.v_registers[vx] = vx_and_kk_value
     load_and_execute_instruction(vm,
                                  0x4000,
                                  load_point=exec_start,
                                  x=vx,
                                  kk=vx_and_kk_value)
     assert vm.program_counter == exec_start + INSTRUCTION_LENGTH
コード例 #10
0
    def test_8xy0_leaves_original_alone(self, x, y):
        """8xy0 leaves VY alone"""

        vm = VM()
        vm.v_registers[x] = 2
        vm.v_registers[y] = 3

        load_and_execute_instruction(vm, 0x8000, x=x, y=y)

        assert other_registers_untouched(vm, {x, y})
コード例 #11
0
def test_00ee_decrements_stack_size(call_location):
    """Return instruction decrements stack size"""
    vm = VM()
    vm.stack_call(call_location)

    load_and_execute_instruction(
        vm,
        0x00EE,  # return instruction
        load_point=call_location)
    assert vm.stack_size == 0
コード例 #12
0
def test_00ee_returns_to_last_location_plus_two(call_location):
    """Return instruction returns to last location on the stack"""
    vm = VM()
    vm.stack_call(call_location)

    load_and_execute_instruction(
        vm,
        0x00EE,  # return instruction
        load_point=call_location)
    assert vm.program_counter == DEFAULT_EXECUTION_START + 2
コード例 #13
0
    def test_9xy0_doesnt_skip_next_if_vx_eq_vy(self, x, y, equal_val):

        vm = VM()
        vm.v_registers[x] = 7
        vm.v_registers[y] = 7

        load_and_execute_instruction(vm, 0x9000, x=x, y=y)

        assert vm.program_counter ==\
               DEFAULT_EXECUTION_START + INSTRUCTION_LENGTH
コード例 #14
0
    def test_8xy6_sets_vf_to_least_significant_digit_of_vy(self, x, y, a, b):
        """8xy6 sets VF to least significant"""
        vm = VM()

        vm.v_registers[x] = a
        vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8006, x=x, y=y)

        assert vm.v_registers[0xF] == b & 1
コード例 #15
0
def test_2nnn_sets_program_counter_and_pushes_stack(memory_location):
    """2nnn instruction jumps to location and increments stack"""
    vm = VM()
    assert vm.stack_size == 0
    assert vm.program_counter == DEFAULT_EXECUTION_START
    load_and_execute_instruction(vm, 0x2000, nnn=memory_location)

    assert vm.program_counter == memory_location
    assert vm.stack_top == DEFAULT_EXECUTION_START
    assert vm.stack_size == 1
コード例 #16
0
    def test_8xy4_sets_vf_to_carry_bit(self, x, y, a, b):
        """8xy4 sets VF to 1 if VX + VY > 255, otherwise 0"""
        vm = VM()

        vm.v_registers[x] = a
        if x != y:
            vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8004, x=x, y=y)

        assert vm.v_registers[0xF] == int(a + b > 255)
コード例 #17
0
    def test_8xy6_sets_vx_to_vy_shifted_right_one(self, x, y, a, b):
        """8xy6 sets VX = VY >> 1"""

        vm = VM()

        vm.v_registers[x] = a
        vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8006, x=x, y=y)

        assert vm.v_registers[x] == b >> 1
コード例 #18
0
    def test_8xye_sets_vx_to_vy_shifted_left_one(self, x, y, a, b):
        """8xyE sets VX = VY >> 1"""

        vm = VM()

        vm.v_registers[x] = a
        vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x800E, x=x, y=y)

        assert vm.v_registers[x] == 0xFF & (b << 1)
コード例 #19
0
    def test_8xy5_sets_vf_to_not_borrow(self, x, y, a, b):
        """8xy5 sets VF to 1 if VX >= VY, otherwise 0"""
        vm = VM()

        vm.v_registers[x] = a
        if x != y:
            vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8005, x=x, y=y)

        assert vm.v_registers[0xF] == int(a >= b)
コード例 #20
0
 def test_4xkk_skips_next_instruction_if_vx_neq_kk(self, vx: int, vx_value,
                                                   kk_value, exec_start):
     vm = VM(execution_start=exec_start)
     vm.v_registers[vx] = vx_value
     load_and_execute_instruction(
         vm,
         0x4000,
         load_point=exec_start,
         x=vx_value,
         kk=kk_value,
     )
     assert vm.program_counter == exec_start + (2 * INSTRUCTION_LENGTH)
コード例 #21
0
    def test_8xy0_sets_vx_to_vy(self, x, y):
        """8xy0 sets VX = VX OR VY"""

        vm = VM()
        original_x_value = 2
        default_y_value = 3

        vm.v_registers[x] = original_x_value
        vm.v_registers[y] = default_y_value

        load_and_execute_instruction(vm, 0x8000, x=x, y=y)

        assert vm.v_registers[x] == default_y_value
コード例 #22
0
    def test_8xye_leaves_other_registers_alone_unless_theyre_vf(self, x, y):
        """8xy6 leaves registers other than VX alone except for VF"""

        vm = VM()

        vm.v_registers[x] = 2
        vm.v_registers[y] = 1

        load_and_execute_instruction(vm, 0x800E, x=x, y=y)

        # make sure we don't check VF since it should always be set
        touched = {x, 0xF}

        assert other_registers_untouched(vm, touched)
コード例 #23
0
    def test_8xy3_sets_vx_to_xor_of_vx_and_vy(self, x, y):
        """8xy3 sets VX to VX XOR VY"""

        vm = VM()

        vm.v_registers[x] = 0b10101111
        vm.v_registers[y] = 0b01011111

        load_and_execute_instruction(vm, 0x8003, x=x, y=y)

        if x != y:
            assert vm.v_registers[x] == 0b11110000

        else:  # any value xor itself yields zero
            assert vm.v_registers[x] == 0
コード例 #24
0
def test_bnnn_jumps_to_address_plus_offset(memory_location, v0):
    """Bnnn sets program counter to nnn + v0"""
    vm = VM()

    assert vm.program_counter == DEFAULT_EXECUTION_START
    assert vm.stack_size == 0

    vm.v_registers[0] = v0
    load_and_execute_instruction(
        vm,
        0xB000,
        nnn=memory_location,
    )
    assert vm.program_counter == memory_location + v0
    assert vm.stack_size == 0
コード例 #25
0
    def test_8xy2_sets_vx_to_and_of_vx_and_vy(self, x, y):
        """8xy2 sets VX to VX AND VY"""

        vm = VM()

        left_half_filled = 0b11110000

        vm.v_registers[x] = 0xFF
        vm.v_registers[y] = left_half_filled

        # set vx = vx AND 0x11110000. If vx is already set to 0x11110000,
        # the value will still be 0x11110000 after the instruction runs.
        load_and_execute_instruction(vm, 0x8002, x=x, y=y)

        assert vm.v_registers[x] == left_half_filled
コード例 #26
0
    def setup_vm(self, x: int) -> VM:
        """
        Helper to create a VM with appropriate instructions loaded.

        This might be better as a fixture once I understand them better.
        """
        vm = VM()
        load_multiple(
            vm,
            (0xF00A, {
                'x': x
            }),
            # no-op, store "load 0 to I" as next to be executed
            0xA000)
        return vm
コード例 #27
0
 def setup_vm(self, x: int, key: int) -> VM:
     """
     Helper function to set up the VM and template instructions
     """
     vm = VM()
     load_multiple(
         vm,
         (0xE09E, {
             'x': x
         }),
         # set the I register. This command can't touch that I, and
         # I is set to zero on VM initialization. Therefore, it is
         # safe to use I as a test condition for ex9e.
         0xA0FF)
     vm.v_registers[x] = key
     return vm
コード例 #28
0
    def test_8xy4_sets_vx_to_sum_of_vx_and_vy(self, x, y, a, b):
        """8xy4 sets VX to VX + VY, modulo 256"""

        vm = VM()

        vm.v_registers[x] = a

        if x != y:
            vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8004, x=x, y=y)

        if x != y:
            assert vm.v_registers[x] == (a + b) % 256
        else:
            assert vm.v_registers[x] == (a * 2) % 256
コード例 #29
0
    def test_8xy1_sets_vx_to_logical_or_of_vx_and_vy(self, x, y):
        """8xy1 sets VX = VX OR VY"""

        vm = VM()
        original_x_value = 0b10101010
        default_y_value = 0b01010101

        vm.v_registers[x] = original_x_value
        if y != x:
            vm.v_registers[y] = default_y_value

        load_and_execute_instruction(vm, 0x8001, x=x, y=y)

        if y != x:
            assert vm.v_registers[x] == original_x_value | default_y_value
        else:
            assert vm.v_registers[x] == original_x_value
コード例 #30
0
    def test_8xy7_sets_vx_to_vy_minus_vx(self, x, y, a, b):
        """8xy7 sets VX = VY - VX, clamped to 0 minimum"""

        vm = VM()

        vm.v_registers[x] = a

        if x != y:
            vm.v_registers[y] = b

        load_and_execute_instruction(vm, 0x8007, x=x, y=y)

        if x != y:
            assert vm.v_registers[x] == max(b - a, 0)

        else:  # any value minus itself yields zero
            assert vm.v_registers[x] == 0