gxsprites.pp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. program gxsprites;
  2. {$J+}
  3. {$macro on}
  4. {$mode objfpc}
  5. uses
  6. cmem, ctypes, gctypes, gccore;
  7. {$include inc/textures.tpl.inc}
  8. {$link build/textures.tpl.o}
  9. const
  10. ballsprites = 0;
  11. const
  12. DEFAULT_FIFO_SIZE = (256 * 1024);
  13. const
  14. RAND_MAX = 2147483647;
  15. var
  16. frameBuffer: array [0..1] of pcuint32 = (nil, nil);
  17. rmode: PGXRModeObj = nil;
  18. const
  19. NUM_SPRITES = 1024;
  20. //simple sprite struct
  21. type
  22. TSprite = record
  23. x, y: cint; // screen co-ordinates
  24. dx, dy: cint; // velocity
  25. image: cint;
  26. end;
  27. var
  28. sprites: array [0..NUM_SPRITES - 1] of TSprite;
  29. texObj: GXTexObj;
  30. fb: cuint32; // initial framebuffer index
  31. first_frame: cuint32;
  32. yscale: f32;
  33. xfbHeight: cuint32;
  34. perspective: Mtx44;
  35. GXmodelView2D: Mtx;
  36. gp_fifo: pointer = nil;
  37. background: GXColor = (r: 0; g: 0; b: 0; a: $ff; );
  38. i: cint;
  39. spriteTPL: TPLFile;
  40. texCoords: array[0..31] of f32 = (
  41. 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.0, 0.5,
  42. 0.5, 0.0, 1.0, 0.0, 1.0, 0.5, 0.5, 0.5,
  43. 0.0, 0.5, 0.5, 0.5, 0.5, 1.0, 0.0, 1.0,
  44. 0.5, 0.5, 1.0, 0.5, 1.0, 1.0, 0.5, 1.0);
  45. procedure drawSpriteTex(x, y, Width, Height, image: cint);
  46. var
  47. texIndex: cint;
  48. begin
  49. texIndex := image * 8;
  50. GX_Begin(GX_QUADS, GX_VTXFMT0, 4); // Draw A Quad
  51. GX_Position2f32(x, y); // Top Left
  52. GX_TexCoord2f32(texCoords[texIndex], texCoords[texIndex + 1]);
  53. texIndex := texIndex + 2;
  54. GX_Position2f32(x + Width - 1, y); // Top Right
  55. GX_TexCoord2f32(texCoords[texIndex], texCoords[texIndex + 1]);
  56. texIndex := texIndex + 2;
  57. GX_Position2f32(x + Width - 1, y + Height - 1); // Bottom Right
  58. GX_TexCoord2f32(texCoords[texIndex], texCoords[texIndex + 1]);
  59. texIndex := texIndex + 2;
  60. GX_Position2f32(x, y + Height - 1); // Bottom Left
  61. GX_TexCoord2f32(texCoords[texIndex], texCoords[texIndex + 1]);
  62. GX_End(); // Done Drawing The Quad
  63. end;
  64. begin
  65. VIDEO_Init();
  66. rmode := VIDEO_GetPreferredMode(nil);
  67. fb := 0;
  68. first_frame := 1;
  69. // allocate 2 framebuffers for double buffering
  70. frameBuffer[0] := (SYS_AllocateFramebuffer(rmode));
  71. frameBuffer[1] := (SYS_AllocateFramebuffer(rmode));
  72. VIDEO_Configure(rmode);
  73. VIDEO_SetNextFramebuffer(frameBuffer[fb]);
  74. VIDEO_SetBlack(False);
  75. VIDEO_Flush();
  76. VIDEO_WaitVSync();
  77. if (rmode^.viTVMode and VI_NON_INTERLACE) <> 0 then
  78. VIDEO_WaitVSync();
  79. // setup the fifo and then init the flipper
  80. gp_fifo := memalign(32, DEFAULT_FIFO_SIZE);
  81. memset(gp_fifo, 0, DEFAULT_FIFO_SIZE);
  82. fb := fb xor 1;
  83. GX_Init(gp_fifo, DEFAULT_FIFO_SIZE);
  84. // clears the bg to color and clears the z buffer
  85. GX_SetCopyClear(background, $00ffffff);
  86. // other gx setup
  87. GX_SetViewport(0, 0, rmode^.fbWidth, rmode^.efbHeight, 0, 1);
  88. yscale := GX_GetYScaleFactor(rmode^.efbHeight, rmode^.xfbHeight);
  89. xfbHeight := GX_SetDispCopyYScale(yscale);
  90. GX_SetScissor(0, 0, rmode^.fbWidth, rmode^.efbHeight);
  91. GX_SetDispCopySrc(0, 0, rmode^.fbWidth, rmode^.efbHeight);
  92. GX_SetDispCopyDst(rmode^.fbWidth, xfbHeight);
  93. GX_SetCopyFilter(rmode^.aa, rmode^.sample_pattern, GX_TRUE, rmode^.vfilter);
  94. if rmode^.viHeight = 2 * rmode^.xfbHeight then
  95. GX_SetFieldMode(rmode^.field_rendering, GX_ENABLE)
  96. else
  97. GX_SetFieldMode(rmode^.field_rendering, GX_DISABLE);
  98. if (rmode^.aa) <> 0 then
  99. GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR)
  100. else
  101. GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
  102. GX_SetCullMode(GX_CULL_NONE);
  103. GX_CopyDisp(frameBuffer[fb], GX_TRUE);
  104. GX_SetDispCopyGamma(GX_GM_1_0);
  105. // setup the vertex descriptor
  106. // tells the flipper to expect direct data
  107. GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
  108. GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
  109. GX_SetNumChans(1);
  110. GX_SetNumTexGens(1);
  111. GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
  112. GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
  113. GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
  114. GX_InvalidateTexAll();
  115. TPL_OpenTPLFromMemory(@spriteTPL, @textures_tpl, textures_tpl_size);
  116. TPL_GetTexture(@spriteTPL, ballsprites, @texObj);
  117. GX_LoadTexObj(@texObj, GX_TEXMAP0);
  118. guOrtho(perspective, 0, 479, 0, 639, 0, 300);
  119. GX_LoadProjectionMtx(perspective, GX_ORTHOGRAPHIC);
  120. WPAD_Init();
  121. randomize();
  122. for i := 0 to NUM_SPRITES - 1 do
  123. begin
  124. //random place and speed
  125. sprites[i].x := random(640 - 32 + 1) shl 8;
  126. sprites[i].y := random(480 - 32 + 1) shl 8;
  127. sprites[i].dx := random($FF + 1) + $100;
  128. sprites[i].dy := random($FF + 1) + $100;
  129. sprites[i].image := random(4);
  130. if random(2) <> 0 then
  131. sprites[i].dx := -sprites[i].dx;
  132. if random(2) <> 0 then
  133. sprites[i].dy := -sprites[i].dy;
  134. end;
  135. while True do
  136. begin
  137. WPAD_ScanPads();
  138. if (WPAD_ButtonsDown(0) and WPAD_BUTTON_HOME) <> 0 then
  139. exit;
  140. GX_SetViewport(0, 0, rmode^.fbWidth, rmode^.efbHeight, 0, 1);
  141. GX_InvVtxCache();
  142. GX_InvalidateTexAll();
  143. GX_ClearVtxDesc();
  144. GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
  145. GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
  146. guMtxIdentity(GXmodelView2D);
  147. guMtxTransApply(GXmodelView2D, GXmodelView2D, 0.0, 0.0, -5.0);
  148. GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
  149. for i := 0 to NUM_SPRITES - 1 do
  150. begin
  151. sprites[i].x := sprites[i].x + sprites[i].dx;
  152. sprites[i].y := sprites[i].y + sprites[i].dy;
  153. //check for collision with the screen boundaries
  154. if (sprites[i].x < (1 shl 8)) or (sprites[i].x > ((640 - 32) shl 8)) then
  155. sprites[i].dx := -sprites[i].dx;
  156. if (sprites[i].y < (1 shl 8)) or (sprites[i].y > ((480 - 32) shl 8)) then
  157. sprites[i].dy := -sprites[i].dy;
  158. drawSpriteTex(sprites[i].x shr 8, sprites[i].y shr 8, 32, 32, sprites[i].image);
  159. end;
  160. GX_DrawDone();
  161. GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
  162. GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
  163. GX_SetAlphaUpdate(GX_TRUE);
  164. GX_SetColorUpdate(GX_TRUE);
  165. GX_CopyDisp(frameBuffer[fb], GX_TRUE);
  166. VIDEO_SetNextFramebuffer(frameBuffer[fb]);
  167. if (first_frame) <> 0 then
  168. begin
  169. VIDEO_SetBlack(False);
  170. first_frame := 0;
  171. end;
  172. VIDEO_Flush();
  173. VIDEO_WaitVSync();
  174. fb := fb xor 1; // flip framebuffer
  175. end;
  176. end.