gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Graphics > double buffering

#38835 - christosterone - Fri Apr 01, 2005 5:54 am

im a total noob to this; i just got the compliler.

my game keeps flickering;

heres the code:

Code:

#include "gba.h"
#include "screenmodes.h"
#include "keypad.h"

u16* theVideoBuffer = (u16*)VideoBuffer;
u16* theBackBuffer = (u16*)BackBuffer;
#define RGB(r,g,b) (r+(g<<5)+(b<<10))    //Macro to build a color from its parts

int x = 50;
int y = 50;

int canMove()
{
   int returnval=0;
   if( x>=0 && x<240 && y>=0 && y<160 )
      returnval=1;
   return returnval;
}

void clrscreen()
{
    for( int i=0; i<(160*240); i++ )
    {
        theVideoBuffer[ i ] = RGB( 256, 0, 0 );
    }
}

void WaitForVsync()
{
   while((volatile u16)REG_VCOUNT != 160){}
}

void flip()
{
  if (REG_DISPCNT & BACKBUFFER)
  {
    REG_DISPCNT &= ~BACKBUFFER;
    theVideoBuffer = theBackBuffer;
  }
  else
  {
    REG_DISPCNT |= BACKBUFFER;
    theVideoBuffer = theBackBuffer;
  }
}

void repaint()
{
    clrscreen();
    WaitForVsync();
    theBackBuffer[ x + (y * 240) ] = RGB( 31, 31, 31 );
    flip();
}

int main()
{
   SetMode( SCREENMODE3 | BG2ENABLE );    //Set screen mode
    repaint();

   while(1)
   {
      if( KEY_DOWN(KEYUP) )
      {
         y--;
         if( canMove()==0 )
            y++;
            repaint();
      }
      else if( KEY_DOWN(KEYDOWN) )
      {
         y++;
         if( canMove()==0 )
            y--;
            repaint();
      }
      else if( KEY_DOWN(KEYRIGHT) )
      {
         x++;
         if( canMove()==0 )
            x--;
            repaint();
      }
      else if( KEY_DOWN(KEYLEFT) )
      {
         x--;
         if( canMove()==0 )
            x++;
            repaint();
      }
   }

 return 0;
}

#38836 - DekuTree64 - Fri Apr 01, 2005 6:22 am

Looks like you're expecting the flip operation to swap the actual memory, when it actually only swaps what area of memory is visible.

What you need to do is, in flip(), swap the 'theVideoBuffer' and 'theBackBuffer' pointers as well, to change where your code writes to.

When the BACKBUFFER bit in DISPCNT is 0, you see the address 0x6000000 on the screen. When the bit is 1, you see address 0x600A000. I'm guessing that VideoBuffer from your headers points to 0x6000000, and BackBuffer to 0x600A000. Those names are a little misleading, since neither of them is really the front or back buffer all the time.

So, if the BACKBUFFER bit is 0, you need to point your theBackBuffer variable to 0x600A000, so you're drawing on the hidden one. If BACKBUFFER is 1, theBackBuffer should point to 0x6000000, which will then be hidden.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#39085 - Cearn - Mon Apr 04, 2005 11:19 am

There is no backbuffer in mode 3. If you really need a backbuffer, you could try modes 4 or 5, or create your own backbuffer in ewram. If you simply define a global array for it, you'll wipe out the whole on GBA's internal memory.
Code:

u16 theBackBuffer[240*160] __attribute__((section(".ewram")));

Of course, if you do use something like this, you'll have to copy it yourself and I should point out that a normal loop like the one you have for clrscreen actually takes a few frames. This thread may be of some help too. Modes 3-5 are nice because they are similar to what you may be used to on a PC, but for actual GBA game programming they may not be the best choice, are you sure you need the bitmap modes?