Skip to content

Improving the WaitForVBlank function

ExpoSeed edited this page Jan 6, 2021 · 7 revisions

The credits for this tutorial belong to DizzyEggg.

In both, Pokémon FireRed/LeafGreen and Pokémon Emerald, Game Freak modified the WaitForVBlank function present in Pokémon Ruby/Sapphire.

WaitForVBlank is used for what is called vsyncing. In short, VBlank is a short period of time in between each refresh of the screen, and it is used to keep the game processes in sync with the GBA's screen.

In Emerald, Gamefreak used a while loop that kept on checking for VBlank over and over again. However, this approach is very wasteful. The while loop is not doing anything, so all it does is waste CPU cycles, and burning CPU cycles like this burns battery power.

The correct way to vsync is to use a software interrupt/BIOS call. In short, we put the CPU in low power mode while we wait for the next VBlank, and on the next VBlank the CPU comes back to life.

The easiest way to do so, is by copying and pasting the function directly from Ruby and Sapphire, which means modifying the function like this:

static void WaitForVBlank(void)
{
    gMain.intrCheck &= ~INTR_FLAG_VBLANK;
-   while (!(gMain.intrCheck & INTR_FLAG_VBLANK))
-       ;
+   VBlankIntrWait();
}

One thing to note is that on agbcc's -O2, we still pay the price of a function call, as VBlankIntrWait fails to be inlined. In general, agbcc is very conservative on optimizations. Most other decent optimizing compilers (or if you make modern) will inline the function.

A solution is to inline it ourselves, for a negligible performance benefit:

static void WaitForVBlank(void)
{
    gMain.intrCheck &= ~INTR_FLAG_VBLANK;
-   while (!(gMain.intrCheck & INTR_FLAG_VBLANK))
-       ;
+   asm("swi 0x5");
}

Save, build a ROM, and so the game will no longer waste CPU power while it is waiting for the next VBlank. The easiest way to notice this is while running the game on a GBA emulator with a FastForward feature implemented, where implementing this fix will give you a 100-150% increase in speed.

Clone this wiki locally