Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // gLib2D by Geecko - A simple, fast, light-weight 2D graphics library.
- //
- // This work is licensed under the Creative Commons BY-SA 3.0 Unported License.
- // See LICENSE for more details.
- #include "glib2d.h"
- #include <pspkernel.h>
- #include <pspdebug.h>
- #include <pspdisplay.h>
- #include <pspgu.h>
- #include <malloc.h>
- #include <string.h>
- #include <math.h>
- #ifdef USE_PNG
- #include <png.h>
- #endif
- #define PSP_LINE_SIZE (512)
- #define PIXEL_SIZE (4)
- #define FRAMEBUFFER_SIZE (PSP_LINE_SIZE*G_SCR_H*PIXEL_SIZE)
- #define MALLOC_STEP (10)
- #define TRANSFORM_STACK_MAX (64)
- #define DEFAULT_SIDE (10)
- #define DEFAULT_COORD_MODE (G_UP_LEFT)
- #define DEFAULT_X (0.f)
- #define DEFAULT_Y (0.f)
- #define DEFAULT_Z (0.f)
- #define DEFAULT_COLOR (WHITE)
- #define DEFAULT_ALPHA (0xFF)
- #define CURRENT_OBJ obj_list[obj_list_size]
- #define CURRENT_TRANSFORM transform_stack[transform_stack_size]
- #define I_OBJ obj_list[i]
- typedef struct
- {
- float x, y, z;
- float rot, rot_sin, rot_cos;
- } Transform;
- typedef struct
- {
- float x, y, z;
- float rot_x, rot_y;
- float rot_sin, rot_cos;
- int crop_x, crop_y;
- int crop_w, crop_h;
- int scale_w, scale_h;
- gColor color;
- } Obj_Properties;
- // * Main vars *
- static unsigned int __attribute__((aligned(16))) gu_list[262144];
- bool init = G_FALSE, start = G_FALSE, zclear = G_TRUE;
- Transform transform_stack[TRANSFORM_STACK_MAX];
- int transform_stack_size;
- // * Object vars *
- Obj_Properties* obj_list = NULL;
- int obj_list_size, obj_list_size_malloc; // Real & malloc'ed size
- bool obj_begin = G_FALSE;
- bool obj_use_z, obj_use_vert_color, obj_use_blend, obj_use_rot, obj_use_tex;
- // * Coord vars *
- gEnum obj_coord_mode;
- float obj_x, obj_y, obj_z;
- // * Crop vars *
- int obj_crop_x, obj_crop_y;
- int obj_crop_w, obj_crop_h;
- // * Scale vars *
- float obj_scale_w, obj_scale_h;
- // * Color & alpha vars *
- gColor obj_color;
- gAlpha obj_alpha;
- bool obj_colors_count, obj_alpha_count;
- // * Rotation vars *
- float obj_rot, obj_rot_sin, obj_rot_cos;
- // * Texture vars *
- gImage* obj_tex;
- // * Internal functions *
- void _gInit()
- {
- // Init & setup GU
- sceGuInit();
- sceGuStart(GU_DIRECT,gu_list);
- sceGuDrawBuffer(GU_PSM_8888,(void*)FRAMEBUFFER_SIZE,PSP_LINE_SIZE);
- sceGuDispBuffer(G_SCR_W,G_SCR_H,(void*)0,PSP_LINE_SIZE);
- sceGuDepthBuffer((void*)(FRAMEBUFFER_SIZE*2),PSP_LINE_SIZE);
- sceGuOffset(2048-(G_SCR_W/2),2048-(G_SCR_H/2));
- sceGuViewport(2048,2048,G_SCR_W,G_SCR_H);
- sceGuScissor(0,0,G_SCR_W,G_SCR_H);
- sceGuDepthRange(65535,0);
- sceGuClearDepth(65535);
- sceGuAlphaFunc(GU_GREATER,0,0xff);
- sceGuDepthFunc(GU_LEQUAL);
- sceGuBlendFunc(GU_ADD,GU_SRC_ALPHA,GU_ONE_MINUS_SRC_ALPHA,0,0);
- sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA);
- sceGuTexFilter(GU_LINEAR,GU_LINEAR);
- sceGuShadeModel(GU_FLAT);
- sceGuDisable(GU_CULL_FACE);
- sceGuDisable(GU_CLIP_PLANES);
- sceGuDisable(GU_DITHER);
- sceGuEnable(GU_ALPHA_TEST);
- sceGuEnable(GU_SCISSOR_TEST);
- sceGuFinish();
- sceGuSync(0,0);
- sceDisplayWaitVblankStart();
- sceGuDisplay(GU_TRUE);
- init = G_TRUE;
- }
- void _gStart()
- {
- if (!init) _gInit();
- sceKernelDcacheWritebackAll();
- sceGuStart(GU_DIRECT,gu_list);
- start = G_TRUE;
- }
- void _gCoordInit()
- {
- gResetCoord();
- obj_use_z = G_FALSE;
- }
- void _gScaleInit()
- {
- gResetScale();
- }
- void _gColorInit()
- {
- gResetColor();
- obj_colors_count = 0;
- obj_use_vert_color = G_FALSE;
- }
- void _gAlphaInit()
- {
- gResetAlpha();
- obj_use_blend = G_FALSE;
- }
- void _gRotationInit()
- {
- gResetRotation();
- obj_use_rot = G_FALSE;
- }
- void _gCropInit()
- {
- gResetCrop();
- }
- // Vertex order: [texture uv] [color] [vertex]
- void* _gSetVertex(void* v, int i, bool x, bool y)
- {
- short* v_p_short = v;
- gColor* v_p_color;
- float* v_p_float = v;
- // Texture
- if (obj_use_tex)
- {
- *(v_p_short++) = I_OBJ.crop_x + (x ? I_OBJ.crop_w : 0);
- *(v_p_short++) = I_OBJ.crop_y + (y ? I_OBJ.crop_h : 0);
- }
- // Color
- v_p_color = (gColor*)v_p_short;
- if (obj_use_vert_color) *(v_p_color++) = I_OBJ.color;
- // Coord
- v_p_float = (float*)v_p_color;
- v_p_float[0] = I_OBJ.x + (x ? I_OBJ.scale_w : 0);
- v_p_float[1] = I_OBJ.y + (y ? I_OBJ.scale_h : 0);
- v_p_float[2] = I_OBJ.z;
- if (obj_use_rot) // Apply the rotation
- {
- float tx = v_p_float[0]-I_OBJ.rot_x, ty = v_p_float[1]-I_OBJ.rot_y;
- v_p_float[0] = I_OBJ.rot_x - I_OBJ.rot_sin*ty + I_OBJ.rot_cos*tx,
- v_p_float[1] = I_OBJ.rot_y + I_OBJ.rot_cos*ty + I_OBJ.rot_sin*tx;
- }
- v_p_float += 3;
- return (void*)v_p_float;
- }
- // Insertion sort, because it is a fast and _stable_ sort.
- void _gVertexSort()
- {
- int i, j;
- Obj_Properties obj_tmp;
- for (i=1; i<obj_list_size; i++)
- {
- j = i;
- memcpy(&obj_tmp,obj_list+j,sizeof(Obj_Properties));
- while (j>0 && obj_list[j-1].z < obj_tmp.z)
- {
- memcpy(obj_list+j,obj_list+j-1,sizeof(Obj_Properties));
- j--;
- }
- memcpy(obj_list+j,&obj_tmp,sizeof(Obj_Properties));
- }
- }
- // * Main functions *
- void gClear(gColor color)
- {
- if (!start) _gStart();
- sceGuClearColor(color);
- sceGuClear(GU_COLOR_BUFFER_BIT | GU_FAST_CLEAR_BIT
- | (zclear ? GU_DEPTH_BUFFER_BIT : 0));
- zclear = G_FALSE;
- }
- void gClearZ()
- {
- sceGuClear(GU_DEPTH_BUFFER_BIT | GU_FAST_CLEAR_BIT);
- zclear = G_TRUE;
- }
- void gBegin(gImage* tex, bool use_tex_blend)
- {
- if (obj_begin) return;
- if (!start) _gStart();
- obj_list_size = 0;
- obj_list_size_malloc = MALLOC_STEP;
- obj_list = realloc(obj_list,obj_list_size_malloc * sizeof(Obj_Properties));
- if (tex == NULL) obj_use_tex = G_FALSE;
- else
- {
- obj_use_tex = G_TRUE;
- obj_tex = tex;
- _gCropInit();
- if (use_tex_blend) obj_use_blend = G_TRUE;
- }
- _gCoordInit();
- _gScaleInit();
- _gColorInit();
- _gAlphaInit();
- _gRotationInit();
- obj_begin = G_TRUE;
- }
- void gEnd()
- {
- if (!obj_begin || obj_list_size <= 0) return;
- // Horror : we need to sort the vertices.
- if (obj_use_z && obj_use_blend) _gVertexSort();
- int prim = (obj_use_rot) ? GU_TRIANGLES : GU_SPRITES,
- v_obj_nbr = (obj_use_rot) ? 6 : 2,
- v_nbr = v_obj_nbr * obj_list_size,
- v_coord_size = 3,
- v_tex_size = (obj_use_tex) ? 2 : 0,
- v_color_size = (obj_use_vert_color) ? 1 : 0,
- v_size = v_tex_size * sizeof(short) +
- v_color_size * sizeof(gColor) +
- v_coord_size * sizeof(float),
- v_type = GU_VERTEX_32BITF | GU_TRANSFORM_2D,
- i;
- if (obj_use_tex) v_type |= GU_TEXTURE_16BIT;
- if (obj_use_vert_color) v_type |= GU_COLOR_8888;
- void *v = sceGuGetMemory(v_nbr * v_size), *vi = v;
- for (i=0; i!=obj_list_size; i++)
- {
- if (!obj_use_rot)
- {
- vi = _gSetVertex(vi,i,0,0);
- vi = _gSetVertex(vi,i,1,1);
- }
- else // Draw 2 triangles per obj
- {
- vi = _gSetVertex(vi,i,0,0);
- vi = _gSetVertex(vi,i,1,0);
- vi = _gSetVertex(vi,i,0,1);
- vi = _gSetVertex(vi,i,0,1);
- vi = _gSetVertex(vi,i,1,0);
- vi = _gSetVertex(vi,i,1,1);
- }
- }
- if (obj_use_z) sceGuEnable(GU_DEPTH_TEST);
- else sceGuDisable(GU_DEPTH_TEST);
- if (obj_use_blend) sceGuEnable(GU_BLEND);
- else sceGuDisable(GU_BLEND);
- if (obj_use_vert_color) sceGuColor(WHITE);
- else sceGuColor(obj_color);
- if (obj_use_tex) sceGuEnable(GU_TEXTURE_2D);
- else sceGuDisable(GU_TEXTURE_2D);
- if (obj_use_tex)
- {
- sceGuTexMode(GU_PSM_8888,0,0,0/*TODO swizzling*/);
- sceGuTexImage(0,obj_tex->tw,obj_tex->th,obj_tex->tw,obj_tex->data);
- }
- sceGuDrawArray(prim,v_type,v_nbr,NULL,v);
- obj_begin = G_FALSE;
- if (obj_use_z) zclear = G_TRUE;
- }
- void gReset()
- {
- gResetCoord();
- gResetScale();
- gResetColor();
- gResetAlpha();
- gResetRotation();
- }
- void gFlip(bool vsync)
- {
- sceGuFinish();
- sceGuSync(0,0);
- if (vsync) sceDisplayWaitVblankStart();
- sceGuSwapBuffers();
- start = G_FALSE;
- }
- void gAdd()
- {
- if (!obj_begin) return;
- if (obj_list_size >= obj_list_size_malloc)
- {
- obj_list_size_malloc += MALLOC_STEP;
- obj_list = realloc(obj_list,obj_list_size_malloc * sizeof(Obj_Properties));
- }
- CURRENT_OBJ.x = obj_x;
- CURRENT_OBJ.y = obj_y;
- CURRENT_OBJ.z = obj_z;
- CURRENT_OBJ.crop_x = obj_crop_x;
- CURRENT_OBJ.crop_y = obj_crop_y;
- CURRENT_OBJ.crop_w = obj_crop_w;
- CURRENT_OBJ.crop_h = obj_crop_h;
- CURRENT_OBJ.scale_w = obj_scale_w;
- CURRENT_OBJ.scale_h = obj_scale_h;
- CURRENT_OBJ.color = obj_color;
- CURRENT_OBJ.rot_x = obj_x;
- CURRENT_OBJ.rot_y = obj_y;
- CURRENT_OBJ.rot_sin = obj_rot_sin;
- CURRENT_OBJ.rot_cos = obj_rot_cos;
- // Coord mode stuff
- CURRENT_OBJ.x -= (obj_coord_mode == G_UP_RIGHT ||
- obj_coord_mode == G_DOWN_RIGHT) ?
- CURRENT_OBJ.scale_w :
- (obj_coord_mode == G_CENTER) ?
- CURRENT_OBJ.scale_w/2 : 0;
- CURRENT_OBJ.y -= (obj_coord_mode == G_DOWN_LEFT ||
- obj_coord_mode == G_DOWN_RIGHT) ?
- CURRENT_OBJ.scale_h :
- (obj_coord_mode == G_CENTER) ?
- CURRENT_OBJ.scale_h/2 : 0;
- // Alpha stuff
- CURRENT_OBJ.color = G_MODULATE(CURRENT_OBJ.color,255,obj_alpha);
- obj_list_size++;
- }
- void gPush()
- {
- if (transform_stack_size >= TRANSFORM_STACK_MAX) return;
- CURRENT_TRANSFORM.x = obj_x;
- CURRENT_TRANSFORM.y = obj_y;
- CURRENT_TRANSFORM.z = obj_z;
- CURRENT_TRANSFORM.rot = obj_rot;
- CURRENT_TRANSFORM.rot_sin = obj_rot_sin;
- CURRENT_TRANSFORM.rot_cos = obj_rot_cos;
- transform_stack_size++;
- }
- void gPop()
- {
- if (transform_stack_size <= 0) return;
- transform_stack_size--;
- obj_x = CURRENT_TRANSFORM.x;
- obj_y = CURRENT_TRANSFORM.y;
- obj_z = CURRENT_TRANSFORM.z;
- obj_rot = CURRENT_TRANSFORM.rot;
- obj_rot_sin = CURRENT_TRANSFORM.rot_sin;
- obj_rot_cos = CURRENT_TRANSFORM.rot_cos;
- }
- // * Coord functions *
- void gResetCoord()
- {
- obj_coord_mode = DEFAULT_COORD_MODE;
- obj_x = DEFAULT_X;
- obj_y = DEFAULT_Y;
- obj_z = DEFAULT_Z;
- }
- void gSetCoordMode(gEnum mode)
- {
- if (mode < G_UP_LEFT || mode > G_CENTER) return;
- obj_coord_mode = mode;
- }
- void gSetCoordXY(float x, float y)
- {
- obj_x = x;
- obj_y = y;
- obj_z = 0;
- }
- void gSetCoordXYZ(float x, float y, float z)
- {
- obj_x = x;
- obj_y = y;
- obj_z = z;
- obj_use_z = G_TRUE;
- }
- void gSetCoordXYRelative(float x, float y, bool use_rot)
- {
- if (!use_rot) gSetCoordXY(obj_x + x, obj_y + y);
- else gSetCoordXY(obj_x - obj_rot_sin*y + obj_rot_cos*x,
- obj_y + obj_rot_cos*y + obj_rot_sin*x);
- }
- void gSetCoordXYZRelative(float x, float y, float z, bool use_rot)
- {
- if (!use_rot) gSetCoordXYZ(obj_x + x, obj_y + y,obj_z + z);
- else gSetCoordXYZ(obj_x - obj_rot_sin*y + obj_rot_cos*x,
- obj_y + obj_rot_cos*y + obj_rot_sin*x,
- obj_z + z);
- }
- // * Scale functions *
- void gResetScale()
- {
- if (!obj_use_tex)
- {
- obj_scale_w = DEFAULT_SIDE;
- obj_scale_h = DEFAULT_SIDE;
- }
- else
- {
- obj_scale_w = obj_tex->w;
- obj_scale_h = obj_tex->h;
- }
- }
- void gSetScale(float w, float h)
- {
- gSetScaleRelative(w,h);
- }
- void gSetScaleWH(int w, int h)
- {
- obj_scale_w = w;
- obj_scale_h = h;
- }
- void gSetScaleRelative(float w, float h)
- {
- obj_scale_w *= w;
- obj_scale_h *= h;
- }
- void gSetScaleWHRelative(int w, int h)
- {
- obj_scale_w += w;
- obj_scale_h += h;
- }
- // * Color functions *
- void gResetColor()
- {
- obj_color = DEFAULT_COLOR;
- }
- void gResetAlpha()
- {
- obj_alpha = DEFAULT_ALPHA;
- }
- void gSetColor(gColor color)
- {
- obj_color = color;
- if (++obj_colors_count > 1) obj_use_vert_color = G_TRUE;
- if (G_GET_A(obj_color) < 255) obj_use_blend = G_TRUE;
- }
- void gSetAlpha(gAlpha alpha)
- {
- obj_alpha = alpha;
- if (obj_alpha > 255) obj_alpha = 255;
- else if (obj_alpha < 0) obj_alpha = 0;
- if (++obj_alpha_count > 1) obj_use_vert_color = G_TRUE;
- if (obj_alpha < 255) obj_use_blend = G_TRUE;
- }
- void gSetAlphaRelative(gAlpha alpha)
- {
- gSetAlpha(obj_alpha + alpha);
- }
- // * Rotations functions *
- void gResetRotation()
- {
- obj_rot = 0.f;
- obj_rot_sin = 0.f;
- obj_rot_cos = 1.f;
- }
- void gSetRotationRad(float radians)
- {
- if (radians == obj_rot) return;
- obj_rot = radians;
- obj_rot_sin = sinf(radians);
- obj_rot_cos = cosf(radians);
- obj_use_rot = G_TRUE;
- }
- void gSetRotation(float degrees)
- {
- gSetRotationRad(degrees * GU_PI / 180.f);
- }
- void gSetRotationRadRelative(float radians)
- {
- gSetRotationRad(obj_rot + radians);
- }
- void gSetRotationRelative(float degrees)
- {
- gSetRotationRadRelative(degrees * GU_PI / 180.f);
- }
- // * Crop functions *
- void gResetCrop()
- {
- if (!obj_use_tex) return;
- obj_crop_x = 0;
- obj_crop_y = 0;
- obj_crop_w = obj_tex->w;
- obj_crop_h = obj_tex->h;
- }
- // TODO limits
- void gSetCropXY(int x, int y)
- {
- obj_crop_x = x;
- obj_crop_y = y;
- }
- void gSetCropWH(int w, int h)
- {
- obj_crop_w = w;
- obj_crop_h = h;
- }
- void gSetCropXYRelative(int x, int y)
- {
- gSetCropXY(obj_crop_x + x, obj_crop_y + y);
- }
- void gSetCropWHRelative(int w, int h)
- {
- gSetCropWH(obj_crop_w + w, obj_crop_h + h);
- }
- // * Texture functions *
- int _getNextPower2(int n)
- {
- int p=1;
- while ((p <<= 1) < n);
- return 128;
- }
- gImage* gTexLoad(char path[], bool swizzle)
- {
- 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;
- u32* line;
- FILE *fp;
- // Open & allocate memory
- if ((fp = fopen(path,"rb")) == NULL) return NULL;
- gImage* image = malloc(sizeof(gImage));
- if (!image) return NULL;
- // Init & read image infos
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
- png_set_error_fn(png_ptr,NULL,NULL,NULL);
- info_ptr = png_create_info_struct(png_ptr);
- png_init_io(png_ptr,fp);
- png_set_sig_bytes(png_ptr,sig_read);
- png_read_info(png_ptr,info_ptr);
- png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,
- &interlace_type,NULL,NULL);
- png_set_strip_16(png_ptr);
- png_set_packing(png_ptr);
- if (color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_palette_to_rgb(png_ptr);
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
- png_set_gray_1_2_4_to_8(png_ptr);
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
- png_set_tRNS_to_alpha(png_ptr);
- png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
- // Image is too big for the PSP, abort
- if (width > 512 || height > 512)
- {
- free(image);
- fclose(fp);
- png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
- return NULL;
- }
- image->w = width;
- image->h = height;
- image->tw = _getNextPower2(width);
- image->th = _getNextPower2(height);
- image->ratio = (float)width / height;
- // Get image data
- image->data = memalign(16, image->tw * image->th * sizeof(gColor));
- line = malloc(width * 4);
- for (y = 0; y < height; y++) {
- png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
- for (x = 0; x < width; x++) {
- u32 color = line[x];
- image->data[x + y * image->tw] = color;
- }
- }
- // Free
- free(line);
- png_read_end(png_ptr, info_ptr);
- png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
- fclose(fp);
- // Writeback cache to ram
- sceKernelDcacheWritebackAll();
- return image;
- }
- // EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement