#include <pspkernel.h>
#include <pspgu.h>

PSP_MODULE_INFO("gutest", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_VFPU | THREAD_ATTR_USER);

#define BUFFER_WIDTH 512
#define BUFFER_HEIGHT 272
#define SCREEN_WIDTH 480
#define SCREEN_HEIGHT BUFFER_HEIGHT

char list[0x20000] __attribute__((aligned(64)));

void initGu(){
    sceGuInit();

    //Set up buffers
    sceGuStart(GU_DIRECT, list);
    sceGuDrawBuffer(GU_PSM_8888,(void*)0,BUFFER_WIDTH);
    sceGuDispBuffer(SCREEN_WIDTH,SCREEN_HEIGHT,(void*)0x88000,BUFFER_WIDTH);
    sceGuDepthBuffer((void*)0x110000,BUFFER_WIDTH);

    //Set up viewport
    sceGuOffset(2048 - (SCREEN_WIDTH / 2), 2048 - (SCREEN_HEIGHT / 2));
    sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT);
    sceGuEnable(GU_SCISSOR_TEST);
    sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    //Set some stuff
    sceGuDepthRange(65535, 0); //Use the full buffer for depth testing - buffer is reversed order

    sceGuDepthFunc(GU_GEQUAL); //Depth buffer is reversed, so GEQUAL instead of LEQUAL
    sceGuEnable(GU_DEPTH_TEST); //Enable depth testing

    sceGuFinish();
    sceGuDisplay(GU_TRUE);
}

void endGu(){
    sceGuDisplay(GU_FALSE);
    sceGuTerm();
}

void startFrame(){
    sceGuStart(GU_DIRECT, list);
    sceGuClearColor(0xFFFFFFFF); // White background
    sceGuClear(GU_COLOR_BUFFER_BIT);
}

void endFrame(){
    sceGuFinish();
    sceGuSync(0, 0);
    sceDisplayWaitVblankStart();
    sceGuSwapBuffers();
}

typedef struct {
    unsigned short u, v;
    short x, y, z;
} Vertex;

void drawTri(Vertex* verts, int vertCt, uint32_t color) {

    sceGuColor(color); // colors are ABGR
    sceGuDrawArray(GU_TRIANGLE_STRIP, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, vertCt, 0, verts);
}


int main() {
    initGu();
    int running = 1;
    while(running){
        startFrame();

        Vertex* oneVerts = (struct Vertex*)sceGuGetMemory(6*sizeof(Vertex));
        oneVerts[0].x = 128;
        oneVerts[0].y = 128;
        
        oneVerts[1].x = 112;
        oneVerts[1].y = 128;
        
        oneVerts[2].x = 128;
        oneVerts[2].y = 48;
        
        oneVerts[3].x = 112;
        oneVerts[3].y = 64;      
        
        oneVerts[4].x = 112;
        oneVerts[4].y = 48;

        oneVerts[5].x = 96;
        oneVerts[5].y = 64;

        uint32_t colorone = 0xFFFF00BB;

        drawTri(oneVerts, 6, colorone);

        Vertex* twoVerts = (struct Vertex*)sceGuGetMemory(7*sizeof(Vertex));
        twoVerts[0].x = 160;
        twoVerts[0].y = 128;

        twoVerts[1].x = 144;
        twoVerts[1].y = 128;

        twoVerts[2].x = 192;
        twoVerts[2].y = 48;

        twoVerts[3].x = 176;
        twoVerts[3].y = 64;      

        twoVerts[4].x = 176;
        twoVerts[4].y = 48;

        twoVerts[5].x = 160;
        twoVerts[5].y = 64;

	twoVerts[6].x = 160;
	twoVerts[6].y = 48;

        uint32_t colortwo = 0xFF00EEEE;
        drawTri(twoVerts, 7, colortwo);

        endFrame();
    }

    return 0;
}
