Created
October 12, 2012 02:20
-
-
Save KapLex/3876973 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pspkernel.h> | |
#include <pspdisplay.h> | |
#include <pspgu.h> | |
#include <pspgum.h> | |
#include <psprtc.h> | |
#include <stdio.h> | |
#include <string.h> | |
//#define TRI_DDLIST | |
#ifdef TRI_DDLIST | |
#define TRI_DLISTMODE GU_SEND | |
#define TRI_DLISTS 2 | |
#define TRI_DLIST_SWAP() (triListIdx^=1) | |
#else | |
#define TRI_DLISTMODE GU_DIRECT | |
#define TRI_DLISTS 1 | |
#define TRI_DLIST_SWAP() (void)0 | |
#endif | |
#define TRI_DLIST() (triList[triListIdx]) | |
extern unsigned long triDlistSizeUser __attribute__((weak)); | |
static unsigned long triDlistSize = 256*1024; | |
// Globals | |
//-------------------------------------------------- | |
static void* triList[TRI_DLISTS]; | |
static unsigned long triListIdx = 0; | |
static void* triFrontbuffer = 0; | |
static void* triBackbuffer = (void*)(FRAME_BUFFER_SIZE*4); | |
void* triFramebuffer = (void*)(0x04000000); // always holds the absolute pointer to current drawbuffer | |
void* triFramebuffer2 = (void*)(0x04000000); // always holds the absolute pointer to last drawbuffer | |
void* triDispbuffers[2] = { 0, 0 }; | |
void* triDepthbuffer = 0; | |
signed long triPsm = GU_PSM_8888; | |
signed long triBpp = 4; | |
static signed long triDoublebuffer = 1; | |
static signed long triInitialized = 0; | |
static signed long triListAvail = 0; | |
static signed long triVBlankEnable = 0; | |
static signed long triPseudoAAEnable = 0; | |
static signed long triSmoothditherEnable = 1; | |
static signed long triVBlankFlag = 0; // was VBlank called manually this frame? | |
static signed long triSmoothditherFlag = 0; | |
static signed long triPseudoAAFlag = 0; | |
#ifdef TRI_DDLIST | |
static PspGeContext triGeContext; | |
#endif | |
static float triFpsValue = 0.f; | |
static float triFpsMinValue = 9999.f; | |
static float triFpsMaxValue = 0.f; | |
static unsigned long long triLastTick = 0; | |
static unsigned long triTickFrequency = 0; | |
static unsigned long long triFrameCount = 0; | |
static unsigned long long triFrameTime = 0; | |
static unsigned long long triCPUTime = 0; | |
static unsigned long long triGPUTime = 0; | |
static unsigned long long triVblankTime = 0; | |
static signed long triColorKey = 0; | |
static signed long triBlend = 0; | |
static signed long triCurContext = 0; | |
#define ALIGN16 __attribute__((aligned(16))) | |
#define UNCACHED(x) (void*)(0x40000000 | (unsigned long)(x)) | |
#define VRAM_BASE (0x04000000) | |
#define VRAM_SIZE (0x00200000) | |
#define VRAM_UNSWIZZLED (0x04200000) // VRAM mirror for unswizzled read | |
#define VRAM_LINEAR (0x04600000) // VRAM mirror for linear read (unswizzled + deinterleave) | |
#define MIN(a,b) ((a)<(b)?(a):(b)) | |
// Do a fast blend of two colors x and y by alpha value z (255-srcalpha), where x is alpha premultiplied | |
#define FASTBLEND(x,y,z) (((x&0xFF00FF) + (((z*(y&0xFF00FF))>>8)&0xFF00FF))|((x&0xFF00) + (((z*(y&0xFF00))>>8)&0xFF00))) | |
static signed long DitherMatrix[2][16] = { { 0, 8, 0, 8, | |
8, 0, 8, 0, | |
0, 8, 0, 8, | |
8, 0, 8, 0 }, | |
{ 8, 8, 8, 8, | |
0, 8, 0, 8, | |
8, 8, 8, 8, | |
0, 8, 0, 8 } }; | |
static float ProjectionMatrix[2][16]; | |
void triGuFinishCallback( int what ) | |
{ | |
sceRtcGetCurrentTick(&triGPUTime); | |
triGPUTime -= triFrameTime; | |
} | |
void triInit( signed long psm, triBool doublebuffer ) | |
{ | |
if (triInitialized!=0) return; | |
triInitialized = 1; | |
triDoublebuffer = doublebuffer; | |
switch (psm) | |
{ | |
case GU_PSM_4444: | |
case GU_PSM_5650: | |
case GU_PSM_5551: | |
triBpp = 2; | |
triPsm = psm; | |
break; | |
default: | |
triBpp = 4; | |
triPsm = GU_PSM_8888; | |
break; | |
} | |
triBackbuffer = vrelptr(triVAlloc(FRAME_BUFFER_SIZE*triBpp)); | |
if (triDoublebuffer) | |
{ | |
triFrontbuffer = vrelptr(triVAlloc(FRAME_BUFFER_SIZE*triBpp)); | |
} | |
else | |
{ | |
triFrontbuffer = triBackbuffer; | |
triDispbuffers[0] = triMalloc(FRAME_BUFFER_SIZE*triBpp); | |
triDispbuffers[1] = triMalloc(FRAME_BUFFER_SIZE*triBpp); | |
memset(triDispbuffers[0],0,FRAME_BUFFER_SIZE*triBpp); | |
memset(triDispbuffers[1],0,FRAME_BUFFER_SIZE*triBpp); | |
} | |
triFramebuffer = vabsptr(triFrontbuffer); | |
triFramebuffer2 = vabsptr(triBackbuffer); | |
if (&triDlistSizeUser != NULL) | |
{ | |
triDlistSize = triDlistSizeUser; | |
} | |
for (triListIdx=0;triListIdx<TRI_DLISTS;triListIdx++) | |
triList[triListIdx] = triMalloc(triDlistSize); | |
triListIdx = 0; | |
sceGuInit(); | |
sceGuSetCallback(GU_CALLBACK_FINISH, &triGuFinishCallback); | |
// setup GU | |
sceGuStart(GU_DIRECT,triList[triListIdx]); | |
sceGuDrawBuffer(triPsm, triFrontbuffer, FRAME_BUFFER_WIDTH); | |
sceGuDispBuffer(512, 512, triBackbuffer, FRAME_BUFFER_WIDTH); | |
sceGuOffset(2048 - (SCREEN_WIDTH/2), 2048 - (SCREEN_HEIGHT/2)); | |
sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT); | |
// Scissoring | |
sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | |
sceGuEnable(GU_SCISSOR_TEST); | |
// Backface culling | |
sceGuFrontFace(GU_CCW); | |
sceGuDisable(GU_CULL_FACE); // no culling in 2D | |
// Depth test | |
sceGuDisable(GU_DEPTH_TEST); | |
sceGuDepthMask(GU_TRUE); // disable z-writes | |
// Color keying | |
sceGuDisable(GU_COLOR_TEST); | |
sceGuDisable(GU_ALPHA_TEST); | |
sceGuDisable(GU_CLIP_PLANES); | |
// Texturing | |
sceGuEnable(GU_TEXTURE_2D); | |
sceGuShadeModel(GU_SMOOTH); | |
sceGuTexWrap(GU_CLAMP, GU_CLAMP); | |
sceGuTexFilter(GU_LINEAR,GU_LINEAR); | |
sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); | |
sceGuTexEnvColor(0xFFFFFFFF); | |
sceGuColor(0xFFFFFFFF); | |
sceGuAmbientColor(0xFFFFFFFF); | |
sceGuTexOffset(0.0f, 0.0f); | |
sceGuTexScale(1.0f, 1.0f); | |
// Blending | |
sceGuEnable(GU_BLEND); | |
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); | |
sceGuDisable(GU_DITHER); | |
if (triBpp<4) | |
{ | |
sceGuSetDither( (ScePspIMatrix4*)DitherMatrix[0] ); | |
sceGuEnable(GU_DITHER); | |
} | |
// Projection | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
gumOrtho( (ScePspFMatrix4*)ProjectionMatrix[0], 0.0f, 480.0f, 272.0f, 0.0f, -1.0f, 1.0f ); | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[1] ); | |
ScePspFVector3 displace = { -0.002f, 0.00367f, 0.0f }; // ~ 1/480, 1/272 | |
gumTranslate( (ScePspFMatrix4*)ProjectionMatrix[1], &displace ); | |
gumMultMatrix( (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
sceGumMatrixMode(GU_PROJECTION); | |
sceGumLoadMatrix( (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
sceGumMatrixMode(GU_VIEW); | |
sceGumLoadIdentity(); | |
sceGumMatrixMode(GU_MODEL); | |
sceGumLoadIdentity(); | |
sceGuClearColor( 0x0 ); | |
sceGuClear(GU_COLOR_BUFFER_BIT|GU_FAST_CLEAR_BIT); | |
sceGuFinish(); | |
sceGuSync(0,0); | |
sceDisplayWaitVblankStart(); | |
sceGuDisplay(1); | |
if (!triDoublebuffer) | |
{ | |
sceDisplaySetFrameBuf( triDispbuffers[1], 512, triPsm, PSP_DISPLAY_SETBUF_NEXTFRAME ); | |
} | |
sceGuStart(TRI_DLISTMODE, TRI_DLIST()); | |
#ifdef TRI_DDLIST | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer2), FRAME_BUFFER_WIDTH); | |
triCurContext = 0; | |
#else | |
triCurContext = 1; | |
#endif | |
triListAvail = 1; | |
sceRtcGetCurrentTick(&triLastTick); | |
triTickFrequency = sceRtcGetTickResolution(); | |
triFrameCount = 0; | |
} | |
void triClose() | |
{ | |
if (!triInitialized) return; | |
triVFree(vabsptr(triBackbuffer)); | |
if (triDoublebuffer) | |
{ | |
triVFree(vabsptr(triFrontbuffer)); | |
} | |
else | |
{ | |
triFree(triDispbuffers[0]); | |
triFree(triDispbuffers[1]); | |
} | |
for (triListIdx=0;triListIdx<TRI_DLISTS;triListIdx++) | |
triFree(triList[triListIdx]); | |
triInitialized = 0; | |
triListAvail = 0; | |
sceGuTerm(); | |
} | |
void triBegin() | |
{ | |
#ifdef TRI_DDLIST | |
sceGuStart(GU_DIRECT, triList[triListIdx^1]); | |
triCurContext = 1; | |
#endif | |
} | |
void triEnd() | |
{ | |
#ifdef TRI_DDLIST | |
if (sceGuFinish()>triDlistSize) | |
{ | |
triLogError("ERROR: Display list overflow!\n"); | |
} | |
triCurContext = 0; | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer2), FRAME_BUFFER_WIDTH); | |
#endif | |
} | |
void triSync() | |
{ | |
#ifdef TRI_DDLIST | |
if (triCurContext==1) | |
sceGuSync(GU_SYNC_LIST,GU_SYNC_WAIT); | |
else | |
sceGuSync(GU_SYNC_SEND,GU_SYNC_WAIT); | |
#else | |
sceGuSync(GU_SYNC_LIST,GU_SYNC_WAIT); | |
#endif | |
} | |
void triSwapbuffers() | |
{ | |
unsigned long long triEndTick; | |
if (!triDoublebuffer) | |
{ | |
if (triCurContext==1) | |
sceGuSync(GU_SYNC_LIST,GU_SYNC_WAIT); | |
else | |
sceGuSync(GU_SYNC_SEND,GU_SYNC_WAIT); | |
sceGuCopyImage(triPsm, 0, 0, 480, 272, 512, triFramebuffer, 0, 0, 512, triDispbuffers[triFrameCount&1]); | |
sceGuTexSync(); | |
} | |
if (sceGuFinish()>triDlistSize) | |
{ | |
triLogError("ERROR: Display list overflow!\n"); | |
} | |
sceRtcGetCurrentTick(&triCPUTime); | |
// Sync to all drawing | |
sceGuSync(GU_SYNC_FINISH,GU_SYNC_WHAT_DONE); | |
if ((triVBlankEnable || triPseudoAAEnable) && !triVBlankFlag) | |
sceDisplayWaitVblankStart(); | |
sceRtcGetCurrentTick(&triEndTick); | |
triCPUTime -= triFrameTime; | |
triVblankTime = triEndTick-triFrameTime; | |
triVBlankFlag = 0; | |
triFramebuffer2 = triFramebuffer; | |
if (triDoublebuffer) | |
{ | |
triFramebuffer = vabsptr(sceGuSwapBuffers()); | |
} | |
else | |
{ | |
sceDisplaySetFrameBuf( triDispbuffers[triFrameCount&1], 512, triPsm, PSP_DISPLAY_SETBUF_IMMEDIATE ); | |
} | |
#ifdef TRI_DDLIST | |
sceGuSendList(GU_TAIL, TRI_DLIST(), &triGeContext); | |
#endif | |
TRI_DLIST_SWAP(); | |
sceGuStart(TRI_DLISTMODE, TRI_DLIST()); | |
#ifdef TRI_DDLIST | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer2), FRAME_BUFFER_WIDTH); | |
#else | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer), FRAME_BUFFER_WIDTH); | |
#endif | |
if (triBpp<4 && triSmoothditherEnable) | |
sceGuSetDither( (ScePspIMatrix4*)DitherMatrix[triSmoothditherFlag^=1] ); | |
if (triPseudoAAEnable) | |
{ | |
sceGumMatrixMode(GU_PROJECTION); | |
sceGumLoadMatrix( (ScePspFMatrix4*)ProjectionMatrix[triPseudoAAFlag^=1] ); | |
sceGumMatrixMode(GU_MODEL); | |
} | |
triFrameCount++; | |
if ((triEndTick-triLastTick)>=(triTickFrequency>>1)) | |
{ | |
triFpsValue = (float)triFrameCount/(triEndTick-triLastTick)*triTickFrequency; | |
if (triFrameCount>1) | |
{ | |
if (triFpsMinValue>triFpsValue) triFpsMinValue = triFpsValue; | |
if (triFpsMaxValue<triFpsValue) triFpsMaxValue = triFpsValue; | |
} | |
triFrameCount = 0; | |
triLastTick = triEndTick; | |
} | |
triFrameTime = triEndTick; | |
} | |
void triClear( unsigned long color ) | |
{ | |
sceGuClearColor( color ); | |
sceGuClear( GU_COLOR_BUFFER_BIT | GU_FAST_CLEAR_BIT ); | |
} | |
void triVblank() | |
{ | |
sceDisplayWaitVblankStart(); | |
triVBlankFlag = 1; | |
} | |
void triCopyToScreen( signed long x, signed long y, signed long w, signed long h, signed long sx, signed long sy, signed long sbw, void* src ) | |
{ | |
if (triCurContext==1) | |
sceGuCopyImage( triPsm, x, y, w, h, 512, triFramebuffer2, sx, sy, sbw, src ); | |
else | |
sceGuCopyImage( triPsm, x, y, w, h, 512, triFramebuffer, sx, sy, sbw, src ); | |
sceGuTexSync(); | |
} | |
void triCopyFromScreen( signed long x, signed long y, signed long w, signed long h, signed long dx, signed long dy, signed long dbw, void* dst ) | |
{ | |
if (triCurContext==1) | |
sceGuCopyImage( triPsm, dx, dy, w, h, dbw, dst, x, y, 512, triFramebuffer2 ); | |
else | |
sceGuCopyImage( triPsm, dx, dy, w, h, dbw, dst, x, y, 512, triFramebuffer ); | |
sceGuTexSync(); | |
} | |
void triPerspective( float fov ) | |
{ | |
if (fov<1.0f || fov>179.0f) fov = 75.0f; | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
gumPerspective( (ScePspFMatrix4*)ProjectionMatrix[0], fov, 16.0f/9.0f, 1.0f, 1000.0f ); | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[1] ); | |
ScePspFVector3 displace = { -0.002f, 0.00367f, 0.0f }; // ~ 1/480, 1/272 | |
gumTranslate( (ScePspFMatrix4*)ProjectionMatrix[1], &displace ); | |
gumMultMatrix( (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
sceGumMatrixMode(GU_PROJECTION); | |
sceGumLoadMatrix( (ScePspFMatrix4*)ProjectionMatrix[triPseudoAAFlag] ); | |
sceGumMatrixMode(GU_MODEL); | |
} | |
void triOrtho() | |
{ | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
gumOrtho( (ScePspFMatrix4*)ProjectionMatrix[0], 0.0f, 480.0f, 272.0f, 0.0f, -1.0f, 1.0f ); | |
gumLoadIdentity( (ScePspFMatrix4*)ProjectionMatrix[1] ); | |
ScePspFVector3 displace = { -0.002f, 0.00367f, 0.0f }; // ~ 1/480, 1/272 | |
gumTranslate( (ScePspFMatrix4*)ProjectionMatrix[1], &displace ); | |
gumMultMatrix( (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[1], (ScePspFMatrix4*)ProjectionMatrix[0] ); | |
sceGumMatrixMode(GU_PROJECTION); | |
sceGumLoadMatrix( (ScePspFMatrix4*)ProjectionMatrix[triPseudoAAFlag] ); | |
sceGumMatrixMode(GU_MODEL); | |
} | |
void triEnable( unsigned long state ) | |
{ | |
switch (state) | |
{ | |
case TRI_VBLANK: | |
triVBlankEnable = 1; | |
break; | |
case TRI_PSEUDO_FSAA: | |
triPseudoAAEnable = 1; | |
break; | |
case TRI_SMOOTH_DITHER: | |
triSmoothditherEnable = 1; | |
break; | |
case TRI_DEPTH_TEST: | |
if (triDepthbuffer!=0) | |
sceGuEnable(GU_DEPTH_TEST); | |
break; | |
case TRI_DEPTH_MASK: | |
if (triDepthbuffer!=0) | |
sceGuDepthMask(0); | |
break; | |
default: | |
sceGuEnable( state ); | |
break; | |
} | |
} | |
void triDisable( unsigned long state ) | |
{ | |
switch (state) | |
{ | |
case TRI_VBLANK: | |
triVBlankEnable = 0; | |
break; | |
case TRI_PSEUDO_FSAA: | |
triPseudoAAEnable = 0; | |
triPseudoAAFlag = 0; | |
break; | |
case TRI_SMOOTH_DITHER: | |
triSmoothditherEnable = 0; | |
break; | |
case TRI_DEPTH_TEST: | |
sceGuDisable(GU_DEPTH_TEST); | |
break; | |
case TRI_DEPTH_MASK: | |
sceGuDepthMask(0xFFFF); | |
break; | |
default: | |
sceGuDisable( state ); | |
break; | |
} | |
} | |
void triRendertotexture( signed long psm, void* tbp, signed long tw, signed long th, signed long tbw ) | |
{ | |
signed long bpp = 0; | |
// check that pixelformat is a legal renderformat | |
switch (psm) | |
{ | |
case GU_PSM_4444: | |
case GU_PSM_5650: | |
case GU_PSM_5551: | |
bpp = 2; | |
break; | |
case GU_PSM_8888: | |
bpp = 4; | |
break; | |
default: | |
triLogPrint("Cannot render in pixelformat %x\n", psm); | |
return; | |
} | |
if ((unsigned long)tbp<VRAM_BASE || ((unsigned long)tbp+tbw*th*bpp)>VRAM_SIZE+VRAM_LINEAR) | |
{ | |
triLogPrint("Cannot render to non VRAM space.\n"); | |
return; // check that texture is in VRAM | |
} | |
sceGuDrawBufferList( psm, vrelptr(tbp), tbw ); | |
sceGuOffset(2048 - (tw/2), 2048 - (th/2)); | |
sceGuViewport(2048, 2048, tw, th); | |
sceGuScissor(0, 0, tw, th); | |
} | |
void triRendertoimage( triImage* img ) | |
{ | |
signed long bpp = 0; | |
// check that pixelformat is a legal renderformat | |
switch (img->format) | |
{ | |
case GU_PSM_4444: | |
case GU_PSM_5650: | |
case GU_PSM_5551: | |
bpp = 2; | |
break; | |
case GU_PSM_8888: | |
bpp = 4; | |
break; | |
default: | |
triLogPrint("Cannot render in pixelformat %x\n", img->format); | |
return; | |
} | |
// make sure the image is in VRAM | |
triImageToVRAM( img ); | |
if ((unsigned long)img->data<VRAM_BASE || ((unsigned long)img->data+img->size)>VRAM_SIZE+VRAM_LINEAR) | |
{ | |
triLogPrint("Cannot render to non VRAM space.\n"); | |
return; // check that texture is in VRAM | |
} | |
sceGuDrawBufferList( img->format, vrelptr(img->data), img->stride ); | |
sceGuOffset(2048 - (img->width/2), 2048 - (img->height/2)); | |
sceGuViewport(2048, 2048, img->width, img->height); | |
sceGuScissor(0, 0, img->width, img->height); | |
} | |
void triRendertoscreen() | |
{ | |
if (triCurContext==1) | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer), FRAME_BUFFER_WIDTH); | |
else | |
sceGuDrawBufferList(triPsm, vrelptr(triFramebuffer2), FRAME_BUFFER_WIDTH); | |
sceGuOffset(2048 - (SCREEN_WIDTH/2), 2048 - (SCREEN_HEIGHT/2)); | |
sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT); | |
sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); | |
} | |
void triDrawLine( float x0, float y0, float x1, float y1, unsigned long color ) | |
{ | |
triVertC* vertices = (triVertC*)sceGuGetMemory(2 * sizeof(triVertC)); | |
vertices[0].color = color; | |
vertices[0].x = x0; | |
vertices[0].y = y0; | |
vertices[0].z = 0.0f; | |
vertices[1].color = color; | |
vertices[1].x = x1; | |
vertices[1].y = y1; | |
vertices[1].z = 0.0f; | |
sceGuDisable(GU_TEXTURE_2D); | |
sceGuShadeModel(GU_FLAT); | |
sceGuDrawArray(GU_LINES, GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); | |
sceGuShadeModel(GU_SMOOTH); | |
sceGuEnable(GU_TEXTURE_2D); | |
} | |
void triDrawLines( triVec2* p, signed long num, unsigned long color ) | |
{ | |
triVertC* vertices = (triVertC*)sceGuGetMemory(num * sizeof(triVertC)); | |
int i = 0; | |
for (;i<num;i++) | |
{ | |
vertices[i].color = color; | |
vertices[i].x = p[i].x; | |
vertices[i].y = p[i].y; | |
vertices[i].z = 0.0f; | |
} | |
sceGuDisable(GU_TEXTURE_2D); | |
sceGuShadeModel(GU_FLAT); | |
sceGuDrawArray(GU_LINE_STRIP, GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D, num, 0, vertices); | |
sceGuShadeModel(GU_SMOOTH); | |
sceGuEnable(GU_TEXTURE_2D); | |
} | |
void triDrawRect( float x, float y, float width, float height, unsigned long color ) | |
{ | |
triVertC* vertices = (triVertC*)sceGuGetMemory(2 * sizeof(triVertC)); | |
vertices[0].color = color; | |
vertices[0].x = x; | |
vertices[0].y = y; | |
vertices[0].z = 0.0f; | |
vertices[1].color = color; | |
vertices[1].x = x + width; | |
vertices[1].y = y + height; | |
vertices[1].z = 0.0f; | |
sceGuDisable(GU_TEXTURE_2D); | |
sceGuShadeModel(GU_FLAT); | |
sceGuDrawArray(GU_SPRITES, GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); | |
sceGuShadeModel(GU_SMOOTH); | |
sceGuEnable(GU_TEXTURE_2D); | |
} | |
// FIXME: Move to triMath.c | |
void triSinCos( float angle, float* sin, float* cos ) | |
{ | |
asm ( | |
"vcst.s S003, VFPU_2_PI\n" | |
"mtv %2, s002\n" | |
"vmul.s s002, s002, s003\n" | |
"vrot.p c000, s002, [s,c]\n" | |
"mfv %0, s000\n" | |
"mfv %1, s001\n" | |
:"=r"(*sin),"=r"(*cos) | |
:"r"(angle) | |
); | |
} | |
void triColorOp( signed long op ) | |
{ | |
sceGuEnable(GU_COLOR_LOGIC_OP); | |
sceGuLogicalOp( op ); | |
} | |
void triNoColorOp() | |
{ | |
sceGuDisable(GU_COLOR_LOGIC_OP); | |
} | |
/** | |
* Set how textures are applied | |
* | |
* Key for the apply-modes: | |
* - Cv - Color value result | |
* - Ct - Texture color | |
* - Cf - Fragment color (vcolor) | |
* - Cc - Constant color (ccolor) | |
* | |
* Available apply-modes are: (TFX) | |
* - GU_TFX_MODULATE - Cv=Ct*Cf TCC_RGB: Av=Af TCC_RGBA: Av=At*Af | |
* - GU_TFX_DECAL - TCC_RGB: Cv=Ct,Av=Af TCC_RGBA: Cv=Cf*(1-At)+Ct*At Av=Af | |
* - GU_TFX_BLEND - Cv=(Cf*(1-Ct))+(Cc*Ct) TCC_RGB: Av=Af TCC_RGBA: Av=At*Af | |
* - GU_TFX_REPLACE - Cv=Ct TCC_RGB: Av=Af TCC_RGBA: Av=At | |
* - GU_TFX_ADD - Cv=Cf+Ct TCC_RGB: Av=Af TCC_RGBA: Av=At*Af | |
*/ | |
void triImageTint( signed long mode, signed long comp, unsigned long vcolor, unsigned long ccolor ) | |
{ | |
sceGuTexFunc(mode, comp); | |
sceGuTexEnvColor(ccolor); | |
sceGuAmbientColor(vcolor); | |
} | |
void triImageNoTint() | |
{ | |
sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); | |
} | |
// Same as triImageTint( GU_TFX_DECAL, GU_TCC_RGB, (alpha<<24)|0xFFFFFF, 0 ); | |
void triImageConstAlpha( unsigned long alpha ) | |
{ | |
sceGuTexFunc(GU_TFX_DECAL, GU_TCC_RGB); | |
sceGuAmbientColor((alpha<<24)|0xFFFFFF); | |
} | |
void triImageBlend( signed long op, signed long src_op, signed long dst_op, unsigned long src_fix, unsigned long dst_fix ) | |
{ | |
sceGuEnable(GU_BLEND); | |
sceGuBlendFunc( op, src_op, dst_op, src_fix, dst_fix ); | |
} | |
void triImageNoBlend() | |
{ | |
sceGuDisable(GU_BLEND); | |
} | |
void triImageColorkey( unsigned long color ) | |
{ | |
sceGuEnable(GU_COLOR_TEST); | |
sceGuColorFunc(GU_NOTEQUAL,color,0xffffff); | |
} | |
void triImageNoColorkey() | |
{ | |
sceGuDisable(GU_COLOR_TEST); | |
} | |
void triDrawImage( float x, float y, float width, float height, // rect pos and size on screen | |
float u0, float v0, float u1, float v1, // area of texture to render | |
triImage* img ) | |
{ | |
if (img==0 || img->width==0 || img->height==0 || width==0 || height==0) return; | |
// Support negative width/height to do easy flipping | |
if (width < 0) | |
{ | |
//x += width; | |
float u = u0; u0 = u1; u1 = u; | |
width = -width; | |
} | |
if (height < 0) | |
{ | |
//y += height; | |
float v = v0; v0 = v1; v1 = v; | |
height = -height; | |
} | |
if (img->format==IMG_FORMAT_T4) | |
{ | |
sceGuClutMode(img->palformat, 0, 0xff, 0); | |
sceGuClutLoad(2, img->palette); | |
} | |
else if (img->format==IMG_FORMAT_T8) | |
{ | |
sceGuClutMode(img->palformat, 0, 0xff, 0); | |
sceGuClutLoad(32, img->palette); | |
} | |
sceGuTexMode(img->format, 0, 0, img->swizzled); | |
sceGuEnable(GU_TEXTURE_2D); | |
float cur_v = v0; | |
float cur_y = y; | |
float v_end = v1; | |
float y_end = y + height; | |
float vslice = 512.f; | |
float ystep = (height/(v1-v0) * vslice); | |
float vstep = ((v1-v0) > 0 ? vslice : -vslice); | |
float x_end = x + width; | |
float uslice = 64.f; | |
//float ustep = (u1-u0)/width * xslice; | |
float xstep = (width/(u1-u0) * uslice); | |
float ustep = ((u1-u0) > 0 ? uslice : -uslice); | |
triChar* data = img->data; | |
for ( ; cur_y < y_end; cur_y+=ystep, cur_v+=vstep ) | |
{ | |
float cur_u = u0; | |
float cur_x = x; | |
float u_end = u1; | |
// support large images (height > 512) | |
int off = (vstep>0) ? ((int)cur_v) : ((int)(cur_v+vstep)); | |
data += ((off*img->stride*img->bits) >> 3); | |
cur_v -= off; | |
v_end -= off; | |
sceGuTexImage(0, MIN(512,img->stride), MIN(512,img->tex_height), img->stride, data); | |
float poly_height = ((cur_y+ystep) > y_end) ? (y_end-cur_y) : ystep; | |
float source_height = vstep; | |
// support negative vsteps | |
if ((vstep > 0) && (cur_v+vstep > v_end)) | |
{ | |
source_height = (v_end-cur_v); | |
} | |
else | |
if ((vstep < 0) && (cur_v+vstep < v_end)) | |
{ | |
source_height = (cur_v-v_end); | |
} | |
triChar* udata = data; | |
// blit maximizing the use of the texture-cache | |
for( ; cur_x < x_end; cur_x+=xstep, cur_u+=ustep ) | |
{ | |
// support large images (width > 512) | |
if (cur_u>512.f || cur_u+ustep>512.f) | |
{ | |
int off = (ustep>0) ? ((int)cur_u & ~31) : ((int)(cur_u+ustep) & ~31); | |
udata += ((off*img->bits) >> 3); | |
cur_u -= off; | |
u_end -= off; | |
sceGuTexImage(0, MIN(512,img->stride), MIN(512,img->tex_height), img->stride, udata); | |
} | |
triVertUV* vertices = (triVertUV*)sceGuGetMemory(2 * sizeof(triVertUV)); | |
float poly_width = ((cur_x+xstep) > x_end) ? (x_end-cur_x) : xstep; | |
float source_width = ustep; | |
// support negative usteps | |
if ((ustep > 0) && (cur_u+ustep > u_end)) | |
{ | |
source_width = (u_end-cur_u); | |
} | |
else | |
if ((ustep < 0) && (cur_u+ustep < u_end)) | |
{ | |
source_width = (cur_u-u_end); | |
} | |
vertices[0].u = cur_u; | |
vertices[0].v = cur_v; | |
vertices[0].x = cur_x; | |
vertices[0].y = cur_y; | |
vertices[0].z = 0; | |
vertices[1].u = cur_u + source_width; | |
vertices[1].v = cur_v + source_height; | |
vertices[1].x = cur_x + poly_width; | |
vertices[1].y = cur_y + poly_height; | |
vertices[1].z = 0; | |
sceGuDrawArray(GU_SPRITES,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,vertices); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment