Advertisement
GeeckoDev

glib2d.c term

Mar 19th, 2012
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 26.19 KB | None | 0 0
  1. // gLib2D by Geecko - A simple, fast, light-weight 2D graphics library.
  2. //
  3. // This work is licensed under the Creative Commons BY-SA 3.0 Unported License.
  4. // See LICENSE for more details.
  5. //
  6. // Please report bugs at : geecko.dev@free.fr
  7.  
  8. #include "glib2d.h"
  9.  
  10. #include <pspkernel.h>
  11. #include <pspdisplay.h>
  12. #include <pspgu.h>
  13. #include <vram.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16.  
  17. #ifdef USE_PNG
  18. #include <png.h>
  19. #endif
  20.  
  21. #ifdef USE_JPEG
  22. #include <jpeglib.h>
  23. #endif
  24.  
  25. #define PSP_LINE_SIZE       (512)
  26. #define PIXEL_SIZE          (4)
  27. #define FRAMEBUFFER_SIZE    (PSP_LINE_SIZE*G2D_SCR_H*PIXEL_SIZE)
  28. #define MALLOC_STEP         (128)
  29. #define TRANSFORM_STACK_MAX (64)
  30. #define SLICE_WIDTH         (64)
  31. #define M_180_PI            (57.29578f)
  32. #define M_PI_180            (0.017453292f)
  33.  
  34. #define DEFAULT_SIZE       (10)
  35. #define DEFAULT_COORD_MODE (G2D_UP_LEFT)
  36. #define DEFAULT_X          (0.f)
  37. #define DEFAULT_Y          (0.f)
  38. #define DEFAULT_Z          (0.f)
  39. #define DEFAULT_COLOR      (WHITE)
  40. #define DEFAULT_ALPHA      (0xFF)
  41.  
  42. #define CURRENT_OBJ obj_list[obj_list_size-1]
  43. #define CURRENT_TRANSFORM transform_stack[transform_stack_size-1]
  44. #define I_OBJ obj_list[i]
  45.  
  46. typedef enum
  47. {
  48.   RECTS, LINES, QUADS, POINTS
  49. } Obj_Type;
  50.  
  51. typedef struct
  52. {
  53.   float x, y, z;
  54.   float rot, rot_sin, rot_cos;
  55.   float scale_w, scale_h;
  56. } Transform;
  57.  
  58. typedef struct
  59. {
  60.   float x, y, z;
  61.   float rot_x, rot_y; // Rotation center
  62.   float rot, rot_sin, rot_cos;
  63.   int crop_x, crop_y;
  64.   int crop_w, crop_h;
  65.   float scale_w, scale_h;
  66.   g2dColor color;
  67.   g2dAlpha alpha;
  68. } Object;
  69.  
  70.  
  71. // * Main vars *
  72. static int* list;
  73. static bool init = false, start = false, zclear = true, scissor = false;
  74. static Transform transform_stack[TRANSFORM_STACK_MAX];
  75. static int transform_stack_size;
  76. static float global_scale = 1.f;
  77. // * Object vars *
  78. static Object *obj_list = NULL, obj;
  79. static Obj_Type obj_type;
  80. static int obj_list_size;
  81. static bool obj_begin = false, obj_line_strip;
  82. static bool obj_use_z, obj_use_vert_color, obj_use_blend, obj_use_rot,
  83.             obj_use_tex_linear, obj_use_tex_repeat, obj_use_int;
  84. static g2dCoord_Mode obj_coord_mode;
  85. static int obj_colors_count;
  86. static g2dImage* obj_tex;
  87.  
  88. g2dImage g2d_draw_buffer = { 512, 512, G2D_SCR_W, G2D_SCR_H,
  89.                              (float)G2D_SCR_W/G2D_SCR_H, false, false,
  90.                              (g2dColor*)FRAMEBUFFER_SIZE },
  91.          g2d_disp_buffer = { 512, 512, G2D_SCR_W, G2D_SCR_H,
  92.                              (float)G2D_SCR_W/G2D_SCR_H, false, false,
  93.                              (g2dColor*)0 };
  94.  
  95. // * Internal functions *
  96.  
  97. void _g2dStart()
  98. {
  99.   if (!init) g2dInit();
  100.  
  101.   sceKernelDcacheWritebackAll();
  102.   sceGuStart(GU_DIRECT,list);
  103.   start = true;
  104. }
  105.  
  106.  
  107. // Vertex order: [texture uv] [color] [vertex]
  108. void* _g2dSetVertex(void* vp, int i, float vx, float vy)
  109. {
  110.   short* v_p_short = vp;
  111.   g2dColor* v_p_color;
  112.   float* v_p_float;
  113.  
  114.   // Texture
  115.   if (obj_tex != NULL)
  116.   {
  117.     *(v_p_short++) = I_OBJ.crop_x + vx * I_OBJ.crop_w;
  118.     *(v_p_short++) = I_OBJ.crop_y + vy * I_OBJ.crop_h;
  119.   }
  120.  
  121.   // Color
  122.   v_p_color = (g2dColor*)v_p_short;
  123.  
  124.   if (obj_use_vert_color)
  125.   {
  126.     *(v_p_color++) = I_OBJ.color;
  127.   }
  128.  
  129.   // Coord
  130.   v_p_float = (float*)v_p_color;
  131.  
  132.   v_p_float[0] = I_OBJ.x + (obj_type == RECTS ? vx * I_OBJ.scale_w : 0.f);
  133.   v_p_float[1] = I_OBJ.y + (obj_type == RECTS ? vy * I_OBJ.scale_h : 0.f);
  134.  
  135.   // Then apply the rotation
  136.   if (obj_use_rot && obj_type == RECTS)
  137.   {
  138.     float tx = v_p_float[0]-I_OBJ.rot_x, ty = v_p_float[1]-I_OBJ.rot_y;
  139.     v_p_float[0] = I_OBJ.rot_x - I_OBJ.rot_sin*ty + I_OBJ.rot_cos*tx,
  140.     v_p_float[1] = I_OBJ.rot_y + I_OBJ.rot_cos*ty + I_OBJ.rot_sin*tx;
  141.   }
  142.  
  143.   if (obj_use_int)
  144.   {
  145.     v_p_float[0] = floorf(v_p_float[0]);
  146.     v_p_float[1] = floorf(v_p_float[1]);
  147.   }
  148.   v_p_float[2] = I_OBJ.z;
  149.  
  150.   v_p_float += 3;
  151.  
  152.   return (void*)v_p_float;
  153. }
  154.  
  155.  
  156. #ifdef USE_VFPU
  157. void vfpu_sincosf(float x, float* s, float* c)
  158. {
  159.   __asm__ volatile (
  160.     "mtv    %2, s000\n"          // s000 = x
  161.     "vcst.s s001, VFPU_2_PI\n"   // s001 = 2/pi
  162.     "vmul.s s000, s000, s001\n"  // s000 = s000*s001
  163.     "vrot.p c010, s000, [s,c]\n" // s010 = sinf(s000), s011 = cosf(s000)
  164.     "mfv    %0, s010\n"          // *s = s010
  165.     "mfv    %1, S011\n"          // *c = s011
  166.     : "=r"(*s), "=r"(*c) : "r"(x)
  167.   );
  168. }
  169. #endif
  170.  
  171. // * Main functions *
  172.  
  173. void g2dInit()
  174. {
  175.   if (init) return;
  176.  
  177.   // Display list allocation
  178.   list = malloc(256*1024);
  179.  
  180.   // Init & setup GU
  181.   sceGuInit();
  182.   sceGuStart(GU_DIRECT,list);
  183.  
  184.   sceGuDrawBuffer(GU_PSM_8888,g2d_draw_buffer.data,PSP_LINE_SIZE);
  185.   sceGuDispBuffer(G2D_SCR_W,G2D_SCR_H,g2d_disp_buffer.data,PSP_LINE_SIZE);
  186.   sceGuDepthBuffer((void*)(FRAMEBUFFER_SIZE*2),PSP_LINE_SIZE);
  187.   sceGuOffset(2048-(G2D_SCR_W/2),2048-(G2D_SCR_H/2));
  188.   sceGuViewport(2048,2048,G2D_SCR_W,G2D_SCR_H);
  189.  
  190.   g2d_draw_buffer.data = vabsptr(g2d_draw_buffer.data);
  191.   g2d_disp_buffer.data = vabsptr(g2d_disp_buffer.data);
  192.  
  193.   g2dResetScissor();
  194.   sceGuDepthRange(65535,0);
  195.   sceGuClearDepth(65535);
  196.   sceGuAlphaFunc(GU_GREATER,0,0xff);
  197.   sceGuDepthFunc(GU_LEQUAL);
  198.   sceGuBlendFunc(GU_ADD,GU_SRC_ALPHA,GU_ONE_MINUS_SRC_ALPHA,0,0);
  199.   sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA);
  200.   sceGuTexFilter(GU_LINEAR,GU_LINEAR);
  201.   sceGuShadeModel(GU_SMOOTH);
  202.  
  203.   sceGuDisable(GU_CULL_FACE);
  204.   sceGuDisable(GU_CLIP_PLANES);
  205.   sceGuDisable(GU_DITHER);
  206.   sceGuEnable(GU_ALPHA_TEST);
  207.   sceGuEnable(GU_SCISSOR_TEST);
  208.   sceGuEnable(GU_BLEND);
  209.  
  210.   sceGuFinish();
  211.   sceGuSync(0,0);
  212.   sceDisplayWaitVblankStart();
  213.   sceGuDisplay(GU_TRUE);
  214.  
  215.   init = true;
  216. }
  217.  
  218.  
  219. void g2dTerm()
  220. {
  221.   if (!init) return;
  222.  
  223.   sceGuTerm();
  224.  
  225.   free(list);
  226.  
  227.   init = false;
  228. }
  229.  
  230.  
  231. void g2dClear(g2dColor color)
  232. {
  233.   if (!start) _g2dStart();
  234.  
  235.   sceGuClearColor(color);
  236.   sceGuClear(GU_COLOR_BUFFER_BIT | GU_FAST_CLEAR_BIT
  237.              | (zclear ? GU_DEPTH_BUFFER_BIT : 0));
  238.   zclear = false;
  239. }
  240.  
  241.  
  242. void g2dClearZ()
  243. {
  244.   if (!start) _g2dStart();
  245.  
  246.   sceGuClear(GU_DEPTH_BUFFER_BIT | GU_FAST_CLEAR_BIT);
  247.   zclear = true;
  248. }
  249.  
  250.  
  251. void _g2dBeginCommon()
  252. {
  253.   if (!start) _g2dStart();
  254.  
  255.   obj_list_size = 0;
  256.   obj_list = realloc(obj_list,MALLOC_STEP * sizeof(Object));
  257.  
  258.   obj_use_z = false;
  259.   obj_use_vert_color = false;
  260.   obj_use_blend = false;
  261.   obj_use_rot = false;
  262.   obj_use_int = false;
  263.   obj_colors_count = 0;
  264.   g2dReset();
  265.  
  266.   obj_begin = true;
  267. }
  268.  
  269.  
  270. void g2dBeginRects(g2dImage* tex)
  271. {
  272.   if (obj_begin) return;
  273.  
  274.   obj_type = RECTS;
  275.   obj_tex = tex;
  276.   _g2dBeginCommon();
  277. }
  278.  
  279.  
  280. void g2dBeginLines(g2dLine_Mode mode)
  281. {
  282.   if (obj_begin) return;
  283.  
  284.   obj_type = LINES;
  285.   obj_tex = NULL;
  286.   obj_line_strip = (mode & G2D_STRIP);
  287.   _g2dBeginCommon();
  288. }
  289.  
  290.  
  291. void g2dBeginQuads(g2dImage* tex)
  292. {
  293.   if (obj_begin) return;
  294.  
  295.   obj_type = QUADS;
  296.   obj_tex = tex;
  297.   _g2dBeginCommon();
  298. }
  299.  
  300.  
  301. void g2dBeginPoints()
  302. {
  303.   if (obj_begin) return;
  304.  
  305.   obj_type = POINTS;
  306.   obj_tex = NULL;
  307.   _g2dBeginCommon();
  308. }
  309.  
  310.  
  311. void _g2dEndRects()
  312. {
  313.   // Define vertices properties
  314.   int prim = (obj_use_rot ? GU_TRIANGLES : GU_SPRITES),
  315.       v_obj_nbr = (obj_use_rot ? 6 : 2),
  316.       v_nbr,
  317.       v_coord_size = 3,
  318.       v_tex_size = (obj_tex != NULL ? 2 : 0),
  319.       v_color_size = (obj_use_vert_color ? 1 : 0),
  320.       v_size = v_tex_size * sizeof(short) +
  321.                v_color_size * sizeof(g2dColor) +
  322.                v_coord_size * sizeof(float),
  323.       v_type = GU_VERTEX_32BITF | GU_TRANSFORM_2D,
  324.       n_slices = -1, i;
  325.  
  326.   if (obj_tex != NULL)    v_type |= GU_TEXTURE_16BIT;
  327.   if (obj_use_vert_color) v_type |= GU_COLOR_8888;
  328.  
  329.   // Count how many vertices to allocate.
  330.   if (obj_tex == NULL || obj_use_rot) // No slicing
  331.   {
  332.     v_nbr = v_obj_nbr * obj_list_size;
  333.   }
  334.   else // Can use texture slicing for tremendous performance :)
  335.   {
  336.     for (n_slices=0, i=0; i!=obj_list_size; i++)
  337.     {
  338.       n_slices += (int)(I_OBJ.crop_w/SLICE_WIDTH)+1;
  339.     }
  340.     v_nbr = v_obj_nbr * n_slices;
  341.   }
  342.  
  343.   // Allocate vertex list memory
  344.   void *v = sceGuGetMemory(v_nbr * v_size), *vi = v;
  345.  
  346.   // Build the vertex list
  347.   for (i=0; i<obj_list_size; i+=1)
  348.   {
  349.     if (!obj_use_rot)
  350.     {
  351.       if (obj_tex == NULL)
  352.       {
  353.         vi = _g2dSetVertex(vi,i,0.f,0.f);
  354.         vi = _g2dSetVertex(vi,i,1.f,1.f);
  355.       }
  356.       else // Use texture slicing
  357.       {
  358.         float u, step = (float)SLICE_WIDTH/I_OBJ.crop_w;
  359.         for (u=0.f; u<1.f; u+=step)
  360.         {
  361.           vi = _g2dSetVertex(vi,i,u,0.f);
  362.           vi = _g2dSetVertex(vi,i,((u+step) > 1.f ? 1.f : u+step),1.f);
  363.         }
  364.       }
  365.     }
  366.     else // Rotation : draw 2 triangles per obj
  367.     {
  368.       vi = _g2dSetVertex(vi,i,0.f,0.f);
  369.       vi = _g2dSetVertex(vi,i,1.f,0.f);
  370.       vi = _g2dSetVertex(vi,i,0.f,1.f);
  371.       vi = _g2dSetVertex(vi,i,0.f,1.f);
  372.       vi = _g2dSetVertex(vi,i,1.f,0.f);
  373.       vi = _g2dSetVertex(vi,i,1.f,1.f);
  374.     }
  375.   }
  376.  
  377.   // Then put it in the display list.
  378.   sceGuDrawArray(prim,v_type,v_nbr,NULL,v);
  379. }
  380.  
  381.  
  382. void _g2dEndLines()
  383. {
  384.   // Define vertices properties
  385.   int prim = (obj_line_strip ? GU_LINE_STRIP : GU_LINES),
  386.       v_obj_nbr = (obj_line_strip ? 1 : 2),
  387.       v_nbr = v_obj_nbr * (obj_line_strip ? obj_list_size
  388.                                           : obj_list_size / 2),
  389.       v_coord_size = 3,
  390.       v_color_size = (obj_use_vert_color ? 1 : 0),
  391.       v_size = v_color_size * sizeof(g2dColor) +
  392.                v_coord_size * sizeof(float),
  393.       v_type = GU_VERTEX_32BITF | GU_TRANSFORM_2D,
  394.       i;
  395.  
  396.   if (obj_use_vert_color) v_type |= GU_COLOR_8888;
  397.  
  398.   // Allocate vertex list memory
  399.   void *v = sceGuGetMemory(v_nbr * v_size), *vi = v;
  400.  
  401.   // Build the vertex list
  402.   if (obj_line_strip)
  403.   {
  404.     vi = _g2dSetVertex(vi,0,0.f,0.f);
  405.     for (i=1; i<obj_list_size; i+=1)
  406.     {
  407.       vi = _g2dSetVertex(vi,i,0.f,0.f);
  408.     }
  409.   }
  410.   else
  411.   {
  412.     for (i=0; i+1<obj_list_size; i+=2)
  413.     {
  414.       vi = _g2dSetVertex(vi,i  ,0.f,0.f);
  415.       vi = _g2dSetVertex(vi,i+1,0.f,0.f);
  416.     }
  417.   }
  418.  
  419.   // Then put it in the display list.
  420.   sceGuDrawArray(prim,v_type,v_nbr,NULL,v);
  421. }
  422.  
  423.  
  424. void _g2dEndQuads()
  425. {
  426.   // Define vertices properties
  427.   int prim = GU_TRIANGLES,
  428.       v_obj_nbr = 6,
  429.       v_nbr = v_obj_nbr * (obj_list_size / 4),
  430.       v_coord_size = 3,
  431.       v_tex_size = (obj_tex != NULL ? 2 : 0),
  432.       v_color_size = (obj_use_vert_color ? 1 : 0),
  433.       v_size = v_tex_size * sizeof(short) +
  434.                v_color_size * sizeof(g2dColor) +
  435.                v_coord_size * sizeof(float),
  436.       v_type = GU_VERTEX_32BITF | GU_TRANSFORM_2D,
  437.       i;
  438.  
  439.   if (obj_tex != NULL)    v_type |= GU_TEXTURE_16BIT;
  440.   if (obj_use_vert_color) v_type |= GU_COLOR_8888;
  441.  
  442.   // Allocate vertex list memory
  443.   void *v = sceGuGetMemory(v_nbr * v_size), *vi = v;
  444.  
  445.   // Build the vertex list
  446.   for (i=0; i+3<obj_list_size; i+=4)
  447.   {
  448.     vi = _g2dSetVertex(vi,i  ,0.f,0.f);
  449.     vi = _g2dSetVertex(vi,i+1,1.f,0.f);
  450.     vi = _g2dSetVertex(vi,i+3,0.f,1.f);
  451.     vi = _g2dSetVertex(vi,i+3,0.f,1.f);
  452.     vi = _g2dSetVertex(vi,i+1,1.f,0.f);
  453.     vi = _g2dSetVertex(vi,i+2,1.f,1.f);
  454.   }
  455.  
  456.   // Then put it in the display list.
  457.   sceGuDrawArray(prim,v_type,v_nbr,NULL,v);
  458. }
  459.  
  460.  
  461. void _g2dEndPoints()
  462. {
  463.   // Define vertices properties
  464.   int prim = GU_POINTS,
  465.       v_obj_nbr = 1,
  466.       v_nbr = v_obj_nbr * obj_list_size,
  467.       v_coord_size = 3,
  468.       v_color_size = (obj_use_vert_color ? 1 : 0),
  469.       v_size = v_color_size * sizeof(g2dColor) +
  470.                v_coord_size * sizeof(float),
  471.       v_type = GU_VERTEX_32BITF | GU_TRANSFORM_2D,
  472.       i;
  473.  
  474.   if (obj_use_vert_color) v_type |= GU_COLOR_8888;
  475.  
  476.   // Allocate vertex list memory
  477.   void *v = sceGuGetMemory(v_nbr * v_size), *vi = v;
  478.  
  479.   // Build the vertex list
  480.   for (i=0; i<obj_list_size; i+=1)
  481.   {
  482.     vi = _g2dSetVertex(vi,i,0.f,0.f);
  483.   }
  484.  
  485.   // Then put it in the display list.
  486.   sceGuDrawArray(prim,v_type,v_nbr,NULL,v);
  487. }
  488.  
  489.  
  490. void g2dEnd()
  491. {
  492.   if (!obj_begin || obj_list_size <= 0)
  493.   {
  494.     obj_begin = false;
  495.     return;
  496.   }
  497.  
  498.   // Manage pspgu extensions
  499.   if (obj_use_z)          sceGuEnable(GU_DEPTH_TEST);
  500.   else                    sceGuDisable(GU_DEPTH_TEST);
  501.   if (obj_use_blend)      sceGuEnable(GU_BLEND);
  502.   else                    sceGuDisable(GU_BLEND);
  503.   if (obj_use_vert_color) sceGuColor(WHITE);
  504.   else                    sceGuColor(obj_list[0].color);
  505.   if (obj_tex == NULL)    sceGuDisable(GU_TEXTURE_2D);
  506.   else
  507.   {
  508.     sceGuEnable(GU_TEXTURE_2D);
  509.     if (obj_use_tex_linear) sceGuTexFilter(GU_LINEAR,GU_LINEAR);
  510.     else                    sceGuTexFilter(GU_NEAREST,GU_NEAREST);
  511.     if (obj_use_tex_repeat) sceGuTexWrap(GU_REPEAT,GU_REPEAT);
  512.     else                    sceGuTexWrap(GU_CLAMP,GU_CLAMP);
  513.     // Load texture
  514.     sceGuTexMode(GU_PSM_8888,0,0,obj_tex->swizzled);
  515.     sceGuTexImage(0,obj_tex->tw,obj_tex->th,obj_tex->tw,obj_tex->data);
  516.   }
  517.  
  518.   switch (obj_type)
  519.   {
  520.     case RECTS:  _g2dEndRects();  break;
  521.     case LINES:  _g2dEndLines();  break;
  522.     case QUADS:  _g2dEndQuads();  break;
  523.     case POINTS: _g2dEndPoints(); break;
  524.   }
  525.  
  526.   sceGuColor(WHITE);
  527.   sceGuEnable(GU_BLEND);
  528.  
  529.   obj_begin = false;
  530.   if (obj_use_z) zclear = true;
  531. }
  532.  
  533.  
  534. void g2dReset()
  535. {
  536.   g2dResetCoord();
  537.   g2dResetScale();
  538.   g2dResetColor();
  539.   g2dResetAlpha();
  540.   g2dResetRotation();
  541.   g2dResetCrop();
  542.   g2dResetTex();
  543. }
  544.  
  545.  
  546. void g2dFlip(g2dFlip_Mode mode)
  547. {
  548.   if (scissor) g2dResetScissor();
  549.  
  550.   sceGuFinish();
  551.   sceGuSync(0,0);
  552.   if (mode & G2D_VSYNC) sceDisplayWaitVblankStart();
  553.  
  554.   g2d_disp_buffer.data = g2d_draw_buffer.data;
  555.   g2d_draw_buffer.data = vabsptr(sceGuSwapBuffers());
  556.  
  557.   start = false;
  558. }
  559.  
  560.  
  561. void g2dAdd()
  562. {
  563.   if (!obj_begin) return;
  564.   if (obj.scale_w == 0 || obj.scale_h == 0) return;
  565.  
  566.   if (!(obj_list_size % MALLOC_STEP))
  567.   {
  568.     obj_list = realloc(obj_list,(obj_list_size+MALLOC_STEP) * sizeof(Object));
  569.   }
  570.  
  571.   obj_list_size++;
  572.   obj.rot_x = obj.x;
  573.   obj.rot_y = obj.y;
  574.   CURRENT_OBJ = obj;
  575.  
  576.   // Coord mode stuff
  577.   CURRENT_OBJ.x -= (obj_coord_mode == G2D_UP_RIGHT ||
  578.                     obj_coord_mode == G2D_DOWN_RIGHT ?
  579.                     CURRENT_OBJ.scale_w :
  580.                    (obj_coord_mode == G2D_CENTER ?
  581.                     CURRENT_OBJ.scale_w/2 : 0));
  582.   CURRENT_OBJ.y -= (obj_coord_mode == G2D_DOWN_LEFT ||
  583.                     obj_coord_mode == G2D_DOWN_RIGHT ?
  584.                     CURRENT_OBJ.scale_h :
  585.                    (obj_coord_mode == G2D_CENTER ?
  586.                     CURRENT_OBJ.scale_h/2 : 0));
  587.  
  588.   // Alpha stuff
  589.   CURRENT_OBJ.color = G2D_MODULATE(CURRENT_OBJ.color,255,obj.alpha);
  590. }
  591.  
  592.  
  593. void g2dPush()
  594. {
  595.   if (transform_stack_size >= TRANSFORM_STACK_MAX) return;
  596.   transform_stack_size++;
  597.   CURRENT_TRANSFORM.x = obj.x;
  598.   CURRENT_TRANSFORM.y = obj.y;
  599.   CURRENT_TRANSFORM.z = obj.z;
  600.   CURRENT_TRANSFORM.rot = obj.rot;
  601.   CURRENT_TRANSFORM.rot_sin = obj.rot_sin;
  602.   CURRENT_TRANSFORM.rot_cos = obj.rot_cos;
  603.   CURRENT_TRANSFORM.scale_w = obj.scale_w;
  604.   CURRENT_TRANSFORM.scale_h = obj.scale_h;
  605. }
  606.  
  607.  
  608. void g2dPop()
  609. {
  610.   if (transform_stack_size <= 0) return;
  611.   obj.x = CURRENT_TRANSFORM.x;
  612.   obj.y = CURRENT_TRANSFORM.y;
  613.   obj.z = CURRENT_TRANSFORM.z;
  614.   obj.rot = CURRENT_TRANSFORM.rot;
  615.   obj.rot_sin = CURRENT_TRANSFORM.rot_sin;
  616.   obj.rot_cos = CURRENT_TRANSFORM.rot_cos;
  617.   obj.scale_w = CURRENT_TRANSFORM.scale_w;
  618.   obj.scale_h = CURRENT_TRANSFORM.scale_h;
  619.   if (obj.rot != 0.f) obj_use_rot = true;
  620.   if (obj.z != 0.f) obj_use_z = true;
  621.   transform_stack_size--;
  622. }
  623.  
  624. // * Coord functions *
  625.  
  626. void g2dResetCoord()
  627. {
  628.   obj_coord_mode = DEFAULT_COORD_MODE;
  629.   obj.x = DEFAULT_X;
  630.   obj.y = DEFAULT_Y;
  631.   obj.z = DEFAULT_Z;
  632. }
  633.  
  634.  
  635. void g2dSetCoordMode(g2dCoord_Mode mode)
  636. {
  637.   if (mode > G2D_CENTER) return;
  638.   obj_coord_mode = mode;
  639. }
  640.  
  641.  
  642. void g2dGetCoordXYZ(float* x, float* y, float* z)
  643. {
  644.   if (x != NULL) *x = obj.x;
  645.   if (y != NULL) *y = obj.y;
  646.   if (z != NULL) *z = obj.z;
  647. }
  648.  
  649.  
  650. void g2dSetCoordXY(float x, float y)
  651. {
  652.   obj.x = x * global_scale;
  653.   obj.y = y * global_scale;
  654.   obj.z = 0.f;
  655. }
  656.  
  657.  
  658. void g2dSetCoordXYZ(float x, float y, float z)
  659. {
  660.   obj.x = x * global_scale;
  661.   obj.y = y * global_scale;
  662.   obj.z = z * global_scale;
  663.   if (z != 0.f) obj_use_z = true;
  664. }
  665.  
  666.  
  667. void g2dSetCoordXYRelative(float x, float y)
  668. {
  669.   float inc_x = x, inc_y = y;
  670.   if (obj.rot_cos != 1.f)
  671.   {
  672.     inc_x = -obj.rot_sin*y + obj.rot_cos*x;
  673.     inc_y =  obj.rot_cos*y + obj.rot_sin*x;
  674.   }
  675.   obj.x += inc_x * global_scale;
  676.   obj.y += inc_y * global_scale;
  677. }
  678.  
  679.  
  680. void g2dSetCoordXYZRelative(float x, float y, float z)
  681. {
  682.   g2dSetCoordXYRelative(x,y);
  683.   obj.z += z * global_scale;
  684.   if (z != 0.f) obj_use_z = true;
  685. }
  686.  
  687.  
  688. void g2dSetCoordInteger(bool use)
  689. {
  690.   obj_use_int = use;
  691. }
  692.  
  693. // * Scale functions *
  694.  
  695. void g2dResetGlobalScale()
  696. {
  697.   global_scale = 1.f;
  698. }
  699.  
  700.  
  701. void g2dResetScale()
  702. {
  703.   if (obj_tex == NULL)
  704.   {
  705.     obj.scale_w = DEFAULT_SIZE;
  706.     obj.scale_h = DEFAULT_SIZE;
  707.   }
  708.   else
  709.   {
  710.     obj.scale_w = obj_tex->w;
  711.     obj.scale_h = obj_tex->h;
  712.   }
  713.  
  714.   obj.scale_w *= global_scale;
  715.   obj.scale_h *= global_scale;
  716. }
  717.  
  718.  
  719. void g2dGetGlobalScale(float* scale)
  720. {
  721.   if (scale != NULL) *scale = global_scale;
  722. }
  723.  
  724.  
  725. void g2dGetScaleWH(float* w, float* h)
  726. {
  727.   if (w != NULL) *w = obj.scale_w;
  728.   if (h != NULL) *h = obj.scale_h;
  729. }
  730.  
  731.  
  732. void g2dSetGlobalScale(float scale)
  733. {
  734.   global_scale = scale;
  735. }
  736.  
  737.  
  738. void g2dSetScale(float w, float h)
  739. {
  740.   g2dResetScale();
  741.   g2dSetScaleRelative(w,h);
  742. }
  743.  
  744.  
  745. void g2dSetScaleWH(float w, float h)
  746. {
  747.   obj.scale_w = w * global_scale;
  748.   obj.scale_h = h * global_scale;
  749.   // A trick to prevent an unexpected behavior when mirroring with GU_SPRITES.
  750.   if (obj.scale_w < 0 || obj.scale_h < 0) obj_use_rot = true;
  751. }
  752.  
  753.  
  754. void g2dSetScaleRelative(float w, float h)
  755. {
  756.   obj.scale_w *= w;
  757.   obj.scale_h *= h;
  758.  
  759.   if (obj.scale_w < 0 || obj.scale_h < 0) obj_use_rot = true;
  760. }
  761.  
  762.  
  763. void g2dSetScaleWHRelative(float w, float h)
  764. {
  765.   obj.scale_w += w * global_scale;
  766.   obj.scale_h += h * global_scale;
  767.  
  768.   if (obj.scale_w < 0 || obj.scale_h < 0) obj_use_rot = true;
  769. }
  770.  
  771. // * Color functions *
  772.  
  773. void g2dResetColor()
  774. {
  775.   obj.color = DEFAULT_COLOR;
  776. }
  777.  
  778.  
  779. void g2dResetAlpha()
  780. {
  781.   obj.alpha = DEFAULT_ALPHA;
  782. }
  783.  
  784.  
  785. void g2dGetAlpha(g2dAlpha* alpha)
  786. {
  787.   if (alpha != NULL) *alpha = obj.alpha;
  788. }
  789.  
  790.  
  791. void g2dSetColor(g2dColor color)
  792. {
  793.   obj.color = color;
  794.   if (++obj_colors_count > 1) obj_use_vert_color = true;
  795.   if (G2D_GET_A(obj.color) < 255) obj_use_blend = true;
  796. }
  797.  
  798.  
  799. void g2dSetAlpha(g2dAlpha alpha)
  800. {
  801.   if (alpha < 0) alpha = 0;
  802.   if (alpha > 255) alpha = 255;
  803.   obj.alpha = alpha;
  804.   if (++obj_colors_count > 1) obj_use_vert_color = true;
  805.   if (obj.alpha < 255) obj_use_blend = true;
  806. }
  807.  
  808.  
  809. void g2dSetAlphaRelative(int alpha)
  810. {
  811.   g2dSetAlpha(obj.alpha + alpha);
  812. }
  813.  
  814. // * Rotations functions *
  815.  
  816. void g2dResetRotation()
  817. {
  818.   obj.rot = 0.f;
  819.   obj.rot_sin = 0.f;
  820.   obj.rot_cos = 1.f;
  821. }
  822.  
  823.  
  824. void g2dGetRotationRad(float* radians)
  825. {
  826.   if (radians != NULL) *radians = obj.rot;
  827. }
  828.  
  829.  
  830. void g2dGetRotation(float* degrees)
  831. {
  832.   if (degrees != NULL) *degrees = obj.rot * M_180_PI;
  833. }
  834.  
  835.  
  836. void g2dSetRotationRad(float radians)
  837. {
  838.   if (radians == obj.rot) return;
  839.   obj.rot = radians;
  840.   #ifdef USE_VFPU
  841.   vfpu_sincosf(radians, &obj.rot_sin, &obj.rot_cos);
  842.   #else
  843.   sincosf(radians, &obj.rot_sin, &obj.rot_cos);
  844.   #endif
  845.   if (radians != 0.f) obj_use_rot = true;
  846. }
  847.  
  848.  
  849. void g2dSetRotation(float degrees)
  850. {
  851.   g2dSetRotationRad(degrees * M_PI_180);
  852. }
  853.  
  854.  
  855. void g2dSetRotationRadRelative(float radians)
  856. {
  857.   g2dSetRotationRad(obj.rot + radians);
  858. }
  859.  
  860.  
  861. void g2dSetRotationRelative(float degrees)
  862. {
  863.   g2dSetRotationRadRelative(degrees * M_PI_180);
  864. }
  865.  
  866. // * Crop functions *
  867.  
  868. void g2dResetCrop()
  869. {
  870.   if (obj_tex == NULL) return;
  871.   obj.crop_x = 0;
  872.   obj.crop_y = 0;
  873.   obj.crop_w = obj_tex->w;
  874.   obj.crop_h = obj_tex->h;
  875. }
  876.  
  877.  
  878. void g2dGetCropXY(int* x, int* y)
  879. {
  880.   if (obj_tex == NULL) return;
  881.   if (x != NULL) *x = obj.crop_x;
  882.   if (y != NULL) *y = obj.crop_y;
  883. }
  884.  
  885.  
  886. void g2dGetCropWH(int* w, int* h)
  887. {
  888.   if (obj_tex == NULL) return;
  889.   if (w != NULL) *w = obj.crop_w;
  890.   if (h != NULL) *h = obj.crop_h;
  891. }
  892.  
  893.  
  894. void g2dSetCropXY(int x, int y)
  895. {
  896.   if (obj_tex == NULL) return;
  897.   obj.crop_x = x;
  898.   obj.crop_y = y;
  899. }
  900.  
  901.  
  902. void g2dSetCropWH(int w, int h)
  903. {
  904.   if (obj_tex == NULL) return;
  905.   obj.crop_w = w;
  906.   obj.crop_h = h;
  907. }
  908.  
  909.  
  910. void g2dSetCropXYRelative(int x, int y)
  911. {
  912.   if (obj_tex == NULL) return;
  913.   g2dSetCropXY(obj.crop_x + x, obj.crop_y + y);
  914. }
  915.  
  916.  
  917. void g2dSetCropWHRelative(int w, int h)
  918. {
  919.   if (obj_tex == NULL) return;
  920.   g2dSetCropWH(obj.crop_w + w, obj.crop_h + h);
  921. }
  922.  
  923. // * Texture functions *
  924.  
  925. void g2dResetTex()
  926. {
  927.   if (obj_tex == NULL) return;
  928.   obj_use_tex_repeat = false;
  929.   obj_use_tex_linear = true;
  930.   if (obj_tex->can_blend) obj_use_blend = true;
  931. }
  932.  
  933.  
  934. void g2dSetTexRepeat(bool use)
  935. {
  936.   if (obj_tex == NULL) return;
  937.   obj_use_tex_repeat = use;
  938. }
  939.  
  940.  
  941. void g2dSetTexBlend(bool use)
  942. {
  943.   if (obj_tex == NULL) return;
  944.   if (!obj_tex->can_blend) return;
  945.   obj_use_blend = use;
  946. }
  947.  
  948.  
  949. void g2dSetTexLinear(bool use)
  950. {
  951.   if (obj_tex == NULL) return;
  952.   obj_use_tex_linear = use;
  953. }
  954.  
  955. // * Texture management *
  956.  
  957. int _getNextPower2(int n)
  958. {
  959.   int p=1;
  960.   while ((p <<= 1) < n);
  961.   return p;
  962. }
  963.  
  964.  
  965. void _swizzle(unsigned char *dest, unsigned char *source, int width, int height)
  966. {
  967.   int i, j;
  968.   int rowblocks = (width / 16);
  969.   int rowblocks_add = (rowblocks-1) * 128;
  970.   unsigned int block_address = 0;
  971.   unsigned int *img = (unsigned int*)source;
  972.   for (j = 0; j < height; j++, block_address += 16)
  973.   {
  974.     unsigned int *block = (unsigned int*)(dest + block_address);
  975.     for (i = 0; i < rowblocks; i++)
  976.     {
  977.       *block++ = *img++;
  978.       *block++ = *img++;
  979.       *block++ = *img++;
  980.       *block++ = *img++;
  981.       block += 28;
  982.     }
  983.     if ((j & 0x7) == 0x7) block_address += rowblocks_add;
  984.   }
  985. }
  986.  
  987.  
  988. g2dImage* _g2dTexCreate(int w, int h, bool can_blend)
  989. {
  990.   g2dImage* tex = malloc(sizeof(g2dImage));
  991.   if (tex == NULL) return NULL;
  992.  
  993.   tex->tw = _getNextPower2(w);
  994.   tex->th = _getNextPower2(h);
  995.   tex->w = w;
  996.   tex->h = h;
  997.   tex->ratio = (float)w / h;
  998.   tex->swizzled = false;
  999.   tex->can_blend = can_blend;
  1000.  
  1001.   tex->data = malloc(tex->tw*tex->th*sizeof(g2dColor));
  1002.   if (tex->data == NULL) { free(tex); return NULL; }
  1003.   memset(tex->data,0,tex->tw*tex->th*sizeof(g2dColor));
  1004.  
  1005.   return tex;
  1006. }
  1007.  
  1008.  
  1009. void g2dTexFree(g2dImage** tex)
  1010. {
  1011.   if (tex == NULL) return;
  1012.   free((*tex)->data);
  1013.   free((*tex));
  1014.   *tex = NULL;
  1015. }
  1016.  
  1017.  
  1018. #ifdef USE_PNG
  1019. g2dImage* _g2dTexLoadPNG(FILE* fp)
  1020. {
  1021.   png_structp png_ptr;
  1022.   png_infop info_ptr;
  1023.   unsigned int sig_read = 0;
  1024.   png_uint_32 width, height;
  1025.   int bit_depth, color_type, interlace_type;
  1026.   u32 x, y, *line;
  1027.   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  1028.   png_set_error_fn(png_ptr,NULL,NULL,NULL);
  1029.   info_ptr = png_create_info_struct(png_ptr);
  1030.   png_init_io(png_ptr,fp);
  1031.   png_set_sig_bytes(png_ptr,sig_read);
  1032.   png_read_info(png_ptr,info_ptr);
  1033.   png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,
  1034.                                 &interlace_type,NULL,NULL);
  1035.   png_set_strip_16(png_ptr);
  1036.   png_set_packing(png_ptr);
  1037.   if (color_type == PNG_COLOR_TYPE_PALETTE)
  1038.     png_set_palette_to_rgb(png_ptr);
  1039.   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
  1040.     png_set_tRNS_to_alpha(png_ptr);
  1041.   png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  1042.   g2dImage* tex = _g2dTexCreate(width,height,true);
  1043.   line = malloc(width * 4);
  1044.   for (y = 0; y < height; y++) {
  1045.     png_read_row(png_ptr, (u8*) line, NULL);
  1046.     for (x = 0; x < width; x++) {
  1047.       u32 color = line[x];
  1048.       tex->data[x + y * tex->tw] =  color;
  1049.     }
  1050.   }
  1051.   free(line);
  1052.   png_read_end(png_ptr, info_ptr);
  1053.   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  1054.  
  1055.   return tex;
  1056. }
  1057. #endif
  1058.  
  1059.  
  1060. #ifdef USE_JPEG
  1061. g2dImage* _g2dTexLoadJPEG(FILE* fp)
  1062. {
  1063.   struct jpeg_decompress_struct dinfo;
  1064.   struct jpeg_error_mgr jerr;
  1065.   dinfo.err = jpeg_std_error(&jerr);
  1066.   jpeg_create_decompress(&dinfo);
  1067.   jpeg_stdio_src(&dinfo, fp);
  1068.   jpeg_read_header(&dinfo, TRUE);
  1069.   int width = dinfo.image_width;
  1070.   int height = dinfo.image_height;
  1071.   jpeg_start_decompress(&dinfo);
  1072.   g2dImage* tex = _g2dTexCreate(width,height,false);
  1073.   u8* line = (u8*) malloc(width * 3);
  1074.   if (dinfo.jpeg_color_space == JCS_GRAYSCALE) {
  1075.     while (dinfo.output_scanline < dinfo.output_height) {
  1076.       int y = dinfo.output_scanline, x;
  1077.       jpeg_read_scanlines(&dinfo, &line, 1);
  1078.       for (x = 0; x < width; x++) {
  1079.         g2dColor c = line[x];
  1080.         tex->data[x + tex->tw * y] = c | (c << 8) | (c << 16) | 0xff000000;
  1081.       }
  1082.     }
  1083.   } else {
  1084.     while (dinfo.output_scanline < dinfo.output_height) {
  1085.       int y = dinfo.output_scanline, x;
  1086.       jpeg_read_scanlines(&dinfo, &line, 1);
  1087.       u8* linePointer = line;
  1088.       for (x = 0; x < width; x++) {
  1089.         g2dColor c = *(linePointer++);
  1090.         c |= (*(linePointer++)) << 8;
  1091.         c |= (*(linePointer++)) << 16;
  1092.         tex->data[x + tex->tw * y] = c | 0xff000000;
  1093.       }
  1094.     }
  1095.   }
  1096.   jpeg_finish_decompress(&dinfo);
  1097.   jpeg_destroy_decompress(&dinfo);
  1098.   free(line);
  1099.  
  1100.   return tex;
  1101. }
  1102. #endif
  1103.  
  1104.  
  1105. g2dImage* g2dTexLoad(char path[], g2dTex_Mode mode)
  1106. {
  1107.   if (path == NULL) return NULL;
  1108.  
  1109.   g2dImage* tex = NULL;
  1110.   FILE* fp = NULL;
  1111.   if ((fp = fopen(path,"rb")) == NULL) goto error;
  1112.  
  1113.   #ifdef USE_PNG
  1114.   if (strstr(path,".png") != NULL)
  1115.   {
  1116.     tex = _g2dTexLoadPNG(fp);
  1117.   }
  1118.   #endif
  1119.   #ifdef USE_JPEG
  1120.   if (strstr(path,".jpg")  != NULL ||
  1121.       strstr(path,".jpeg") != NULL )
  1122.   {
  1123.     tex = _g2dTexLoadJPEG(fp);
  1124.   }
  1125.   #endif
  1126.   if (tex == NULL) goto error;
  1127.  
  1128.   fclose(fp);
  1129.   fp = NULL;
  1130.   sceKernelDcacheWritebackAll();
  1131.  
  1132.   // The PSP can't draw 512*512+ textures.
  1133.   if (tex->w > 512 || tex->h > 512) goto error;
  1134.  
  1135.   // Swizzling is useless with small textures.
  1136.   if ((mode & G2D_SWIZZLE) && (tex->w >= 16 || tex->h >= 16))
  1137.   {
  1138.     u8* tmp = malloc(tex->tw*tex->th*PIXEL_SIZE);
  1139.     _swizzle(tmp,(u8*)tex->data,tex->tw*PIXEL_SIZE,tex->th);
  1140.     free(tex->data);
  1141.     tex->data = (g2dColor*)tmp;
  1142.     tex->swizzled = true;
  1143.     sceKernelDcacheWritebackAll();
  1144.   }
  1145.   else tex->swizzled = false;
  1146.  
  1147.   return tex;
  1148.  
  1149.   // Load failure... abort
  1150.   error:
  1151.   if (fp != NULL) fclose(fp);
  1152.   g2dTexFree(&tex);
  1153.   return NULL;
  1154. }
  1155.  
  1156. // * Scissor functions *
  1157.  
  1158. void g2dResetScissor()
  1159. {
  1160.   g2dSetScissor(0,0,G2D_SCR_W,G2D_SCR_H);
  1161.   scissor = false;
  1162. }
  1163.  
  1164.  
  1165. void g2dSetScissor(int x, int y, int w, int h)
  1166. {
  1167.   sceGuScissor(x,y,x+w,y+h);
  1168.   scissor = true;
  1169. }
  1170.  
  1171. // EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement