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.
- {pyboy-2.5.2/pyboy.egg-info → pyboy-2.5.4}/PKG-INFO +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/__main__.py +7 -10
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sprite.py +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/conftest.py +15 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cpu.py +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/interaction.py +3 -3
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/lcd.pxd +2 -4
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/lcd.py +3 -10
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/mb.pxd +2 -2
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/mb.py +8 -6
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/sound.pxd +2 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/sound.py +1 -2
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/base_plugin.pxd +5 -2
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/base_plugin.py +5 -10
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug.pxd +23 -6
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug.py +29 -33
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_pinball.py +60 -16
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_super_mario_land.pxd +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_super_mario_land.py +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_tetris.pxd +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_tetris.py +1 -2
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/rewind.pxd +2 -2
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/rewind.py +14 -6
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_sdl2.py +3 -3
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/pyboy.pxd +2 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/pyboy.py +17 -8
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/utils.pxd +7 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/utils.py +19 -0
- {pyboy-2.5.2 → pyboy-2.5.4/pyboy.egg-info}/PKG-INFO +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/pyproject.toml +1 -1
- {pyboy-2.5.2 → pyboy-2.5.4}/LICENSE.md +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/MANIFEST.in +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/README.md +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/constants.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/gameshark.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/gameshark.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/memory_scanner.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/memory_scanner.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/screen.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/screen.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sound.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sound.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/sprite.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tile.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tile.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tilemap.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/api/tilemap.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom_cgb.bin +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/bootrom_dmg.bin +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/base_mbc.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/base_mbc.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/cartridge.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/cartridge.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc1.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc1.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc2.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc2.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc3.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc3.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc5.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/mbc5.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/rtc.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cartridge/rtc.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/cpu.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/interaction.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/opcodes_gen.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/ram.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/ram.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/timer.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/core/timer.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/default_rom.gb +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/_logging.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/logging.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/logging/logging.pyx +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/__init__.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/auto_pause.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/auto_pause.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug_prompt.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/debug_prompt.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/font.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_kirby_dream_land.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_kirby_dream_land.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_gen1.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_gen1.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/game_wrapper_pokemon_pinball.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/manager_gen.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/record_replay.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/record_replay.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screen_recorder.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screen_recorder.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screenshot_recorder.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/screenshot_recorder.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_null.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_null.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_open_gl.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_open_gl.py +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy/plugins/window_sdl2.pxd +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/SOURCES.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/dependency_links.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/entry_points.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/not-zip-safe +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/requires.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/pyboy.egg-info/top_level.txt +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/setup.cfg +0 -0
- {pyboy-2.5.2 → pyboy-2.5.4}/setup.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
|
27
|
-
cdef
|
|
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
|
|
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
|
-
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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=
|
|
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
|
|
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=
|
|
126
|
-
height=
|
|
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 +=
|
|
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 = ((
|
|
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 -
|
|
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.
|
|
343
|
-
palette, vbank, horiflip, vertflip, bg_priority = self.
|
|
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(
|
|
420
|
-
xx =
|
|
421
|
-
yy =
|
|
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 ==
|
|
426
|
-
for x in range(
|
|
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(
|
|
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 +
|
|
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 ==
|
|
438
|
-
for x in range(
|
|
439
|
-
if 0 <= xx + x <
|
|
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(
|
|
445
|
-
if 0 <= xx + x <
|
|
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 +
|
|
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(
|
|
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(
|
|
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(
|
|
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 >
|
|
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(
|
|
628
|
-
for x in range(
|
|
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):
|