def STA_ADDRESS_MODE_TESTS() -> bool: TEST_NAME = f'STA_ADDRESS_MODE_TESTS' INSTRUCTION = 'STA' IMMEDIATE_VALUE = None # VALUE_TO_TEST = 0xA5 ZP_ADDRESS = 0x0059 IND_ZP_ADDRESS = 0x0069 FULL_ADDRESS = 0xAA48 EXPECTED_VALUE = 0x05 CYCLE_COUNTS = { 'ZP': 3, 'ZP_X': 4, 'ABS': 4, 'ABS_X': 5, 'ABS_Y': 5, 'IND_X': 6, 'IND_Y': 6 } INITIAL_REGISTERS = { 'A': EXPECTED_VALUE, 'X': 0x01, 'Y': 0x05 } EXPECTED_REGISTERS = { 'A': EXPECTED_VALUE, 'X': 0x01, 'Y': 0x05 } INITIAL_FLAGS = { 'C': 0, 'Z': 0, 'I': 0, 'D': 0, 'B': 0, 'V': 0, 'N': 0 } EXPECTED_FLAGS = { 'C': 0, 'Z': 0, 'I': 0, 'D': 0, 'B': 0, 'V': 0, 'N': 0 } programs = generateProgram(instruction=INSTRUCTION, registers=INITIAL_REGISTERS, immediate_value=IMMEDIATE_VALUE, zp_address=ZP_ADDRESS, ind_zp_address=IND_ZP_ADDRESS, sixteen_bit_address=FULL_ADDRESS, CYCLE_COUNTS=CYCLE_COUNTS) print(f'{bcolors.UNDERLINE}Running {TEST_NAME}{bcolors.ENDC}') errors = False for label, program in programs.items(): print(f'\tTesting {label}... ', end='') PROGRAM = program[0] EXPECTED_CYCLES = program[1] cpu = CPU6502(cycle_limit=100) cpu.reset(program_counter=0xFF00) cpu.load_program(instructions=PROGRAM, memoryAddress=0xFF00) cpu.registers = INITIAL_REGISTERS.copy() cpu.flags = INITIAL_FLAGS.copy() # cpu.memory[ZP_ADDRESS] = VALUE_TO_TEST # ZP, ZP_X, and ZP_Y Location cpu.memory[IND_ZP_ADDRESS] = FULL_ADDRESS & 0b0000000011111111 cpu.memory[IND_ZP_ADDRESS + 1] = (FULL_ADDRESS & 0b1111111100000000) >> 8 # cpu.memory[FULL_ADDRESS] = VALUE_TO_TEST # ABS, ABS_X, ABS_Y, and IND_X Location # cpu.memory[FULL_ADDRESS + INITIAL_REGISTERS['Y']] = VALUE_TO_TEST # IND_Y Location # EXPECTED_MEMORY = cpu.memory.copy() cpu.execute() if (cpu.registers != EXPECTED_REGISTERS) \ or (cpu.flags != EXPECTED_FLAGS) \ or (cpu.cycles - 1 != EXPECTED_CYCLES) \ or (EXPECTED_VALUE is not None and label in ['ZP', 'ZP_X', 'ZP_Y'] and cpu.memory[ZP_ADDRESS] != EXPECTED_VALUE) \ or (EXPECTED_VALUE is not None and label in ['ABS', 'ABS_X', 'ABS_Y', 'IND_X'] and cpu.memory[FULL_ADDRESS] != EXPECTED_VALUE) \ or (EXPECTED_VALUE is not None and label in ['IND_Y'] and cpu.memory[FULL_ADDRESS + INITIAL_REGISTERS['Y']] != EXPECTED_VALUE): print(f'{bcolors.FAIL}FAILED{bcolors.ENDC}', end='\n') if cpu.registers != EXPECTED_REGISTERS: print(f'\t{bcolors.FAIL}REGISTERS DO NOT MATCH{bcolors.ENDC}', end='\n') if cpu.flags != EXPECTED_FLAGS: print(f'\t{bcolors.FAIL}FLAGS DO NOT MATCH{bcolors.ENDC}', end='\n') if cpu.cycles - 1 != EXPECTED_CYCLES: print(f'\t{bcolors.FAIL}CYCLE COUNT DOES NOT MATCH{bcolors.ENDC}', end='\n') # Memory tests # Test that memory was unchanged # if EXPECTED_VALUE is not None and label in ['ZP', 'ZP_X', 'ZP_Y', 'ABS', 'ABS_X', 'ABS_Y', 'IND_X', 'IND_Y'] and cpu.memory != EXPECTED_MEMORY: # print(f'\t{bcolors.FAIL}MEMORY CONTENTS DO NOT MATCH{bcolors.ENDC}', end='\n') # Test that value was written to correct memory location if (EXPECTED_VALUE is not None and label in ['ZP', 'ZP_X', 'ZP_Y'] and cpu.memory[ZP_ADDRESS] != EXPECTED_VALUE) \ or (EXPECTED_VALUE is not None and label in ['ABS', 'ABS_X', 'ABS_Y', 'IND_X'] and cpu.memory[FULL_ADDRESS] != EXPECTED_VALUE) \ or (EXPECTED_VALUE is not None and label in ['IND_Y'] and cpu.memory[FULL_ADDRESS + INITIAL_REGISTERS['Y']] != EXPECTED_VALUE): print(f'\t{bcolors.FAIL}MEMORY CONTENTS DO NOT MATCH{bcolors.ENDC}', end='\n') cpu.print_log() cpu.memory_dump(startingAddress=0xFF00, endingAddress=(0xFF00 + len(program))) cpu.memory_dump(startingAddress=ZP_ADDRESS, endingAddress=ZP_ADDRESS + 1) cpu.memory_dump(startingAddress=IND_ZP_ADDRESS, endingAddress=IND_ZP_ADDRESS + 1) cpu.memory_dump(startingAddress=FULL_ADDRESS, endingAddress=FULL_ADDRESS + 1) print(f'Program: ' + ', '.join('0x{0:0{1}X}'.format(x, 2) for x in program[0])) print(f'Cycles: {cpu.cycles-1} Expected Cycles: {EXPECTED_CYCLES}') print(f'Expected Registers: {EXPECTED_REGISTERS}') print(f'Expected Flags: {EXPECTED_FLAGS}') errors = True else: print(f'{bcolors.OKGREEN}PASSED{bcolors.ENDC}', end='\n') if errors: return False return True
def TEST_0xEA_LSR_ACC_MODE_TESTS(): TEST_NAME = f'TEST_0xEA_LSR_ACC_MODE_TESTS' INSTRUCTION = 'LSR' VALUE_IN_MEMORY = 0x02 # Set this for loading an initial value into memory IMMEDIATE_VALUE = None # Set this for loading an initial value into memory ZP_ADDRESS = 0x62 # Set this for loading an initial value into memory IND_ZP_ADDRESS = 0x72 # Set this for loading an initial value into memory FULL_ADDRESS = 0xABDC # Set this for loading an initial value into memory EXPECTED_VALUE = 0x01 # Set this when a value should be written to memory CYCLE_COUNTS = {'ACC': 2} INITIAL_REGISTERS = {'A': 0x02, 'X': 0x01, 'Y': 0x05} EXPECTED_REGISTERS = {'A': EXPECTED_VALUE, 'X': 0x01, 'Y': 0x05} INITIAL_FLAGS = {'C': 0, 'Z': 0, 'I': 0, 'D': 0, 'B': 0, 'V': 0, 'N': 0} EXPECTED_FLAGS = {'C': 0, 'Z': 0, 'I': 0, 'D': 0, 'B': 0, 'V': 0, 'N': 0} programs = generateProgram(instruction=INSTRUCTION, registers=INITIAL_REGISTERS, immediate_value=IMMEDIATE_VALUE, zp_address=ZP_ADDRESS, ind_zp_address=IND_ZP_ADDRESS, sixteen_bit_address=FULL_ADDRESS, CYCLE_COUNTS=CYCLE_COUNTS) print(f'{bcolors.UNDERLINE}Running {TEST_NAME}{bcolors.ENDC}') errors = False for label, program in programs.items(): print(f'\tTesting {label}... ', end='') PROGRAM = program[0] EXPECTED_CYCLES = program[1] cpu = CPU6502(cycle_limit=100) cpu.reset(program_counter=0xFF00) cpu.load_program(instructions=PROGRAM, memoryAddress=0xFF00) cpu.registers = INITIAL_REGISTERS.copy() cpu.flags = INITIAL_FLAGS.copy() if ZP_ADDRESS is not None and VALUE_IN_MEMORY is not None: cpu.memory[ ZP_ADDRESS] = VALUE_IN_MEMORY # ZP, ZP_X, and ZP_Y Location if IND_ZP_ADDRESS is not None and VALUE_IN_MEMORY is not None: cpu.memory[IND_ZP_ADDRESS] = FULL_ADDRESS & 0b0000000011111111 cpu.memory[IND_ZP_ADDRESS + 1] = (FULL_ADDRESS & 0b1111111100000000) >> 8 if FULL_ADDRESS is not None and VALUE_IN_MEMORY is not None: cpu.memory[ FULL_ADDRESS] = VALUE_IN_MEMORY # ABS, ABS_X, ABS_Y, and IND_X Location cpu.memory[ FULL_ADDRESS + INITIAL_REGISTERS['Y']] = VALUE_IN_MEMORY # IND_Y Location INITIAL_MEMORY = None # cpu.memory.copy() # Change to None if testing a memory write cpu.execute() if (cpu.registers != EXPECTED_REGISTERS) \ or (cpu.flags != EXPECTED_FLAGS) \ or (cpu.cycles - 1 != EXPECTED_CYCLES) \ or (INITIAL_MEMORY is not None and INITIAL_MEMORY != cpu.memory) \ or (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['ZP', 'ZP_X', 'ZP_Y'] and cpu.memory[ZP_ADDRESS] != EXPECTED_VALUE) \ or (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['ABS', 'ABS_X', 'ABS_Y', 'IND_X'] and cpu.memory[FULL_ADDRESS] != EXPECTED_VALUE) \ or (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['IND_Y'] and cpu.memory[FULL_ADDRESS + INITIAL_REGISTERS['Y']] != EXPECTED_VALUE): print(f'{bcolors.FAIL}FAILED{bcolors.ENDC}', end='\n') if cpu.registers != EXPECTED_REGISTERS: print(f'\t{bcolors.FAIL}REGISTERS DO NOT MATCH{bcolors.ENDC}', end='\n') if cpu.flags != EXPECTED_FLAGS: print(f'\t{bcolors.FAIL}FLAGS DO NOT MATCH{bcolors.ENDC}', end='\n') if cpu.cycles - 1 != EXPECTED_CYCLES: print( f'\t{bcolors.FAIL}CYCLE COUNT DOES NOT MATCH{bcolors.ENDC}', end='\n') # Memory tests # Test that value was written to correct memory location if (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['ZP', 'ZP_X', 'ZP_Y'] and cpu.memory[ZP_ADDRESS] != EXPECTED_VALUE) \ or (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['ABS', 'ABS_X', 'ABS_Y', 'IND_X'] and cpu.memory[FULL_ADDRESS] != EXPECTED_VALUE) \ or (INITIAL_MEMORY is None and EXPECTED_VALUE is not None and label in ['IND_Y'] and cpu.memory[FULL_ADDRESS + INITIAL_REGISTERS['Y']] != EXPECTED_VALUE) \ or (INITIAL_MEMORY is not None and INITIAL_MEMORY != cpu.memory): print( f'\t{bcolors.FAIL}MEMORY CONTENTS DO NOT MATCH{bcolors.ENDC}', end='\n') cpu.print_log() cpu.memory_dump(startingAddress=0xFF00, endingAddress=(0xFF00 + len(program))) cpu.memory_dump(startingAddress=ZP_ADDRESS, endingAddress=ZP_ADDRESS + 1) cpu.memory_dump(startingAddress=IND_ZP_ADDRESS, endingAddress=IND_ZP_ADDRESS + 1) cpu.memory_dump(startingAddress=FULL_ADDRESS, endingAddress=FULL_ADDRESS + 1) print(f'Program: ' + ', '.join('0x{0:0{1}X}'.format(x, 2) for x in program[0])) print(f'Cycles: {cpu.cycles-1} Expected Cycles: {EXPECTED_CYCLES}') print(f'Expected Registers: {EXPECTED_REGISTERS}') print(f'Expected Flags: {EXPECTED_FLAGS}') errors = True else: print(f'{bcolors.OKGREEN}PASSED{bcolors.ENDC}', end='\n') if errors: return False return True