示例#1
0
def test_zword_bitwise_operations():
    zw = ZWord.from_unsigned_int(0b1010_1010_1010_1010) << 1
    assert zw.unsigned_int == 0b0101_0101_0101_0100

    zw = ZWord.from_unsigned_int(0b0000_1111_0000_1111) << 4
    assert zw.unsigned_int == 0b1111_0000_1111_0000

    zw = ZWord.from_unsigned_int(0b0000_1111_1111_0000) >> 4
    assert zw.unsigned_int == 0b0000_0000_1111_1111

    zw = ZWord.from_unsigned_int(0b0001_0000) >> 1
    assert zw.unsigned_int == 0b0000_1000

    zw = ZWord.from_unsigned_int(0b1111_1111) & 0b0101_0101
    assert zw.unsigned_int == 0b0101_0101

    zw = ZWord.from_unsigned_int(0b1111_0000) | 0b0000_1111
    assert zw.bytes == b'\x00\xff'

    zw = ~ZWord.from_unsigned_int(0b0101_0101)
    assert zw.unsigned_int == 0b1111_1111_1010_1010

    zw = ~ZWord.from_unsigned_int(0b0000_1111)
    assert zw.unsigned_int == 0b1111_1111_1111_0000

    zw = ZWord.from_unsigned_int(0b1111_0000_1111_0000)
    assert zw.is_bit_set(15) is True
    assert zw.is_bit_set(0) is False
    assert zw.is_bit_set(4) is True
    assert zw.is_bit_clear(15) is False
    assert zw.is_bit_clear(0) is True
    assert zw.is_bit_clear(4) is False

    assert ZWord.from_int(-1) == ZWord(b'\xff\xff')
    assert ZWord.from_int(-1) != ZWord(b'\x00\x00')
示例#2
0
def test_set_own_property_v5(zork_v5_obj_table: ZMachineObjectTable):
    # Property #46 is a two-byte property
    zorkmid = zork_v5_obj_table.object(122)

    zorkmid.properties.set(46, ZWord(b'\x12\x34'))
    assert ZWord(b'\x12\x34') == zorkmid.properties.value(46)

    you = zork_v5_obj_table.object(21)
    with pytest.raises(ZMachineIllegalOperation,
                       match='size 8 with a value of size '):
        you.properties.set(46, ZWord(b'\x12\x34'))
示例#3
0
def test_stack_quetzal_chunk_with_routine_calls():
    new_stack = ZMachineStack()
    new_stack.push_routine_call(PC(0x1234), 2, ZByte.from_int(0),
                                *[ZWord.from_int(1),
                                  ZWord.from_int(2)])
    new_stack.push(ZWord.from_int(1955))
    new_stack.push(ZWord.from_int(1985))

    quetzal_stack = StacksQuetzalChunk.create(new_stack)
    restored_stack_chunk, next_chunk = StacksQuetzalChunk.read(
        quetzal_stack.bytes())

    assert next_chunk == len(quetzal_stack.bytes())
    assert restored_stack_chunk.saved_stack(
    ).frames == new_stack.frames, 'initial stack and saved stack are not the same'
示例#4
0
def test_short_form_opcodes(opcodes_v3: ZMachineOpcodeParserV3):
    # One operand of type LARGE_CONSTANT
    jump, next_pc = opcodes_v3.parse(0x85ab)
    assert jump.name == 'jump'
    assert len(jump.operand_types) == 1
    assert len(jump.operands) == 1
    assert jump.operand_types[0] == ZMachineOperandTypes.LARGE_CONSTANT
    assert jump.operands[0] == ZWord(bytes([0x00, 0x0b]))
    assert next_pc == 0x85ab + 3

    # One operand of type VARIABLE
    load, next_pc = opcodes_v3.parse(0x7d58)
    assert load.name == 'load'
    assert len(load.operand_types) == 1
    assert len(load.operands) == 1
    assert load.operand_types[0] == ZMachineOperandTypes.VARIABLE
    assert load.operands[0] == ZByte(b'\x00')
    assert next_pc == 0x7d58 + 3

    # Zero operands
    print_ret, next_pc = opcodes_v3.parse(0x4fb1)
    assert print_ret.name == 'print_ret'
    assert print_ret.operand_types is None
    assert print_ret.operands is None
    assert next_pc == 0x4fc4
示例#5
0
def test_own_properties_v5(zork_v5_obj_table: ZMachineObjectTable):
    door = zork_v5_obj_table.object(127)

    # Get own properties
    own_properties = door.properties.all()
    assert 46 in own_properties
    assert own_properties[46] == ZWord(b'\x4d\xff')

    assert 45 in own_properties
    assert own_properties[45] == ZWord(b'\x3e\x24')

    assert 44 in own_properties
    assert own_properties[44].hex() == '50364a60'

    assert own_properties[46] == door.properties.value(46)
    assert own_properties[45] == door.properties.value(45)
    assert own_properties[44] == door.properties.value(44)
示例#6
0
def test_push_peek_and_pop(stack: ZMachineStack):
    a = ZWord.from_int(42)
    b = ZWord(bytes([0, 69]))
    c = ZByte.from_int(-3)

    stack.push(a)
    stack.push(b)
    stack.push(c)

    assert stack.peek() == c.pad()
    assert stack.pop() == c.pad()

    assert stack.peek() == b
    assert stack.pop() == b

    assert stack.peek() == a
    assert stack.pop() == a
示例#7
0
def test_set_own_property_v3(zork_v3_obj_table: ZMachineObjectTable):
    # Property #16 is a single-byte property
    pair_of_hands = zork_v3_obj_table.object(1)

    # Set with a single byte
    pair_of_hands.properties.set(16, ZByte(b'\x42'))
    assert ZByte(b'\x42') == pair_of_hands.properties.value(16), \
        'a single byte property is set with a single byte value'

    # Set with two bytes
    pair_of_hands.properties.set(16, ZWord.from_int(-6))
    assert ZByte.from_int(-6) == pair_of_hands.properties.value(16), \
        'a single byte property is set with a two byte value'

    # Property #18 is a two-byte property
    zorkmid = zork_v3_obj_table.object(2)

    zorkmid.properties.set(18, ZWord(b'\x12\x34'))
    assert ZWord(b'\x12\x34') == zorkmid.properties.value(18)
示例#8
0
def test_own_properties_v3(zork_v3_obj_table: ZMachineObjectTable):
    door = zork_v3_obj_table.object(181)

    # Get own properties
    own_properties = door.properties.all()
    assert 18 in own_properties
    assert own_properties[18] == ZWord(b'\x3f\x9d')

    assert 17 in own_properties
    assert own_properties[17] == ZWord(b'\x6d\x57')

    assert 16 in own_properties
    assert own_properties[16] == ZWord(b'\xc9\xca')

    assert own_properties[18] == door.properties.get(18).value
    assert own_properties[17] == door.properties.get(17).value
    assert own_properties[16] == door.properties.get(16).value

    assert own_properties[18] == door.properties.value(18)
    assert own_properties[17] == door.properties.value(17)
    assert own_properties[16] == door.properties.value(16)
示例#9
0
def test_variable_form_opcodes(opcodes_v3: ZMachineOpcodeParserV3):
    # Test variable form of 2OP opcode instructions
    call, next_pc = opcodes_v3.parse(0x5157)
    assert call.name == 'je'
    assert len(call.operand_types) == 3
    assert call.operand_types == (ZMachineOperandTypes.VARIABLE,
                                  ZMachineOperandTypes.SMALL_CONSTANT,
                                  ZMachineOperandTypes.SMALL_CONSTANT)
    assert call.operands == (ZByte(b'\x88'), ZByte(b'\x32'), ZByte(b'\x12'))
    assert next_pc == 0x5157 + 6

    # Test unique variable opcode instructions
    call, next_pc = opcodes_v3.parse(0x4f05)
    assert call.name == 'call'
    assert len(call.operand_types) == 3
    assert call.operand_types == (ZMachineOperandTypes.LARGE_CONSTANT,
                                  ZMachineOperandTypes.LARGE_CONSTANT,
                                  ZMachineOperandTypes.LARGE_CONSTANT)
    assert len(call.operands) == 3

    assert call.operands == (ZWord(bytes([0x2a,
                                          0x39])), ZWord(bytes([0x80, 0x10])),
                             ZWord(bytes([0xff, 0xff])))
    assert next_pc == 0x4f05 + 9
示例#10
0
def test_zword_to_zbyte_math():
    zw = ZWord.from_int(129) + ZByte.from_int(127)
    assert zw.bytes == b'\x01\x00', 'ZWord + ZByte'

    zw = ZWord.from_int(0) - ZByte.from_int(127)
    assert zw.int == -127, 'ZWord - ZByte'

    zw = ZWord.from_int(-4) * ZByte.from_int(64)
    assert zw.int == -256, 'ZWord * ZByte'

    zw = ZWord.from_int(126) // ZByte.from_int(2)
    assert zw.int == 63, 'ZWord/ZByte integer division'

    with pytest.raises(ZMachineIllegalOperation, match='Divide by zero'):
        ZWord.from_int(45) // ZByte.from_int(0)

    with pytest.raises(ZMachineIllegalOperation):
        ZWord.from_int(4) / ZByte.from_int(8)
示例#11
0
def test_umem_quetzal_chunk(zork_v3_obj_table: ZMachineObjectTable):
    original_memory = bytes(zork_v3_obj_table._memory)

    cretin = zork_v3_obj_table.object(4)
    cretin.properties.set(18, ZWord(bytes.fromhex('ffff')))
    prop_address = cretin.properties.get(18).value_address

    cmem_chunk = UMemQuetzalChunk(zork_v3_obj_table._memory)

    restored_chunk, offset = UMemQuetzalChunk.read(cmem_chunk.bytes())
    assert offset == len(cmem_chunk.bytes())
    restored_memory = restored_chunk.saved_memory()

    for i in range(len(restored_memory)):
        if i not in [prop_address, prop_address + 1]:
            assert restored_memory[i] == original_memory[
                i], f'memory different at {hex(i)} should be different at {hex(prop_address)}'
        else:
            assert restored_memory[i] != original_memory[
                i], f'memory should be different at {hex(i)} for prop at address {hex(prop_address)}'
示例#12
0
def test_zbyte_to_zword_math():
    zw = ZByte.from_int(0) + ZWord.from_int(256)
    assert zw.bytes == b'\x01\x00', 'ZByte + ZWord'

    zw = ZByte.from_int(0) - ZWord.from_int(129)
    assert zw.int == -129, 'ZByte - ZWord'

    zw = ZByte.from_int(-2) * ZWord.from_int(128)
    assert zw.int == -256, 'ZByte * ZWord'

    zw = ZByte.from_int(126) // ZWord.from_int(2)
    assert zw.int == 63, 'ZByte/ZWord integer division'

    with pytest.raises(ZMachineIllegalOperation, match='Divide by zero'):
        ZByte.from_int(45) // ZWord.from_int(0)

    with pytest.raises(ZMachineIllegalOperation):
        ZByte.from_int(4) / ZWord.from_int(8)

    zw = ZByte.from_int(127) % ZWord.from_int(2)
    assert zw.int == 1

    zw = ZByte.from_int(-128) % ZWord.from_int(2)
    assert zw.int == 0
示例#13
0
def test_zword_write_memory(zork1_v3_data: memoryview):
    ZWord.from_unsigned_int(0x4269).write(zork1_v3_data, 6)
    assert zork1_v3_data[6:8] == b'\x42\x69'
示例#14
0
def test_zword_zword_math():
    zw = ZWord.from_int(0) + ZWord.from_int(512)
    assert zw.bytes == b'\x02\x00', 'ZWord + ZWord'

    zw = ZWord.from_int(0) - ZWord.from_int(1)
    assert zw.bytes == b'\xff\xff', 'ZWord - ZWord'

    zw = ZWord.from_int(-32768) - ZWord.from_int(1)
    assert zw.bytes == b'\x7f\xff', 'ZWord arithmetic truncation'

    zw = ZWord.from_int(-2) * ZWord.from_int(8)
    assert zw.int == -16, 'ZWord * ZWord'

    zw = ZWord.from_int(32767) * ZWord.from_int(32767)
    assert zw.bytes == b'\x00\x01', 'ZWord multiplication truncation'

    zw = ZWord.from_int(3) // ZWord.from_int(2)
    assert zw.bytes == b'\x00\x01', 'ZWord integer division'

    with pytest.raises(ZMachineIllegalOperation, match='Divide by zero'):
        ZWord.from_int(45) // ZWord.from_int(0)

    with pytest.raises(ZMachineIllegalOperation):
        ZWord.from_int(4) / ZWord.from_int(8)

    zw = ZWord(b'\x00\x01').inc()
    assert zw.bytes == b'\x00\x02'

    zw = ZWord(b'\xff\xfe').inc()
    assert zw.bytes == b'\xff\xff'

    zw = ZWord(b'\xff\xff').inc()
    assert zw.bytes == b'\x00\x00', 'Rollover on increment'

    zw = ZWord.from_int(500).dec()
    assert zw.int == 499

    zw = ZWord(b'\xff\xff').dec()
    assert zw.bytes == b'\xff\xfe'

    zw = ZWord(b'\x00\x00').dec()
    assert zw.bytes == b'\xff\xff', 'Rollover on decrement'

    zw = ZWord.from_int(32767) % ZWord.from_int(2)
    assert zw.int == 1

    zw = ZWord.from_int(-32768) % ZWord.from_int(2)
    assert zw.int == 0
示例#15
0
def test_instantiate_zword():
    zw = ZWord(bytes.fromhex('1234'))
    assert zw.bytes == b'\x12\x34', 'Instantiate ZWord from bytes'

    zw = ZWord(memoryview(bytes.fromhex('4242')))
    assert zw.bytes == b'\x42\x42', 'Instantiate ZWord from memoryview'

    zw = ZWord.from_int(-1)
    assert zw.bytes == b'\xff\xff', 'Instantiate ZWord from int'

    zw = ZWord.from_unsigned_int(0xf0f0)
    assert zw.bytes == b'\xf0\xf0', 'Instantiate ZWord from unsigned int'

    with pytest.raises(TypeError):
        ZWord(22)

    with pytest.raises(ValueError):
        ZWord(b'\x12')

    with pytest.raises(ValueError):
        ZWord(b'')

    with pytest.raises(ValueError):
        ZWord.from_int(-32769)

    with pytest.raises(ValueError):
        ZWord.from_int(32768)

    with pytest.raises(ValueError):
        ZWord.from_unsigned_int(-1)

    with pytest.raises(ValueError):
        ZWord.from_unsigned_int(65536)
示例#16
0
def read_token_block(memory: memoryview, parse_buf: int, token_num: int):
    block_offset = parse_buf + 2 + (token_num * 4)

    return TokenBlock(
        ZWord(memory, block_offset).unsigned_int, memory[block_offset + 2],
        memory[block_offset + 3])
示例#17
0
def test_routine_calls(stack: ZMachineStack):
    ret_a = PC(1234)
    ret_var_a = ZByte.from_int(2)
    a_locals = [
        ZWord.from_int(1),
        ZWord.from_int(2),
        ZWord.from_int(3),
        ZByte.from_int(4)
    ]

    ret_b = PC(5678)
    ret_var_b = ZByte.from_unsigned_int(45)
    b_locals = [ZWord.from_int(42), ZWord.from_int(56)]

    stack.push_routine_call(ret_a, len(a_locals), ret_var_a, *a_locals)
    assert stack.local_var(0) == a_locals[0]
    assert stack.local_var(1) == a_locals[1]
    assert stack.local_var(2) == a_locals[2]
    stack.set_local_var(3, ZWord.from_int(34))
    assert stack.local_var(3) == ZWord.from_int(34)
    stack.push(ZWord.from_int(69))

    stack.push_routine_call(ret_b, len(b_locals), ret_var_b, *b_locals)
    assert stack.local_var(0) == b_locals[0]
    assert stack.local_var(1) == b_locals[1]
    stack.push(ZWord.from_int(342))
    ret_pc, ret_var = stack.pop_routine_call()
    assert ret_pc == ret_b
    assert ret_var == ret_var

    # Now ensure the previous call's variables are still correct
    assert stack.local_var(0) == a_locals[0]
    assert stack.local_var(1) == a_locals[1]
    assert stack.local_var(2) == a_locals[2]
    assert stack.local_var(3) == ZWord.from_int(34)
    assert stack.pop() == ZWord.from_int(69)

    ret_pc, ret_var = stack.pop_routine_call()
    assert ret_pc == ret_a
    assert ret_var == ret_var_a