Adds support for MultipleLoadStore, LoadStoreImmediateOffset, and
MoveShiftedRegister. This allows waitloop skipping to work in Spiderman
the Movie, bringing in-game fps from 280 to 375 and title screen fps
from 450 to 700.
This change also disallows instructions that branch from participating
in waitloop skipping. I don't expect this to affect anything, but I
figure it's better to be overly cautious.
This change introduces a first attempt at waitloop detection and
skipping. Games like Pokemon Emerald and Kirby Nightmare in Dreamland
don't properly halt the CPU when waiting for an event like VBLANK, and
instead just burn the CPU in a loop.
This change specifically focuses on those games. Other games likely use
more instructions than I added support for here, and other games likely
also may use a waitloop technique that this approach can't prove to be
free of side-effects. Further changes will add support for more
instructions, but I don't expect to add support for games that wait in a
more complicated way. (This emulator is for my own enjoyment, after all,
and it supports the games I want to play :p)
Prior to this change, Pokemon Ruby saw ~430 fps on my M2 MacBook Air,
while Pokemon Emerald and Kirby both saw ~290 fps. With this change, all
games now see ~430 fps, including Ruby which didn't see any regression.
For this reason, I've enabled waitloop skipping by default.
In subsequent changes, I plan to add support for more instructions, add
proper configuration in the UI (enable/disable, set instruction limit,
etc), as well as potentially add a CPU meter to better visualize the
impact of this change.
This change removes bounds checking for Slices, which represents most
indexable storage in the emulator. Removing these checks makes the
emulator less safe, without a doubt. However, it amounts a roughly 5%
improvement in the games tested. Most of the checks today occur in
fixed-length arrays where the index cannot be out of bounds, so I'm
chosing to make this tradeoff.
This change updates most uses of Array to Slice in order to avoid an
extra object on the heap and an extra reference to follow when indexing
into these objects. This amounts to a roughly 5% performance improvement
in the games tested.
This change also updates the GBC palette writing code to not allocate
new arrays when new palettes are written.
The fact that this fixes Supestar Saga is both happy and sad for me. I spent so
much time trying to fix that game before, but I didn't even mean to fix it this
time. Either way, it works now. Finally.