Program Flow

This is a very important chapter, many times I have seen newbies use disturbing ways of timing the flow of their program.


Rendering Cycle

Now, the normal way to do things is to time everything to the rendering cycle. The rendering cycle can be split up into 3 states, active/rendering, HBlank/horizontal blanking period, and VBlank/vertical blanking period. It goes through these states 60 times a second, thus giving you a fixed 60fps frame rate (well, actually about 59.8261 fps :P). The rendering cycle is always looping through these states regardless of what the program is doing.

I think with some displays, HBlank was the period of time it took to move the rendering thingy back to the left side of the screen, and the VBlank period was the time it took to move the raster line back to the top. (I'm not sure if this is done with LCDs but it can be emulated easily)

Anyway, during the blanking periods, the display engine isn't rendering anything! This gives you two advantages: you have fast access to the video memory, and the display engine isn't drawing anything. When the display engine is drawing, you don't want to mess with the positioning/data of certain elements. For example, see what happens when you move the ball down 5 pixels when the display engine is busy rendering it:

Yikes! The ball will be displayed like that for one frame. What happened is that half of the ball was already drawn in it's original position, and then the ball was moved down 5 pixels. The display engine then started rendering the ball again in the new position. This effect is called shearing, it can sometimes be used to create cool graphical effects, and it can be accidentally used to create undesirable effects.

If you don't know what a raster line is, it is the current line that is being rendered by the display engine.

Now, to avoid this problem, we can take advantage of the VBlank period. During the VBlank period, the display isn't drawing anything! Thus it is safe to change any of the graphical information. The VBlank period is limited, so your program has to be fast enough to change all of the rendering information before the screen starts drawing again.

During the rendering period, the program can do other things, like update all of the program logic. When it's done updating that, there isn't much else to do, so the program can enter a halted state until the next VBlank period. This is done using the swiWaitForVBlank function described in previous chapters.

One other thing is the HBlank period. This is a short period when the screen is finished drawing a single line. Sometimes you can achieve cool raster effects by changing certain data while the screen is drawing. To make sure that the effect runs smoothly, the HBlank period can be used to update data safely mid-frame. This is quite an advanced topic and will not be explained further throughout this tutorial.

In conclusion, your main loop should take advantage of these rendering states to ensure a smooth graphical display and program flow. An example main loop should look like this:

int main(void)
{
    irqInit();
    irqEnable( IRQ_VBLANK ); // enable vblank irq for swiWaitForVBlank

    while(1)  // infinite loops are perfectly normal when coding for consoles
    {
        // Rendering period:
        // update game objects (move things around, calculate velocities, etc)
        update_logic();
        
        // wait for the vblank period
        swiWaitForVBlank();

        // VBlank Period: (safe to modify graphics)
        // move the graphics around
        update_graphics();
    }
}
Previous: DesigningContentsNext: VRAM banks