sceGuCopyImage problem

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

Moderators: cheriff, TyRaNiD

Post Reply
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

sceGuCopyImage problem

Post by lego »

Hi.

I have a simple program, which must draws dots as on a chess-board in the top left corner of the screen. But instead, it draws two lines.

gu.c:

Code: Select all

#include <malloc.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
/*
#include <GL/gl.h>
#include <GL/glu.h>
*/
#include <math.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspthreadman.h>
#include <pspdisplay.h>
#include <pspnet_inet.h>
#include <pspnet.h>
#include <psputility.h>
#include <pspgu.h>
#include <pspgum.h>
#include <psputils.h>


PSP_MODULE_INFO&#40;"ogl", 0, 3, 5&#41;;
PSP_MAIN_THREAD_ATTR&#40;PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU&#41;;
PSP_HEAP_SIZE_KB&#40;-1024&#41;;
PSP_MAIN_THREAD_STACK_SIZE_KB&#40;1024&#41;;

#define printf pspDebugScreenPrintf

#define BUF_WIDTH &#40;512&#41;
#define SCR_WIDTH &#40;480&#41;
#define SCR_HEIGHT &#40;272&#41;

void *dList;// display List, used by sceGUStart
void *fbp0;// frame buffer


typedef struct &#123;
  unsigned short u, v;
  float x, y, z;
&#125; vertexT_t;

uint32_t __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; tmpt&#91;&#93; = &#123;
  0xff0000ff, 0xff000000, 0xff00ff00, 0xff000000,
  0xff000000, 0xff0000ff, 0xff000000, 0xff00ff00,
  0xff00ff00, 0xff000000, 0xffff0000, 0xff000000,
  0xff000000, 0xff00ff00, 0xff000000, 0xffff0000&#125;;



/*************************************************************
 * EXIT CALLBACK STUFF
 *************************************************************/
/* 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;
  
void initGU&#40; void &#41;
&#123; 
  // Init GU
  sceGuInit&#40;&#41;;
  sceGuStart&#40; GU_DIRECT, dList &#41;;
    
  // Set Buffers
  sceGuDrawBuffer&#40; GU_PSM_8888, fbp0, BUF_WIDTH &#41;;
  sceGuDispBuffer&#40; SCR_WIDTH, SCR_HEIGHT, &#40;void*&#41;0x88000, BUF_WIDTH&#41;;
  sceGuDepthBuffer&#40; &#40;void*&#41;0x110000, BUF_WIDTH&#41;;

  sceGuOffset&#40; 2048 - &#40;SCR_WIDTH/2&#41;, 2048 - &#40;SCR_HEIGHT/2&#41;&#41;;
  sceGuViewport&#40; 2048, 2048, SCR_WIDTH, SCR_HEIGHT&#41;;
  sceGuDepthRange&#40; 65535, 0&#41;;
    
  // Set Render States
  sceGuScissor&#40; 0, 0, SCR_WIDTH, SCR_HEIGHT&#41;;
  sceGuEnable&#40; GU_SCISSOR_TEST &#41;;
  sceGuDepthFunc&#40; GU_GEQUAL &#41;;
  sceGuEnable&#40; GU_DEPTH_TEST &#41;;
  sceGuFrontFace&#40; GU_CCW &#41;;
  sceGuShadeModel&#40; GU_SMOOTH &#41;;
  sceGuEnable&#40; GU_CULL_FACE &#41;;
  sceGuEnable&#40; GU_CLIP_PLANES &#41;;
  sceGuFinish&#40;&#41;;
  sceGuSync&#40;0,0&#41;;
 
  sceDisplayWaitVblankStart&#40;&#41;;
  sceGuDisplay&#40;GU_TRUE&#41;;
  // finish
&#125;

void setupProjection&#40; void &#41;
&#123;
  // setup matrices for the triangle

  sceGumMatrixMode&#40;GU_PROJECTION&#41;;
  sceGumLoadIdentity&#40;&#41;;
  sceGumOrtho&#40;0, 480, 272 , 0, -1, 1&#41;;
  //  sceGumPerspective&#40; 75.0f, 16.0f/9.0f, 0.5f, 1000.0f&#41;;
 
  sceGumMatrixMode&#40;GU_VIEW&#41;;
  sceGumLoadIdentity&#40;&#41;;
 
  sceGuClearColor&#40; GU_COLOR&#40; 0.0f, 0.0f, 1.0f, 0.0f &#41; &#41;; 
  sceGuClearDepth&#40;0&#41;;

  sceGumMatrixMode&#40;GU_MODEL&#41;;
  sceGumLoadIdentity&#40;&#41;;
&#125;

int main&#40;void&#41;
&#123;

  SetupCallbacks&#40;&#41;;
  pspDebugScreenInit&#40;&#41;;

  if &#40; SDL_Init&#40;SDL_INIT_VIDEO&#41; &#41; &#123;
    printf&#40;"Error&#58; %s\n", SDL_GetError&#40;&#41;&#41;;
    return 1;
  &#125;

  dList = memalign&#40;16, 524288&#41;;
  initGU&#40;&#41;;
  setupProjection&#40;&#41;;

  sceGuStart&#40;GU_DIRECT, dList&#41;;
    sceGuClear&#40;GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT&#41;;

    sceGuCopyImage&#40;GU_PSM_8888, 0, 0, 4, 4, 4,
                   &#40;void*&#41;tmpt,
                   1, 1, 512, &#40;void*&#41;0x4000000&#41;;
  sceGuFinish&#40;&#41;;
  sceGuSync&#40;0, 0&#41;;

  sceDisplayWaitVblankStart&#40;&#41;;
  sceGuSwapBuffers&#40;&#41;;

  sceKernelSleepThreadCB&#40;&#41;;

  return 0;
&#125;
Makefile:

Code: Select all

.PHONY&#58; myclean

MOUNTDIR &#58;= /media/usbflash
DESTDIR &#58;= $&#40;MOUNTDIR&#41;/psp/game5xx/CopyImage_test
TARGET = gu.c
OBJS = gu.o
PSP-PREF = $&#40;shell psp-config --psp-prefix&#41;

CFLAGS += -O2 -G0 -Wall -I$&#40;PSP-PREF&#41;/include \
        -I/home/lego/work/psp/pspdev/psp/include/SDL
LDFLAGS &#58;=
LIBS =  -L$&#40;PSP-PREF&#41;/lib -L$&#40;shell psp-config --pspsdk-path&#41;/lib \
        -lconfig \
        -lpng -lz -lSDL_ttf -lSDL -lglut -lGLU -lGL \
        -lfreetype -lpspvfpu -lpspgum -lm -lpspgu -lpspaudio -lpspwlan \
        -lpsphprm -lpsprtc 
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

BUILD_PRX = 1
PSP_FW_VERSION = 500
PSP_LARGE_MEMORY = 1

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = CopyImage test

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak

myclean&#58;
        rm -f *~

install&#58; all
        mount $&#40;MOUNTDIR&#41;
        mkdir -p $&#40;DESTDIR&#41; || true
        cp EBOOT.PBP $&#40;DESTDIR&#41;/
        umount $&#40;MOUNTDIR&#41;

lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

If I change the line:

Code: Select all

sceGuCopyImage&#40;GU_PSM_8888, 0, 0, 4, 4, 4,
                   &#40;void*&#41;tmpt,
                   1, 1, 512, &#40;void*&#41;0x4000000&#41;;
to the following one:

Code: Select all

sceGuCopyImage&#40;GU_PSM_8888, 0, 0, 4, 2, 8,
                   &#40;void*&#41;tmpt,
                   1, 1, 512, &#40;void*&#41;0x4000000&#41;;
it seems that everything drawn correctly.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

From the docs:

Code: Select all

void sceGuCopyImage  	&#40;  	int   	 psm,
		int  	sx,
		int  	sy,
		int  	width,
		int  	height,
		int  	srcw,
		void *  	src,
		int  	dx,
		int  	dy,
		int  	destw,
		void *  	dest	 
	&#41; 			

Image transfer using the GE.

Note&#58;
    Data must be aligned to 1 quad word &#40;16 bytes&#41;

Example&#58; Copy a fullscreen 32-bit image from RAM to VRAM

     sceGuCopyImage&#40;GU_PSM_8888,0,0,480,272,512,pixels,0,0,512,&#40;void*&#41;&#40;&#40;&#40;unsigned int&#41;framebuffer&#41;+0x4000000&#41;&#41;;

Parameters&#58;
    	psm 	- Pixel format for buffer
    	sx 	- Source X
    	sy 	- Source Y
    	width 	- Image width
    	height 	- Image height
    	srcw 	- Source buffer width &#40;block aligned&#41;
    	src 	- Source pointer
    	dx 	- Destination X
    	dy 	- Destination Y
    	destw 	- Destination buffer width &#40;block aligned&#41;
    	dest 	- Destination pointer

References sendCommandi&#40;&#41;.
http://psp.jim.sh/pspsdk-doc/
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

Hm... Possibly, I incorrectly explained.

I have a dots array with 16 elements within. If I use it like a 4x4 array of dots:

Code: Select all

sceGuCopyImage&#40;GU_PSM_8888, 0, 0, 4, 4, 4,
                   &#40;void*&#41;tmpt,
                   1, 1, 512, &#40;void*&#41;0x4000000&#41;; 
I see on the screen something wrong. And if I use it like a 2x4 image in the 2x8 array:

Code: Select all

sceGuCopyImage&#40;GU_PSM_8888, 0, 0, 4, 2, 8,
                   &#40;void*&#41;tmpt,
                   1, 1, 512, &#40;void*&#41;0x4000000&#41;; 
I see right 2x4 image.

But I don't understand what wrong with my 4x4 image :-( ...
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

How about some shots of what the "wrong" thing looks like. Your description doesn't really help.
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

Sorry :-).

I couldn't make photos of a PSP, so I made shots by hands. My background is blue.

This is what I want (4x4):

Image

This is what I get (wrong 4x4 image):
Image

This is right 2x4 image:
Image


So, I don't understand why my 4x4 image wrong and at the same time my 2x4 image in the 2x8 buffer right.

Thanks for replies.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Your init doesn't seem very complete. Here's the one in the "standard" graphics.c:

Code: Select all

	sceGuInit&#40;&#41;;

	guStart&#40;&#41;;
	sceGuDrawBuffer&#40;GU_PSM_8888, &#40;void*&#41;FRAMEBUFFER_SIZE, PSP_LINE_SIZE&#41;;
	sceGuDispBuffer&#40;SCREEN_WIDTH, SCREEN_HEIGHT, &#40;void*&#41;0, PSP_LINE_SIZE&#41;;
	sceGuClear&#40;GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT&#41;;
	sceGuDepthBuffer&#40;&#40;void*&#41; &#40;FRAMEBUFFER_SIZE*2&#41;, PSP_LINE_SIZE&#41;;
	sceGuOffset&#40;2048 - &#40;SCREEN_WIDTH / 2&#41;, 2048 - &#40;SCREEN_HEIGHT / 2&#41;&#41;;
	sceGuViewport&#40;2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
	sceGuDepthRange&#40;0xc350, 0x2710&#41;;
	sceGuScissor&#40;0, 0, SCREEN_WIDTH, SCREEN_HEIGHT&#41;;
	sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
	sceGuAlphaFunc&#40;GU_GREATER, 0, 0xff&#41;;
	sceGuEnable&#40;GU_ALPHA_TEST&#41;;
	sceGuDepthFunc&#40;GU_GEQUAL&#41;;
	sceGuEnable&#40;GU_DEPTH_TEST&#41;;
	sceGuFrontFace&#40;GU_CW&#41;;
	sceGuShadeModel&#40;GU_SMOOTH&#41;;
	sceGuEnable&#40;GU_CULL_FACE&#41;;
	sceGuEnable&#40;GU_TEXTURE_2D&#41;;
	sceGuEnable&#40;GU_CLIP_PLANES&#41;;
	sceGuTexMode&#40;GU_PSM_8888, 0, 0, 0&#41;;
	sceGuTexFunc&#40;GU_TFX_REPLACE, GU_TCC_RGBA&#41;;
	sceGuTexFilter&#40;GU_NEAREST, GU_NEAREST&#41;;
	sceGuAmbientColor&#40;0xffffffff&#41;;
	sceGuEnable&#40;GU_BLEND&#41;;
	sceGuBlendFunc&#40;GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0&#41;;
	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0, 0&#41;;

	sceDisplayWaitVblankStart&#40;&#41;;
	sceGuDisplay&#40;GU_TRUE&#41;;
	initialized = 1;
You also seem to have an undefined variable (fbp0).
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

fbp0 is initialized to 0 by default, like an any global variable which is not initialized explicitly.

My init function is lacking of a texture stuff, but I don't use textures in this code. So, I think my init function is similar to your. In any case I will try to use your init function.

J.F., does my code work on your psp in the same manner?
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Haven't tried it. In fact, I don't even have the psp toolchain setup on this computer (yet).

Have you tried some of the existing samples to see if you're even making properly working executables?
a_noob
Posts: 97
Joined: Sun Sep 17, 2006 8:33 am
Location: _start: jr 0xDEADBEEF

Post by a_noob »

lego wrote:fbp0 is initialized to 0 by default, like an any global variable which is not initialized explicitly.

My init function is lacking of a texture stuff, but I don't use textures in this code. So, I think my init function is similar to your. In any case I will try to use your init function.

J.F., does my code work on your psp in the same manner?
Eww, worst assumption ever! NEVER EVER assume a pointer is NULL, or valid. That is one of the big problems that can occur in pointer programming.

as for the gu setup you can use

Code: Select all

#define BUF_WIDTH &#40;512&#41;
#define SCR_WIDTH &#40;480&#41;
#define SCR_HEIGHT &#40;272&#41;
#define FRAME_SIZE &#40;BUF_WIDTH * SCR_HEIGHT * 4&#41;

void initGU&#40;&#41;&#123;
	
	sceGuInit&#40;&#41;;
	
	sceGuStart&#40;GU_DIRECT,list&#41;;

	sceGuDrawBuffer&#40;GU_PSM_8888,&#40;void*&#41;0,BUF_WIDTH&#41;;
	sceGuDispBuffer&#40;SCR_WIDTH,SCR_HEIGHT,&#40;void*&#41;FRAME_SIZE,BUF_WIDTH&#41;;
	sceGuDepthBuffer&#40;&#40;void*&#41;&#40;FRAME_SIZE*2&#41;,BUF_WIDTH&#41;;

	sceGuOffset&#40;2048 - &#40;SCR_WIDTH/2&#41;,2048 - &#40;SCR_HEIGHT/2&#41;&#41;;
	sceGuViewport&#40;2048,2048,SCR_WIDTH,SCR_HEIGHT&#41;;
	sceGuDepthRange&#40;65535,0&#41;;
	sceGuScissor&#40;0,0,SCR_WIDTH,SCR_HEIGHT&#41;;
	sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
	sceGuFrontFace&#40;GU_CW&#41;;

	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;
	sceGuDisplay&#40;1&#41;;
&#125;
this would be one of your more minimalistic context initializations of course.

Code: Select all

.øOº'ºOø.
'ºOo.oOº'
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

J.F. wrote:Haven't tried it. In fact, I don't even have the psp toolchain setup on this computer (yet).

Have you tried some of the existing samples to see if you're even making properly working executables?
Yes. I run some gu examples. It worked fine.
lego
Posts: 43
Joined: Fri Oct 17, 2008 1:09 am

Post by lego »

a_noob wrote:
lego wrote:fbp0 is initialized to 0 by default, like an any global variable which is not initialized explicitly.

My init function is lacking of a texture stuff, but I don't use textures in this code. So, I think my init function is similar to your. In any case I will try to use your init function.

J.F., does my code work on your psp in the same manner?
Eww, worst assumption ever! NEVER EVER assume a pointer is NULL, or valid. That is one of the big problems that can occur in pointer programming.
Ok, but what about C standard :-)? Which say that every _global_ variable non initialized by user initialize to 0 by default.

I tried your init function. It gave me the same result :-(.
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

lego wrote:
a_noob wrote:Eww, worst assumption ever! NEVER EVER assume a pointer is NULL, or valid. That is one of the big problems that can occur in pointer programming.
Ok, but what about C standard :-)? Which say that every _global_ variable non initialized by user initialize to 0 by default.
a_noob beat me to it, but I'd have said the same thing, because not every C compiler is 100% compatible with the standard. And in any case it's just good practice to initialize all variables - especially pointers - to a known value so that you don't need to rely on a default.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

That would be a glaring fuck up of a C compiler if it didn't do that.
Jim
Criptych
Posts: 64
Joined: Sat Sep 12, 2009 5:18 am

Post by Criptych »

Maybe so, but it's still good practice to initialize explicitly. Even if the compiler does give global variables some default value, say you decide to make one a static local instead - suddenly it doesn't have that default, and you may end up with a pretty sneaky bug.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

The compiler doesn't clear uninitialized variables... ever. It's not up to the compiler. Uninitialized variables merely go into the BSS. It's up to the start code linked to the head of the program to clear the BSS segment. Look in crt0 or crt1 files for that code. I've seen some that rely on the memory allocator to provide a zeroed block of memory for the BSS, and don't clear it themselves. My own start code specifically clears the BSS - it may not be needed, but it's good practice, and since this occurs at start up, it's not going to slow the program.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

J.F. wrote:The compiler doesn't clear uninitialized variables... ever. It's not up to the compiler. Uninitialized variables merely go into the BSS. It's up to the start code linked to the head of the program to clear the BSS segment. Look in crt0 or crt1 files for that code. I've seen some that rely on the memory allocator to provide a zeroed block of memory for the BSS, and don't clear it themselves. My own start code specifically clears the BSS - it may not be needed, but it's good practice, and since this occurs at start up, it's not going to slow the program.
But if you declare a variable at compile time, say int x; it's put in the binary as FF FF FF FF? Are ALL variables hardcoded like this or does it intelligently malloc uninitialized arrays etc to save space? I don't think the PSP toolchain does this, but on other platforms?
a_noob
Posts: 97
Joined: Sun Sep 17, 2006 8:33 am
Location: _start: jr 0xDEADBEEF

Post by a_noob »

Wether or not the compiler or system does it, adding = 0 isnt hard, and can avoid these problems ;D. Especially with pointers, assumptions can be bad. Wether it's 0 or not by default is not the case. Setting it your self is always a better programming practice because then you know that it is always going to be the value you need it to be.

Code: Select all

.øOº'ºOø.
'ºOo.oOº'
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Torch wrote:
J.F. wrote:The compiler doesn't clear uninitialized variables... ever. It's not up to the compiler. Uninitialized variables merely go into the BSS. It's up to the start code linked to the head of the program to clear the BSS segment. Look in crt0 or crt1 files for that code. I've seen some that rely on the memory allocator to provide a zeroed block of memory for the BSS, and don't clear it themselves. My own start code specifically clears the BSS - it may not be needed, but it's good practice, and since this occurs at start up, it's not going to slow the program.
But if you declare a variable at compile time, say int x; it's put in the binary as FF FF FF FF? Are ALL variables hardcoded like this or does it intelligently malloc uninitialized arrays etc to save space? I don't think the PSP toolchain does this, but on other platforms?
Uninitialized variables are merely an offset in the BSS. There's nothing like "placeholder" data. Broadly put, most executable formats are like this:

code and constant data section: the actual code and data is stored along with offsets for functions and variables
initialized data section: the actual data is stored along with offsets for the variables
uninitialized data section: only offsets for the variables are here

It's up to either the OS loader or the start code in the executable to set the uninitialized data are to a preset value, and some OSes/start code don't bother. Old C implementations specifically mentioned that you could not count on uninitialized variables having a set value. They would be whatever happened to be in the memory location when the file was loaded.
Post Reply