Example #1
0
    def _install_mpu_observers(self,getc_addr,putc_addr,fsio_addr):
        def putc(address, value):
            try:
                self.stdout.write(chr(value))
            except UnicodeEncodeError: # Python 3
                self.stdout.write("?")
            self.stdout.flush()

        def getc(address):
            char = console.getch_noblock(self.stdin)
            if char:
                byte = ord(char)
            else:
                byte = 0
            return byte


        m = ObservableMemory(addrWidth=self.addrWidth)
        m.subscribe_to_write([self.putc_addr], putc)
        m.subscribe_to_read([self.getc_addr], getc)

        fs = FileSystem()
        fsio_range = range(fsio_addr, fsio_addr+fs.registers)
        m.subscribe_to_write(fsio_range, fs.write_mem)
        m.subscribe_to_read(fsio_range, fs.read_mem)

        self._mpu.memory = m
Example #2
0
    def __init__(self, filename):
        self.nsf = NSFParser(bytearray(file(filename).read()))

        # Set up Memory with Hooks
        self.mem = ObservableMemory()
        self.mem.write(self.nsf.load_addr, self.nsf.data)
        self.cpu = MPU(self.mem)
        self.deltaCallTime = 0
        self.totalCycles = 0
Example #3
0
 def test_write_directly_writes_values_to_subject(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
 
     def write_subscriber(address, value):
         return 0xFF
     mem.subscribe_to_write([0xC000,0xC001], write_subscriber)
     
     mem.write(0xC000, [0x01, 002])
     self.assertEqual(0x01, subject[0xC000])
     self.assertEqual(0x02, subject[0xC001])
Example #4
0
    def test_write_directly_writes_values_to_subject(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        def write_subscriber(address, value):
            return 0xFF

        mem.subscribe_to_write([0xC000, 0xC001], write_subscriber)

        mem.write(0xC000, [0x01, 002])
        self.assertEqual(0x01, subject[0xC000])
        self.assertEqual(0x02, subject[0xC001])
Example #5
0
class NSFSoftCPU:
	NES_CLK_period = 46 * 12

	def __init__(self, filename):
		self.nsf = NSFParser(bytearray(file(filename).read()))

		# Set up Memory with Hooks
		self.mem = ObservableMemory()
		self.mem.write(self.nsf.load_addr, self.nsf.data)
		self.cpu = MPU(self.mem)
		self.deltaCallTime = 0
		self.totalCycles = 0

	def subscribe_to_write(self, range, callback):
		self.mem.subscribe_to_write(range, callback)

	# Call NSF Init code
	def setup(self, start_song = -1):
		if start_song == -1:
			start_song = self.nsf.start_song - 1

		# Push a special address -1 to the stack to implement function calls
		self.cpu.stPushWord(0x1337 - 1)

		# NSF Style init call
		self.cpu.a = start_song
		self.cpu.x = 0
		self.cpu.pc = self.nsf.init_addr

		while self.cpu.pc != 0x1337:
			self.cpu.step()

	# Execute 1 CPU Step, or wait to until enough cycles have passed
	def play_cycle(self):
		self.deltaCallTime = self.deltaCallTime + self.NES_CLK_period

		self.check_frame()
		if self.cpu.pc != 0x1337:
			self.totalCycles = self.totalCycles + 1
			if self.totalCycles == self.cpu.processorCycles:
				self.cpu.step()


	# Internal: Check if frame is completed and restart it periodically
	def check_frame(self):
		if self.cpu.pc == 0x1337:
			frame_time = self.nsf.ntsc_ticks * 1000
			if self.deltaCallTime >= frame_time:
				self.deltaCallTime = self.deltaCallTime - frame_time
				self.cpu.stPushWord(0x1337 - 1)
				self.cpu.pc = self.nsf.play_addr
				print "Frame Completed"
Example #6
0
 def test__subscribe_to_read_does_not_register_same_listener_twice(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
     
     calls = []
     def read_subscriber(address):
         calls.append('read_subscriber')
     
     mem.subscribe_to_read([0xC000], read_subscriber)
     mem.subscribe_to_read([0xC000], read_subscriber)
 
     value = mem[0xC000]
     self.assertEqual(['read_subscriber'], calls)
Example #7
0
 def test_subscribe_to_read_covers_all_addresses_in_range(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
 
     def read_subscriber(address, value):
         return 0xAB
     
     mem.subscribe_to_read(xrange(0xC000, 0xC001+1), read_subscriber)
 
     mem[0xC000] = 0xAB
     mem[0xC001] = 0xAB
     self.assertEqual(0xAB, subject[0xC001])
     self.assertEqual(0xAB, subject[0xC001])
Example #8
0
    def test_subscribe_to_read_covers_all_addresses_in_range(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        def read_subscriber(address, value):
            return 0xAB

        mem.subscribe_to_read(range(0xC000, 0xC001 + 1), read_subscriber)

        mem[0xC000] = 0xAB
        mem[0xC001] = 0xAB
        self.assertEqual(0xAB, subject[0xC001])
        self.assertEqual(0xAB, subject[0xC001])
Example #9
0
class NSFSoftCPU:
    NES_CLK_period = 46 * 12

    def __init__(self, filename):
        self.nsf = NSFParser(bytearray(file(filename).read()))

        # Set up Memory with Hooks
        self.mem = ObservableMemory()
        self.mem.write(self.nsf.load_addr, self.nsf.data)
        self.cpu = MPU(self.mem)
        self.deltaCallTime = 0
        self.totalCycles = 0

    def subscribe_to_write(self, range, callback):
        self.mem.subscribe_to_write(range, callback)

    # Call NSF Init code
    def setup(self, start_song=-1):
        if start_song == -1:
            start_song = self.nsf.start_song - 1

        # Push a special address -1 to the stack to implement function calls
        self.cpu.stPushWord(0x1337 - 1)

        # NSF Style init call
        self.cpu.a = start_song
        self.cpu.x = 0
        self.cpu.pc = self.nsf.init_addr

        while self.cpu.pc != 0x1337:
            self.cpu.step()

    # Execute 1 CPU Step, or wait to until enough cycles have passed
    def play_cycle(self):
        self.deltaCallTime = self.deltaCallTime + self.NES_CLK_period

        self.check_frame()
        if self.cpu.pc != 0x1337:
            self.totalCycles = self.totalCycles + 1
            if self.totalCycles == self.cpu.processorCycles:
                self.cpu.step()

    # Internal: Check if frame is completed and restart it periodically
    def check_frame(self):
        if self.cpu.pc == 0x1337:
            frame_time = self.nsf.ntsc_ticks * 1000
            if self.deltaCallTime >= frame_time:
                self.deltaCallTime = self.deltaCallTime - frame_time
                self.cpu.stPushWord(0x1337 - 1)
                self.cpu.pc = self.nsf.play_addr
                print "Frame Completed"
Example #10
0
    def test__subscribe_to_read_does_not_register_same_listener_twice(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        calls = []

        def read_subscriber(address):
            calls.append('read_subscriber')

        mem.subscribe_to_read([0xC000], read_subscriber)
        mem.subscribe_to_read([0xC000], read_subscriber)

        value = mem[0xC000]
        self.assertEqual(['read_subscriber'], calls)
Example #11
0
 def test___setitem__uses_result_of_last_subscriber(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
 
     def write_subscriber_1(address, value):
         return 0x01
 
     def write_subscriber_2(address, value):
         return 0x02
     
     mem.subscribe_to_write([0xC000], write_subscriber_1)
     mem.subscribe_to_write([0xC000], write_subscriber_2)
     
     mem[0xC000] = 0xAB
     self.assertEqual(0x02, subject[0xC000])
Example #12
0
 def test___getitem__ignores_read_subscribers_returning_none(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
 
     def read_subscriber_1(address):
         return None
 
     def read_subscriber_2(address):
         return None
     
     mem.subscribe_to_read([0xC000], read_subscriber_1)
     mem.subscribe_to_read([0xC000], read_subscriber_2)
     
     mem[0xC000] = 0xAB
     self.assertEqual(0xAB, subject[0xC000])
Example #13
0
    def test___getitem__ignores_read_subscribers_returning_none(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        def read_subscriber_1(address):
            return None

        def read_subscriber_2(address):
            return None

        mem.subscribe_to_read([0xC000], read_subscriber_1)
        mem.subscribe_to_read([0xC000], read_subscriber_2)

        mem[0xC000] = 0xAB
        self.assertEqual(0xAB, subject[0xC000])
Example #14
0
    def test___setitem__uses_result_of_last_subscriber(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        def write_subscriber_1(address, value):
            return 0x01

        def write_subscriber_2(address, value):
            return 0x02

        mem.subscribe_to_write([0xC000], write_subscriber_1)
        mem.subscribe_to_write([0xC000], write_subscriber_2)

        mem[0xC000] = 0xAB
        self.assertEqual(0x02, subject[0xC000])
Example #15
0
 def __init__(self, console_fo, disk_fo):
     self.mpu = NMOS6502(memory=ObservableMemory())
     self.hw = {}
     self.hw['console'] = Console(self, console_fo)
     self.hw['info'] = Info(self)
     self.hw['pmc'] = Power(self)
     self.hw['disk'] = Disk(self, disk_fo)
     self._status = 'halted'
Example #16
0
    def get_cpu(self, filename):
        start, data = self.get_data(filename)

        self.memory = ObservableMemory()
        self.memory[0xf000:0xffff] = data

        cpu = TestMPU(self.memory, start)
        cpu.reset()
        return cpu
Example #17
0
    def _install_mpu_observers(self):
        def putc(address, value):
            self.stdout.write(chr(value))
            self.stdout.flush()

        def getc(address):
            char = console.getch_noblock(self.stdin)
            if char:
                byte = ord(char)
            else:
                byte = 0
            return byte

        m = ObservableMemory(addrWidth=self.addrWidth)
        m.subscribe_to_write([0xF001], putc)
        m.subscribe_to_read([0xF004], getc)

        self._mpu.memory = m
Example #18
0
	def __init__(self, filename):
		self.nsf = NSFParser(bytearray(file(filename).read()))

		# Set up Memory with Hooks
		self.mem = ObservableMemory()
		self.mem.write(self.nsf.load_addr, self.nsf.data)
		self.cpu = MPU(self.mem)
		self.deltaCallTime = 0
		self.totalCycles = 0
Example #19
0
    def test___getitem__calls_all_read_subscribers_uses_last_result(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)
        
        calls = []
        def read_subscriber_1(address):
            calls.append('read_subscriber_1')
            return 0x01
    
        def read_subscriber_2(address):
            calls.append('read_subscriber_2')
            return 0x02
        
        mem.subscribe_to_read([0xC000], read_subscriber_1)
        mem.subscribe_to_read([0xC000], read_subscriber_2)
    
        subject[0xC000] = 0xAB
        self.assertEqual(0x02, mem[0xC000])

        expected_calls = ['read_subscriber_1', 'read_subscriber_2']
        self.assertEqual(expected_calls, calls)
Example #20
0
    def _install_mpu_observers(self,getc_addr,putc_addr):
        def putc(address, value):
            try:
                self.stdout.write(chr(value))
            except UnicodeEncodeError: # Python 3
                self.stdout.write("?")
            self.stdout.flush()

        def getc(address):
            char = console.getch_noblock(self.stdin)
            if char:
                byte = ord(char)
            else:
                byte = 0
            return byte

        m = ObservableMemory(addrWidth=self.addrWidth)
        m.subscribe_to_write([self.putc_addr], putc)
        m.subscribe_to_read([self.getc_addr], getc)

        self._mpu.memory = m
Example #21
0
    def test___getitem__calls_all_read_subscribers_uses_last_result(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        calls = []

        def read_subscriber_1(address):
            calls.append('read_subscriber_1')
            return 0x01

        def read_subscriber_2(address):
            calls.append('read_subscriber_2')
            return 0x02

        mem.subscribe_to_read([0xC000], read_subscriber_1)
        mem.subscribe_to_read([0xC000], read_subscriber_2)

        subject[0xC000] = 0xAB
        self.assertEqual(0x02, mem[0xC000])

        expected_calls = ['read_subscriber_1', 'read_subscriber_2']
        self.assertEqual(expected_calls, calls)
Example #22
0
    def _install_mpu_observers(self):
        def putc(address, value):
            self.stdout.write(chr(value))
            self.stdout.flush()

        def getc(address):
            char = console.getch_noblock(self.stdin)
            if char:
                byte = ord(char)
            else:
                byte = 0
            return byte

        m = ObservableMemory()
        #m.subscribe_to_write([0xF001], putc)
        #m.subscribe_to_read([0xF004], getc)

        self._mpu.memory = m
Example #23
0
    def _install_mpu_observers(self, getc_addr, putc_addr):
        def putc(address, value):
            try:
                self.stdout.write(chr(value))
            except UnicodeEncodeError: # Python 3
                self.stdout.write("?")
            self.stdout.flush()

        def getc(address):
            char = console.getch_noblock(self.stdin)
            if char:
                byte = ord(char)
            else:
                byte = 0
            return byte

        m = ObservableMemory(subject=self.memory, addrWidth=self.addrWidth)
        m.subscribe_to_write([self.putc_addr], putc)
        m.subscribe_to_read([self.getc_addr], getc)

        self._mpu.memory = m
Example #24
0
        def _install_io(self):

            def getc_from_test(_):
                """Parameter (originally "address") required by py65mon
                but unused here as "_"
                """
                global test_string, test_index
                test_index = test_index + 1

                if test_index < len(test_string):
                    result = ord(test_string[test_index])
                else:
                    result = 0

                return result

            def putc_results(_, value):
                """First parameter (originally "address") required
                by py65mon but unused here as "_"
                """
                global fout

                # Save results to file.
                if value != 0:
                    if not args.suppress_tester or \
                       test_index > end_of_tester:
                        fout.write(chr(value).encode())

                # Print to the screen if we are not muted.
                if not args.mute:
                    if not args.suppress_tester or \
                       test_index > end_of_tester:
                        sys.stdout.write(chr(value))
                        sys.stdout.flush()

            # Install the above handlers for I/O
            mem = ObservableMemory(subject=self.memory)
            mem.subscribe_to_write([0xF001], putc_results)
            mem.subscribe_to_read([0xF004], getc_from_test)
            self._mpu.memory = mem
Example #25
0
 def reset(self):
     self.mpu = NMOS6502(memory=ObservableMemory())
     for name, module in self.hw.items():
         module.reset()
     self.status = 'halted'
Example #26
0
    def test___setitem__with_no_listeners_changes_memory(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        mem[0xC000] = 0xAB
        self.assertEqual(0xAB, subject[0xC000])
Example #27
0
        def _install_io(self):

            def getc_from_test(_):
                """Parameter (originally "address") required by py65mon
                but unused here as "_"
                """
                global test_string, test_index
                test_index = test_index + 1

                if test_index < len(test_string):
                    result = ord(test_string[test_index])
                else:
                    result = 0

                return result

            def putc_results(_, value):
                """First parameter (originally "address") required
                by py65mon but unused here as "_"
                """
                global fout
                # Save results to file.
                if value != 0:
                    fout.write(chr(value).encode())

                # Print to the screen if we are not muted.
                if not args.mute:
                    sys.stdout.write(chr(value))
                    sys.stdout.flush()

            def update_cycle_start(_):
                """Parameter (originally "address") required by py65mon
                but unused here as "_"
                """
                # When this address is read from, note the cycle time.
                self.cycle_start = self._mpu.processorCycles
                return 0

            def update_cycle_end(_):
                """Parameter (originally "address") required by py65mon
                but unused here as "_"
                """
                # When this address is read from, note the cycle time.
                self.cycle_end = self._mpu.processorCycles
#                # Compute the elapsed time (in CPU cycles).
#                # With a 1MHz clock, this will also be in microseconds.
#                fout.write((" CYCLES: "+str(self.cycle_end-self.cycle_start)+" ").encode())
#
#                # Print to the screen if we are not muted.
#                if not args.mute:
#                    sys.stdout.write((" CYCLES: "+str(self.cycle_end-self.cycle_start)+" "))
#                    sys.stdout.flush()

                return 0

            def read_cycle_count(address):
                """Break up the 32-bit result into bytes for Tali to
                read out of virtual memory.  Note that the hex value
                12345678 is stored in memory as bytes 34 12 78 56.
                The value will be read (as a double) starting at
                memory address 0xFF00
                """
                if address == 0xFF00:
                    return ((self.cycle_end-self.cycle_start)&0x00FF0000)>>16
                elif address == 0xFF01:
                    return ((self.cycle_end-self.cycle_start)&0xFF000000)>>24
                elif address == 0xFF02:
                    return ((self.cycle_end-self.cycle_start)&0x000000FF)
                elif address == 0xFF03:
                    return ((self.cycle_end-self.cycle_start)&0x0000FF00)>>8
                else:
                    return 0

            # Install the above handlers for I/O
            mem = ObservableMemory(subject=self.memory)
            mem.subscribe_to_write([0xF001], putc_results)
            mem.subscribe_to_read([0xF004], getc_from_test)

            # Install the handlers for timing cycles.
            mem.subscribe_to_read([0xF002], update_cycle_start)
            mem.subscribe_to_read([0xF003], update_cycle_end)
            mem.subscribe_to_read([0xFF00, 0xFF01, 0xFF02, 0xFF03], read_cycle_count)
            self._mpu.memory = mem
Example #28
0
 def test__getattr__proxies_subject(self):
     subject = self._make_subject()
     mem = ObservableMemory(subject=subject)
     self.assertEqual(subject.count, mem.count)
Example #29
0
    def test___getitem__with_no_write_subscribers_changes_memory(self):
        subject = self._make_subject()
        mem = ObservableMemory(subject=subject)

        subject[0xC000] = 0xAB
        self.assertEqual(0xAB, mem[0xC000])