1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: mgt-fifo-brkpt.c
4
5 Copyright 1998-2006 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 *---------------------------------------------------------------------------*/
14
15 /*---------------------------------------------------------------------------*
16 This demo is based on the smp-texexample demo, except we animate to make
17 it clear that this code actually works.
18
19 We use ONE fifo to hold TWO frames' data. One of the frames is
20 being consumed by the GP. The other is being produced by the CPU.
21
22 We prevent the GP from starting on the second frame prematurely by
23 placing a FIFO breakpoint right where the CPU is about to start
24 writing the next frame (see FifoTick).
25
26 We prevent the CPU from starting on a third frame by synchronizing
27 with the GP. Since we cannot rely on GXDrawDone, we poll with
28 GXReadDrawSync (see MyDEMODoneRender).
29
30 There is no need to worry about the CPU trampling over the data the
31 GP hasn't read yet - the high watermark interrupt will get triggered
32 before that.
33
34 Look at FifoInit to see how we re-allocate the FIFO object, because
35 in a real application, the default fifo might not be large enough to
36 hold 2 frames worth of command data.
37 *---------------------------------------------------------------------------*/
38
39 #include <demo.h>
40
41 #define BALL64_TEX_ID 8
42
43 #define BIG_FIFO_SIZE (512*1024)
44 #define FIFO_DRAWDONE_TOKEN 0xBEEF
45 #define FIFO_DRAWING_TOKEN 0xB00B
46
47 /*---------------------------------------------------------------------------*
48 Model Data
49 *---------------------------------------------------------------------------*/
50
51 static s8 Vert_s8[] ATTRIBUTE_ALIGN(32) =
52 {
53 -100, 100, 0, // 0
54 100, 100, 0, // 1
55 -100, -100, 0 // 2
56 };
57
58 static u32 Colors_u32[] ATTRIBUTE_ALIGN(32) =
59 {
60 // r g b a
61 0xff0000ff, // 0
62 0x00ff00ff, // 1
63 0x0000ffff // 2
64 };
65
66 // Array of texture coordinates
67 static u8 TexCoords_u8[] ATTRIBUTE_ALIGN(32) =
68 {
69 0x00, 0x00, // 0
70 // s t fixed point format is unsigned 8.0
71 0x01, 0x00, // 1
72 0x00, 0x01 // 2
73 };
74
75 /*---------------------------------------------------------------------------*
76 Forward references
77 *---------------------------------------------------------------------------*/
78 static void FifoInit ( GXFifoObj* fifo );
79 static void FifoTick ( void );
80 static void MyDEMODoneRender ( void );
81 static void CameraInit ( Mtx v );
82
83 /*---------------------------------------------------------------------------*
84 Application main loop
85 *---------------------------------------------------------------------------*/
main(void)86 void main ( void )
87 {
88 PADStatus pad[4]; // game pad state
89 GXFifoObj appFifo; // fifo object
90 GXTexObj texObj; // texture object
91 Mtx v; // view matrix
92 Mtx r; // rotation matrix
93 u8 i; // loop variable
94 u32 deg; // rotation angle
95 TPLPalettePtr tpl = 0; // texture palette
96
97 pad[0].button = 0;
98
99 DEMOInit(NULL); // Init os, pad, gx, vi
100 FifoInit(&appFifo);
101
102 CameraInit(v);
103
104 GXSetNumChans(1); // Enable light channel; by default = vertex color
105
106 GXClearVtxDesc();
107 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
108 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
109 // Add an indexed texture coordinate to the vertex description
110 GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
111
112 GXSetArray(GX_VA_POS, Vert_s8, 3*sizeof(s8));
113 GXSetArray(GX_VA_CLR0, Colors_u32, 1*sizeof(u32));
114 GXSetArray(GX_VA_TEX0, TexCoords_u8, 2*sizeof(u8));
115
116 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
117 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
118 // Describe the texture coordinate format
119 // fixed point format is unsigned 8.0
120 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 0);
121
122 // Load the texture palette
123 TPLGetPalette(&tpl, "gxTextrs.tpl");
124 // Initialize a texture object to contain the correct texture
125 TPLGetGXTexObjFromPalette(tpl, &texObj, BALL64_TEX_ID);
126 // Load the texture object; tex0 is used in stage 0
127 GXLoadTexObj(&texObj, GX_TEXMAP0);
128
129 // Set the Texture Environment (Tev) Mode for stage 0
130 // GXInit sets default of 1 TexCoordGen
131 // Default TexCoordGen is texcoord(n) from tex(n) with 2x4 identity mtx
132 // Default number of tev stages is 1
133 // Default stage0 uses texcoord0, texmap0, color0a0
134 // Only need to change the tevop
135 GXSetTevOp(GX_TEVSTAGE0, GX_DECAL);
136
137 OSReport("\n\n********************************\n");
138 OSReport("to quit:\n");
139 OSReport(" hit the start button\n");
140 OSReport("********************************\n");
141
142 deg = 0;
143
144 while(!(pad[0].button & PAD_BUTTON_MENU))
145 {
146 FifoTick();
147
148 DEMOBeforeRender();
149
150 MTXRotDeg( r, 'Y', deg++);
151 MTXConcat(v, r, r);
152 GXLoadPosMtxImm(r, GX_PNMTX0);
153
154 // Draw a triangle, front and back
155 GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3);
156 for (i = 0; i < 3; i++)
157 {
158 GXPosition1x8(i);
159 GXColor1x8(i);
160 // Add texture coordinate
161 GXTexCoord1x8(i);
162 }
163 GXEnd();
164 GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3);
165 for (i = 0; i < 3; i++)
166 {
167 GXPosition1x8 ((u8)(2 - i));
168 GXColor1x8 ((u8)(2 - i));
169 // Add texture coordinate
170 GXTexCoord1x8 ((u8)(2 - i));
171 }
172 GXEnd();
173 MyDEMODoneRender();
174 PADRead(pad);
175 }
176
177 OSHalt("End of demo");
178 }
179
180 /*---------------------------------------------------------------------------*
181 Functions
182 *---------------------------------------------------------------------------*/
183
184 /*---------------------------------------------------------------------------*
185 Name: CameraInit
186
187 Description: Initialize the projection matrix and load into hardware.
188 Initialize the view matrix
189
190 Arguments: v view matrix
191
192 Returns: none
193 *---------------------------------------------------------------------------*/
194
CameraInit(Mtx v)195 static void CameraInit ( Mtx v )
196 {
197 Mtx44 p;
198 Vec camPt = {0.0F, 0.0F, 800.0F};
199 Vec at = {0.0F, 0.0F, -100.0F};
200 Vec up = {0.0F, 1.0F, 0.0F};
201
202 MTXFrustum(p, 240.0F,-240.0F,-320.0F, 320.0F, 500, 2000);
203 GXSetProjection(p, GX_PERSPECTIVE);
204 MTXLookAt(v, &camPt, &up, &at);
205 }
206
207 /*---------------------------------------------------------------------------*
208 Name: MyDEMODoneRender()
209
210 Description: rewrite of DEMODoneRender function - performs post-rendering operations.
211 receives a stopwatch activated at the top of the 'main' demoloop.
212 checks stopwatch after GXDrawDone and before VIWaitForRetrace to
213 compute actual frame rendering time in milliseconds.
214
215 Arguments: globals: writes DemoFrameBuffer1,
216 writes DemoFrameBuffer2,
217 writes DemoCurrentBuffer
218
219 Returns: none
220 *---------------------------------------------------------------------------*/
MyDEMODoneRender(void)221 static void MyDEMODoneRender ( void )
222 {
223 extern void* DemoFrameBuffer1; // static global variables from DEMOInit.c
224 extern void* DemoFrameBuffer2;
225 extern void* DemoCurrentBuffer;
226
227
228 // copy out the other framebuffer since GP is a frame behind
229 if( DemoCurrentBuffer == DemoFrameBuffer1 )
230 GXCopyDisp(DemoFrameBuffer2, GX_TRUE);
231 else
232 GXCopyDisp(DemoFrameBuffer1, GX_TRUE);
233
234 GXSetDrawSync( FIFO_DRAWDONE_TOKEN );
235
236 // wait until GP is finished by polling for the drawdone token in
237 // current GP Fifo (previously processed by CPU)
238 while( (GXReadDrawSync()) != FIFO_DRAWDONE_TOKEN )
239 {
240 }
241
242 //============================
243
244 // Wait for vertical retrace and set the next frame buffer
245 // Display the buffer which was just filled by GXCopyDisplay
246 DEMOSwapBuffers();
247
248 }
249
250 /*---------------------------------------------------------------------------*
251 Name: FifoTick
252
253 Description: changes the GP breakpoint so CPU can calculate next frame
254 while GP processes last frame. should be called before any
255 commands are sent to GP (at the top of the main loop)
256 since this function assumes that both the CPU and GP are
257 not processing.
258
259 Arguments: none
260
261 Returns: none
262 *----------------------------------------------------------------------------*/
FifoTick(void)263 static void FifoTick( void )
264 {
265 GXFifoObj currFifoObj;
266 void *readPtr, *writePtr;
267
268 // Set a breakpoint at the current point in the CPU
269 // and disable the previous one to let the GP start processing
270 GXGetCPUFifo( &currFifoObj );
271
272 GXGetFifoPtrs( &currFifoObj, &readPtr, &writePtr );
273 GXEnableBreakPt( writePtr );
274
275 GXSetDrawSync( FIFO_DRAWING_TOKEN );
276 }
277
278 /*---------------------------------------------------------------------------*
279 Name: FifoInit
280
281 Description: Resizes the default FIFO from DEMOInit.
282
283 Arguments: fifo : GX fifo object to use in this app.
284
285 Returns: none
286 *----------------------------------------------------------------------------*/
FifoInit(GXFifoObj * fifo)287 static void FifoInit( GXFifoObj* fifo )
288 {
289 // get the default fifo and free it later
290 GXSetDrawDone();
291
292 // allocate new fifo
293 GXInitFifoBase( fifo, MEMAllocFromAllocator(&DemoAllocator1, BIG_FIFO_SIZE), BIG_FIFO_SIZE );
294
295 // set the CPU and GP fifo to this new one
296 GXSetCPUFifo( fifo );
297 GXSetGPFifo( fifo );
298
299 // so that the first fifo will fire off immediately
300 GXSetDrawSync( FIFO_DRAWDONE_TOKEN );
301
302 // Default fifo area allocated in the demo library is left unused.
303 }
304