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