Please help. I can't use Ram more then 12MB

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

Moderators: cheriff, TyRaNiD

Post Reply
leenoi
Posts: 9
Joined: Fri Jul 08, 2005 4:35 pm

Please help. I can't use Ram more then 12MB

Post by leenoi »

I check my ram before I load png picture it have free space 22.29MB

so I try to load PNG pic (dimansion 3200 x 1200) 3200*1200*4 = 15.34MB
it crash. when I load it.

but when I change to anothor pic (3200 x 640) 3200*640*4= 8.19MB
it work.

you can take a look my load function was call from main()


//***** chkram and load pic to ram ****
fbefor=GetRAMFree();
if ((ImageBG=LoadPng("bg.png",GU_PSM_4444,1,0)) != NULL)png = 1;
fafter=GetRAMFree();
//**********************



Can any one help me please. this is my code.. Thank you very much
PS. all code I learn and grab from this board. Thank you PSPDEV Board.

Code: Select all


#include <pspkernel.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <png.h>
#include <zlib.h>
#include <pspctrl.h>
#include <pspgu.h>
#include <psprtc.h>
PSP_MODULE_INFO&#40;"ImageViewer", 0, 1, 1&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER&#41;;
static unsigned int __attribute__&#40;&#40;aligned&#40;16&#41;&#41;&#41; list&#91;262144&#93;;

#define printf pspDebugScreenPrintf

#define BUF_WIDTH &#40;512&#41;
#define SCR_WIDTH &#40;512&#41;
#define SCR_HEIGHT &#40;256&#41;

typedef u32 Color;
#define A&#40;color&#41; &#40;&#40;u8&#41;&#40;color >> 24 & 0xFF&#41;&#41;
#define B&#40;color&#41; &#40;&#40;u8&#41;&#40;color >> 16 & 0xFF&#41;&#41;
#define G&#40;color&#41; &#40;&#40;u8&#41;&#40;color >> 8 & 0xFF&#41;&#41;
#define R&#40;color&#41; &#40;&#40;u8&#41;&#40;color & 0xFF&#41;&#41;

typedef struct
&#123;
        int textureWidth;  // the real width of data, 2^n with n>=0
        int textureHeight;  // the real height of data, 2^n with n>=0
        int imageWidth;  // the image width
        int imageHeight;
        Color * data;
&#125; Image;


static int exitRequest = 0;
static unsigned int staticOffset = 0;

static unsigned int getMemorySize&#40;unsigned int width, unsigned int height, unsigned int psm&#41;
&#123;
   switch &#40;psm&#41;
   &#123;
      case GU_PSM_T4&#58;
         return &#40;width * height&#41; >> 1;

      case GU_PSM_T8&#58;
         return width * height;

      case GU_PSM_5650&#58;
      case GU_PSM_5551&#58;
      case GU_PSM_4444&#58;
      case GU_PSM_T16&#58;
         return 2 * width * height;

      case GU_PSM_8888&#58;
      case GU_PSM_T32&#58;
         return 4 * width * height;

      default&#58;
         return 0;
   &#125;
&#125;

void* getStaticVramBuffer&#40;unsigned int width, unsigned int height, unsigned int psm&#41;
&#123;
   unsigned int memSize = getMemorySize&#40;width,height,psm&#41;;
   void* result = &#40;void*&#41;staticOffset;
   staticOffset += memSize;

   return result;
&#125;
int exit_callback&#40;int arg1, int arg2, void *common&#41; &#123;
          sceKernelExitGame&#40;&#41;;
          return 0;
&#125;
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;
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 user_warning_fn&#40;png_structp png_ptr, png_const_charp warning_msg&#41;
&#123;
   // ignore PNG warnings
&#125;

int PowerOfTwo&#40;int value&#41;
&#123;
int poweroftwo = 1;
    while &#40;poweroftwo < value &#41;&#123;
      poweroftwo <<= 1;
   &#125;
   return poweroftwo;
&#125;

unsigned short Color8888To5551&#40;unsigned int Color32&#41;
&#123;
unsigned char Red = &#40;Color32&#41;;
unsigned short Red16 = Red>>3;
unsigned char Green = &#40;Color32>>8&#41;;
unsigned short Green16 = &#40;Green>>3&#41;<<5;
unsigned char Blue = &#40;Color32>>16&#41;;
unsigned short Blue16 = &#40;Blue>>3&#41;<<10;
unsigned char Alpha = &#40;Color32>>24&#41;;
unsigned short Alpha16 = &#40;Alpha>>3&#41;<<15;
unsigned short Color16 = Red16 | Green16 | Blue16 | Alpha16;
return Color16;
&#125;

unsigned short Color8888To4444&#40;unsigned int Color32&#41;
&#123;
unsigned char Red = &#40;Color32&#41;;
unsigned short Red16 = Red>>4;
unsigned char Green = &#40;Color32>>8&#41;;
unsigned short Green16 = &#40;Green>>4&#41;<<4;
unsigned char Blue = &#40;Color32>>16&#41;;
unsigned short Blue16 = &#40;Blue>>4&#41;<<8;
unsigned char Alpha = &#40;Color32>>24&#41;;
unsigned short Alpha16 = &#40;Alpha>>4&#41;<<12;
unsigned short Color16 = Red16 | Green16 | Blue16 | Alpha16;
return Color16;
&#125;

unsigned short Color8888To5650&#40;unsigned int Color32&#41;
&#123;
unsigned char Red = &#40;Color32&#41;;
unsigned short Red16 = Red>>3;
unsigned char Green = &#40;Color32>>8&#41;;
unsigned short Green16 = &#40;Green>>2&#41;<<5;
unsigned char Blue = &#40;Color32>>16&#41;;
unsigned short Blue16 = &#40;Blue>>3&#41;<<11;
//unsigned char Alpha = &#40;Color32>>24&#41;;
unsigned short Color16 = Red16 | Green16 | Blue16;
return Color16;
&#125;


void swizzle_fast&#40;u8* out, const u8* in, unsigned int width, unsigned int height&#41;
&#123;
   unsigned int blockx, blocky;
   unsigned int j;
 
   unsigned int width_blocks = &#40;width / 16&#41;;
   unsigned int height_blocks = &#40;height / 8&#41;;
 
   unsigned int src_pitch = &#40;width-16&#41;/4;
   unsigned int src_row = width * 8;
 
   const u8* ysrc = in;
   u32* dst = &#40;u32*&#41;out;
 
   for &#40;blocky = 0; blocky < height_blocks; ++blocky&#41;
   &#123;
      const u8* xsrc = ysrc;
      for &#40;blockx = 0; blockx < width_blocks; ++blockx&#41;
      &#123;
         const u32* src = &#40;u32*&#41;xsrc;
         for &#40;j = 0; j < 8; ++j&#41;
         &#123;
            *&#40;dst++&#41; = *&#40;src++&#41;;
            *&#40;dst++&#41; = *&#40;src++&#41;;
            *&#40;dst++&#41; = *&#40;src++&#41;;
            *&#40;dst++&#41; = *&#40;src++&#41;;
            src += src_pitch;
         &#125;
         xsrc += 16;
     &#125;
     ysrc += src_row;
   &#125;
&#125;

Image* LoadPng&#40;const char* filename,int ColorMode,int Swizzle,int Vram&#41;
&#123;
    unsigned short *Buffer;
   unsigned short *swizzled_pixels = NULL;
   Image *Image1;
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type, x, y;
   unsigned int* line;
   FILE *fp;
   int OutBytesPerPixel;
   int imageWidth = 0;
   int imageHeight = 0;
   if&#40;ColorMode == GU_PSM_4444 || ColorMode == GU_PSM_5650 || ColorMode == GU_PSM_5551&#41;OutBytesPerPixel = 2;
   else OutBytesPerPixel = 4;

   if &#40;&#40;fp = fopen&#40;filename, "rb"&#41;&#41; == NULL&#41;&#123;
            printf&#40;"Can't open file %s\n",filename&#41;;
            return NULL;
    &#125;
   png_ptr = png_create_read_struct&#40;PNG_LIBPNG_VER_STRING, NULL, NULL, NULL&#41;;
   if &#40;png_ptr == NULL&#41; &#123;
      fclose&#40;fp&#41;;
      return NULL;
   &#125;
   png_set_error_fn&#40;png_ptr, &#40;png_voidp&#41; NULL, &#40;png_error_ptr&#41; NULL, user_warning_fn&#41;;
   info_ptr = png_create_info_struct&#40;png_ptr&#41;;
   if &#40;info_ptr == NULL&#41; &#123;
      fclose&#40;fp&#41;;
      png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
      return NULL;
   &#125;
   png_init_io&#40;png_ptr, fp&#41;;
   png_set_sig_bytes&#40;png_ptr, sig_read&#41;;
   png_read_info&#40;png_ptr, info_ptr&#41;;
   png_get_IHDR&#40;png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL&#41;;
   png_set_strip_16&#40;png_ptr&#41;;
   png_set_packing&#40;png_ptr&#41;;
   if &#40;color_type == PNG_COLOR_TYPE_PALETTE&#41; png_set_palette_to_rgb&#40;png_ptr&#41;;
   if &#40;color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8&#41; png_set_gray_1_2_4_to_8&#40;png_ptr&#41;;
   if &#40;png_get_valid&#40;png_ptr, info_ptr, PNG_INFO_tRNS&#41;&#41; png_set_tRNS_to_alpha&#40;png_ptr&#41;;
   png_set_filler&#40;png_ptr, 0xff, PNG_FILLER_AFTER&#41;;
   line = &#40;unsigned int*&#41; malloc&#40;width * 4&#41;;
   if &#40;!line&#41; &#123;
      fclose&#40;fp&#41;;
      png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
      return NULL;
   &#125;
   imageWidth = PowerOfTwo&#40;width&#41;;
   imageHeight = PowerOfTwo&#40;height&#41;;
   Buffer = memalign&#40;16,imageWidth*imageHeight*OutBytesPerPixel&#41;;
   for &#40;y = 0; y < height; y++&#41; &#123;
      png_read_row&#40;png_ptr, &#40;unsigned char*&#41; line, png_bytep_NULL&#41;;
      for &#40;x = 0; x < width; x++&#41; &#123;
         unsigned int *Buffer32 = &#40;unsigned int*&#41;Buffer;
         unsigned int color32 = line&#91;x&#93;;
         unsigned short color16;
         //printf&#40;"%d&#58;%d %u ",y,x,color32&#41;;
         if&#40;ColorMode == GU_PSM_5551&#41;&#123;
            color16 = Color8888To5551&#40;color32&#41;;
            Buffer&#91;y*imageWidth+x&#93; = color16;
         &#125;
         else if&#40;ColorMode == GU_PSM_4444&#41;&#123;
            color16 = Color8888To4444&#40;color32&#41;;
            Buffer&#91;y*imageWidth+x&#93; = color16;
         &#125;
         else if&#40;ColorMode == GU_PSM_5650&#41;&#123;
            color16 = Color8888To5650&#40;color32&#41;;
            Buffer&#91;y*imageWidth+x&#93; = color16;
         &#125;
         else &#123;
            Buffer32&#91;y*imageWidth+x&#93; = color32;
         &#125;
         //printf&#40;"%u \n",Buffer&#91;y*width+x&#93;&#41;;
         //printf&#40;"%u \n",color16&#41;;
      &#125;
   &#125;
   free&#40;line&#41;;
   png_read_end&#40;png_ptr, info_ptr&#41;;
   png_destroy_read_struct&#40;&png_ptr, &info_ptr, png_infopp_NULL&#41;;
   fclose&#40;fp&#41;;   

Image1 = malloc&#40;sizeof&#40;Image&#41;&#41;;

Image1->textureWidth = width;
Image1->textureHeight = height;
Image1->imageWidth = imageWidth;
Image1->imageHeight = imageHeight;

swizzled_pixels = memalign&#40;16,Image1->imageHeight*Image1->imageWidth*OutBytesPerPixel&#41;;
swizzle_fast&#40;&#40;u8*&#41;swizzled_pixels,&#40;const u8*&#41;Buffer,Image1->imageWidth*OutBytesPerPixel,Image1->imageHeight&#41;;
// 512*2 because swizzle operates in bytes, and each pixel in a 16-bit texture is 2 bytes
sceKernelDcacheWritebackAll&#40;&#41;;

Image1->data = swizzled_pixels;
free&#40;Buffer&#41;;

//sceGuFinish&#40;&#41;;
//sceGuSync&#40;0,0&#41;;

return Image1;   
&#125;

float GetRAMFree&#40;&#41;&#123; 
   float ram; 
//a hacky little way to estimate RAM left to use    
int ramAdd&#91;320&#93;; 
int i=0; 
for&#40;i=0;i<320;i++&#41;&#123; 
ramAdd&#91;i&#93; = malloc&#40;100000&#41;; 
if&#40;ramAdd&#91;i&#93; == 0&#41;&#123;//malloc failed 
ram = &#40;float&#41;i; 
int z=0; 
for&#40;z=0;z<i;z++&#41;&#123; 
free&#40;ramAdd&#91;z&#93;&#41;; 
&#125; 
break; 
&#125; 
&#125; 
return ram/10; 
&#125;

int main&#40;int argc, char* argv&#91;&#93;&#41;
&#123;
   unsigned int i = 0,png = 0;
	float fbefor,fafter;
   pspDebugScreenInit&#40;&#41;;
   SetupCallbacks&#40;&#41;;

   Image * ImageBG;

	sceGuInit&#40;&#41;;

	void* fbp0 = getStaticVramBuffer&#40;BUF_WIDTH,SCR_HEIGHT,GU_PSM_8888&#41;;
	void* fbp1 = getStaticVramBuffer&#40;BUF_WIDTH,SCR_HEIGHT,GU_PSM_8888&#41;;
	void* zbp = getStaticVramBuffer&#40;BUF_WIDTH,SCR_HEIGHT,GU_PSM_4444&#41;;
	sceGuStart&#40;GU_DIRECT,list&#41;;
	sceGuDrawBuffer&#40;GU_PSM_8888,fbp0,BUF_WIDTH&#41;;
	sceGuDispBuffer&#40;SCR_WIDTH,SCR_HEIGHT,fbp1,BUF_WIDTH&#41;;
	sceGuDepthBuffer&#40;zbp,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;0xc350,0x2710&#41;;
	sceGuScissor&#40;0,0,SCR_WIDTH,SCR_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;;
	sceGuFinish&#40;&#41;;
	sceGuSync&#40;0,0&#41;;

	sceDisplayWaitVblankStart&#40;&#41;;
	sceGuDisplay&#40;GU_TRUE&#41;;
//***** chkram  and load pic to ram ****
	fbefor=GetRAMFree&#40;&#41;;
	if &#40;&#40;ImageBG=LoadPng&#40;"bg.png",GU_PSM_4444,1,0&#41;&#41; != NULL&#41;png = 1;
	fafter=GetRAMFree&#40;&#41;;
//**********************
	
	  pspDebugScreenSetOffset&#40;&#40;int&#41;fbp0&#41;;
      pspDebugScreenSetXY&#40;10,10&#41;;
	  pspDebugScreenPrintf&#40;"ram befor load = %f\n",fbefor&#41;;

      pspDebugScreenSetXY&#40;10,100&#41;;
	  pspDebugScreenPrintf&#40;"ram after load = %f\n",fafter&#41;;
      sceGuFinish&#40;&#41;;
      sceGuSync&#40;0,0&#41;;

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

sceKernelSleepThread&#40;&#41;;
sceGuTerm&#40;&#41;;

return 0;

&#125;
Last edited by leenoi on Wed Jan 31, 2007 10:21 pm, edited 1 time in total.
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

Please use code tags in the future to encapsulate source.
Regarding your problem, take a look at the png loader and how it changes the image width and height to the next power of two.
So trying to load a 3200x1200 image will end up allocating memory for 4096x2048 pixels ~ 33MB. Too much for the PSP.
The other image will end up with 4096x1024, so that's still roughly 16MB.
Reconsider that code. Such large images anyway can't be used as GU textures directly, so you can load them with their real dimensions.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
nofx_sk8
Posts: 1
Joined: Sat Nov 04, 2006 11:51 pm

Post by nofx_sk8 »

Also you might want to take a look at this
http://forums.ps2dev.org/viewtopic.php? ... highlight=
leenoi
Posts: 9
Joined: Fri Jul 08, 2005 4:35 pm

Post by leenoi »

Raphael wrote:Please use code tags in the future to encapsulate source.
Regarding your problem, take a look at the png loader and how it changes the image width and height to the next power of two.
So trying to load a 3200x1200 image will end up allocating memory for 4096x2048 pixels ~ 33MB. Too much for the PSP.
The other image will end up with 4096x1024, so that's still roughly 16MB.
Reconsider that code. Such large images anyway can't be used as GU textures directly, so you can load them with their real dimensions.
Thank you Raphael , Yeah it's my mistake , it work right now. Thank you very much

nofx_sk8 Thank you for your reply , I'm interest those extra 4 MB too. but I'm new in this SDK , can you give me some simple code I try to modify my code like this

Code: Select all

//***** chkram  and load pic to ram ****
	int size;
	fbefor=GetRAMFree&#40;&#41;;
	sceKernelVolatileMemLock&#40;0,&ImageBG, &size&#41;;
	if &#40;&#40;ImageBG=LoadPng&#40;"bg.png",GU_PSM_4444,1,0&#41;&#41; != NULL&#41;png = 1;
	fafter=GetRAMFree&#40;&#41;;
//**********************
Post Reply