pyboy 2.5.2__tar.gz → 2.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. {pyboy-2.5.2/pyboy.egg-info → pyboy-2.5.4}/PKG-INFO +1 -1
  2. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/__main__.py +7 -10
  3. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sprite.py +1 -1
  4. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/conftest.py +15 -1
  5. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cpu.py +1 -1
  6. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/interaction.py +3 -3
  7. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/lcd.pxd +2 -4
  8. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/lcd.py +3 -10
  9. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/mb.pxd +2 -2
  10. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/mb.py +8 -6
  11. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/sound.pxd +2 -1
  12. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/sound.py +1 -2
  13. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/base_plugin.pxd +5 -2
  14. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/base_plugin.py +5 -10
  15. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug.pxd +23 -6
  16. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug.py +29 -33
  17. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_pinball.py +60 -16
  18. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_super_mario_land.pxd +1 -1
  19. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_super_mario_land.py +1 -1
  20. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_tetris.pxd +1 -1
  21. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_tetris.py +1 -2
  22. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/rewind.pxd +2 -2
  23. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/rewind.py +14 -6
  24. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_sdl2.py +3 -3
  25. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/pyboy.pxd +2 -0
  26. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/pyboy.py +17 -8
  27. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/utils.pxd +7 -0
  28. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/utils.py +19 -0
  29. {pyboy-2.5.2 → pyboy-2.5.4/pyboy.egg-info}/PKG-INFO +1 -1
  30. {pyboy-2.5.2 → pyboy-2.5.4}/pyproject.toml +1 -1
  31. {pyboy-2.5.2 → pyboy-2.5.4}/LICENSE.md +0 -0
  32. {pyboy-2.5.2 → pyboy-2.5.4}/MANIFEST.in +0 -0
  33. {pyboy-2.5.2 → pyboy-2.5.4}/README.md +0 -0
  34. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/__init__.py +0 -0
  35. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/__init__.py +0 -0
  36. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/constants.py +0 -0
  37. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/gameshark.pxd +0 -0
  38. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/gameshark.py +0 -0
  39. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/memory_scanner.pxd +0 -0
  40. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/memory_scanner.py +0 -0
  41. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/screen.pxd +0 -0
  42. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/screen.py +0 -0
  43. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sound.pxd +0 -0
  44. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sound.py +0 -0
  45. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sprite.pxd +0 -0
  46. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tile.pxd +0 -0
  47. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tile.py +0 -0
  48. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tilemap.pxd +0 -0
  49. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tilemap.py +0 -0
  50. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/__init__.py +0 -0
  51. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom.pxd +0 -0
  52. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom.py +0 -0
  53. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom_cgb.bin +0 -0
  54. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom_dmg.bin +0 -0
  55. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/__init__.py +0 -0
  56. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/base_mbc.pxd +0 -0
  57. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/base_mbc.py +0 -0
  58. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/cartridge.pxd +0 -0
  59. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/cartridge.py +0 -0
  60. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc1.pxd +0 -0
  61. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc1.py +0 -0
  62. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc2.pxd +0 -0
  63. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc2.py +0 -0
  64. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc3.pxd +0 -0
  65. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc3.py +0 -0
  66. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc5.pxd +0 -0
  67. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc5.py +0 -0
  68. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/rtc.pxd +0 -0
  69. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/rtc.py +0 -0
  70. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cpu.pxd +0 -0
  71. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/interaction.pxd +0 -0
  72. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes.pxd +0 -0
  73. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes.py +0 -0
  74. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes_gen.py +0 -0
  75. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/ram.pxd +0 -0
  76. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/ram.py +0 -0
  77. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/timer.pxd +0 -0
  78. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/timer.py +0 -0
  79. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/default_rom.gb +0 -0
  80. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/__init__.py +0 -0
  81. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/_logging.py +0 -0
  82. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/logging.pxd +0 -0
  83. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/logging.pyx +0 -0
  84. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/__init__.py +0 -0
  85. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/auto_pause.pxd +0 -0
  86. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/auto_pause.py +0 -0
  87. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug_prompt.pxd +0 -0
  88. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug_prompt.py +0 -0
  89. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/font.txt +0 -0
  90. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_kirby_dream_land.pxd +0 -0
  91. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_kirby_dream_land.py +0 -0
  92. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_gen1.pxd +0 -0
  93. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_gen1.py +0 -0
  94. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_pinball.pxd +0 -0
  95. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager.pxd +0 -0
  96. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager.py +0 -0
  97. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager_gen.py +0 -0
  98. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/record_replay.pxd +0 -0
  99. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/record_replay.py +0 -0
  100. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screen_recorder.pxd +0 -0
  101. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screen_recorder.py +0 -0
  102. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screenshot_recorder.pxd +0 -0
  103. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screenshot_recorder.py +0 -0
  104. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_null.pxd +0 -0
  105. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_null.py +0 -0
  106. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_open_gl.pxd +0 -0
  107. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_open_gl.py +0 -0
  108. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_sdl2.pxd +0 -0
  109. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/SOURCES.txt +0 -0
  110. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/dependency_links.txt +0 -0
  111. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/entry_points.txt +0 -0
  112. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/not-zip-safe +0 -0
  113. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/requires.txt +0 -0
  114. {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/top_level.txt +0 -0
  115. {pyboy-2.5.2 → pyboy-2.5.4}/setup.cfg +0 -0
  116. {pyboy-2.5.2 → pyboy-2.5.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyboy
3
- Version: 2.5.2
3
+ Version: 2.5.4
4
4
  Summary: Game Boy emulator written in Python
5
5
  Author-email: Mads Ynddal <mads@ynddal.dk>
6
6
  License: GNU Lesser General Public License
@@ -8,13 +8,9 @@ import argparse
8
8
  import copy
9
9
  import os
10
10
 
11
- import pyboy
12
11
  from pyboy import PyBoy
13
12
  from pyboy.plugins.manager import parser_arguments
14
13
  from pyboy.pyboy import defaults
15
- from pyboy.utils import PyBoyInvalidInputException
16
-
17
- logger = pyboy.logging.get_logger(__name__)
18
14
 
19
15
  INTERNAL_LOADSTATE = "INTERNAL_LOADSTATE_TOKEN"
20
16
 
@@ -22,21 +18,20 @@ INTERNAL_LOADSTATE = "INTERNAL_LOADSTATE_TOKEN"
22
18
  def color_tuple(string):
23
19
  color_palette = [int(c.strip(), 16) for c in string.split(",")]
24
20
  if not (len(color_palette) == 4):
25
- raise PyBoyInvalidInputException(f"Not the correct amount of colors! Expected four, got {len(color_palette)}")
21
+ parser.error(f"Not the correct amount of colors! Expected four, got {len(color_palette)}")
26
22
  return color_palette
27
23
 
28
24
 
29
25
  def cgb_color_tuple(string):
30
26
  color_palette = [int(c.strip(), 16) for c in string.split(",")]
31
27
  if not (len(color_palette) == 12):
32
- raise PyBoyInvalidInputException(f"Not the correct amount of colors! Expected twelve, got {len(color_palette)}")
28
+ parser.error(f"Not the correct amount of colors! Expected twelve, got {len(color_palette)}")
33
29
  return [color_palette[0:4], color_palette[4:8], color_palette[8:12]]
34
30
 
35
31
 
36
32
  def valid_file_path(path):
37
33
  if not path == INTERNAL_LOADSTATE and not os.path.isfile(path):
38
- logger.error("Filepath '%s' couldn't be found, or isn't a file!", path)
39
- exit(1)
34
+ parser.error(f"Filepath '{path}' couldn't be found, or isn't a file!")
40
35
  return path
41
36
 
42
37
 
@@ -46,14 +41,14 @@ def valid_volume(vol):
46
41
  elif vol.isnumeric() and (0 <= int(vol) <= 100):
47
42
  return int(vol)
48
43
  else:
49
- raise ValueError("Invalid volume")
44
+ parser.error("Invalid volume")
50
45
 
51
46
 
52
47
  def valid_sample_rate(freq):
53
48
  if freq.isnumeric() and int(freq) % 60 == 0:
54
49
  return int(freq)
55
50
  else:
56
- raise ValueError("Invalid sample rate")
51
+ parser.error("Invalid sample rate")
57
52
 
58
53
 
59
54
  parser = argparse.ArgumentParser(
@@ -153,6 +148,8 @@ parser.add_argument(
153
148
  help="Set sound sample rate. Has to be divisible in 60.",
154
149
  )
155
150
 
151
+ parser.add_argument("--title-status", action="store_true", help="Enable performance status in window title")
152
+
156
153
  for arguments in parser_arguments():
157
154
  for a in arguments:
158
155
  *args, kwargs = a
@@ -147,7 +147,7 @@ class Sprite:
147
147
  self.attr_palette_number = _bit(attr, 4)
148
148
 
149
149
  LCDC = LCDCRegister(self.mb.getitem(LCDC_OFFSET))
150
- sprite_height = 16 if LCDC._get_sprite_height() else 8
150
+ sprite_height = 16 if LCDC.sprite_height else 8
151
151
  self.shape = (8, sprite_height)
152
152
  """
153
153
  Sprites can be set to be 8x8 or 8x16 pixels (16 pixels tall). This is defined globally for the rendering
@@ -15,7 +15,6 @@ from zipfile import ZipFile
15
15
 
16
16
  import numpy as np
17
17
  import pytest
18
- from cryptography.fernet import Fernet
19
18
  from filelock import FileLock
20
19
 
21
20
  from pyboy.utils import cython_compiled
@@ -83,6 +82,8 @@ def secrets():
83
82
  if not os.path.isdir(path):
84
83
  if not os.environ.get("PYTEST_SECRETS_KEY"):
85
84
  pytest.skip("Cannot access secrets")
85
+ from cryptography.fernet import Fernet
86
+
86
87
  fernet = Fernet(os.environ["PYTEST_SECRETS_KEY"].encode())
87
88
 
88
89
  test_data = url_open("https://pyboy.dk/mirror/test_data.encrypted")
@@ -176,6 +177,19 @@ def doctest_fixtures(doctest_namespace, default_rom, default_rom_cgb, supermario
176
177
  yield None
177
178
 
178
179
 
180
+ @pytest.fixture(autouse=True, scope="function")
181
+ def check_stderr_empty(request):
182
+ capsys = request.getfixturevalue("capsys")
183
+ yield
184
+ # If tests want to ignore errors on stderr, they should issue capsys.readouterr() after known errors
185
+ captured = capsys.readouterr()
186
+ try:
187
+ assert captured.err == "", "stderr is not empty"
188
+ # assert captured.out == "", "stdout is not empty"
189
+ except AssertionError as e:
190
+ raise e
191
+
192
+
179
193
  # Code taken from PyTest is licensed with the following:
180
194
  # The MIT License (MIT)
181
195
 
@@ -5,9 +5,9 @@
5
5
  import pyboy
6
6
 
7
7
  from . import opcodes
8
+ from pyboy.utils import INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW
8
9
 
9
10
  FLAGC, FLAGH, FLAGN, FLAGZ = range(4, 8)
10
- INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW = [1 << x for x in range(5)]
11
11
 
12
12
 
13
13
  logger = pyboy.logging.get_logger(__name__)
@@ -79,15 +79,15 @@ class Interaction:
79
79
  # Guess to make first 4 and last 2 bits true, while keeping selected bits
80
80
  joystickByte = 0xFF & (joystickbyte | 0b11001111)
81
81
  if P14 and P15:
82
- pass
82
+ joystickByte = 0xF
83
83
  elif not P14 and not P15:
84
- pass
84
+ pass # FIXME: What happens when both are requested?
85
85
  elif not P14:
86
86
  joystickByte &= self.directional
87
87
  elif not P15:
88
88
  joystickByte &= self.standard
89
89
 
90
- return joystickByte
90
+ return joystickByte | 0b11000000
91
91
 
92
92
  def save_state(self, f):
93
93
  f.write(self.directional)
@@ -14,7 +14,7 @@ from pyboy.logging.logging cimport Logger
14
14
  from pyboy.utils cimport IntIOInterface
15
15
 
16
16
 
17
- cdef uint8_t INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW
17
+ cdef uint8_t INTR_VBLANK, INTR_LCDC
18
18
  cdef uint16_t LCDC, STAT, SCY, SCX, LY, LYC, DMA, BGP, OBP0, OBP1, WY, WX
19
19
  cdef int ROWS, COLS, TILES, FRAME_CYCLES, VIDEO_RAM, OBJECT_ATTRIBUTE_MEMORY
20
20
  cdef uint32_t COL0_FLAG, BG_PRIORITY_FLAG
@@ -105,7 +105,7 @@ cdef class LCDCRegister:
105
105
  cdef bint window_enable
106
106
  cdef bint tiledata_select
107
107
  cdef bint backgroundmap_select
108
- cdef bint sprite_height
108
+ cdef readonly bint sprite_height
109
109
  cdef bint sprite_enable
110
110
  cdef bint background_enable
111
111
  cdef bint cgb_master_priority
@@ -113,8 +113,6 @@ cdef class LCDCRegister:
113
113
  cdef uint16_t backgroundmap_offset
114
114
  cdef uint16_t windowmap_offset
115
115
 
116
- cpdef int _get_sprite_height(self) noexcept
117
-
118
116
  cdef class Renderer:
119
117
  cdef uint8_t[:] _tilecache0_state, _tilecache1_state, _spritecache0_state, _spritecache1_state
120
118
  cdef str color_format
@@ -8,17 +8,13 @@ from ctypes import c_void_p
8
8
  from random import getrandbits
9
9
 
10
10
  import pyboy
11
- from pyboy.utils import PyBoyException
11
+ from pyboy.utils import PyBoyException, INTR_VBLANK, INTR_LCDC, FRAME_CYCLES
12
+ from pyboy.api.constants import ROWS, COLS, TILES
12
13
 
13
14
  logger = pyboy.logging.get_logger(__name__)
14
15
 
15
16
  VIDEO_RAM = 8 * 1024 # 8KB
16
17
  OBJECT_ATTRIBUTE_MEMORY = 0xA0
17
- INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW = [1 << x for x in range(5)]
18
- ROWS, COLS = 144, 160
19
- TILES = 384
20
-
21
- FRAME_CYCLES = 70224
22
18
 
23
19
 
24
20
  def rgb_to_bgr(color):
@@ -454,9 +450,6 @@ class LCDCRegister:
454
450
  self.backgroundmap_offset = 0x1800 if self.backgroundmap_select == 0 else 0x1C00
455
451
  self.windowmap_offset = 0x1800 if self.windowmap_select == 0 else 0x1C00
456
452
 
457
- def _get_sprite_height(self):
458
- return self.sprite_height
459
-
460
453
 
461
454
  COL0_FLAG = 0b01
462
455
  BG_PRIORITY_FLAG = 0b10
@@ -625,7 +618,7 @@ class Renderer:
625
618
  # The lowest X-coordinate has priority, when overlapping
626
619
  spriteheight = 16 if lcd._LCDC.sprite_height else 8
627
620
  sprite_count = 0
628
- for n in range(0x00, 0xA0, 4):
621
+ for n in range(0x00, OBJECT_ATTRIBUTE_MEMORY, 4):
629
622
  y = lcd.OAM[n] - 16 # Documentation states the y coordinate needs to be subtracted by 16
630
623
  x = lcd.OAM[n + 1] - 8 # Documentation states the x coordinate needs to be subtracted by 8
631
624
 
@@ -23,8 +23,8 @@ cdef Logger logger
23
23
 
24
24
  cdef int64_t MAX_CYCLES
25
25
  cdef uint16_t STAT, LY, LYC
26
- cdef short VBLANK, LCDC, TIMER, SERIAL, HIGHTOLOW
27
- cdef int INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW
26
+ cdef int INTR_TIMER, INTR_HIGHTOLOW
27
+ cdef uint16_t OPCODE_BRK
28
28
  cdef int STATE_VERSION
29
29
 
30
30
 
@@ -4,16 +4,18 @@
4
4
  #
5
5
 
6
6
  import pyboy
7
- from pyboy.utils import STATE_VERSION, PyBoyException, PyBoyOutOfBoundsException
7
+ from pyboy.utils import (
8
+ STATE_VERSION,
9
+ PyBoyException,
10
+ PyBoyOutOfBoundsException,
11
+ INTR_TIMER,
12
+ INTR_HIGHTOLOW,
13
+ OPCODE_BRK,
14
+ )
8
15
 
9
16
  from . import bootrom, cartridge, cpu, interaction, lcd, ram, sound, timer
10
17
 
11
- INTR_VBLANK, INTR_LCDC, INTR_TIMER, INTR_SERIAL, INTR_HIGHTOLOW = [1 << x for x in range(5)]
12
- OPCODE_BRK = 0xDB
13
-
14
-
15
18
  logger = pyboy.logging.get_logger(__name__)
16
-
17
19
  MAX_CYCLES = 1 << 31
18
20
 
19
21
 
@@ -8,7 +8,8 @@ from libc.stdint cimport int8_t, int64_t, uint8_t, uint16_t, uint64_t
8
8
 
9
9
  from pyboy.logging.logging cimport Logger
10
10
  from pyboy.utils cimport IntIOInterface, double_to_uint64_ceil
11
- from pyboy.core.lcd cimport FRAME_CYCLES
11
+
12
+ cdef int FRAME_CYCLES
12
13
 
13
14
 
14
15
  cdef Logger logger
@@ -12,10 +12,9 @@ from array import array
12
12
 
13
13
  import pyboy
14
14
  from pyboy.utils import PyBoyAssertException, cython_compiled
15
+ from pyboy.utils import FRAME_CYCLES
15
16
 
16
17
  if not cython_compiled:
17
- from pyboy.core.lcd import FRAME_CYCLES
18
-
19
18
  # Hide it from Cython in 'exec' statement
20
19
  exec("from pyboy.utils import double_to_uint64_ceil")
21
20
 
@@ -8,7 +8,7 @@ cimport numpy as cnp
8
8
  from cpython.array cimport array
9
9
  from libc.stdint cimport int64_t, uint8_t, uint16_t, uint32_t
10
10
 
11
- from pyboy.core.lcd cimport Renderer
11
+ from pyboy.core.lcd cimport LCD, Renderer, CGBRenderer
12
12
  from pyboy.core.sound cimport Sound
13
13
  from pyboy.core.mb cimport Motherboard
14
14
  from pyboy.logging.logging cimport Logger
@@ -22,6 +22,10 @@ cdef int ROWS, COLS
22
22
  cdef class PyBoyPlugin:
23
23
  cdef object pyboy
24
24
  cdef Motherboard mb
25
+ cdef Renderer renderer
26
+ cdef bint is_cgb_renderer
27
+ cdef CGBRenderer cgb_renderer
28
+ cdef LCD lcd
25
29
  cdef bint cgb
26
30
  cdef dict pyboy_argv
27
31
  @cython.locals(event=WindowEvent)
@@ -37,7 +41,6 @@ cdef class PyBoyWindowPlugin(PyBoyPlugin):
37
41
  cdef int scale
38
42
  cdef int[2] _scaledresolution
39
43
  cdef bint enable_title
40
- cdef Renderer renderer
41
44
  cdef Sound sound
42
45
 
43
46
  cdef int64_t _ftime
@@ -20,6 +20,7 @@ import numpy as np
20
20
 
21
21
  import pyboy
22
22
  from pyboy.api.constants import SPRITES, TILES_CGB
23
+ from pyboy.core.lcd import CGBRenderer
23
24
  from pyboy import utils
24
25
 
25
26
  logger = pyboy.logging.get_logger(__name__)
@@ -31,16 +32,14 @@ class PyBoyPlugin:
31
32
  argv = []
32
33
 
33
34
  def __init__(self, pyboy, mb, pyboy_argv):
34
- if not utils.cython_compiled:
35
- self.pyboy = pyboy
36
- self.mb = mb
37
- self.pyboy_argv = pyboy_argv
38
35
  self.cgb = mb.cgb
39
-
40
- def __cinit__(self, pyboy, mb, pyboy_argv, *args, **kwargs):
41
36
  self.pyboy = pyboy
42
37
  self.mb = mb
43
38
  self.pyboy_argv = pyboy_argv
39
+ self.renderer = self.mb.lcd.renderer
40
+ self.is_cgb_renderer = isinstance(self.mb.lcd.renderer, CGBRenderer)
41
+ if self.is_cgb_renderer:
42
+ self.cgb_renderer = self.mb.lcd.renderer
44
43
 
45
44
  def handle_events(self, events):
46
45
  return events
@@ -80,9 +79,6 @@ class PyBoyWindowPlugin(PyBoyPlugin):
80
79
  self.renderer = mb.lcd.renderer
81
80
  self.sound = self.mb.sound
82
81
 
83
- def __cinit__(self, *args, **kwargs):
84
- self.renderer = self.mb.lcd.renderer
85
-
86
82
  def frame_limiter(self, speed):
87
83
  self._ftime += int((1.0 / (60.0 * speed)) * 1_000_000_000)
88
84
  now = time.perf_counter_ns()
@@ -142,7 +138,6 @@ class PyBoyGameWrapper(PyBoyPlugin):
142
138
 
143
139
  self.saved_state = io.BytesIO()
144
140
 
145
- def __cinit__(self, pyboy, mb, pyboy_argv, *args, **kwargs):
146
141
  self.tilemap_background = self.pyboy.tilemap_background
147
142
  self.tilemap_window = self.pyboy.tilemap_window
148
143
 
@@ -9,11 +9,15 @@ from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
9
9
 
10
10
  cimport pyboy.plugins.window_sdl2
11
11
  from pyboy.api.tilemap cimport TileMap
12
- from pyboy.core.mb cimport Motherboard
12
+ from pyboy.api.tile cimport Tile
13
+ from pyboy.api.sprite cimport Sprite
14
+ from pyboy.core.lcd cimport Renderer, CGBRenderer
13
15
  from pyboy.logging.logging cimport Logger
14
16
  from pyboy.plugins.base_plugin cimport PyBoyWindowPlugin
15
17
  from pyboy.utils cimport WindowEvent
16
18
 
19
+ cdef uint64_t COLS, ROWS, TILES, VRAM_OFFSET, HIGH_TILEMAP, SPRITES
20
+ cdef uint32_t COLOR, COLOR_BACKGROUND, SPRITE_BACKGROUND, COLOR_WINDOW
17
21
 
18
22
  cdef Logger logger
19
23
 
@@ -77,11 +81,22 @@ cdef class TileViewWindow(BaseDebugWindow):
77
81
 
78
82
  cdef uint8_t[:,:] tilecache # Fixing Cython locals
79
83
  cdef uint32_t[:] palette_rgb # Fixing Cython locals
80
- @cython.locals(mem_offset=uint16_t, tile_index=int, tile_column=int, tile_row=int)
84
+ @cython.locals(
85
+ mem_offset=uint16_t,
86
+ tile_index=int,
87
+ tile_column=int,
88
+ tile_row=int,
89
+ tile_num = uint8_t,
90
+ palette = uint8_t,
91
+ vbank = uint8_t,
92
+ horiflip = uint8_t,
93
+ vertflip = uint8_t,
94
+ bg_priority = uint8_t,
95
+ )
81
96
  cdef void post_tick(self) noexcept
82
97
 
83
98
  # scanlineparameters=uint8_t[:,:],
84
- @cython.locals(x=int, y=int, xx=int, yy=int, row=int, column=int)
99
+ @cython.locals(x=int, y=int, xx=int, yy=int, row=int, column=int, background_view=bint, t=MarkedTile)
85
100
  cdef void draw_overlay(self) noexcept
86
101
 
87
102
  @cython.locals(tile_x=int, tile_y=int, tile_identifier=int)
@@ -107,7 +122,7 @@ cdef class SpriteWindow(BaseDebugWindow):
107
122
  @cython.locals(tile_x=int, tile_y=int, sprite_identifier=int, sprite=object)
108
123
  cdef list handle_events(self, list)
109
124
 
110
- @cython.locals(t=MarkedTile, xx=int, yy=int, sprite=object, i=int)
125
+ @cython.locals(m=MarkedTile, xx=int, yy=int, sprite=object, i=int, sprite_index=int)
111
126
  cdef void draw_overlay(self) noexcept
112
127
 
113
128
  @cython.locals(title=str)
@@ -120,7 +135,7 @@ cdef class SpriteViewWindow(BaseDebugWindow):
120
135
  @cython.locals(t=int, x=int, y=int)
121
136
  cdef void post_tick(self) noexcept
122
137
 
123
- @cython.locals(t=MarkedTile, sprite=object, i=int)
138
+ @cython.locals(m=MarkedTile, sprite=Sprite, i=int, sprite_index=int)
124
139
  cdef void draw_overlay(self) noexcept
125
140
 
126
141
  @cython.locals(title=str)
@@ -142,10 +157,12 @@ cdef class MemoryWindow(BaseDebugWindow):
142
157
  cdef int[3] bg_color
143
158
 
144
159
  cdef void write_border(self) noexcept
145
- @cython.locals(header=bytes, addr=bytes)
160
+ # @cython.locals(header=uint8_t[:], addr=uint8_t[:])
146
161
  cdef void write_addresses(self) noexcept
162
+ # @cython.locals(a=uint8_t[:])
147
163
  cdef void write_memory(self) noexcept
148
164
  @cython.locals(text=uint8_t[:])
149
165
  cdef void render_text(self) noexcept
150
166
  @cython.locals(i=int, c=uint8_t)
151
167
  cdef void draw_text(self, int, int, uint8_t[:]) noexcept
168
+ cdef void _scroll_view(self, int)
@@ -10,7 +10,8 @@ from array import array
10
10
  from base64 import b64decode
11
11
  from ctypes import c_void_p
12
12
 
13
- from pyboy.api import Sprite, constants
13
+ from pyboy.api.sprite import Sprite
14
+ from pyboy.api.constants import COLS, ROWS, TILES, VRAM_OFFSET, HIGH_TILEMAP, SPRITES
14
15
  from pyboy.api.tilemap import TileMap
15
16
  from pyboy.plugins.base_plugin import PyBoyWindowPlugin
16
17
  from pyboy.plugins.window_sdl2 import sdl2_event_pump
@@ -122,8 +123,8 @@ class Debug(PyBoyWindowPlugin):
122
123
  pyboy_argv,
123
124
  scale=2,
124
125
  title="Sprite View",
125
- width=constants.COLS,
126
- height=constants.ROWS,
126
+ width=COLS,
127
+ height=ROWS,
127
128
  pos_x=window_pos,
128
129
  pos_y=0,
129
130
  )
@@ -139,7 +140,7 @@ class Debug(PyBoyWindowPlugin):
139
140
  pos_x=window_pos,
140
141
  pos_y=self.spriteview.height * 2 + 68,
141
142
  )
142
- window_pos += constants.COLS * self.spriteview.scale
143
+ window_pos += COLS * self.spriteview.scale
143
144
 
144
145
  self.memory = MemoryWindow(
145
146
  pyboy, mb, pyboy_argv, scale=1, title="Memory", width=8 * 60, height=16 * 36, pos_x=window_pos, pos_y=0
@@ -148,7 +149,7 @@ class Debug(PyBoyWindowPlugin):
148
149
 
149
150
  window_pos = 0
150
151
  tile_data_width = 16 * 8 # Change the 16 to however wide you want the tile window
151
- tile_data_height = ((constants.TILES * 8) // tile_data_width) * 8
152
+ tile_data_height = ((TILES * 8) // tile_data_width) * 8
152
153
  self.tiledata0 = TileDataWindow(
153
154
  pyboy,
154
155
  mb,
@@ -323,7 +324,7 @@ class TileViewWindow(BaseDebugWindow):
323
324
 
324
325
  def post_tick(self):
325
326
  # Updating screen buffer by copying tiles from cache
326
- mem_offset = self.tilemap.map_offset - constants.VRAM_OFFSET
327
+ mem_offset = self.tilemap.map_offset - VRAM_OFFSET
327
328
  for n in range(mem_offset, mem_offset + 0x400):
328
329
  tile_index = self.mb.lcd.VRAM0[n]
329
330
 
@@ -339,8 +340,8 @@ class TileViewWindow(BaseDebugWindow):
339
340
 
340
341
  # tilecache = None
341
342
  # palette_rgb = None
342
- if self.cgb:
343
- palette, vbank, horiflip, vertflip, bg_priority = self.renderer._cgb_get_background_map_attributes(
343
+ if self.is_cgb_renderer:
344
+ palette, vbank, horiflip, vertflip, bg_priority = self.cgb_renderer._cgb_get_background_map_attributes(
344
345
  self.mb.lcd, n
345
346
  )
346
347
  self.renderer.update_tilecache1(self.mb.lcd, tile_index, 1)
@@ -392,11 +393,7 @@ class TileViewWindow(BaseDebugWindow):
392
393
 
393
394
  def update_title(self):
394
395
  title = self.base_title
395
- title += (
396
- " [HIGH MAP 0x9C00-0x9FFF]"
397
- if self.tilemap.map_offset == constants.HIGH_TILEMAP
398
- else " [LOW MAP 0x9800-0x9BFF]"
399
- )
396
+ title += " [HIGH MAP 0x9C00-0x9FFF]" if self.tilemap.map_offset == HIGH_TILEMAP else " [LOW MAP 0x9800-0x9BFF]"
400
397
  title += (
401
398
  " [HIGH DATA (SIGNED) 0x8800-0x97FF]"
402
399
  if self.tilemap.signed_tile_data
@@ -410,41 +407,40 @@ class TileViewWindow(BaseDebugWindow):
410
407
 
411
408
  def draw_overlay(self):
412
409
  global marked_tiles
413
- scanlineparameters = self.pyboy.screen.tilemap_position_list
414
410
 
415
411
  background_view = self.scanline_x == 0
416
412
 
417
413
  # TODO: Refactor this
418
414
  # Mark screen area
419
- for y in range(constants.ROWS):
420
- xx = int(scanlineparameters[y][self.scanline_x])
421
- yy = int(scanlineparameters[y][self.scanline_y])
415
+ for y in range(ROWS):
416
+ xx = self.mb.lcd._scanlineparameters[y][self.scanline_x]
417
+ yy = self.mb.lcd._scanlineparameters[y][self.scanline_y]
422
418
 
423
419
  if background_view: # Background
424
420
  # Wraps around edges of the screen
425
- if y == 0 or y == constants.ROWS - 1: # Draw top/bottom bar
426
- for x in range(constants.COLS):
421
+ if y == 0 or y == ROWS - 1: # Draw top/bottom bar
422
+ for x in range(COLS):
427
423
  self.buf0[(yy + y) % 0xFF, (xx + x) % 0xFF] = COLOR
428
424
  else: # Draw body
429
425
  self.buf0[(yy + y) % 0xFF, xx % 0xFF] = COLOR
430
- for x in range(constants.COLS):
426
+ for x in range(COLS):
431
427
  self.buf0[(yy + y) % 0xFF, (xx + x) % 0xFF] &= self.color
432
- self.buf0[(yy + y) % 0xFF, (xx + constants.COLS) % 0xFF] = COLOR
428
+ self.buf0[(yy + y) % 0xFF, (xx + COLS) % 0xFF] = COLOR
433
429
  else: # Window
434
430
  # Takes a cut of the screen
435
431
  xx = -xx
436
432
  yy = -yy
437
- if yy + y == 0 or y == constants.ROWS - 1: # Draw top/bottom bar
438
- for x in range(constants.COLS):
439
- if 0 <= xx + x < constants.COLS:
433
+ if yy + y == 0 or y == ROWS - 1: # Draw top/bottom bar
434
+ for x in range(COLS):
435
+ if 0 <= xx + x < COLS:
440
436
  self.buf0[yy + y, xx + x] = COLOR
441
437
  else: # Draw body
442
438
  if 0 <= yy + y:
443
439
  self.buf0[yy + y, max(xx, 0)] = COLOR
444
- for x in range(constants.COLS):
445
- if 0 <= xx + x < constants.COLS:
440
+ for x in range(COLS):
441
+ if 0 <= xx + x < COLS:
446
442
  self.buf0[yy + y, xx + x] &= self.color
447
- self.buf0[yy + y, xx + constants.COLS] = COLOR
443
+ self.buf0[yy + y, xx + COLS] = COLOR
448
444
 
449
445
  # Mark selected tiles
450
446
  for t, match in zip(
@@ -457,10 +453,10 @@ class TileViewWindow(BaseDebugWindow):
457
453
 
458
454
  # Mark current scanline directly from LY,SCX,SCY,WX,WY
459
455
  if background_view:
460
- for x in range(constants.COLS):
456
+ for x in range(COLS):
461
457
  self.buf0[(self.mb.lcd.SCY + self.mb.lcd.LY) % 0xFF, (self.mb.lcd.SCX + x) % 0xFF] = 0xFF00CE12
462
458
  else:
463
- for x in range(constants.COLS):
459
+ for x in range(COLS):
464
460
  self.buf0[(self.mb.lcd.WY + self.mb.lcd.LY) % 0xFF, (self.mb.lcd.WX + x) % 0xFF] = 0xFF00CE12
465
461
 
466
462
 
@@ -481,7 +477,7 @@ class TileDataWindow(BaseDebugWindow):
481
477
  else:
482
478
  self.palette_rgb = self.mb.lcd.BGP.palette_mem_rgb
483
479
 
484
- for t in range(constants.TILES):
480
+ for t in range(TILES):
485
481
  if self.tilecache_select:
486
482
  self.renderer.update_tilecache1(self.mb.lcd, t, 1)
487
483
  else:
@@ -581,7 +577,7 @@ class SpriteWindow(BaseDebugWindow):
581
577
  if event.mouse_button == 0:
582
578
  tile_x, tile_y = event.mouse_x // 8, event.mouse_y // sprite_height
583
579
  sprite_identifier = tile_y * (self.width // 8) + tile_x
584
- if sprite_identifier > constants.SPRITES:
580
+ if sprite_identifier > SPRITES:
585
581
  # Out of bounds
586
582
  continue
587
583
  sprite = Sprite(self.mb, sprite_identifier)
@@ -624,8 +620,8 @@ class SpriteWindow(BaseDebugWindow):
624
620
 
625
621
  class SpriteViewWindow(BaseDebugWindow):
626
622
  def post_tick(self):
627
- for y in range(constants.ROWS):
628
- for x in range(constants.COLS):
623
+ for y in range(ROWS):
624
+ for x in range(COLS):
629
625
  self.buf0[y, x] = SPRITE_BACKGROUND
630
626
 
631
627
  for ly in range(144):