Zal0 / ZGB

Game Boy / Color engine with lots of features
MIT License
706 stars 50 forks source link

Avoid reading from t in UPDATE_TILE with out-of-bounds arguments #60

Closed Calindro closed 1 year ago

Calindro commented 1 year ago

Reading from t in UPDATE_TILE with out-of-bounds arguments can trip an exception in debugging emulators (see description below). Since in case of out-of-bounds arguments the read value is discarded, the read can be moved to the sane case.

Description of why an exception can be tripped by this: The exception occurs because UPDATE_TILE tries to read from VRAM. It does that because its parameter t points to VRAM. t points to VRAM here because ScrollUpdateColumnR is being called with pending_h_map pointing to VRAM. This happens because ScrollUpdateColumnWithDelay sets pending_h_map to scroll_map + scroll_tiles_w y + x with y being -1. (If y = -1 then scroll_map + scroll_tiles_w y + x is 0xa000 + 32 -1 + x. x is a value between 0 and 31. so 0xa000 + 32 -1 + x is a value between 0x9fe0 and 0x9fff which is VRAM. If scroll_map was in WRAM at 0xc000 then it would read a value from between 0xbfe0 and 0xbfff which is SRAM and thus doesn't trip the VRAM access exception. If scroll_map was in ROM at for example 0x4000, then it would read a value from between 0x3fe0 and 0x3fff which is ROM and thus also doesn't trigger any exception.)

ScrollUpdateColumnWithDelay is getting -1 passed for y. This happens when new_row in MoveScroll is 0 (because SCREEN_PAD_TOP is 1 and gets subtracted from new_row before it gets passed to ScrollUpdateColumnWithDelay in y).

MoveScroll is being called from RefreshScroll. RefreshScroll passes scroll_y as y to MoveScroll.

RefreshScroll is being called from SpriteManagerUpdate which is being called from main.

So if SpriteManagerUpdate gets called by main when scroll_y is 0, the exception trips.

This PR changes the code to avoid tripping this exception and also saves some cycles in the out-of-bounds case.