Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scanline performance #335

Merged
merged 9 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions docs/api/screen.html
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,9 @@ <h1 class="title">Module <code>pyboy.api.screen</code></h1>
list:
Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
&#34;&#34;&#34;
# self.tilemap_position_list = np.asarray(self.mb.lcd.renderer._scanlineparameters, dtype=np.uint8).reshape(144, 5)[:, :4]
# self.tilemap_position_list = self.mb.lcd.renderer._scanlineparameters

# # return self.mb.lcd.renderer._scanlineparameters
if self.mb.lcd._LCDC.lcd_enable:
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd.renderer._scanlineparameters]
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd._scanlineparameters]
else:
return [[0, 0, 0, 0] for line in range(144)]

Expand Down Expand Up @@ -467,12 +464,9 @@ <h2 class="section-title" id="header-classes">Classes</h2>
list:
Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
&#34;&#34;&#34;
# self.tilemap_position_list = np.asarray(self.mb.lcd.renderer._scanlineparameters, dtype=np.uint8).reshape(144, 5)[:, :4]
# self.tilemap_position_list = self.mb.lcd.renderer._scanlineparameters

# # return self.mb.lcd.renderer._scanlineparameters
if self.mb.lcd._LCDC.lcd_enable:
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd.renderer._scanlineparameters]
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd._scanlineparameters]
else:
return [[0, 0, 0, 0] for line in range(144)]

Expand Down Expand Up @@ -569,12 +563,9 @@ <h2 id="returns">Returns</h2>
list:
Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
&#34;&#34;&#34;
# self.tilemap_position_list = np.asarray(self.mb.lcd.renderer._scanlineparameters, dtype=np.uint8).reshape(144, 5)[:, :4]
# self.tilemap_position_list = self.mb.lcd.renderer._scanlineparameters

# # return self.mb.lcd.renderer._scanlineparameters
if self.mb.lcd._LCDC.lcd_enable:
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd.renderer._scanlineparameters]
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd._scanlineparameters]
else:
return [[0, 0, 0, 0] for line in range(144)]</code></pre>
</details>
Expand Down
8 changes: 4 additions & 4 deletions docs/api/tile.html
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,9 @@ <h1 class="title">Module <code>pyboy.api.tile</code></h1>
byte1 = self.mb.lcd.VRAM1[self.data_address + k - VRAM_OFFSET]
byte2 = self.mb.lcd.VRAM1[self.data_address + k + 1 - VRAM_OFFSET]

colorcode = self.mb.lcd.renderer.colorcode(byte1, byte2)
for x in range(8):
colorcode = utils.color_code(byte1, byte2, 7 - x)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor(colorcode)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor((colorcode &gt;&gt; x * 8) &amp; 0xFF)
return self.data

def __eq__(self, other):
Expand Down Expand Up @@ -419,9 +419,9 @@ <h2 class="section-title" id="header-classes">Classes</h2>
byte1 = self.mb.lcd.VRAM1[self.data_address + k - VRAM_OFFSET]
byte2 = self.mb.lcd.VRAM1[self.data_address + k + 1 - VRAM_OFFSET]

colorcode = self.mb.lcd.renderer.colorcode(byte1, byte2)
for x in range(8):
colorcode = utils.color_code(byte1, byte2, 7 - x)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor(colorcode)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor((colorcode &gt;&gt; x * 8) &amp; 0xFF)
return self.data

def __eq__(self, other):
Expand Down
24 changes: 15 additions & 9 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ <h2 id="kwargs">Kwargs</h2>

for k, v in defaults.items():
if k not in kwargs:
kwargs[k] = kwargs.get(k, defaults[k])
kwargs[k] = v

_log_level(log_level)

Expand Down Expand Up @@ -3201,14 +3201,12 @@ <h2 id="args">Args</h2>
start -= 0x4000
stop -= 0x4000
# Cartridge ROM Banks
assert stop &lt; 0x4000, &#34;Out of bounds for reading ROM bank&#34;
assert stop &lt;= 0x4000, &#34;Out of bounds for reading ROM bank&#34;
assert bank &lt;= self.mb.cartridge.external_rom_count, &#34;ROM Bank out of range&#34;

# TODO: If you change a RAM value outside of the ROM banks above, the memory value will stay the same no matter
# what the game writes to the address. This can be used so freeze the value for health, cash etc.
if bank == -1:
assert start &lt;= 0xFF, &#34;Start address out of range for bootrom&#34;
assert stop &lt;= 0xFF, &#34;Start address out of range for bootrom&#34;
assert stop &lt;= 0x100, &#34;Start address out of range for bootrom&#34;
if not is_single:
# Writing slice of memory space
if hasattr(v, &#34;__iter__&#34;):
Expand Down Expand Up @@ -3240,7 +3238,7 @@ <h2 id="args">Args</h2>
stop -= 0x8000
# CGB VRAM Banks
assert self.mb.cgb or (bank == 0), &#34;Selecting bank of VRAM is only supported for CGB mode&#34;
assert stop &lt; 0x2000, &#34;Out of bounds for reading VRAM bank&#34;
assert stop &lt;= 0x2000, &#34;Out of bounds for reading VRAM bank&#34;
assert bank &lt;= 1, &#34;VRAM Bank out of range&#34;

if bank == 0:
Expand Down Expand Up @@ -3273,7 +3271,7 @@ <h2 id="args">Args</h2>
start -= 0xA000
stop -= 0xA000
# Cartridge RAM banks
assert stop &lt; 0x2000, &#34;Out of bounds for reading cartridge RAM bank&#34;
assert stop &lt;= 0x2000, &#34;Out of bounds for reading cartridge RAM bank&#34;
assert bank &lt;= self.mb.cartridge.external_ram_count, &#34;ROM Bank out of range&#34;
if not is_single:
# Writing slice of memory space
Expand All @@ -3295,7 +3293,7 @@ <h2 id="args">Args</h2>
stop -= 0x1000
# CGB VRAM banks
assert self.mb.cgb or (bank == 0), &#34;Selecting bank of WRAM is only supported for CGB mode&#34;
assert stop &lt; 0x1000, &#34;Out of bounds for reading VRAM bank&#34;
assert stop &lt;= 0x1000, &#34;Out of bounds for reading VRAM bank&#34;
assert bank &lt;= 7, &#34;WRAM Bank out of range&#34;
if not is_single:
# Writing slice of memory space
Expand Down Expand Up @@ -3377,69 +3375,77 @@ <h2 id="args">Args</h2>
True
```
&#34;&#34;&#34;

def __init__(self, cpu):
self.cpu = cpu

@property
def A(self):
return self.cpu.A

@A.setter
def A(self, value):
self.cpu.A = value &amp; 0xFF

@property
def F(self):
return self.cpu.F

@F.setter
def F(self, value):
self.cpu.F = value &amp; 0xF0

@property
def B(self):
return self.cpu.B

@B.setter
def B(self, value):
self.cpu.B = value &amp; 0xFF

@property
def C(self):
return self.cpu.C

@C.setter
def C(self, value):
self.cpu.C = value &amp; 0xFF

@property
def D(self):
return self.cpu.D

@D.setter
def D(self, value):
self.cpu.D = value &amp; 0xFF

@property
def E(self):
return self.cpu.E

@E.setter
def E(self, value):
self.cpu.E = value &amp; 0xFF

@property
def HL(self):
return self.cpu.HL

@HL.setter
def HL(self, value):
self.cpu.HL = value &amp; 0xFFFF

@property
def SP(self):
return self.cpu.SP

@SP.setter
def SP(self, value):
self.cpu.SP = value &amp; 0xFFFF

@property
def PC(self):
return self.cpu.PC

@PC.setter
def PC(self, value):
self.cpu.PC = value &amp; 0xFFFF</code></pre>
Expand Down
7 changes: 2 additions & 5 deletions docs/utils.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ <h1 class="title">Module <code>pyboy.utils</code></h1>

__all__ = [&#34;WindowEvent&#34;, &#34;dec_to_bcd&#34;, &#34;bcd_to_dec&#34;]

STATE_VERSION = 10
STATE_VERSION = 11

##############################################################
# Buffer classes
Expand Down Expand Up @@ -143,10 +143,7 @@ <h1 class="title">Module <code>pyboy.utils</code></h1>
# Misc


# TODO: Would a lookup-table increase performance? For example a lookup table of each 4-bit nibble?
# That&#39;s 16**2 = 256 values. Index calculated as: (byte1 &amp; 0xF0) | ((byte2 &amp; 0xF0) &gt;&gt; 4)
# and then: (byte1 &amp; 0x0F) | ((byte2 &amp; 0x0F) &gt;&gt; 4)
# Then could even be preloaded for each color palette
# NOTE: Legacy function. Use look-up table in Renderer
def color_code(byte1, byte2, offset):
&#34;&#34;&#34;Convert 2 bytes into color code at a given offset.

Expand Down
5 changes: 1 addition & 4 deletions pyboy/api/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,9 @@ def tilemap_position_list(self):
list:
Nested list of SCX, SCY, WX and WY for each scanline (144x4). Returns (0, 0, 0, 0) when LCD is off.
"""
# self.tilemap_position_list = np.asarray(self.mb.lcd.renderer._scanlineparameters, dtype=np.uint8).reshape(144, 5)[:, :4]
# self.tilemap_position_list = self.mb.lcd.renderer._scanlineparameters

# # return self.mb.lcd.renderer._scanlineparameters
if self.mb.lcd._LCDC.lcd_enable:
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd.renderer._scanlineparameters]
return [[line[0], line[1], line[2], line[3]] for line in self.mb.lcd._scanlineparameters]
else:
return [[0, 0, 0, 0] for line in range(144)]

Expand Down
4 changes: 2 additions & 2 deletions pyboy/api/tile.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import cython

from libc.stdint cimport uint8_t, uint16_t, uint32_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t

from pyboy cimport utils
from pyboy.core.mb cimport Motherboard
Expand All @@ -25,5 +25,5 @@ cdef class Tile:
cpdef object ndarray(self) noexcept

cdef uint32_t[:,:] data # TODO: Add to locals instead
@cython.locals(byte1=uint8_t, byte2=uint8_t, colorcode=uint32_t)
@cython.locals(byte1=uint8_t, byte2=uint8_t, colorcode=uint64_t)
cdef uint32_t[:,:] _image_data(self) noexcept
4 changes: 2 additions & 2 deletions pyboy/api/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ def _image_data(self):
byte1 = self.mb.lcd.VRAM1[self.data_address + k - VRAM_OFFSET]
byte2 = self.mb.lcd.VRAM1[self.data_address + k + 1 - VRAM_OFFSET]

colorcode = self.mb.lcd.renderer.colorcode(byte1, byte2)
for x in range(8):
colorcode = utils.color_code(byte1, byte2, 7 - x)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor(colorcode)
self.data[k // 2][x] = self.mb.lcd.BGP.getcolor((colorcode >> x * 8) & 0xFF)
return self.data

def __eq__(self, other):
Expand Down
1 change: 1 addition & 0 deletions pyboy/core/cartridge/base_mbc.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ cdef class BaseMBC:
cdef bint rambank_initialized
cdef uint16_t rambank_selected
cdef uint16_t rombank_selected
cdef uint16_t rombank_selected_low
cdef bint cgb

cdef void save_state(self, IntIOInterface) noexcept
Expand Down
9 changes: 3 additions & 6 deletions pyboy/core/cartridge/base_mbc.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ def __init__(self, filename, rombanks, external_ram_count, carttype, sram, batte
self.rambank_enabled = False
self.rambank_selected = 0
self.rombank_selected = 1
self.rombank_selected_low = 0

self.cgb = bool(self.getitem(0x0143) >> 7)
self.cgb = bool(self.rombanks[0, 0x0143] >> 7)

if not os.path.exists(self.filename):
logger.debug("No RAM file found. Skipping.")
Expand Down Expand Up @@ -118,11 +119,7 @@ def overrideitem(self, rom_bank, address, value):
logger.error("Invalid override address: %0.4x", address)

def getitem(self, address):
if 0x0000 <= address < 0x4000:
return self.rombanks[0, address]
elif 0x4000 <= address < 0x8000:
return self.rombanks[self.rombank_selected, address - 0x4000]
elif 0xA000 <= address < 0xC000:
if 0xA000 <= address < 0xC000:
# if not self.rambank_initialized:
# logger.error("RAM banks not initialized: 0.4x", address)

Expand Down
18 changes: 7 additions & 11 deletions pyboy/core/cartridge/mbc1.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,15 @@ def setitem(self, address, value):
self.rambanks[self.rambank_selected % self.external_ram_count, address - 0xA000] = value
# else:
# logger.error("Invalid writing address: %0.4x", address)
if self.memorymodel == 1:
self.rombank_selected_low = (self.bank_select_register2 << 5) % self.external_rom_count
else:
self.rombank_selected_low = 0
self.rombank_selected = ((self.bank_select_register2 << 5) |
self.bank_select_register1) % self.external_rom_count

def getitem(self, address):
if 0x0000 <= address < 0x4000:
if self.memorymodel == 1:
self.rombank_selected = (self.bank_select_register2 << 5) % self.external_rom_count
else:
self.rombank_selected = 0
return self.rombanks[self.rombank_selected, address]
elif 0x4000 <= address < 0x8000:
self.rombank_selected = \
((self.bank_select_register2 << 5) | self.bank_select_register1) % self.external_rom_count
return self.rombanks[self.rombank_selected, address - 0x4000]
elif 0xA000 <= address < 0xC000:
if 0xA000 <= address < 0xC000:
if not self.rambank_initialized:
logger.error("RAM banks not initialized: %0.4x", address)

Expand Down
Loading
Loading