Getting simple framebuffer going

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Getting simple framebuffer going

Post by Sdw »

I've just got my PSP development environment up and running, and I'm trying to do some really basic things like getting a simple framebuffer to work.
However the only thing I get is a black screen. Can anyone spot any obvious mistakes:

Code: Select all

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

PSP_MODULE_INFO&#40;"Gfx Test", 0, 1, 1&#41;;

unsigned int frameBuf&#91;512*272&#93;;

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41; 
&#123;
	sceKernelExitGame&#40;&#41;;
   return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41; 
&#123;
	 int cbid;
	
	 cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
	 sceKernelRegisterExitCallback&#40;cbid&#41;;	
	 sceKernelSleepThreadCB&#40;&#41;;	
	 return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41; 
&#123;
	int thid = 0;

	thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
  	if&#40;thid >= 0&#41; 
  	&#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
   &#125;
	return thid;
&#125;

int main&#40;&#41; 
&#123;
	int x,y;
	
	SetupCallbacks&#40;&#41;;
	for&#40;x=0;x<480;x++&#41;
	&#123;
		for&#40;y=0;y<272;y++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;;
		&#125;
	&#125;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;&#40;char*&#41;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;; 
	sceKernelSleepThread&#40;&#41;;
	return 0;
&#125;
kururin
Posts: 36
Joined: Wed Jul 05, 2006 7:19 am

Re: Getting simple framebuffer going

Post by kururin »

Sdw wrote:I've just got my PSP development environment up and running, and I'm trying to do some really basic things like getting a simple framebuffer to work.
However the only thing I get is a black screen. Can anyone spot any obvious mistakes:

Code: Select all

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

PSP_MODULE_INFO&#40;"Gfx Test", 0, 1, 1&#41;;

unsigned int frameBuf&#91;512*272&#93;;

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41; 
&#123;
	sceKernelExitGame&#40;&#41;;
   return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41; 
&#123;
	 int cbid;
	
	 cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
	 sceKernelRegisterExitCallback&#40;cbid&#41;;	
	 sceKernelSleepThreadCB&#40;&#41;;	
	 return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41; 
&#123;
	int thid = 0;

	thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
  	if&#40;thid >= 0&#41; 
  	&#123;
		sceKernelStartThread&#40;thid, 0, 0&#41;;
   &#125;
	return thid;
&#125;

int main&#40;&#41; 
&#123;
	int x,y;
	
	SetupCallbacks&#40;&#41;;
	for&#40;x=0;x<480;x++&#41;
	&#123;
		for&#40;y=0;y<272;y++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;;
		&#125;
	&#125;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;&#40;char*&#41;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;; 
	sceKernelSleepThread&#40;&#41;;
	return 0;
&#125;
unsigned int frameBuf[512*272]; -> unsigned int *frameBuf = (u32 *)0x04000000;
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

Thanks for the reply! I gave it a try, but it didn't make any difference - still black screen.
If I understand it correctly, the change was to put the framebuffer in videomem instead of main mem, right?
I read an article that stated that if you were planning on filling the framebuffer with CPU-calculated stuff as opposed to using the GPU, you should actually keep the framebuffer in main mem for better performance, however this might have been wrong.

However, right now I would be happy if it could display any framebuffer at all, be it from main or video mem... Argh, it seems like such a simple thing, I just can't see what is going wrong!

-edit-

Just to clarify what happens - I get a black screen, however the PSP hasn't locked up or anything, when I press the "home" button I get the "do you want to quit.." prompt just as it is supposed to.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Code: Select all

...

unsigned int frameBuf&#91;512*272&#93;;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	int x,y;
	
	SetupCallbacks&#40;&#41;;
	for&#40;y=0;y<272;y++&#41;
	&#123;
		for&#40;x=0;x<480;x++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;;
		&#125;
	&#125;
	sceKernelDcacheWritebackAll&#40;&#41;;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;;
	
	sceKernelSleepThread&#40;&#41;;
	sceKernelExitGame&#40;&#41;;
	return&#40;0&#41;;
&#125;
Works perfectly fine for me. Make sure you're on the latest toolchain and SDK. Also, if you really want to do software drawing having the framebuffer in sys ram is faster, yes.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

I still just get the black screen. Could you post your entire code, and also your Makefile and I'll see if I can compile it EXACTLY as yours.

I'm using the latest toolchain downloaded from ps2dev.org. My makefile looks like this:

Code: Select all

TARGET = test
OBJS = test.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Gfx Test

PSPSDK=/usr/local/pspdev/psp/sdk
include $&#40;PSPSDK&#41;/lib/build.mak
and I compile it with 'make kxploit'
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

AAAAAARGHHH!! This is driving me TOTALLY NUTS! I've developed for tons of more or less strange systems (GP32, TI83, C64DTV etc. etc.) and I have never ever been so totally stuck (going on 24 hours now!) with something so basic!

How hard can it be to get a god damn framebuffer going? Can't someone please provide a complete source. I've been searching the net for several hours now and I can't find a single complete source code that shows how to do this.
I found a whole bunch of samples that shows using the 3D hardware and all other jazz, but nothing that just shows "set up a double buffered linear 32 bit framebuffer, then do a fire effect" or something like that.
The only "simple" sources I found only use pspDebugScreenInit()/pspDebugScreenPrintf and that works fine for me, but I want a framebuffer that I can draw to myself!
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

OK, I think I've found the problem. The following code demonstrates the problem:

Code: Select all

unsigned int* frameBuf = &#40;0x40000000 | &#40;0x04000000&#41;&#41;;
//unsigned int frameBuf&#91;512*272&#93;;

int main&#40;&#41; 
&#123;
	int x,y;
	
	SetupCallbacks&#40;&#41;;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;; 
	for&#40;y=0;y<272;y++&#41;
	&#123;
		for&#40;x=0;x<480;x++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;+&#40;&#40;&#40;x+y&#41;&255&#41;*65536&#41;;
		&#125;
	&#125;
	sceKernelDelayThread&#40;3000000&#41;;	
	pspDebugScreenInit&#40;&#41;;
	for&#40;y=0;y<272;y++&#41;
	&#123;
		for&#40;x=0;x<480;x++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;+&#40;&#40;&#40;x+y&#41;&255&#41;*65536&#41;;
		&#125;
	&#125;	
	sceKernelSleepThread&#40;&#41;;	
	return 0;
&#125;
The first three seconds is only black screen, then the image is shown correctly. Using a non vram-framebuffer (the commented code) yields black screen all the time.
So my only conclusion is that sceDisplaySetFrameBuf is somehow completely buggy and does just about nothing useful, but that doesn't make any sense at all...
Somehow running pspDebugScreenInit seems to point the frameBuffer at the default location (0x44000000), but this is a poor solution since I don't get double buffer etc. and I had preferred to have the buffer in main mem anyway.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Because you haven't flushed the dcache.

sceKernelDcacheWritebackAll();

Jim
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Code: Select all

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

PSP_MODULE_INFO&#40;"Gfx Test", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;0&#41;;

/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41;
&#123;
   sceKernelExitGame&#40;&#41;;
   return 0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41;
&#123;
    int cbid;
   
    cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
    sceKernelRegisterExitCallback&#40;cbid&#41;;   
    sceKernelSleepThreadCB&#40;&#41;;   
    return 0;
&#125;

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks&#40;void&#41;
&#123;
   int thid = 0;

   thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
     if&#40;thid >= 0&#41;
     &#123;
      sceKernelStartThread&#40;thid, 0, 0&#41;;
   &#125;
   return thid;
&#125;

unsigned int frameBuf&#91;512*272&#93;;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	int x,y;
	
	SetupCallbacks&#40;&#41;;
	for&#40;y=0;y<272;y++&#41;
	&#123;
		for&#40;x=0;x<480;x++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;;
		&#125;
	&#125;
	sceKernelDcacheWritebackAll&#40;&#41;;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;;
	
	sceKernelSleepThread&#40;&#41;;
	sceKernelExitGame&#40;&#41;;
	return&#40;0&#41;;
&#125;
Makefile:

Code: Select all

TARGET = main6
OBJS = main6.o

INCDIR =
CFLAGS = -O2 -G3 -g -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

LIBDIR =
LDFLAGS =
LIBS=-lpspdisplay

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Test

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
As said, it works perfectly, don't know what problem you have with that.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

OK, now this problem has passed way into bizarro-land!
I built with Raphaels code, both makefile and source and I get the SAME PROBLEM! Just black screen!
I've uploaded the compiled files here:
http://sdw.webhop.net/tmp/test.zip
Please someone try them on your PSP and see if you get graphics or not.
Also, Raphael, could you post the binaries you built, so I can try them and also do a binary compare and see if our toolchains produce different results.

Could it be something with my PSP? I run 3.40 OE-A and I place the files in the "GAME150" directory. But I haven't had any problems with other homebrew, so I've got a hard time thinking the problem is on the hardware side.

I build using cygwin (latest release, downloaded yesterday) and psptoolchain-20070626.tar.bz2.
I get no compiler errors/warning or other indications that something should not be right.
Strangeness++!!!
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Your eboot works fine for me too, at least from PSPLink. From XMB I get the same result as you though (even with my binary). After finding this, I tried around a bit more and it seems the setFrameBuf call somehow fails when called from XMB, as a subsequent getFrameBuf call always returns the same, no matter if setFrameBuf was called or not (though the returned address is weird - it's 0, same for width, only the pixelformat is correct, so probably that call just fails too? but why is the pfm set correctly?).
Apart from that, the same function works just fine within PMP Mod, where it is used to display the decoded video in system RAM. So I really don't know what's happening here.
I also tried running the app in Kernel mode, but that didn't make a difference (only the home button callback was messed up by not accepting my O button input on YES).
As a last resort, I could imagine to try to call the function from a new thread (as is done in PMP Mod), though I don't know why that should make a difference.
Maybe TyRaNiD has an idea why it works flawless from PSPLink, though I'm pretty sure it's nothing specific with PSPLink that makes the call succeed.

At least, it's nothing to do with your setup.

here's the last code I used:

Code: Select all


__attribute__&#40;&#40;aligned&#40;64&#41;&#41;&#41; unsigned int frameBuf&#91;512*272&#93;;


int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	int x,y;
	void *buf = -1;
	int width = -512, pfm = -3, vsync = -9;
	SetupCallbacks&#40;&#41;;

	for&#40;y=0;y<272;y++&#41;
	&#123;
		for&#40;x=0;x<480;x++&#41;
		&#123;
			frameBuf&#91;y*512+x&#93;=&#40;x&255&#41;+&#40;&#40;y&255&#41;*256&#41;;
		&#125;
	&#125;
	sceKernelDcacheWritebackAll&#40;&#41;;
	sceDisplaySetMode&#40;0,480,272&#41;;
	sceDisplaySetFrameBuf&#40;frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE&#41;;
	int ret = sceDisplayGetFrameBuf&#40; &buf, &width, &pfm, &vsync &#41;;
	sceKernelDelayThread&#40;1000*2000&#41;;

	pspDebugScreenInit&#40;&#41;;
	pspDebugScreenPrintf&#40;"&#40;%i&#41; %p&#58;%i&#58;%i&#58;%i\n", ret, buf, width, pfm, vsync &#41;;
	
	sceKernelSleepThread&#40;&#41;;
	sceKernelExitGame&#40;&#41;;
	return&#40;0&#41;;
&#125;
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Some more findings:
I wondered why the SetFrameBuf function wouldn't return a error code like all other pspdisplay functions do, so I just tried making it return a value and it seems it really does. Running from PSPLink the function returns 0 (success), while from XMB it returns 0x80000107, which looks like some error code. After some testing from PSPLink, it seems the code denotes a wrong argument, as it is given when the buffer width or pixelformat are different from 512 and 3 (seems like SetFrameBuf only works in 32bit). The error code 0x80000103 means something like "invalid pointer", since this is the return value if you supply a -1 as framebuffer argument (not with null though?) or a null pointer for GetFrameBuf - not the last argument though, see below for explanation.

So from here it was clear that the function was denied because of a wrong argument, but using 512, 3, PSP_DISPLAY_SETBUF_IMMEDIATE didn't change the behaviour in XMB. Now I tried 512, 3, 1 (_NEXT) and tada - it works.
I'm not sure yet, why the call from XMB will resolve PSP_DISPLAY_SETBUF_IMMEDIATE as invalid argument, but that shouldn't be a problem to find out (maybe the call just happens at a problematic time, like during the vblank? At least the same argument is used in PMP Mod and works there).

Now regarding GetFrameBuf:
As the tests showed, the function doesn't care about the last argument being NULL, so it seems the last argument isn't a pointer but rather an immediate value - my guess is the same as in SetFrameBuf, since that would make sense: It denotes when the poll for the frame buffer mode is to be done, immediately or on next vblank.

I'm gonna throw up a patch for this and post it later.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

Raphael - I can't thank you enough for helping me with this!
I was just about ready to tear my hair and/or throw the PSP in the wall, but now it seems like it was one of those rare occasions when a bug actually was NOT caused by my code! :D

It is really strange though, I wonder how all other programs that work from the XMB access the framebuffer (say emulators etc.) Perhaps they always do some kind of render-to-texture and use the video hardware?
But I do find it strange that noone has encountered this before, I thought my example was just about the first thing any programmer would try!
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

Exactly how did your code look when you got it to work, I didn't quite get what you meant by "512, 3, 1 (_NEXT)" ?
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Normally emulators and other applications use the GU to render stuff, which directly draws to VRAM so they don't make use of SetFrameBuf at all. Only exception I know of is PMP Mod and as said, it worked there.

Code: Select all

sceDisplaySetFrameBuf&#40; frameBuf, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_NEXTFRAME &#41;;
This works fine from XMB.

Glad I could help with this, as I just know too well how frustrating PSP development can be sometimes. Hope to see some good stuff from you in the future to make up though ;P
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Probably _IMMEDIATE only works in certain cases. pspDebugScreenInit (which most homebrew calls at startup.. including psplink) uses _NEXTFRAME. Maybe after that _IMMEDIATE is fine, but sticking with _NEXTFRAME seems safe -- as far as I know nobody has ever had a problem with pspDebugScreenInit.
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

Raphael wrote:Glad I could help with this, as I just know too well how frustrating PSP development can be sometimes. Hope to see some good stuff from you in the future to make up though ;P
Aw man, that's some serious pressure you are putting on me!
Well, I'll see what I can come up with... :)
I'm guessing my 15-minutes-of-code-radial-plasma I just finished isn't going to cut it? At least I finished what I set out to do a couple of days ago, only it took like 60 hours total instead of the 30 minutes I originally anticipated... ;)
Sdw
Posts: 29
Joined: Tue Jul 17, 2007 9:50 am

Post by Sdw »

Image

Yay! Triple buffered plasma up and running! And there was much rejoicing... :)
PeterM
Posts: 125
Joined: Sat Dec 31, 2005 7:25 pm
Location: Edinburgh, UK
Contact:

Post by PeterM »

Woo, looks pretty! Thanks for sharing!
http://aaiiee.wordpress.com/

I can no longer do any homebrew PSP development nor discuss PSP specific topics.
Post Reply