 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
casual otaku
Joined: 14 Dec 2005 Posts: 3
|
Posted: Wed Dec 14, 2005 4:59 am Post subject: Double Buffering question |
|
|
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 |
|
 |
Brunni
Joined: 08 Oct 2005 Posts: 186
|
Posted: Wed Dec 14, 2005 5:22 am Post subject: |
|
|
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 |
|
 |
dr_watson
Joined: 28 Nov 2005 Posts: 42
|
Posted: Wed Dec 14, 2005 11:48 am Post subject: |
|
|
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 |
|
 |
casual otaku
Joined: 14 Dec 2005 Posts: 3
|
Posted: Thu Dec 15, 2005 2:38 am Post subject: |
|
|
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 |
|
 |
dr_watson
Joined: 28 Nov 2005 Posts: 42
|
|
| Back to top |
|
 |
casual otaku
Joined: 14 Dec 2005 Posts: 3
|
Posted: Thu Dec 15, 2005 7:27 pm Post subject: |
|
|
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 |
|
 |
jsharrad
Joined: 20 Oct 2005 Posts: 102
|
Posted: Fri Dec 23, 2005 5:48 pm Post subject: |
|
|
Built that fine, but when I tried to run it on my psp, it just turned off:( |
|
| Back to top |
|
 |
Warrick
Joined: 06 Dec 2005 Posts: 9
|
Posted: Sat Dec 24, 2005 1:40 am Post subject: |
|
|
| jsharrad, do you also copy all png resources of game 04 to correct directory? |
|
| Back to top |
|
 |
|
|
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
|