1 /*---------------------------------------------------------------------------*
2 Project: Dolphin
3 File: gd-texture-gc.c
4
5 Copyright 2001-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 $Log: gd-texture-gc.c,v $
14 Revision 1.4 2006/08/18 21:50:57 carlmu
15 Added explanatory output.
16
17 Revision 1.3 02/20/2006 04:13:10 mitu
18 changed include path from dolphin/ to revolution/.
19
20 Revision 1.2 02/09/2006 01:17:32 hirose
21 Replaced TEX library calls by TPL library.
22
23 Revision 1.1 02/08/2006 11:19:43 mitu
24 1st version.
25
26
27 5 02/09/06 11:26:00 Hirose
28 Resolved future time stamp problem.
29
30 5 10/19/02 6:53p Hirose
31 Changed location of data file.
32
33 4 10/11/01 4:05p Carl
34 Added use of color-index texture and TLUT.
35
36 3 9/25/01 6:46p Carl
37 Adjusted #pragma usage.
38
39 2 9/24/01 2:23p Hirose
40 Changed flag definition.
41
42 1 9/19/01 4:27p Carl
43 Sources for GD texture demo.
44
45 $NoKeywords: $
46 *---------------------------------------------------------------------------*/
47
48 #include <demo.h>
49 #include <math.h>
50
51 #include <revolution/gd.h>
52
53 /*---------------------------------------------------------------------------*
54 Defines
55 *---------------------------------------------------------------------------*/
56
57 // This macro is used to copy a 3x4 matrix into a 3x3 matrix
58 #define COPY3x3(ms, md) \
59 { md[0][0]=ms[0][0]; md[0][1]=ms[0][1]; md[0][2]=ms[0][2]; \
60 md[1][0]=ms[1][0]; md[1][1]=ms[1][1]; md[1][2]=ms[1][2]; \
61 md[2][0]=ms[2][0]; md[2][1]=ms[2][1]; md[2][2]=ms[2][2]; }
62
63 /*---------------------------------------------------------------------------*
64 Forward references
65 *---------------------------------------------------------------------------*/
66
67 void main ( void );
68
69 static void CameraInit ( void );
70 static void DrawInit ( void );
71 static void DrawTick ( void );
72
73 static void AnimTick ( void );
74
75 static void ParameterInit ( void );
76
77 static void PatchTexPtrs(u32 numTplFiles, TPLPalettePtr tplFilePtrs[],
78 u32 numTextures, u32 tplFileNums[], u32 tplTexNums[],
79 GDLObj *dlObj, u32 dlOffsets[]);
80
81 #ifdef LOAD_DL_FROM_FILE
82 static void LoadDLs ( void );
83 #else
84 extern void CreateDLs( void );
85 #endif
86
87 /*---------------------------------------------------------------------------*
88 Global variables
89 *---------------------------------------------------------------------------*/
90
91 // Display lists *************************************************************
92
93 // These are only created during runtime if LOAD_DL_FROM_FILE is not defined.
94 // Otherwise, these are loaded from a file.
95
96 // This DL is used with the "Draw" display list.
97 // It initializes state that will be used by the Draw DL.
98
99 GDLObj InitDLO;
100
101 // This DL draws a textured cube. It must be paired with the Init DL.
102
103 GDLObj DrawDLO;
104
105 // This array indicates the offsets to patch memory addresses for the
106 // primitive data arrays (positions, normals, texture coordinates)
107 // referred to in the Init DL.
108
109 u32 *setArrayOffsets;
110
111 // This array tells us the offsets for where to patch the memory addresses
112 // for the textures in the Draw DL.
113
114 u32 *texAddrOffsets;
115
116 // This array tells us the offsets for where to patch the main memory
117 // addresses for loading the TLUTs in the Init DL.
118
119 u32 *tlutAddrOffsets;
120
121 /*---------------------------------------------------------------------------*/
122
123 // Actual primitive data follows
124
125 #define SIDE 30
126 #define NORM (sqrt(3.0))/3.0
127
128 // Remember: Alignment of vertex arrays to 32B IS NOT required, but it
129 // may result in a slight performance improvement.
130
131 float FloatVert[] ATTRIBUTE_ALIGN(32) =
132 {
133 -SIDE, SIDE, -SIDE,
134 -SIDE, SIDE, SIDE,
135 -SIDE, -SIDE, SIDE,
136 -SIDE, -SIDE, -SIDE,
137 SIDE, SIDE, -SIDE,
138 SIDE, -SIDE, -SIDE,
139 SIDE, -SIDE, SIDE,
140 SIDE, SIDE, SIDE,
141 };
142
143 float FloatNorm[] ATTRIBUTE_ALIGN(32) =
144 {
145 -1, 1, -1,
146 -1, 1, 1,
147 -1, -1, 1,
148 -1, -1, -1,
149 1, 1, -1,
150 1, -1, -1,
151 1, -1, 1,
152 1, 1, 1,
153 };
154
155 float FloatTex[] ATTRIBUTE_ALIGN(32) =
156 {
157 0.0F, 0.0F,
158 1.0F, 0.0F,
159 1.0F, 1.0F,
160 0.0F, 1.0F,
161 };
162
163 // Misc data...
164
165 Mtx v; // view matrix
166 u32 rot; // current cube rotation
167
168 /*---------------------------------------------------------------------------*
169 Application main loop
170 *---------------------------------------------------------------------------*/
171
main(void)172 void main ( void )
173 {
174 DEMOInit(NULL);
175
176 OSReport("\n\n");
177 OSReport("**********************************************\n");
178 OSReport("gd-texture-gc: Texture display list demo\n");
179 OSReport("**********************************************\n");
180 OSReport("To quit hit the start button.\n");
181 OSReport("\n");
182 OSReport("A button toggles animation.\n");
183 OSReport("**********************************************\n");
184 OSReport("\n\n");
185
186 DrawInit(); // Prepare the display lists and such
187
188 ParameterInit();
189
190 DEMOPadRead(); // Read the joystick for this frame
191
192 // While the quit button is not pressed
193 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
194 {
195 DEMOPadRead(); // Read the joystick for this frame
196
197 AnimTick(); // Do animation based on input
198
199 DEMOBeforeRender();
200
201 DrawTick(); // Draw the model.
202
203 DEMODoneRender();
204 }
205
206 OSHalt("End of test");
207 }
208
209 /*---------------------------------------------------------------------------*
210 Functions
211 *---------------------------------------------------------------------------*/
212
213 /*---------------------------------------------------------------------------*
214 Name: PatchTexPtrs
215
216 Description: This routine will look up TPL texture references and will
217 patch a DL with HW pointers to the actual texture data.
218 The references are provided as a list of TPL file numbers
219 and a list of texture numbers within the given TPL's, as
220 well as a list of TPL TexPalettePtr's.
221
222 This function uses a GDLObj to reference the DL. The
223 dlOffsets point to two bytes after the GDSetTexImgPtr
224 commands within the DL (ie, they point directly to the
225 bytes to be patched).
226
227 Texture Lists: (length = numTextures)
228
229 entry TPL file # TPL texture # DL offset
230 (tplFileNums) (tplTexNums) (dlOffsets)
231 ----- ---------- ------------- -----------
232 0 a i x
233 1 b j y
234 2 c k z
235
236 TPL List: (length = numTplFiles)
237
238 entry TPLPalettePtr's
239 (tplFilePtrs)
240 ----- ---------------
241 0 A
242 1 B
243 2 C
244
245 You should have already called TPLGetPalette for all the
246 TPL files you are going to use.
247
248 Arguments: numTplFiles: input, length of tplFilePtrs list
249 tplFilePtrs: input, list of pointers to TPL file data
250 numTextures: input, number of textures to be looked up
251 tplFileNums: input, which TPL file number per texture
252 tplTexNums: input, which TPL texture number per texture
253 dlObj: input, should point to the DL to patch
254 dlOffsets: input, offsets to GDSetTexImgPtr data in DL
255 (data = command start + 2)
256 Returns: none
257 *---------------------------------------------------------------------------*/
258
PatchTexPtrs(u32 numTplFiles,TPLPalettePtr tplFilePtrs[],u32 numTextures,u32 tplFileNums[],u32 tplTexNums[],GDLObj * dlObj,u32 dlOffsets[])259 static void PatchTexPtrs(u32 numTplFiles, TPLPalettePtr tplFilePtrs[],
260 u32 numTextures, u32 tplFileNums[], u32 tplTexNums[],
261 GDLObj *dlObj, u32 dlOffsets[])
262 {
263 #ifndef _DEBUG
264 #pragma unused(numTplFiles)
265 #endif
266 u32 i;
267 u32 fn;
268 TPLDescriptorPtr tdescp;
269 void *tp;
270 void *cp;
271 u32 saveOffset;
272
273 GDSetCurrent(dlObj);
274
275 // Note: we preserve the current offset just in case it is used
276 // to hold something important, such as the actual data length.
277 saveOffset = GDGetCurrOffset();
278
279 for(i=0; i<numTextures; i++)
280 {
281 fn = tplFileNums[i];
282 ASSERTMSG( fn < numTplFiles, "TPL number out of range");
283
284 // Get the texture descriptor
285 tdescp = TPLGet(tplFilePtrs[fn], tplTexNums[i]);
286 // Get the data ptr
287 tp = (void *) tdescp->textureHeader->data;
288
289 // Now patch it in
290 GDSetCurrOffset(dlOffsets[i]); // set the offset
291 cp = GDGetCurrPointer(); // save ptr for flushing later
292 GDPatchTexImgPtr(tp); // patch in the texture address ptr
293
294 // We assume that the patches will lie within separate
295 // 32B ranges, so go ahead and flush it to memory now.
296 // If more than 1 patch is in the same range, then we're
297 // just doing extra work (no harm done).
298 DCStoreRange(cp, BP_DATA_LENGTH);
299 }
300
301 // Because we are flushing as we go along, we don't have
302 // to flush the entire list to memory later. If we didn't
303 // flush as we went along, we'd need this:
304 //
305 // GDFlushCurrToMem();
306
307 // Restore the offset
308 GDSetCurrOffset(saveOffset);
309
310 GDSetCurrent(NULL); // bug-prevention
311 }
312
313
314 /*---------------------------------------------------------------------------*
315 Name: CameraInit
316
317 Description: Initialize the projection matrix and load into hardware.
318
319 Arguments: v view matrix to be passed to ViewInit
320 cameraLocScale scale for the camera's distance from the
321 object - to be passed to ViewInit
322
323 Returns: none
324 *---------------------------------------------------------------------------*/
CameraInit(void)325 static void CameraInit ( void )
326 {
327 Mtx44 p;
328 Vec camPt = {0.0F, 0.0F, 650.0F};
329 Vec up = {0.0F, 1.0F, 0.0F};
330 Vec origin = {0.0F, 0.0F, 0.0F};
331
332 MTXFrustum(p, 112, -112, -160, 160, 500, 2000);
333
334 GXSetProjection(p, GX_PERSPECTIVE);
335
336 MTXLookAt(v, &camPt, &up, &origin);
337 }
338
339
340 /*---------------------------------------------------------------------------*
341 Name: LoadDLs
342
343 Description: Loads the display lists used by the program from a file.
344 This routine is only called if LOAD_DL_FROM_FILE is defined.
345
346 Arguments: none
347
348 Returns: none
349 *---------------------------------------------------------------------------*/
350 #ifdef LOAD_DL_FROM_FILE
LoadDLs(void)351 static void LoadDLs ( void )
352 {
353 s32 err;
354 GDGList *DLDescArray;
355 GDGList *PLDescArray;
356 u32 numDLs, numPLs;
357
358 err = GDReadDLFile("gddemo/gdTextr.gdl", &numDLs, &numPLs,
359 &DLDescArray, &PLDescArray);
360
361 OSReport("(%d) Read %d DLs, %d PLs\n", err, numDLs, numPLs);
362
363 ASSERTMSG(!err, "Error reading GDL file.\n");
364
365 ASSERTMSG(numDLs == 2 && numPLs == 3, "Incorrect data in GDL file.\n");
366
367 // Note: We put the DL length into the "offset" field, since that's
368 // where the run-time code expects it. We do this since the CreateDLs
369 // function uses an oversize "length" field, and the actual valid data
370 // length is saved in the "offset" field in that case. Thus we do the
371 // same thing here for consistency.
372
373 GDInitGDLObj( &InitDLO, DLDescArray[0].ptr, DLDescArray[0].byteLength );
374 GDSetCurrent( &InitDLO );
375 GDSetCurrOffset( DLDescArray[0].byteLength );
376
377 GDInitGDLObj( &DrawDLO, DLDescArray[1].ptr, DLDescArray[1].byteLength );
378 GDSetCurrent( &DrawDLO );
379 GDSetCurrOffset( DLDescArray[1].byteLength );
380
381 GDSetCurrent( NULL );
382
383 ASSERTMSG(PLDescArray[0].byteLength == 3 * sizeof(u32),
384 "Incorrect data in Patch List 0.\n");
385
386 ASSERTMSG(PLDescArray[1].byteLength == 6 * sizeof(u32),
387 "Incorrect data in Patch List 1.\n");
388
389 ASSERTMSG(PLDescArray[2].byteLength == 1 * sizeof(u32),
390 "Incorrect data in Patch List 2.\n");
391
392 setArrayOffsets = (u32 *) PLDescArray[0].ptr;
393 texAddrOffsets = (u32 *) PLDescArray[1].ptr;
394 tlutAddrOffsets = (u32 *) PLDescArray[2].ptr;
395 }
396 #endif
397
398
399 /*---------------------------------------------------------------------------*
400 Name: DrawInit
401
402 Description: Calls the correct initialization function for the current
403 model.
404
405 Arguments: none
406
407 Returns: none
408 *---------------------------------------------------------------------------*/
DrawInit(void)409 static void DrawInit( void )
410 {
411 u32 i;
412 u32 numTpls = 1; // How many TPL files we have
413 TPLPalettePtr tpls[1]; // pointer to each
414 u32 numTexs = 6; // How many textures in our display list
415 static u32 tplFileNums[6]={0, 0, 0, 0, 0, 0}; // which file for each
416 static u32 tplTexNums[6] ={1, 2, 6, 10, 13, 3}; // which descriptor
417 static void *basePtrs[3] = { FloatVert, FloatNorm, FloatTex };
418 void *cp;
419 u32 length;
420
421 TPLDescriptorPtr tdescp;
422
423 GXLightObj MyLight;
424 GXColor White = {255, 255, 255, 255};
425
426 // Load or create all the display lists and patch lists.
427
428 #ifdef LOAD_DL_FROM_FILE
429 LoadDLs();
430 #else
431 CreateDLs();
432 #endif
433
434 tpls[0] = 0; // important: this must be initialized to 0!
435
436 // In tex-06.tpl:
437 //
438 // index width height format ws wt mnf mgf mnl mxl lb mm face
439 // 0 128 128 RGBA8 r r l/l l 0 7 0 Y
440 // 1 128 128 RGB5A3 r r l/l l 0 7 0 Y 1
441 // 2 128 128 CMPR r r l/l l 0 7 0 Y 2
442 // 3 128 128 CI8 r r l/l l 0 7 0 N 6
443 // 4 128 128 RGB565 r r l/l l 0 7 0 Y
444 // 5 128 128 RGBA8 r r l/l l 0 7 0 Y
445 // 6 128 128 RGBA8 r r l/l l 0 7 0 Y 3
446 // 7 128 128 RGB565 r r l/l l 0 7 0 Y
447 // 8 128 128 CMPR r r l/l l 0 7 0 Y
448 // 9 128 128 RGB5A3 r r l/l l 0 7 0 Y
449 // 10 128 128 I4 r r l/l l 0 7 0 Y 4
450 // 11 128 128 IA4 r r l/l l 0 7 0 Y
451 // 12 128 128 I8 r r l/l l 0 7 0 Y
452 // 13 128 128 IA8 r r l/l l 0 7 0 Y 5
453
454 // Load all the TPL files
455 TPLGetPalette(&tpls[0], "gxTests/tex-06.tpl");
456
457 // Set up the textures in the DrawList
458 //
459 // We need to insert their memory addresses into the DrawList.
460
461 // We get the texture data addresses from the TPL file(s)
462 // and patch them into the GDLObj using texAddrOffsets to tell where.
463 PatchTexPtrs(numTpls, tpls, numTexs, tplFileNums, tplTexNums,
464 &DrawDLO, texAddrOffsets);
465
466 // Now, we need to patch in the vertex array base pointers
467 GDSetCurrent(&InitDLO);
468 length = GDGetCurrOffset(); // preserve the offset!
469
470 for(i=0; i<3; i++)
471 {
472 GDSetCurrOffset( setArrayOffsets[i] );
473 cp = GDGetCurrPointer();
474 GDPatchArrayPtr( basePtrs[i] );
475 DCStoreRange( cp, CP_DATA_LENGTH );
476 }
477
478 // Patch the address for the TLUT for texture #3 (the color-index one).
479 tdescp = TPLGet( tpls[0], 3 );
480 GDSetCurrOffset( tlutAddrOffsets[0] );
481 cp = GDGetCurrPointer();
482 GDPatchTlutPtr( tdescp->CLUTHeader->data );
483 DCStoreRange( cp, BP_DATA_LENGTH );
484
485 // Restore the original offset, which reflects the valid data length.
486 GDSetCurrOffset(length);
487 GDSetCurrent(NULL);
488
489 // Set ALL texture coordinates to scale manually.
490 // This way, GX won't try to do any automatic scaling.
491 GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_ENABLE, 1, 1);
492 GXSetTexCoordScaleManually(GX_TEXCOORD1, GX_ENABLE, 1, 1);
493 GXSetTexCoordScaleManually(GX_TEXCOORD2, GX_ENABLE, 1, 1);
494 GXSetTexCoordScaleManually(GX_TEXCOORD3, GX_ENABLE, 1, 1);
495 GXSetTexCoordScaleManually(GX_TEXCOORD4, GX_ENABLE, 1, 1);
496 GXSetTexCoordScaleManually(GX_TEXCOORD5, GX_ENABLE, 1, 1);
497 GXSetTexCoordScaleManually(GX_TEXCOORD6, GX_ENABLE, 1, 1);
498 GXSetTexCoordScaleManually(GX_TEXCOORD7, GX_ENABLE, 1, 1);
499
500 // Proceed with the usual sort of initialization...
501
502 CameraInit(); // Initialize the camera.
503
504 // Set up a light
505 GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
506 GXInitLightColor(&MyLight, White);
507 GXLoadLightObjImm(&MyLight, GX_LIGHT0);
508 GXSetChanCtrl(
509 GX_COLOR0,
510 GX_ENABLE, // enable channel
511 GX_SRC_REG, // amb source
512 GX_SRC_REG, // mat source
513 GX_LIGHT0, // light mask
514 GX_DF_CLAMP, // diffuse function
515 GX_AF_NONE);
516
517 // Set up TEV
518 GXSetNumChans(1);
519 GXSetNumTevStages(1);
520 GXSetTevOp (GX_TEVSTAGE0, GX_MODULATE);
521 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
522
523 // Fix up normals
524 for(i = 0; i < 24; i++)
525 {
526 FloatNorm[i] *= NORM;
527 }
528
529 // Flush new normals to memory
530 DCFlushRange((void *)FloatNorm, sizeof(FloatNorm));
531 }
532
533 /*---------------------------------------------------------------------------*
534 Name: DrawTick
535
536 Description: Draw the current model once.
537
538 Arguments: v view matrix
539 m model matrix
540
541 Returns: none
542 *---------------------------------------------------------------------------*/
DrawTick(void)543 static void DrawTick( void )
544 {
545 // Draw the cube
546
547 // Call the init DL to set up the parameters for the draw DL.
548 GXCallDisplayList(GDGetGDLObjStart(&InitDLO), GDGetGDLObjOffset(&InitDLO));
549
550 // Call the draw DL to draw the cube.
551 GXCallDisplayList(GDGetGDLObjStart(&DrawDLO), GDGetGDLObjOffset(&DrawDLO));
552 }
553
554 /*---------------------------------------------------------------------------*
555 Name: AnimTick
556
557 Description: Animates the camera and object based on the joystick's
558 state.
559
560 Arguments: none
561
562 Returns: none
563 *---------------------------------------------------------------------------*/
AnimTick(void)564 static void AnimTick ( void )
565 {
566 Mtx ry, rz, mv, tm, mn;
567 f32 tx, ty;
568 u16 buttons = DEMOPadGetButton(0);
569
570 // Just simple controls right now...
571
572 if(buttons & PAD_BUTTON_A)
573 {
574 // suspend animation
575 } else {
576
577 rot ++;
578 if(rot > 2159)
579 rot = 0;
580 }
581
582 // Set up our transformations...
583
584 tx = 0.0f;
585 ty = 0.0f;
586
587 MTXRotDeg(ry, 'X', (float)rot);
588 MTXRotDeg(rz, 'Y', (float)rot / 3.0F);
589 MTXTrans(tm, tx, ty, 0);
590
591 MTXConcat(rz, ry, mv);
592 MTXConcat(tm, mv, mv);
593 MTXConcat(v, mv, mv);
594 GXLoadPosMtxImm(mv, GX_PNMTX0);
595
596 MTXInverse(mv, mn);
597 MTXTranspose(mn, mn);
598 GXLoadNrmMtxImm(mn, GX_PNMTX0);
599 }
600
601 /*---------------------------------------------------------------------------*
602 Name: ParameterInit
603
604 Description: Initialize parameters for single frame display
605
606 Arguments: none
607
608 Returns: none
609 *---------------------------------------------------------------------------*/
ParameterInit(void)610 static void ParameterInit ( void )
611 {
612 rot = 45;
613 }
614
615 /****************************************************************************/
616