Advertisement
GeeckoDev

gLib2D swizzling

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