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])
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, 0o02]) self.assertEqual(0x01, subject[0xC000]) self.assertEqual(0x02, subject[0xC001])
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"
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"