diff --git a/docs/index.html b/docs/index.html index 175e11905..30dc01166 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1041,7 +1041,8 @@

Kwargs

A `target_speed` of `0` means unlimited. I.e. fastest possible execution. - Some window types do not implement a frame-limiter, and will always run at full speed. + Due to backwards compatibility, the null window starts at unlimited speed (i.e. `target_speed=0`), while + others start at realtime (i.e. `target_speed=1`). Example: ```python @@ -1055,11 +1056,6 @@

Kwargs

Args: target_speed (int): Target emulation speed as multiplier of real-time. """ - if self.initialized and self._plugin_manager.window_null_enabled: - logger.warning( - 'This window type does not support frame-limiting. `pyboy.set_emulation_speed(...)` will have no effect, as it\'s always running at full speed.' - ) - if target_speed > 5: logger.warning("The emulation speed might not be accurate when speed-target is higher than 5") self.target_emulationspeed = target_speed @@ -2343,7 +2339,8 @@

Returns

target_speed.

The speed is defined as a multiple of real-time. I.e target_speed=2 is double speed.

A target_speed of 0 means unlimited. I.e. fastest possible execution.

-

Some window types do not implement a frame-limiter, and will always run at full speed.

+

Due to backwards compatibility, the null window starts at unlimited speed (i.e. target_speed=0), while +others start at realtime (i.e. target_speed=1).

Example:

>>> pyboy.tick() # Delays 16.67ms
 True
@@ -2369,7 +2366,8 @@ 

Args

A `target_speed` of `0` means unlimited. I.e. fastest possible execution. - Some window types do not implement a frame-limiter, and will always run at full speed. + Due to backwards compatibility, the null window starts at unlimited speed (i.e. `target_speed=0`), while + others start at realtime (i.e. `target_speed=1`). Example: ```python @@ -2383,11 +2381,6 @@

Args

Args: target_speed (int): Target emulation speed as multiplier of real-time. """ - if self.initialized and self._plugin_manager.window_null_enabled: - logger.warning( - 'This window type does not support frame-limiting. `pyboy.set_emulation_speed(...)` will have no effect, as it\'s always running at full speed.' - ) - if target_speed > 5: logger.warning("The emulation speed might not be accurate when speed-target is higher than 5") self.target_emulationspeed = target_speed
diff --git a/docs/plugins/base_plugin.html b/docs/plugins/base_plugin.html index f10207b0c..26e59efb6 100644 --- a/docs/plugins/base_plugin.html +++ b/docs/plugins/base_plugin.html @@ -40,6 +40,7 @@

Module pyboy.plugins.base_plugin

import io import random +import time from array import array import numpy as np @@ -92,6 +93,8 @@

Module pyboy.plugins.base_plugin

def __init__(self, pyboy, mb, pyboy_argv, *args, **kwargs): super().__init__(pyboy, mb, pyboy_argv, *args, **kwargs) + self._ftime = time.perf_counter_ns() + if not self.enabled(): return @@ -110,7 +113,14 @@

Module pyboy.plugins.base_plugin

self.renderer = self.mb.lcd.renderer def frame_limiter(self, speed): - return False + self._ftime += int((1.0 / (60.0*speed)) * 1_000_000_000) + now = time.perf_counter_ns() + if (self._ftime > now): + delay = (self._ftime - now) // 1_000_000 + time.sleep(delay / 1000) + else: + self._ftime = now + return True def set_title(self, title): pass diff --git a/pyboy/plugins/base_plugin.pxd b/pyboy/plugins/base_plugin.pxd index 6f555480c..cc65f0ca3 100644 --- a/pyboy/plugins/base_plugin.pxd +++ b/pyboy/plugins/base_plugin.pxd @@ -6,7 +6,7 @@ cimport cython cimport numpy as cnp from cpython.array cimport array -from libc.stdint cimport uint8_t, uint16_t, uint32_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, int64_t from pyboy.core.lcd cimport Renderer from pyboy.core.mb cimport Motherboard @@ -38,6 +38,7 @@ cdef class PyBoyWindowPlugin(PyBoyPlugin): cdef bint enable_title cdef Renderer renderer + cdef int64_t _ftime cdef bint frame_limiter(self, int) noexcept cdef void set_title(self, str) noexcept diff --git a/pyboy/plugins/base_plugin.py b/pyboy/plugins/base_plugin.py index 71d737bf1..295285266 100644 --- a/pyboy/plugins/base_plugin.py +++ b/pyboy/plugins/base_plugin.py @@ -13,6 +13,7 @@ import io import random +import time from array import array import numpy as np @@ -65,6 +66,8 @@ class PyBoyWindowPlugin(PyBoyPlugin): def __init__(self, pyboy, mb, pyboy_argv, *args, **kwargs): super().__init__(pyboy, mb, pyboy_argv, *args, **kwargs) + self._ftime = time.perf_counter_ns() + if not self.enabled(): return @@ -83,7 +86,14 @@ def __cinit__(self, *args, **kwargs): self.renderer = self.mb.lcd.renderer def frame_limiter(self, speed): - return False + self._ftime += int((1.0 / (60.0*speed)) * 1_000_000_000) + now = time.perf_counter_ns() + if (self._ftime > now): + delay = (self._ftime - now) // 1_000_000 + time.sleep(delay / 1000) + else: + self._ftime = now + return True def set_title(self, title): pass diff --git a/pyboy/plugins/window_null.py b/pyboy/plugins/window_null.py index 2257db97d..783dd20d8 100644 --- a/pyboy/plugins/window_null.py +++ b/pyboy/plugins/window_null.py @@ -22,6 +22,8 @@ def __init__(self, pyboy, mb, pyboy_argv): 'Deprecated use of "headless" or "dummy" window. Change to "null" window instead. https://github.com/Baekalfen/PyBoy/wiki/Migrating-from-v1.x.x-to-v2.0.0' ) + pyboy.set_emulation_speed(0) + def enabled(self): return self.pyboy_argv.get("window") in ["null", "headless", "dummy"] diff --git a/pyboy/plugins/window_open_gl.pxd b/pyboy/plugins/window_open_gl.pxd index 3d5c9203f..e13dd9101 100644 --- a/pyboy/plugins/window_open_gl.pxd +++ b/pyboy/plugins/window_open_gl.pxd @@ -22,7 +22,6 @@ cdef int ROWS, COLS cdef class WindowOpenGL(PyBoyWindowPlugin): cdef list events - cdef int64_t _ftime cdef void _glkeyboard(self, str, int, int, bint) noexcept cdef void _glkeyboardspecial(self, char, int, int, bint) noexcept diff --git a/pyboy/plugins/window_open_gl.py b/pyboy/plugins/window_open_gl.py index 7374c3b40..fae5c887d 100644 --- a/pyboy/plugins/window_open_gl.py +++ b/pyboy/plugins/window_open_gl.py @@ -50,7 +50,7 @@ def __init__(self, pyboy, mb, pyboy_argv): glPixelZoom(self.scale, self.scale) glutReshapeFunc(self._glreshape) glutDisplayFunc(self._gldraw) - self._ftime = time.perf_counter_ns() + # Cython does not cooperate with lambdas def _key(self, c, x, y): @@ -139,16 +139,6 @@ def _gldraw(self): glDrawPixels(COLS, ROWS, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, buf) glFlush() - def frame_limiter(self, speed): - self._ftime += int((1.0 / (60.0*speed)) * 1_000_000_000) - now = time.perf_counter_ns() - if (self._ftime > now): - delay = (self._ftime - now) // 1_000_000 - time.sleep(delay / 1000) - else: - self._ftime = now - return True - def enabled(self): if self.pyboy_argv.get("window") == "OpenGL": if opengl_enabled: diff --git a/pyboy/plugins/window_sdl2.pxd b/pyboy/plugins/window_sdl2.pxd index 558d54c0d..4d6cb843b 100644 --- a/pyboy/plugins/window_sdl2.pxd +++ b/pyboy/plugins/window_sdl2.pxd @@ -25,7 +25,6 @@ cpdef list sdl2_event_pump(list) noexcept cdef class WindowSDL2(PyBoyWindowPlugin): - cdef int64_t _ftime cdef dict _key_down cdef dict _key_up cdef bint fullscreen diff --git a/pyboy/plugins/window_sdl2.py b/pyboy/plugins/window_sdl2.py index 7919a45af..6ae03add4 100644 --- a/pyboy/plugins/window_sdl2.py +++ b/pyboy/plugins/window_sdl2.py @@ -157,9 +157,7 @@ def __init__(self, pyboy, mb, pyboy_argv): if not self.enabled(): return - sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_GAMECONTROLLER) - self._ftime = time.perf_counter_ns() self._window = sdl2.SDL_CreateWindow( b"PyBoy", sdl2.SDL_WINDOWPOS_CENTERED, sdl2.SDL_WINDOWPOS_CENTERED, self._scaledresolution[0], @@ -205,16 +203,6 @@ def enabled(self): else: return False - def frame_limiter(self, speed): - self._ftime += int((1.0 / (60.0*speed)) * 1_000_000_000) - now = time.perf_counter_ns() - if (self._ftime > now): - delay = (self._ftime - now) // 1_000_000 - sdl2.SDL_Delay(delay) - else: - self._ftime = now - return True - def stop(self): sdl2.SDL_DestroyWindow(self._window) for _ in range(10): # At least 2 to close diff --git a/pyboy/pyboy.py b/pyboy/pyboy.py index f2c969134..cf09628b2 100644 --- a/pyboy/pyboy.py +++ b/pyboy/pyboy.py @@ -970,7 +970,8 @@ def set_emulation_speed(self, target_speed): A `target_speed` of `0` means unlimited. I.e. fastest possible execution. - Some window types do not implement a frame-limiter, and will always run at full speed. + Due to backwards compatibility, the null window starts at unlimited speed (i.e. `target_speed=0`), while + others start at realtime (i.e. `target_speed=1`). Example: ```python @@ -984,11 +985,6 @@ def set_emulation_speed(self, target_speed): Args: target_speed (int): Target emulation speed as multiplier of real-time. """ - if self.initialized and self._plugin_manager.window_null_enabled: - logger.warning( - 'This window type does not support frame-limiting. `pyboy.set_emulation_speed(...)` will have no effect, as it\'s always running at full speed.' - ) - if target_speed > 5: logger.warning("The emulation speed might not be accurate when speed-target is higher than 5") self.target_emulationspeed = target_speed