Hello... first post here although I've been spending quite a good time reading the forum, and also searched for answers for my problem (not managing to solve it). I've also done some homebrew for other platforms and am pretty good in C (and even ARM assembly).
I'm trying to port one of my apps from another platform to the PSP but I'm having trouble with the display. I've borrowed the display code from s9xpsp_tyl but it's not working right.
The original resolution is 320x240 and for now I just want to draw a 320x240 image from a buffer in RAM to the PSP screen. The s9xpsp_tyl code is basically the same from the Blit sample in the SDK, drawing vertical stripe sprites with a width of 64 each and assigning the image buffer to a texture.
I know the texture image buffer width must be block-aligned to 512 so although my image is 320x240x16bits I set the buffer to 512x240 and modified the app code accordingly.
Now, instead of the B&W text that should have appeared in the screen, I have lots of "cut" horizontal lines--seems like a width alignment problem. Sometimes I change something and it actually displays only the first line...
Here's my drawing code. Note that I call the init and sutdown functions accordingly.
Code: Select all
unsigned int __attribute__((aligned(64))) list[262144*4];
struct Vertex
{
unsigned short u, v;
short x, y, z;
};
unsigned short __attribute__((aligned(16))) internal_screen[512*240*2];
int swap_buf;
#define SLICE_SIZE 64 // change this to experiment with different page-cache sizes
#define FRAMESIZE 0x44000 //in byte (512*272*2)
#define RELEASE
void blit_reinit(void){
sceGuStart(GU_DIRECT,list);
swap_buf=0;
sceGuDrawBuffer(GU_PSM_5650,(void*)0,512);
sceGuDispBuffer(480,272,(void*)FRAMESIZE,512);
sceGuOffset(2048 - (480/2),2048 - (272/2));
sceGuViewport(2048,2048,480,272);
/*sceGuDepthBuffer((void*)(FRAMESIZE*2),256);
sceGuEnable(GU_DEPTH_TEST);
sceGuDepthRange(256,0);
sceGuDepthOffset(0);
sceGuDepthFunc(GU_GREATER);*/
sceGuFinish();
sceGuSync(0,0);
sceGuStart(GU_DIRECT,list);
/*sceGuEnable(GU_SCISSOR_TEST);
sceGuScissor(0,0,256,240);*/
sceGuEnable(GU_TEXTURE_2D);
sceGuTexMode(GU_PSM_5650,0,0,0); // 8-bit image
sceGuTexFilter(GU_NEAREST,GU_NEAREST);
sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGBA);
sceGuTexScale(1.0f/512.0f,1.0f/512.0f);
sceGuTexOffset(0,0);
//sceGuEnable(GU_ALPHA_TEST);
//sceGuAlphaFunc(GU_EQUAL,0,0x1);
sceGuClutMode(GU_PSM_5650,0,255,0);
sceGuClearColor(0);
sceGuClear(GU_COLOR_BUFFER_BIT);
sceGuFinish();
sceGuSync(0,0);
sceDisplayWaitVblankStart();
//cache stuff
// tile_reset_cache();
}
void blit_init(void){
//cache stuff
// tile_init_cache();
// setup GU
sceGuInit();
sceGuDisplay(1);
blit_reinit();
}
void guClear(int dst_w,int dst_h){
unsigned int cx,cy;
sceGuStart(GU_DIRECT,list);
sceGuEnable(GU_SCISSOR_TEST);
#ifdef RELEASE
cx=(480-dst_w)/2;
cy=(272-dst_h)/2;
#else
cx=cy=0;
#endif
sceGuScissor(cx,cy,cx+dst_w,cy+dst_h);
sceGuClearColor(0);
sceGuClear(GU_COLOR_BUFFER_BIT);
sceGuFinish();
sceGuSync(0,0);
}
#define os9x_screenWidth 320
#define os9x_screenHeight 240
#define os9x_screenLeft 0
#define os9x_screenTop 0
void guDrawBuffer(unsigned short* video_buffer,int src_w,int src_h,int src_pitch,int dst_w,int dst_h){
unsigned int j,cx,cy;
struct Vertex* vertices,*vertices_ptr;
sceGuStart(GU_DIRECT,list);
/*sceGuOffset(2048 - (480/2),2048 - (272/2));
sceGuViewport(2048,2048,480,272);*/
sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGB);
sceGuDrawBufferList(GU_PSM_5650,(void*)(512*272*2*swap_buf),512);
sceGuEnable(GU_SCISSOR_TEST);
//sceGuDisable(GU_SCISSOR_TEST);
#ifdef RELEASE
cx=(480-dst_w)/2;
cy=(272-dst_h)/2;
#else
cx=cy=0;
#endif
sceGuScissor(cx,cy,cx+dst_w,cy+dst_h);
sceGuDisable(GU_DEPTH_TEST);
sceGuDisable(GU_ALPHA_TEST);
sceGuTexMode(GU_PSM_5650,0,0,0);
sceKernelDcacheWritebackInvalidateAll();
sceGuTexImage(0,src_w,src_w,src_pitch,video_buffer);
sceGuTexFunc(GU_TFX_REPLACE,0);
/*if (os9x_smoothing) sceGuTexFilter(GU_LINEAR,GU_LINEAR);
else*/ sceGuTexFilter(GU_NEAREST,GU_NEAREST);
sceGuTexScale(1.0f/src_w,1.0f/src_w); // scale UVs to 0..1
sceGuTexOffset(0,0);
sceGuTexWrap(GU_CLAMP,GU_CLAMP);
vertices = (struct Vertex*)sceGuGetMemory(2*(1+src_w/SLICE_SIZE) * sizeof(struct Vertex));
vertices_ptr=vertices;
for (j = 0; (j+SLICE_SIZE) < src_w; j = j+SLICE_SIZE) {
vertices_ptr[0].u = j; vertices_ptr[0].v = (240-src_h)/2;
vertices_ptr[0].x = cx+j*(dst_w+os9x_screenWidth)/src_w+os9x_screenLeft; vertices_ptr[0].y = cy+0+os9x_screenTop; vertices_ptr[0].z = 0;
vertices_ptr[1].u = j+SLICE_SIZE; vertices_ptr[1].v = src_h-(240-src_h)/2;
vertices_ptr[1].x = cx+(j+SLICE_SIZE)*(dst_w+os9x_screenWidth)/src_w+os9x_screenLeft; vertices_ptr[1].y = cy+dst_h+os9x_screenHeight+os9x_screenTop; vertices_ptr[1].z = 0;
vertices_ptr+=2;
}
if (j<src_w){
vertices_ptr[0].u = j; vertices_ptr[0].v = (240-src_h)/2;
vertices_ptr[0].x = cx+j*(dst_w+os9x_screenWidth)/src_w+os9x_screenLeft; vertices_ptr[0].y = cy+0+os9x_screenTop; vertices_ptr[0].z = 0;
vertices_ptr[1].u = src_w; vertices_ptr[1].v = src_h-(240-src_h)/2;
vertices_ptr[1].x = cx+(dst_w+os9x_screenWidth)+os9x_screenLeft; vertices_ptr[1].y = cy+dst_h+os9x_screenHeight+os9x_screenTop; vertices_ptr[1].z = 0;
vertices_ptr+=2;
}
sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,vertices_ptr-vertices,0,vertices);
/*vertices = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex));
vertices[0].u = 0; vertices[0].v = 0;
vertices[0].x = cx; vertices[0].y = cy; vertices[0].z = 0;
vertices[1].u = 320; vertices[1].v = 240;
vertices[1].x = cx+320; vertices[1].y = cy+240; vertices[1].z = 0;
sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_VERTEX_16BIT|GU_TRANSFORM_2D,2,0,vertices);*/
sceGuFinish();
sceGuSync(0,0);
sceDisplayWaitVblankStart(); //or not?
sceGuSwapBuffers();
swap_buf^=1;
//pg_drawframe=swap_buf^1;
}
void blit_shutdown(){
sceGuTerm();
}
void video_flip(void) //called from inside the app
{
guDrawBuffer(internal_screen,320,240,512,320,240);
}