def test_pop_ix_takes_4_m_cycles(self): ram = RAM() ram[0x1000] = 0x55 ram[0x1001] = 0x33 cpu = CPU(ROM(b'\xdd\xe1'), ram) cpu.SP = 0x1000 cpu.readOp() self.assertEqual(4, cpu.m_cycles)
def test_dec_mem_iy_that_does_not_generate_carry_on_12bit_resets_h_flag( self): ram = RAM() ram[0x500] = 0x1 cpu = CPU(ROM(b'\xfd\x35\x00'), ram) cpu.IY = 0x500 cpu.HFlag = True cpu.readOp() self.assertFalse(cpu.HFlag)
def test_dec_mem_iy_that_results_in_value_greater_than_zero_resets_s_flag( self): ram = RAM() ram[0x500] = 0x1 cpu = CPU(ROM(b'\xfd\x35\x00'), ram) cpu.IY = 0x500 cpu.SFLag = True cpu.readOp() self.assertFalse(cpu.SFlag)
def test_dec_mem_iy_that_results_in_borrow_sets_h_flag(self): ram = RAM() ram[0x500] = 0x0 cpu = CPU(ROM(b'\xfd\x35\x00'), ram) cpu.IY = 0x500 cpu.CFlag = True cpu.HFlag = False cpu.readOp() self.assertTrue(cpu.HFlag)
def test_dec_mem_iy_that_results_non_zero_resets_z_flag(self): ram = RAM() ram[0x500] = 0x2 cpu = CPU(ROM(b'\xfd\x35\x00'), ram) cpu.IY = 0x500 cpu.CFlag = True cpu.ZFlag = True cpu.readOp() self.assertFalse(cpu.ZFlag)
def __init__(self): """Construct a new CPU.""" self.reg = [0b0] * 8 self.ram = RAM() self.pc = 0 self.mar = None # holds address currently being read or written self.mdr = None # holds value to write or value just read self.dispatch_table = {} self.setup_instructions()
def test_pop_iy_takes_14_t_states(self): ram = RAM() ram[0x1000] = 0x55 ram[0x1001] = 0x33 cpu = CPU(ROM(b'\xfd\xe1'), ram) cpu.SP = 0x1000 cpu.readOp() self.assertEqual(14, cpu.t_states)
def test_ret_takes_10_t_states(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xc9'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.readOp() self.assertEqual(10, cpu.t_states)
def test_rrd_does_modify_value_correctly(self): ram = RAM() ram[0x5000] = 0b00100000 cpu = CPU(ROM(b'\xed\x67'), ram) cpu.A = 0b10000100 cpu.HL = 0x5000 cpu.readOp() self.assertEqual(0b10000000, cpu.A) self.assertEqual(0b01000010, cpu.ram[cpu.HL])
def test_pop_bc_takes_7_t_states(self): ram = RAM() ram[0x1000] = 0x55 ram[0x1001] = 0x33 cpu = CPU(ROM(b'\xc1'), ram) cpu.SP = 0x1000 cpu.readOp() self.assertEqual(7, cpu.t_states)
def test_pop_bc_takes_3_m_cycles(self): ram = RAM() ram[0x1000] = 0x55 ram[0x1001] = 0x33 cpu = CPU(ROM(b'\xc1'), ram) cpu.SP = 0x1000 cpu.readOp() self.assertEqual(3, cpu.m_cycles)
def test_pop_af_correctly_retreives_value_from_stack(self): ram = RAM() ram[0x1000] = 0x55 ram[0x1001] = 0x33 cpu = CPU(ROM(b'\xf1'), ram) cpu.SP = 0x1000 cpu.readOp() self.assertEqual(0x3355, cpu.AF)
def cpu(): ram = RAM() ppu = PPU() cpu = CPU(ram, ppu) cpu.start_up() cpu.rom = MagicMock() cpu.rom.memory_start_location = 0 cpu.rom.memory_end_location = 0x1FFF return cpu
def test_call_takes_5_m_cycles(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xcd\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.readOp() self.assertEqual(5, cpu.m_cycles)
def test_ret_cc_does_takes_5_t_states_if_cc_is_false(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xf0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.SFlag = Bits.set() cpu.readOp() self.assertEqual(5, cpu.t_states)
def test_ret_cc_does_takes_3_m_cycles_if_cc_is_true(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xf0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.SFlag = Bits.reset() cpu.readOp() self.assertEqual(3, cpu.m_cycles)
def test_call_po_doesnt_jumps_if_PVFlag_is_set(self): ram = RAM() cpu = CPU(ROM(b'\x00' * 0x1A47 + b'\xe4\x35\x21'), ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.PVFlag = True cpu.readOp() self.assertEqual(0x1A4a, cpu.PC) self.assertEqual(0x3002, cpu.SP)
def test_retn_0xed75_does_sets_PC_correctly(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xed\x75'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.readOp() self.assertEqual(0x18B5, cpu.PC) self.assertEqual(0x4002, cpu.SP)
def test_ret_nz_does_sets_PC_correctly_if_Zflag_is_set(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xc0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.ZFlag = Bits.set() cpu.readOp() self.assertEqual(0x3536, cpu.PC) self.assertEqual(0x4000, cpu.SP)
def test_ret_po_does_sets_PC_correctly_if_PVflag_is_reset(self): ram = RAM() ram[0x4000] = 0xB5 ram[0x4001] = 0x18 cpu = CPU(ROM(b'\x00' * 0x3535 + b'\xe0'), ram) cpu.PC = 0x3535 cpu.SP = 0x4000 cpu.PVFlag = Bits.reset() cpu.readOp() self.assertEqual(0x18b5, cpu.PC) self.assertEqual(0x4002, cpu.SP)
def test_call_cc_takes_10_t_cycles_if_condition_is_false(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xDC\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.CFlag = Bits.reset() cpu.readOp() self.assertEqual(10, cpu.t_states)
def test_call_cc_takes_5_m_cycles_if_condition_is_true(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xDC\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.CFlag = Bits.set() cpu.readOp() self.assertEqual(5, cpu.m_cycles)
def __init__(self, config, original_speed, fps, no_ui): self.config = config self.original_speed = original_speed self.fps = fps self.no_ui = no_ui self.ram = RAM() self.keyboard = Keyboard(self.ram) self.z80 = Z80(self.ram) self.cmd = CMD(self.ram) self.entry_addr = self.cmd.load(config["cmd"]) self.ram.backup() self.reset()
def test_call_c_does_not_jumps_if_CFlag_is_set(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xD4\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.CFlag = True cpu.readOp() self.assertEqual(0x1A4a, cpu.PC) self.assertEqual(0x3002, cpu.SP)
def test_call(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xcd\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.readOp() self.assertEqual(0x2135, cpu.PC) self.assertEqual(0x1A, cpu.ram[0x3001]) self.assertEqual(0x4A, cpu.ram[0x3000])
def test_call_z_jumps_if_ZFlag_is_set(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xCC\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.ZFlag = True cpu.readOp() self.assertEqual(0x2135, cpu.PC) self.assertEqual(0x1A, cpu.ram[0x3001]) self.assertEqual(0x4A, cpu.ram[0x3000])
def test_call_c_jumps_if_CFlag_is_not_set(self): ram = RAM() rom = ROM(b'\x00' * 0x1A47 + b'\xD4\x35\x21') cpu = CPU(rom, ram) cpu.PC = 0x1A47 cpu.SP = 0x3002 cpu.CFlag = False cpu.readOp() self.assertEqual(0x2135, cpu.PC) self.assertEqual(0x1A, cpu.ram[0x3001]) self.assertEqual(0x4A, cpu.ram[0x3000])
def __init__(self, run_state=1, run_next_inst=False, mem_size=2**12): super(SPECTRE_VM, self).__init__() # this must be a daemon, so it exits with the main program self.setDaemon(True) # cpu registers # self.mem = RAM(2**11) # 2048 bits | 0.25 kB = 256 bytes self.mem = RAM(mem_size) # 4096 bits | 0.50 kB = 512 bytes print(f'mem size: {self.mem.size_bytes} bytes') # self.mem = RAM(2**13) # 8192 bits | 1.00 kB = 1024 bytes self.memlock = threading.Lock() self.cpu = CPU(self.mem, self.memlock) self.__run_state = run_state return
def main(): # set up command line argument parser parser = argparse.ArgumentParser(description="NES Emulator.") parser.add_argument('rom_path', metavar='R', type=str, help='path to nes rom') parser.add_argument('--test') args = parser.parse_args() # TODO: validate rom path is correct print(args.rom_path) # load rom with open(args.rom_path, 'rb') as file: rom_bytes = file.read() # create ram ram = RAM() # create ppu ppu = PPU() # create apu apu = APU() rom = ROM(rom_bytes) # create cpu cpu: CPU = CPU(ram, ppu, apu) cpu.start_up() cpu.load_rom(rom, args.test) # check if running test rom if args.test: # load in the test log with open('test_log.log', 'r') as nes_test_file: nes_test_log = NesTestLog(nes_test_file.readlines()) while True: cpu.identify() nes_test_log.compare(cpu) cpu.execute() else: while True: cpu.identify() cpu.execute()
def __init__(self, rom_bytes, testing): self.rom = ROM(rom_bytes) # create ram self.ram = RAM() # create ppu and apu self.ppu = PPU() self.apu = APU() # create cpu self.cpu = CPU(self.ram, self.ppu, self.apu) # create ppu window self.window = Window() self.testing = testing self.nes_test_log = None