From 2a0db1a59f6d7c54cad057679afbffd2e3246491 Mon Sep 17 00:00:00 2001 From: Mads Ynddal Date: Sat, 21 Sep 2024 14:16:49 +0200 Subject: [PATCH] Fixup cycles on CPU and introduce LCD._cycles_to_frame --- pyboy/core/cpu.pxd | 2 +- pyboy/core/cpu.py | 4 ++++ pyboy/core/lcd.pxd | 2 +- pyboy/core/lcd.py | 3 +++ pyboy/core/mb.py | 2 +- pyboy/utils.py | 2 +- 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pyboy/core/cpu.pxd b/pyboy/core/cpu.pxd index 831aaba15..f1893ab04 100644 --- a/pyboy/core/cpu.pxd +++ b/pyboy/core/cpu.pxd @@ -30,7 +30,7 @@ cdef class CPU: cdef uint8_t interrupts_flag, interrupts_enabled, interrupts_flag_register, interrupts_enabled_register - cdef int64_t cycles_target, _cycles + cdef int64_t _cycles cdef inline int check_interrupts(self) noexcept nogil cdef void set_interruptflag(self, int) noexcept nogil diff --git a/pyboy/core/cpu.py b/pyboy/core/cpu.py index b71d7fa40..5c7259af5 100644 --- a/pyboy/core/cpu.py +++ b/pyboy/core/cpu.py @@ -54,6 +54,7 @@ def save_state(self, f): f.write(self.interrupts_enabled_register) f.write(self.interrupt_queued) f.write(self.interrupts_flag_register) + f.write_64bit(self._cycles) def load_state(self, f, state_version): self.A, self.F, self.B, self.C, self.D, self.E = [f.read() for _ in range(6)] @@ -70,6 +71,8 @@ def load_state(self, f, state_version): if state_version >= 8: self.interrupt_queued = f.read() self.interrupts_flag_register = f.read() + if state_version >= 12: + self._cycles = f.read_64bit() logger.debug("State loaded: %s", self.dump_state("")) def dump_state(self, sym_label): @@ -132,6 +135,7 @@ def tick(self, cycles_target): self._cycles += self.fetch_and_execute() if self.bail: # Possible cycles-target changes break + return self._cycles - _cycles0 def check_interrupts(self): diff --git a/pyboy/core/lcd.pxd b/pyboy/core/lcd.pxd index be382d8be..e4d32857b 100644 --- a/pyboy/core/lcd.pxd +++ b/pyboy/core/lcd.pxd @@ -48,7 +48,7 @@ cdef class LCD: cdef PaletteRegister OBP1 cdef Renderer renderer cdef uint8_t[144][5] _scanlineparameters - cdef int64_t _cycles_to_interrupt + cdef int64_t _cycles_to_interrupt, _cycles_to_frame @cython.locals(interrupt_flag=uint8_t,bx=int,by=int,wx=int,wy=int) cdef uint8_t tick(self, int) noexcept nogil diff --git a/pyboy/core/lcd.py b/pyboy/core/lcd.py index 9b93f65f1..670d75a4b 100644 --- a/pyboy/core/lcd.py +++ b/pyboy/core/lcd.py @@ -59,6 +59,7 @@ def __init__(self, cgb, cartridge_cgb, color_palette, cgb_color_palette, randomi self.cgb = cgb self._scanlineparameters = [[0, 0, 0, 0, 0] for _ in range(ROWS)] self._cycles_to_interrupt = 0 + self._cycles_to_frame = FRAME_CYCLES if self.cgb: # Setting for both modes, even though CGB is ignoring them. BGP[0] used in scanline_blank. @@ -204,6 +205,7 @@ def tick(self, cycles): self.renderer.blank_screen(self) self._cycles_to_interrupt = self.clock_target - self.clock + self._cycles_to_frame = self.clock - FRAME_CYCLES return interrupt_flag def save_state(self, f): @@ -294,6 +296,7 @@ def load_state(self, f, state_version): self.clock = f.read_64bit() self.clock_target = f.read_64bit() + self._cycles_to_frame = self.clock - FRAME_CYCLES self.next_stat_mode = f.read() if self.cgb: diff --git a/pyboy/core/mb.py b/pyboy/core/mb.py index 8d0b42ee4..38ba725ca 100644 --- a/pyboy/core/mb.py +++ b/pyboy/core/mb.py @@ -296,12 +296,12 @@ def tick(self): min( self.timer._cycles_to_interrupt, self.lcd._cycles_to_interrupt, # TODO: Be more agreesive. Only if actual interrupt enabled. + self.lcd._cycles_to_frame, self.sound._cycles_to_interrupt, # TODO: Not implemented # self.serial.cycles_to_interrupt(), mode0_cycles ) ) - # cycles_target = 4 cycles = self.cpu.tick(cycles_target) #TODO: Support General Purpose DMA diff --git a/pyboy/utils.py b/pyboy/utils.py index 8dee8a1bb..168844edc 100644 --- a/pyboy/utils.py +++ b/pyboy/utils.py @@ -5,7 +5,7 @@ __all__ = ["WindowEvent", "dec_to_bcd", "bcd_to_dec"] -STATE_VERSION = 11 +STATE_VERSION = 12 ############################################################## # Buffer classes