Code: Select all
#include <pspkernel.h>
unsigned short __attribute__((aligned(16))) pixels[SPRITE_HEIGHT*SPRITE_WIDTH];
unsigned short __attribute__((aligned(16))) swizzled_pixels[SPRITE_HEIGHT*SPRITE_WIDTH];
unsigned short *pixels2;
struct Vertex
{
	unsigned short u, v;
	unsigned short color;
	float x, y, z;
};
void advancedBlit(float sx, float sy, int sw, int sh, float dx, float dy)
{
	int start, end;
	// blit maximizing the use of the texture-cache
	/*
		the texture cache is 8kB. It is used in the following fashions:
		4-bit: 128x128
		8-bit: 128x64
		16-bit: 64x64
		32-bit: 64x32
		swizzling your input will give more than 100% increase in speed
	*/
	for (start = sx, end = sx+sw; start < end; start += SLICE_SIZE, dx += SLICE_SIZE)
	{
		struct Vertex* vertices = (struct Vertex*)sceGuGetMemory(2 * sizeof(struct Vertex));
		int width = (start + SLICE_SIZE) < end ? SLICE_SIZE : end-start;
		vertices[0].u = start; vertices[0].v = sy;
		vertices[0].color = 0;
		vertices[0].x = dx; vertices[0].y = dy; vertices[0].z = 0;
		vertices[1].u = start + width; vertices[1].v = sy + sh;
		vertices[1].color = 0;
		vertices[1].x = dx + width; vertices[1].y = dy + sh; vertices[1].z = 0;
		sceGuDrawArray(GU_SPRITES,GU_TEXTURE_16BIT|GU_COLOR_5551|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,vertices);
	}
}
void swizzle_fast(u8* out, const u8* in, unsigned int width, unsigned int height)
{
   unsigned int blockx, blocky;
   unsigned int j;
 
   unsigned int width_blocks = (width / 16);
   unsigned int height_blocks = (height / 8);
 
   unsigned int src_pitch = (width-16)/4;
   unsigned int src_row = width * 8;
 
   const u8* ysrc = in;
   u32* dst = (u32*)out;
 
   for (blocky = 0; blocky < height_blocks; ++blocky)
   {
      const u8* xsrc = ysrc;
      for (blockx = 0; blockx < width_blocks; ++blockx)
      {
         const u32* src = (u32*)xsrc;
         for (j = 0; j < 8; ++j)
         {
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            *(dst++) = *(src++);
            src += src_pitch;
         }
         xsrc += 16;
     }
     ysrc += src_row;
   }
}
void InitGFX()
{
	sceGuInit();
	// setup
	sceGuStart(GU_DIRECT,list);
	sceGuDrawBuffer(GU_PSM_5551,(void*)0,512);
	sceGuDispBuffer(480,272,(void*)0x44000,512);
	sceGuDepthBuffer((void*)0x88000,512);
	sceGuOffset(2048 - (480/2),2048 - (272/2));
	sceGuViewport(2048,2048,480,272);
	sceGuDepthRange(0xc350,0x2710);
	sceGuScissor(0,0,480,272);
	sceGuEnable(GU_SCISSOR_TEST);
	sceGuFrontFace(GU_CW);
	sceGuEnable(GU_TEXTURE_2D);
	sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
	sceGuFinish();
	sceGuSync(0,0);
	sceDisplayWaitVblankStart();
	sceGuDisplay(1);
}
int main(int argc, char* argv[])
{
	float x = 0,y = 0;
	int i;
	pspDebugScreenInit();
	SetupCallbacks();
	
	InitGFX();
	
	for(i=0;i<SPRITE_WIDTH*SPRITE_HEIGHT;i++){
		pixels[i] = 0xFC00;
	}
	
	swizzle_fast((u8*)swizzled_pixels,(const u8*)pixels,SPRITE_WIDTH*2,SPRITE_HEIGHT); 
	// 512*2 because swizzle operates in bytes, and each pixel in a 16-bit texture is 2 bytes
	
	sceGuCopyImage(GU_PSM_5551,0,0,SPRITE_WIDTH,SPRITE_HEIGHT,SPRITE_WIDTH,swizzled_pixels,0,0,SPRITE_WIDTH,(sceGeEdramGetAddr()+512*272*2*3));
	
	pixels2 = sceGeEdramGetAddr()+512*272*2*3;
	sceKernelDcacheWritebackAll();
	while (!done)
	{
		SceCtrlData pad;
		sceCtrlReadBufferPositive(&pad, 1);
		if((pad.Buttons & PSP_CTRL_RIGHT) && x<479-SPRITE_WIDTH)x+=2;
		if((pad.Buttons & PSP_CTRL_LEFT) && x>1)x-=2;
		if((pad.Buttons & PSP_CTRL_UP) && y>1)y-=2;
		if((pad.Buttons & PSP_CTRL_DOWN) && y<271-SPRITE_HEIGHT)y+=2;
		sceGuStart(GU_DIRECT,list);
		sceGuTexMode(GU_PSM_5551,0,0,1); // 16-bit RGBA
		sceGuTexImage(0,SPRITE_WIDTH,SPRITE_HEIGHT,SPRITE_WIDTH,pixels2); 
		sceGuTexFunc(GU_TFX_REPLACE,GU_TCC_RGBA); // don't get influenced by any vertex colors
		sceGuTexFilter(GU_NEAREST,GU_NEAREST); // point-filtered sampling
		sceGuClearColor(0);
		sceGuClear(GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT);
		
		advancedBlit(0,0,SPRITE_WIDTH,SPRITE_HEIGHT,x,y);
		sceGuFinish();
		sceGuSync(0,0);
//		sceDisplayWaitVblankStart();
		sceGuSwapBuffers();
		
		
	}
	sceGuTerm();
	sceKernelExitGame();
	return 0;
}