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