forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Double Buffering question

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
casual otaku



Joined: 14 Dec 2005
Posts: 3

PostPosted: Wed Dec 14, 2005 4:59 am    Post subject: Double Buffering question Reply with quote

Hi,

I have created a simple program that lets the user control a character on the screen. At the moment all screen output is very flickery, I'm guessing that I have to implement double buffering but am not sure how to do this? My code is below:

Code:

#include <pspdisplay.h>
#include <pspctrl.h>
#include <pspkernel.h>
#include <pspdebug.h>

PSP_MODULE_INFO("Character", 0, 1, 1);

SceCtrlData pad;

int x = 20, y = 20; // (0,0) denotes top left corner of PSP screen

/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
  sceKernelExitGame();
  return 0;
}



/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
  int cbid;

  cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
  sceKernelRegisterExitCallback(cbid);

  sceKernelSleepThreadCB();

  return 0;
}


/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
  int thid = 0;

  thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
 
  if(thid >= 0)
  {
    sceKernelStartThread(thid, 0, 0);
  }

  return thid;
}



void drawCharacter()
{
  pspDebugScreenClear();
 
  pspDebugScreenSetXY(x, y); 
  pspDebugScreenPrintf("O");   // character that the user controls   
}



void inputLoop()
{
  while (1)
  {
    pspDebugScreenSetXY(0, 0);
    pspDebugScreenPrintf("Press X, O, [] or /\\ to move character... \n");
   
    sceCtrlReadBufferPositive(&pad, 1);
   
    if((pad.Buttons) & (PSP_CTRL_CROSS)) // move down
    {
      y++; 
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_SQUARE)) // move left
    {
      x--;
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_TRIANGLE)) // move up
    {
      y--;     
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_CIRCLE)) // move down
    {
      x++;     
      drawCharacter();
    }
  }     
}



int main()
{
  pspDebugScreenInit(); 
  SetupCallbacks();
 
  pspDebugScreenSetXY(x, y); // initialise to x, y
 
  inputLoop();
 
  return 0;
}
Back to top
View user's profile Send private message
Brunni



Joined: 08 Oct 2005
Posts: 186

PostPosted: Wed Dec 14, 2005 5:22 am    Post subject: Reply with quote

It seems like you can't use double buffering with the standard console (you need to write your own text routines, rendered on a backbuffer). But you should at least wait the VBlank in your main loop, like this:
Code:
void inputLoop()
{
  while (1)
  {
    pspDebugScreenSetXY(0, 0);
    pspDebugScreenPrintf("Press X, O, [] or /\\ to move character... \n");
   
    sceCtrlReadBufferPositive(&pad, 1);
   
    if((pad.Buttons) & (PSP_CTRL_CROSS)) // move down
    {
      y++; 
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_SQUARE)) // move left
    {
      x--;
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_TRIANGLE)) // move up
    {
      y--;     
      drawCharacter();
    }
    else if((pad.Buttons) & (PSP_CTRL_CIRCLE)) // move down
    {
      x++;     
      drawCharacter();
    }
    sceDisplayWaitVblankStart();
  }     
}

Also, I don't think it's a good idea to redraw the character one time in each 'if' in your loop, because it will become more and more complex as your game becomes bigger. For example, you could save its coordinates and compare them with those of the last time and redraw it only if they have changed...
_________________
Sorry for my bad english
Oldschool library for PSP - PC version released
Back to top
View user's profile Send private message
dr_watson



Joined: 28 Nov 2005
Posts: 42

PostPosted: Wed Dec 14, 2005 11:48 am    Post subject: Reply with quote

Guess you're blitting your images by writing to VRAM directly? This is how I did double buffering:

Code:

int main()
{
   SceCtrlData pad;
   struct timeval tick;
   
   unsigned int oldButtons = 0;

   pBufferPointer[0] = (u32*)(0x04000000+0x40000000);                  // pointer to 1st page in VRAM
   pBufferPointer[1] = (u32*)(0x04000000+0x40000000+FRAME_BUFFER_SIZE);   // pointer to 2nd page in VRAM

   pspDebugScreenInit();   // do this so that we can use pspDebugScreenPrintf
   SetupCallbacks();
   
   sceCtrlSetSamplingCycle(0);
   sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
   
   sceDisplaySetMode(0, SCREEN_WIDTH, SCREEN_HEIGHT);   

   bg = LoadImage("bg.png");         // load bg
   mario = LoadImage("m.png");         // load our character
   cursor = LoadImage("cursor.png");   // load a cursor

   currentPage = 1;                     // prepare a page to be displayed
   pVRAM = pBufferPointer[currentPage];
   
   Render();                           // render to page 1
   
   
   int lastTime = Sys_Milliseconds();

   while (!done)
   {
      int timeNow = Sys_Milliseconds();
      int delta = timeNow-lastTime;
      lastTime = timeNow;

      offset--;               // change the offset position to draw the background image
      if (offset<=-128)         // this will give us an illusion of a moving background
         offset = 0;
      
      gettimeofday(&tick, 0);

       sceCtrlPeekBufferPositive(&pad, 1);      // using sceCtrlPeekBufferPositive is faster than sceCtrlReadBufferPositive
                                    // because sceCtrlReadBufferPositive waits for vsync

      if (pad.Buttons != 0)               // one or more buttons have been pressed
      {
         // do a screen shot only if CIRCLE button wasn't in 'down' state previously
         if ((pad.Buttons&PSP_CTRL_CIRCLE) && !(oldButtons&PSP_CTRL_CIRCLE))   
         {
            ScreenShot("ms0:/screenshot.png");
         }

         // CROSS button to exit
         if (pad.Buttons & PSP_CTRL_CROSS)
         {
            done = true;
         }
   
         if (pad.Buttons & PSP_CTRL_LEFT)
         {
            if (xMan > 0) xMan--;
         }
         else if (pad.Buttons & PSP_CTRL_RIGHT)
         {
            if (xMan < SCREEN_WIDTH-1) xMan++;
         }
         
      }
      
      oldButtons = pad.Buttons;
      
      // range of pad.Lx and pad.Ly is 0-255
      if (pad.Lx<64)
      {
         if (x>0) x--;
      }
      else if (pad.Lx>196)
      {
         if (x<SCREEN_WIDTH-1)
            x++;
      }
      if (pad.Ly<64)
      {
         if (y>0) y--;
      }
      else if (pad.Ly>196)
      {
         if (y<SCREEN_HEIGHT-1)
            y++;
      }

      // flip and bring the background page to the front
      sceDisplayWaitVblankStart();
      sceDisplaySetFrameBuf(pVRAM, FRAME_BUFFER_WIDTH, PSP_DISPLAY_PIXEL_FORMAT_8888, 0);

      // make the previous page as the background page for rendering
      currentPage = 1-currentPage;
      pVRAM = pBufferPointer[currentPage];

      Render();      // render all images to buffer
   
   }
   
   FreeImage(bg);                     // free the images
   FreeImage(mario);
   FreeImage(cursor);
   
   sceKernelExitGame();
   return 0;
}
Back to top
View user's profile Send private message
casual otaku



Joined: 14 Dec 2005
Posts: 3

PostPosted: Thu Dec 15, 2005 2:38 am    Post subject: Reply with quote

Thanks for posting the code, but it's not much use to me because you haven't included the parts that initialise variables such as pVRAM, FRAME_BUFFER_SIZE and FRAME_BUFFER_WIDTH? If you provide me with this info then I can try to integrate your code into mine in order to implement double buffering.

Thanks
Back to top
View user's profile Send private message
dr_watson



Joined: 28 Nov 2005
Posts: 42

PostPosted: Thu Dec 15, 2005 12:00 pm    Post subject: Reply with quote

I was trying to just give you an idea on how to do double buffering so I only posted a code segment :)

Here is the complete source code:
http://www.khors.com/JGE/game04_src.zip
(You'll need libpng to build it)

If you want to use Gu instead, you can have a look of the source code of my game StarBugz:

http://forums.ps2dev.org/viewtopic.php?t=4286
Back to top
View user's profile Send private message
casual otaku



Joined: 14 Dec 2005
Posts: 3

PostPosted: Thu Dec 15, 2005 7:27 pm    Post subject: Reply with quote

Thanks! I doubt I'll need that PNG library as I'm only interested in the double buffering stuff and not the imaging. I'll give it a go later today.

Again, thanks.
Back to top
View user's profile Send private message
jsharrad



Joined: 20 Oct 2005
Posts: 102

PostPosted: Fri Dec 23, 2005 5:48 pm    Post subject: Reply with quote

Quote:
Here is the complete source code:
http://www.khors.com/JGE/game04_src.zip
(You'll need libpng to build it)


Built that fine, but when I tried to run it on my psp, it just turned off:(
Back to top
View user's profile Send private message
Warrick



Joined: 06 Dec 2005
Posts: 9

PostPosted: Sat Dec 24, 2005 1:40 am    Post subject: Reply with quote

jsharrad, do you also copy all png resources of game 04 to correct directory?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group