1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tg-clr-persp.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 #include <demo.h>
15
16 /*---------------------------------------------------------------------------*
17 Global Data
18 *---------------------------------------------------------------------------*/
19 // view matrix
20 Mtx g_viewMtx;
21 // Draw mode
22 u8 g_mode = 0;
23 // What texture maps to use
24 u8 g_map = 0;
25 // Base texture?
26 u8 g_base = 0;
27 // Alpha texture?
28 u8 g_alpha = 1;
29 // Vectors to keep track of the camera's coordinate system orientation
30 Vec g_camX = {1.0F, 0.0F, 0.0F};
31 Vec g_camY = {0.0F, 1.0F, 0.0F};
32 Vec g_camZ = {0.0F, 0.0F, 1.0F};
33 // Distance (Z) of Cam (one for each mode)
34 f32 g_dist[3] = {800.0F, 800.0F, 800.0F};
35 #define MAX_DIST 2500.0F
36 #define MIN_DIST 10.0F
37 // Texture maps
38 #define NUM_TEXTURES 15
39 GXTexObj g_texMap[NUM_TEXTURES];
40
41 /*---------------------------------------------------------------------------*
42 Macros
43 *---------------------------------------------------------------------------*/
44 #define COLOR_ADJUST(color, size) \
45 (u8)(((size) / (size - 1)) * color + (((size) / (size - 1)) * 128))
46
47 /*---------------------------------------------------------------------------*
48 CubeModelData
49 *---------------------------------------------------------------------------*/
50 // Vertices
51 static f32 cube_vrt_f32[] ATTRIBUTE_ALIGN(32) = {
52 -128.0F, 128.0F, 128.0F,
53 128.0F, 128.0F, 128.0F,
54 128.0F, -128.0F, 128.0F,
55 -128.0F, -128.0F, 128.0F,
56 -128.0F, 128.0F, -128.0F,
57 128.0F, 128.0F, -128.0F,
58 128.0F, -128.0F, -128.0F,
59 -128.0F, -128.0F, -128.0F,
60 };
61 // Colors
62 static u32 cube_clr_u32[] ATTRIBUTE_ALIGN(32) = {
63 0xff0000ff,
64 0x00ff00ff,
65 0x0000ffff,
66 0xff00ffff,
67 0xff000010,
68 0x00ff0010,
69 0x0000ff10,
70 0xffffff10,
71 };
72 // Colors (RG)
73 static u32 cube_clr0_u32[] ATTRIBUTE_ALIGN(32) = {
74 0xff000000,
75 0x00ff0000,
76 0x00000000,
77 0xff000000,
78 0xff000000,
79 0x00ff0000,
80 0x00000000,
81 0xffff0000,
82 };
83 // Colors (BA) Channels moved into (RG) Channels
84 static u32 cube_clr1_u32[] ATTRIBUTE_ALIGN(32) = {
85 0x00ff0000,
86 0x00ff0000,
87 0xffff0000,
88 0xffff0000,
89 0x00100000,
90 0x00100000,
91 0xff100000,
92 0xff100000,
93 };
94 // Texture
95 static f32 cube_txt_f32[] ATTRIBUTE_ALIGN(32) =
96 {
97 0.0F, 0.0F,
98 1.0F, 0.0F,
99 1.0F, 1.0F,
100 0.0F, 1.0F,
101 };
102 // Face Info
103 static u32 cube_quad_order[6][4] = {
104 // Front
105 {0, 1, 2, 3},
106 // Right
107 {1, 5, 6, 2},
108 // Back
109 {5, 4, 7, 6},
110 // Left
111 {4, 0, 3, 7},
112 // Top
113 {4, 5, 1, 0},
114 // Bottom
115 {3, 2, 6, 7},
116 };
117 static u32 cube_tri_order[12][3] = {
118 // Front
119 {0, 1, 3}, {1, 2, 3},
120 // Right
121 {1, 5, 2}, {5, 6, 2},
122 // Back
123 {5, 4, 6}, {4, 7, 6},
124 // Left
125 {4, 0, 7}, {0, 3, 7},
126 // Top
127 {4, 5, 0}, {5, 1, 0},
128 // Bottom
129 {3, 2, 7}, {2, 6, 7},
130 };
131 static u32 cube_tex_order[12] = {0, 1, 3, 1, 2, 3, 0};
132
133 /*---------------------------------------------------------------------------*
134 WallData
135 *---------------------------------------------------------------------------*/
136 #define WALL_SIZE 64
137
138 /*---------------------------------------------------------------------------*
139 LightData
140 *---------------------------------------------------------------------------*/
141 // Number of Lights
142 u8 g_numHwLights = 4;
143 GXLightObj g_lightObj[8];
144 // Vertices
145 static Vec light_vtx_vec[] ATTRIBUTE_ALIGN(32) = {
146 {-128.0F, 128.0F, 30.0F},
147 {-128.0F, -128.0F, 30.0F},
148 {128.0F, 128.0F, 30.0F},
149 {128.0F, -128.0F, 30.0F},
150 };
151 // Colors
152 static GXColor light_clr_clr[] ATTRIBUTE_ALIGN(32) = {
153 {0xc0, 0x00, 0x00, 0xff}, // burgundy
154 {0x70, 0xc0, 0x40, 0xff}, // olive green
155 {0xc0, 0xa0, 0x70, 0xff}, // beige
156 {0x40, 0x00, 0xc0, 0xff}, // indigo
157 };
158 GXColor g_ambClr = {0x00, 0x00, 0x00, 0x00};
159 GXColor g_matClr = {0xFF, 0xFF, 0xFF, 0xFF};
160
161 /*---------------------------------------------------------------------------*
162 PlaneData
163 *---------------------------------------------------------------------------*/
164 // Colors
165 static u32 plane_clr0_u32[] ATTRIBUTE_ALIGN(32) = {
166 0xff0000ff,
167 0x00ff00ff,
168 0x0000ffff,
169 0xff00ffff,
170 };
171 // Colors (BA)
172 static u32 plane_clr1_u32[] ATTRIBUTE_ALIGN(32) = {
173 0x00ff0000,
174 0x00ff0000,
175 0xffff0000,
176 0xffff0000,
177 };
178
179 /*---------------------------------------------------------------------------*
180 Forward references
181 *---------------------------------------------------------------------------*/
182 static void CameraInit(Mtx v);
183 static void MakeModelMtx(Vec xAxis, Vec yAxis, Vec zAxis, Mtx m);
184 static void DrawCube(u32 * cube_clr0_u32, u32 * cube_clr1_u32,
185 f32 * cube_tex_f32);
186 static void AnimTick(u8 * mode);
187 static void DrawTick(u8 mode);
188 static void DrawInit(void);
189 static void DrawState(u8 mode);
190 static void DrawWall(u16 size);
191 static void DrawZPlane(u32 * wall_clr0_u32, u32 * wall_clr1_u32);
192 static void PrintIntro( void );
193
194
195 /*---------------------------------------------------------------------------*
196 Application main loop
197 *---------------------------------------------------------------------------*/
main(void)198 void main ( void )
199 {
200 DEMOInit(NULL); // Init os, pad, gx, vi
201
202 PrintIntro();
203
204 CameraInit(g_viewMtx);
205
206 DrawInit();
207
208 OSReport("********************************\n");
209 while (1)
210 {
211 AnimTick(&g_mode);
212 DEMOBeforeRender();
213 DrawTick(g_mode);
214 DEMODoneRender();
215 DEMOPadRead();
216 }
217 OSHalt("End of demo");
218 }
219
220 /*---------------------------------------------------------------------------*
221 Functions
222 *---------------------------------------------------------------------------*/
223
224 /*---------------------------------------------------------------------------*
225 Name: CameraInit
226
227 Description: Initialize the projection matrix and load into hardware.
228 Initialize the view matrix
229
230 Arguments: v view matrix
231
232 Returns: none
233 *---------------------------------------------------------------------------*/
CameraInit(Mtx v)234 static void CameraInit ( Mtx v )
235 {
236 Mtx44 p;
237 Vec camPt = {0.0F, 0.0F, 800.0F};
238 Vec at = {0.0F, 0.0F, -100.0F};
239 Vec up = {0.0F, 1.0F, 0.0F};
240
241 MTXFrustum(p, 240.0F,-240.0F,-320.0F, 320.0F, 400, 2000);
242 MTXPerspective(p, 90.0F, 4.0F/3.0F, 5.0F, 10000);
243 GXSetProjection(p, GX_PERSPECTIVE);
244 MTXLookAt(v, &camPt, &up, &at);
245 }
246
247 /*---------------------------------------------------------------------------*
248 Name: MakeModelMtx
249
250 Description: computes a model matrix from 3 vectors representing an
251 object's coordinate system.
252
253 Arguments: xAxis vector for the object's X axis
254 yAxis vector for the object's Y axis
255 zAxis vector for the object's Z axis
256
257 Returns: none
258 *---------------------------------------------------------------------------*/
MakeModelMtx(Vec xAxis,Vec yAxis,Vec zAxis,Mtx m)259 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m )
260 {
261 VECNormalize(&xAxis,&xAxis);
262 VECNormalize(&yAxis,&yAxis);
263 VECNormalize(&zAxis, &zAxis);
264
265 m[0][0] = xAxis.x;
266 m[1][0] = xAxis.y;
267 m[2][0] = xAxis.z;
268
269 m[0][1] = yAxis.x;
270 m[1][1] = yAxis.y;
271 m[2][1] = yAxis.z;
272
273 m[0][2] = zAxis.x;
274 m[1][2] = zAxis.y;
275 m[2][2] = zAxis.z;
276
277 m[0][3] = 0.0F;
278 m[1][3] = 0.0F;
279 m[2][3] = 0.0F;
280 }
281
282 /*---------------------------------------------------------------------------*
283 Name: DrawCube
284
285 Description: Draws a Cube.
286
287 Arguments:
288 cube_clr0_u32 if not Null the color0 vtx data
289 (must be an array of 8 u32s)
290 cube_clr1_u32 if not Null the color1 vtx data
291 (must be an array of 8 u32s)
292 cube_tex_f32 if not NULL the texture coords
293 (must be an array of 4 f32s);
294
295 Returns: none
296 *---------------------------------------------------------------------------*/
DrawCube(u32 * cube_clr0_u32,u32 * cube_clr1_u32,f32 * cube_tex_f32)297 static void DrawCube(u32 * cube_clr0_u32, u32 * cube_clr1_u32,
298 f32 * cube_tex_f32)
299 {
300 // Face Info
301 u32 i, j;
302
303 // Setup
304 GXClearVtxDesc();
305
306 // Vertices
307 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
308 GXSetArray(GX_VA_POS, cube_vrt_f32, 3*sizeof(f32));
309 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
310
311 // Colors
312 if (cube_clr0_u32 != NULL)
313 {
314 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
315 GXSetArray(GX_VA_CLR0, cube_clr0_u32, 1*sizeof(u32));
316 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
317 }
318
319 // Colors
320 if (cube_clr1_u32 != NULL)
321 {
322 GXSetVtxDesc(GX_VA_CLR1, GX_INDEX8);
323 GXSetArray(GX_VA_CLR1, cube_clr1_u32, 1*sizeof(u32));
324 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
325 }
326
327 // Textures
328 if (cube_txt_f32 != NULL)
329 {
330 GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
331 GXSetArray(GX_VA_TEX0, cube_txt_f32, 2*sizeof(f32));
332 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
333 }
334
335 // Draw a cube
336 for (i = 0; i < 6; i++)
337 {
338 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
339 for (j = 0; j < 4; j++)
340 {
341 GXPosition1x8((u8)cube_quad_order[i][j]);
342 if (cube_clr0_u32) GXColor1x8((u8)cube_quad_order[i][j]);
343 if (cube_clr1_u32) GXColor1x8((u8)cube_quad_order[i][j]);
344 if (cube_tex_f32) GXTexCoord1x8((u8)j);
345 }
346 GXEnd();
347 }
348 }
349
350 /*---------------------------------------------------------------------------*
351 Name: DrawWall
352
353 Description: Draws a tessellated wall
354
355 Arguments: size of the wall. The wall will be sizeXsize
356
357 Returns: none
358 *---------------------------------------------------------------------------*/
DrawWall(u16 size)359 static void DrawWall(u16 size)
360 {
361 s32 x, y, i;
362 f32 xx, yy0, yy1;
363 f32 half;
364 #define STEP 10
365
366 half = size / 2;
367
368 // Setup
369 GXClearVtxDesc();
370
371 // Vertices
372 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
373 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
374
375 // Normal
376 GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
377 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
378
379 for (y = 0; y < size - 1; ++y)
380 {
381 i = y * size;
382 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16)(size * 2));
383 for (x = 0; x < size; ++x)
384 {
385 xx = (f32)(x * STEP - half * STEP);
386 yy0 = (f32)(y * STEP - half * STEP);
387 yy1 = (f32)((y + 1) * STEP - half * STEP);
388 GXPosition3f32(xx, yy0, 0.0F);
389 GXNormal3f32(0.0F, 0.0F, 1.0F);
390 GXPosition3f32(xx, yy1, 0.0F);
391 GXNormal3f32(0.0F, 0.0F, 1.0F);
392 }
393 GXEnd();
394 }
395 }
396
397 /*---------------------------------------------------------------------------*
398 Name: DrawZPlane
399
400 Description: Draws a quad in the X-Y axis
401
402 Arguments:
403 cube_clr0_u32 the color0 vtx data (will be written)
404 (must be an array of 4 u32s)
405 cube_clr1_u32 the color1 vtx data (will be written)
406 (must be an array of 4 u32s)
407
408 Returns: none
409 *---------------------------------------------------------------------------*/
DrawZPlane(u32 * wall_clr0_u32,u32 * wall_clr1_u32)410 static void DrawZPlane(u32 * wall_clr0_u32, u32 * wall_clr1_u32)
411 {
412
413 // Setup
414 GXClearVtxDesc();
415
416 // Vertices
417 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
418 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
419
420 // Colors
421 if (wall_clr0_u32)
422 {
423 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
424 GXSetArray(GX_VA_CLR0, wall_clr0_u32, 1*sizeof(u32));
425 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
426 }
427
428 // Colors
429 if (wall_clr1_u32)
430 {
431 GXSetVtxDesc(GX_VA_CLR1, GX_INDEX16);
432 GXSetArray(GX_VA_CLR1, wall_clr1_u32, 1*sizeof(u32));
433 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0);
434 }
435
436 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4);
437 GXPosition3f32(0.0F, -64.0F, 1500.0F);
438 if (wall_clr0_u32) GXColor1x16(0);
439 if (wall_clr1_u32) GXColor1x16(0);
440 GXPosition3f32(0.0F, 64.0F, 1500.0F);
441 if (wall_clr0_u32) GXColor1x16(1);
442 if (wall_clr1_u32) GXColor1x16(1);
443 GXPosition3f32(0.0F, -64.0F, -1500.0F);
444 if (wall_clr0_u32) GXColor1x16(2);
445 if (wall_clr1_u32) GXColor1x16(2);
446 GXPosition3f32(0.0F, 64.0F, -1500.0F);
447 if (wall_clr0_u32) GXColor1x16(3);
448 if (wall_clr1_u32) GXColor1x16(3);
449 GXEnd();
450 }
451
452 /*---------------------------------------------------------------------------*
453 Name: DrawTick
454
455 Description:
456
457 Arguments: mode current draw mode
458
459 Returns: none
460 *---------------------------------------------------------------------------*/
DrawTick(u8 mode)461 static void DrawTick(u8 mode)
462 {
463 switch (mode)
464 {
465 case 0:
466 if (!g_base)
467 {
468 DrawState(0);
469 GXSetCurrentMtx(GX_PNMTX0);
470 // Note: Drawing twice for cheap z-sort
471 GXSetCullMode(GX_CULL_FRONT);
472 DrawCube(cube_clr_u32, NULL, cube_txt_f32);
473 GXSetCullMode(GX_CULL_BACK);
474 DrawCube(cube_clr_u32, NULL, cube_txt_f32);
475
476 DrawState(1);
477 GXSetCurrentMtx(GX_PNMTX1);
478 // Note: Drawing twice for cheap z-sort
479 GXSetCullMode(GX_CULL_FRONT);
480 DrawCube(cube_clr0_u32, cube_clr1_u32, cube_txt_f32);
481 GXSetCullMode(GX_CULL_BACK);
482 DrawCube(cube_clr0_u32, cube_clr1_u32, cube_txt_f32);
483 }
484 else
485 {
486 DrawState(2);
487 GXSetCurrentMtx(GX_PNMTX0);
488 // Note: Drawing twice for cheap z-sort
489 GXSetCullMode(GX_CULL_FRONT);
490 DrawCube(cube_clr_u32, NULL, cube_txt_f32);
491 GXSetCullMode(GX_CULL_BACK);
492 DrawCube(cube_clr_u32, NULL, cube_txt_f32);
493
494 DrawState(3);
495 GXSetCurrentMtx(GX_PNMTX1);
496 // Note: Drawing twice for cheap z-sort
497 GXSetCullMode(GX_CULL_FRONT);
498 DrawCube(cube_clr0_u32, cube_clr1_u32, cube_txt_f32);
499 GXSetCullMode(GX_CULL_BACK);
500 DrawCube(cube_clr0_u32, cube_clr1_u32, cube_txt_f32);
501 }
502 break;
503 case 1:
504 GXSetCurrentMtx(GX_PNMTX7);
505 DrawState(4);
506 GXSetCullMode(GX_CULL_NONE);
507 DrawWall(WALL_SIZE);
508 break;
509 case 2:
510 GXSetCullMode(GX_CULL_NONE);
511
512 DrawState(0);
513 GXSetCurrentMtx(GX_PNMTX0);
514 DrawZPlane(plane_clr0_u32, NULL);
515
516 DrawState(1);
517 GXSetCurrentMtx(GX_PNMTX1);
518 DrawZPlane(plane_clr0_u32, cube_clr1_u32);
519 break;
520 }
521 }
522
523 /*---------------------------------------------------------------------------*
524 Name: AnimTick
525
526 Description:
527
528 Arguments: mode pointer to current draw mode
529
530 Returns: none
531 *---------------------------------------------------------------------------*/
AnimTick(u8 * mode)532 static void AnimTick(u8 * mode)
533 {
534 static f32 rotX = 0, rotY = 0;
535 static f32 lrotZ = 0;
536 static u8 rotate = 1;
537 s8 stickX, stickY;
538 s8 substickX, substickY;
539 Mtx temp;
540 Mtx mtx0;
541 Mtx mtx1;
542 f32 ddist;
543 u16 button;
544 u16 i;
545 u16 w, h;
546
547 button = DEMOPadGetButtonDown(0);
548 stickX = DEMOPadGetStickX(0);
549 stickY = DEMOPadGetStickY(0);
550 substickX = DEMOPadGetSubStickX(0);
551 substickY = DEMOPadGetSubStickY(0);
552
553 // Global Button Controls
554 switch (button)
555 {
556 // Swap Texture!
557 case PAD_BUTTON_X:
558 g_map = (u8)((g_map + 1) % 7);
559 GXLoadTexObj(&g_texMap[2 * g_map], GX_TEXMAP0);
560 GXLoadTexObj(&g_texMap[2 * g_map + 1], GX_TEXMAP1);
561 w = GXGetTexObjWidth(&g_texMap[2 * g_map]);
562 h = GXGetTexObjHeight(&g_texMap[2 * g_map]);
563 OSReport("Rasterization Lookup Texture: %d (%dx%d)\n",
564 g_map, w, h);
565 break;
566 case PAD_BUTTON_A:
567 *mode = (u8)((*mode + 1) % 3);
568 break;
569 case PAD_BUTTON_B:
570 rotate ^= 1;
571 break;
572 }
573
574 // Mode Controls
575 switch (*mode)
576 {
577 case 0:
578 // Cube Rotation
579 if (rotate)
580 {
581 rotX += 0.33F;
582 rotY += 0.32F;
583 }
584 rotX += (f32)stickX / 3.0F;
585 rotY -= (f32)stickY / 3.0F;
586
587 // Button Controls
588 switch (button)
589 {
590 case PAD_BUTTON_UP:
591 g_base ^= 1;
592 break;
593 case PAD_BUTTON_LEFT:
594 g_alpha ^= 1;
595 break;
596 }
597
598 // Stick Controls
599 if (substickX || substickY)
600 {
601 if (substickX)
602 {
603 if (stickX > 0)
604 MTXRotAxisDeg(temp, &g_camY, 3.0F);
605 else
606 MTXRotAxisDeg(temp, &g_camY, -3.0F);
607
608 MTXMultVec(temp, &g_camX, &g_camX);
609 MTXMultVec(temp, &g_camZ, &g_camZ);
610 }
611
612 if (substickY)
613 {
614 if (stickY > 0)
615 MTXRotAxisDeg(temp, &g_camX, 3.0F);
616 else
617 MTXRotAxisDeg(temp, &g_camX, -3.0F);
618
619 MTXMultVec(temp, &g_camY, &g_camY);
620 MTXMultVec(temp, &g_camZ, &g_camZ);
621 }
622 }
623 ddist = DEMOPadGetTriggerL(0) / 3.0F;
624 if (g_dist[0] - ddist > MIN_DIST) g_dist[0] -= ddist;
625 ddist = DEMOPadGetTriggerR(0) / 3.0F;
626 if (g_dist[0] + ddist < MAX_DIST) g_dist[0] += ddist;
627
628 // Create View Matrix
629 MakeModelMtx(g_camX, g_camY, g_camZ, g_viewMtx);
630 MTXTranspose(g_viewMtx, g_viewMtx);
631 MTXTrans(temp, 0.0F, 0.0F, -g_dist[0]);
632 MTXConcat(temp, g_viewMtx, g_viewMtx);
633
634 // Cube 0
635 MTXTrans(mtx0, -200.0F, 0.0F, 0.0F);
636 MTXRotDeg(temp, 'x', rotX);
637 MTXConcat(mtx0, temp, mtx0);
638 MTXRotDeg(temp, 'y', rotY);
639 MTXConcat(mtx0, temp, mtx0);
640 MTXConcat(g_viewMtx, mtx0, mtx0);
641
642 // Cube 1
643 MTXTrans(mtx1, 200.0F, 0.0F, 0.0F);
644 MTXRotDeg(temp, 'x', rotX);
645 MTXConcat(mtx1, temp, mtx1);
646 MTXRotDeg(temp, 'y', rotY);
647 MTXConcat(mtx1, temp, mtx1);
648 MTXConcat(g_viewMtx, mtx1, mtx1);
649
650 GXLoadPosMtxImm(mtx0, GX_PNMTX0);
651 GXLoadPosMtxImm(mtx1, GX_PNMTX1);
652 break;
653 case 1:
654 // Camera Control
655 ddist = (f32)substickY / 5.0F;
656 if (g_dist[1] - ddist < MAX_DIST && g_dist[1] - ddist > MIN_DIST)
657 {
658 g_dist[1] -= ddist;
659 }
660 MTXIdentity(g_viewMtx);
661 MTXTrans(temp, 0.0F, 0.0F, -g_dist[1]);
662 MTXConcat(temp, g_viewMtx, g_viewMtx);
663
664 // Model Control
665 GXLoadPosMtxImm(g_viewMtx, GX_PNMTX7);
666
667 // Normal
668 MTXInverse(g_viewMtx, temp);
669 MTXTranspose(temp, temp);
670 GXLoadNrmMtxImm(temp, GX_PNMTX7);
671
672 // Rotate Lights
673 if (rotate)
674 {
675 lrotZ = 0.32F;
676 }
677 else
678 {
679 lrotZ = 0.0F;
680 }
681 MTXRotDeg(temp, 'z', lrotZ);
682 for (i = 0; i < g_numHwLights; ++i)
683 {
684 MTXMultVec(temp, &light_vtx_vec[i], &light_vtx_vec[i]);
685 }
686
687 break;
688 case 2:
689 // Camera Control
690 ddist = (f32)substickY / 5.0F;
691 if (g_dist[2] - ddist < MAX_DIST && g_dist[2] - ddist > MIN_DIST)
692 {
693 g_dist[2] -= ddist;
694 }
695 MTXIdentity(g_viewMtx);
696 MTXTrans(temp, 0.0F, 0.0F, -g_dist[2]);
697 MTXConcat(temp, g_viewMtx, g_viewMtx);
698
699 // Model Control
700 MTXTrans(mtx0, -200.0F, 0.0F, 0.0F);
701 MTXConcat(g_viewMtx, mtx0, mtx0);
702 MTXTrans(mtx1, 200.0F, 0.0F, 0.0F);
703 MTXConcat(g_viewMtx, mtx1, mtx1);
704 GXLoadPosMtxImm(mtx0, GX_PNMTX0);
705 GXLoadPosMtxImm(mtx1, GX_PNMTX1);
706 break;
707 }
708 }
709
710 /*---------------------------------------------------------------------------*
711 Name: DrawInit
712
713 Description: Initializes Drawing state
714
715 Arguments: none
716
717 Returns: none
718 *---------------------------------------------------------------------------*/
DrawInit(void)719 static void DrawInit(void)
720 {
721 TPLDescriptorPtr tdp;
722 TPLPalettePtr tpl = 0;
723 GXColor black = {0, 0, 0, 0};
724 u32 i;
725
726 // Setup Textures
727 TPLGetPalette(&tpl, "gxTests/tg-pc.tpl");
728 // First
729 for (i = 0; i < NUM_TEXTURES; i++)
730 {
731 tdp = TPLGet(tpl, i);
732 GXInitTexObj(&g_texMap[i],
733 tdp->textureHeader->data,
734 tdp->textureHeader->width,
735 tdp->textureHeader->height,
736 (GXTexFmt)tdp->textureHeader->format,
737 GX_CLAMP,
738 GX_CLAMP,
739 GX_FALSE);
740 }
741 GXLoadTexObj(&g_texMap[0], GX_TEXMAP0);
742 GXLoadTexObj(&g_texMap[1], GX_TEXMAP1);
743 GXLoadTexObj(&g_texMap[NUM_TEXTURES - 1], GX_TEXMAP2);
744
745 // Global Modes
746 GXSetCullMode(GX_CULL_NONE);
747
748 // Copy
749 GXSetDispCopyGamma(GX_GM_1_0);
750 GXSetCopyClear(black, GX_MAX_Z24);
751 }
752
753 /*---------------------------------------------------------------------------*
754 Name: DrawState
755
756 Description: Sets draw state
757
758 Arguments: mode What mode to draw
759
760 Returns: none
761 *---------------------------------------------------------------------------*/
DrawState(u8 mode)762 static void DrawState(u8 mode)
763 {
764 u8 i;
765 Vec temp;
766 GXColor color;
767 u32 mask0 = 0;
768 u32 mask1 = 0;
769 int lookup[] = {
770 GX_LIGHT0, GX_LIGHT1, GX_LIGHT2, GX_LIGHT3,
771 GX_LIGHT4, GX_LIGHT5, GX_LIGHT6, GX_LIGHT7};
772
773 if (g_alpha)
774 {
775 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
776 }
777 else
778 {
779 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_NOOP);
780 }
781
782 switch (mode)
783 {
784 case 0:
785 /*-------------------------------------------------*
786 Rasterize Color State (vtx color => final color)
787 => Not Perspective Correct Interpolation
788 *-------------------------------------------------*/
789
790 // Don't forget these!
791 GXSetNumChans(1);
792 GXSetNumTexGens(0);
793 GXSetNumTevStages(1);
794
795 // Color Channel (Vertex Color)
796 GXSetChanCtrl(GX_COLOR0A0,
797 GX_DISABLE,
798 GX_SRC_VTX,
799 GX_SRC_VTX,
800 GX_LIGHT_NULL,
801 GX_DF_NONE,
802 GX_AF_NONE);
803
804 // Tev 0
805 GXSetTevOrder(GX_TEVSTAGE0,
806 GX_TEXCOORD_NULL,
807 GX_TEXMAP_NULL,
808 GX_COLOR0A0);
809 GXSetTevColorIn(GX_TEVSTAGE0,
810 GX_CC_ZERO,
811 GX_CC_ZERO,
812 GX_CC_ZERO,
813 GX_CC_RASC);
814 GXSetTevAlphaIn(GX_TEVSTAGE0,
815 GX_CA_ZERO,
816 GX_CA_ZERO,
817 GX_CA_ZERO,
818 GX_CA_RASA);
819 GXSetTevColorOp(GX_TEVSTAGE0,
820 GX_TEV_ADD,
821 GX_TB_ZERO,
822 GX_CS_SCALE_1,
823 GX_ENABLE,
824 GX_TEVPREV);
825 GXSetTevAlphaOp(GX_TEVSTAGE0,
826 GX_TEV_ADD,
827 GX_TB_ZERO,
828 GX_CS_SCALE_1,
829 GX_ENABLE,
830 GX_TEVPREV);
831
832 break;
833 case 1:
834 /*-------------------------------------------------*
835 Rasterize Color => Texture Coords => Perspective
836 Correct Texture Interpolation
837 *-------------------------------------------------*/
838
839 // Don't forget these!
840 GXSetNumChans(2);
841 GXSetNumTexGens(2);
842 GXSetNumTevStages(2);
843
844 // Color Channels
845 // Send vertex color data through the color channels
846 GXSetChanCtrl(GX_COLOR0A0,
847 GX_DISABLE,
848 GX_SRC_VTX,
849 GX_SRC_VTX,
850 GX_LIGHT_NULL,
851 GX_DF_NONE,
852 GX_AF_NONE);
853 GXSetChanCtrl(GX_COLOR1A1,
854 GX_DISABLE,
855 GX_SRC_VTX,
856 GX_SRC_VTX,
857 GX_LIGHT_NULL,
858 GX_DF_NONE,
859 GX_AF_NONE);
860
861 // Convert color0 to s,t for 2-D texture lookup (RG)
862 GXSetTexCoordGen(GX_TEXCOORD0,
863 GX_TG_SRTG,
864 GX_TG_COLOR0,
865 GX_IDENTITY);
866 // Convert color1 to s,t for 2-D texture lookup (BA)
867 GXSetTexCoordGen(GX_TEXCOORD1,
868 GX_TG_SRTG,
869 GX_TG_COLOR1,
870 GX_IDENTITY);
871
872 // Tev 0: Use rasterization lookup table (RG)
873 // Note: Blue = 0 and Alpha = 0;
874 GXSetTevOrder(GX_TEVSTAGE0,
875 GX_TEXCOORD0,
876 GX_TEXMAP0,
877 GX_COLOR_NULL);
878 GXSetTevColorIn(GX_TEVSTAGE0,
879 GX_CC_ZERO,
880 GX_CC_ZERO,
881 GX_CC_ZERO,
882 GX_CC_TEXC);
883 GXSetTevAlphaIn(GX_TEVSTAGE0,
884 GX_CA_ZERO,
885 GX_CA_ZERO,
886 GX_CA_ZERO,
887 GX_CA_ZERO);
888 GXSetTevColorOp(GX_TEVSTAGE0,
889 GX_TEV_ADD,
890 GX_TB_ZERO,
891 GX_CS_SCALE_1,
892 GX_ENABLE,
893 GX_TEVPREV);
894 GXSetTevAlphaOp(GX_TEVSTAGE0,
895 GX_TEV_ADD,
896 GX_TB_ZERO,
897 GX_CS_SCALE_1,
898 GX_ENABLE,
899 GX_TEVPREV);
900
901 // Tev 1: Use rasterization lookup table (BA),
902 // then add previous tev (RG + BA)
903 GXSetTevOrder(GX_TEVSTAGE1,
904 GX_TEXCOORD1,
905 GX_TEXMAP1,
906 GX_COLOR_NULL);
907 GXSetTevColorIn(GX_TEVSTAGE1,
908 GX_CC_ZERO,
909 GX_CC_TEXC,
910 GX_CC_ONE,
911 GX_CC_CPREV);
912 GXSetTevAlphaIn(GX_TEVSTAGE1,
913 GX_CA_ZERO,
914 GX_CA_TEXA,
915 GX_CA_ONE,
916 GX_CA_APREV);
917 GXSetTevColorOp(GX_TEVSTAGE1,
918 GX_TEV_ADD,
919 GX_TB_ZERO,
920 GX_CS_SCALE_1,
921 GX_ENABLE,
922 GX_TEVPREV);
923 GXSetTevAlphaOp(GX_TEVSTAGE1,
924 GX_TEV_ADD,
925 GX_TB_ZERO,
926 GX_CS_SCALE_1,
927 GX_ENABLE,
928 GX_TEVPREV);
929 break;
930 case 2:
931 /*-------------------------------------------------*
932 Rasterize Color State (vtx color => final color)
933 => Not Perspective Correct Interpolation
934 + Base Texture
935 *-------------------------------------------------*/
936
937 // Don't forget these!
938 GXSetNumChans(1);
939 GXSetNumTexGens(1);
940 GXSetNumTevStages(1);
941
942 // Color Channel (Vertex Color)
943 GXSetChanCtrl(GX_COLOR0A0,
944 GX_DISABLE,
945 GX_SRC_VTX,
946 GX_SRC_VTX,
947 GX_LIGHT_NULL,
948 GX_DF_NONE,
949 GX_AF_NONE);
950
951 // Base Texture Coordinates
952 GXSetTexCoordGen(GX_TEXCOORD0,
953 GX_TG_MTX2x4,
954 GX_TG_TEX0,
955 GX_IDENTITY);
956
957 // Tev 0
958 GXSetTevOrder(GX_TEVSTAGE0,
959 GX_TEXCOORD0,
960 GX_TEXMAP2,
961 GX_COLOR0A0);
962 GXSetTevColorIn(GX_TEVSTAGE0,
963 GX_CC_ZERO,
964 GX_CC_RASC,
965 GX_CC_TEXC,
966 GX_CC_ZERO);
967 GXSetTevAlphaIn(GX_TEVSTAGE0,
968 GX_CA_ZERO,
969 GX_CA_ZERO,
970 GX_CA_ZERO,
971 GX_CA_RASA);
972 GXSetTevColorOp(GX_TEVSTAGE0,
973 GX_TEV_ADD,
974 GX_TB_ZERO,
975 GX_CS_SCALE_1,
976 GX_ENABLE,
977 GX_TEVPREV);
978 GXSetTevAlphaOp(GX_TEVSTAGE0,
979 GX_TEV_ADD,
980 GX_TB_ZERO,
981 GX_CS_SCALE_1,
982 GX_ENABLE,
983 GX_TEVPREV);
984
985 break;
986 case 3:
987 /*-------------------------------------------------*
988 Rasterize Color => Texture Coords => Perspective
989 Correct Texture Interpolation
990 + Base Texture
991 *-------------------------------------------------*/
992
993 // Don't forget these!
994 GXSetNumChans(2);
995 GXSetNumTexGens(3);
996 GXSetNumTevStages(3);
997
998 // Color Channels
999 // Send vertex color data through the color channels
1000 GXSetChanCtrl(GX_COLOR0A0,
1001 GX_DISABLE,
1002 GX_SRC_VTX,
1003 GX_SRC_VTX,
1004 GX_LIGHT_NULL,
1005 GX_DF_NONE,
1006 GX_AF_NONE);
1007 GXSetChanCtrl(GX_COLOR1A1,
1008 GX_DISABLE,
1009 GX_SRC_VTX,
1010 GX_SRC_VTX,
1011 GX_LIGHT_NULL,
1012 GX_DF_NONE,
1013 GX_AF_NONE);
1014
1015 // Note: The following TexCoordGen order is important.
1016 // See "Functional Ordering Requirements" on man page.
1017
1018 // Base Texture Coordinates
1019 GXSetTexCoordGen(GX_TEXCOORD0,
1020 GX_TG_MTX2x4,
1021 GX_TG_TEX0,
1022 GX_IDENTITY);
1023 // Convert color0 to s,t for 2-D texture lookup (RG)
1024 GXSetTexCoordGen(GX_TEXCOORD1,
1025 GX_TG_SRTG,
1026 GX_TG_COLOR0,
1027 GX_IDENTITY);
1028 // Convert color1 to s,t for 2-D texture lookup (BA)
1029 GXSetTexCoordGen(GX_TEXCOORD2,
1030 GX_TG_SRTG,
1031 GX_TG_COLOR1,
1032 GX_IDENTITY);
1033
1034 // Tev 0: Use rasterization lookup table (RG)
1035 // Note: Blue = 0 and Alpha = 0;
1036 GXSetTevOrder(GX_TEVSTAGE0,
1037 GX_TEXCOORD1,
1038 GX_TEXMAP0,
1039 GX_COLOR_NULL);
1040 GXSetTevColorIn(GX_TEVSTAGE0,
1041 GX_CC_ZERO,
1042 GX_CC_ZERO,
1043 GX_CC_ZERO,
1044 GX_CC_TEXC);
1045 GXSetTevAlphaIn(GX_TEVSTAGE0,
1046 GX_CA_ZERO,
1047 GX_CA_ZERO,
1048 GX_CA_ZERO,
1049 GX_CA_ZERO);
1050 GXSetTevColorOp(GX_TEVSTAGE0,
1051 GX_TEV_ADD,
1052 GX_TB_ZERO,
1053 GX_CS_SCALE_1,
1054 GX_ENABLE,
1055 GX_TEVPREV);
1056 GXSetTevAlphaOp(GX_TEVSTAGE0,
1057 GX_TEV_ADD,
1058 GX_TB_ZERO,
1059 GX_CS_SCALE_1,
1060 GX_ENABLE,
1061 GX_TEVPREV);
1062
1063 // Tev 1: Use rasterization lookup table (BA),
1064 // then add previous tev (RG + BA)
1065 GXSetTevOrder(GX_TEVSTAGE1,
1066 GX_TEXCOORD2,
1067 GX_TEXMAP1,
1068 GX_COLOR_NULL);
1069 GXSetTevColorIn(GX_TEVSTAGE1,
1070 GX_CC_ZERO,
1071 GX_CC_TEXC,
1072 GX_CC_ONE,
1073 GX_CC_CPREV);
1074 GXSetTevAlphaIn(GX_TEVSTAGE1,
1075 GX_CA_ZERO,
1076 GX_CA_TEXA,
1077 GX_CA_ONE,
1078 GX_CA_APREV);
1079 GXSetTevColorOp(GX_TEVSTAGE1,
1080 GX_TEV_ADD,
1081 GX_TB_ZERO,
1082 GX_CS_SCALE_1,
1083 GX_ENABLE,
1084 GX_TEVPREV);
1085 GXSetTevAlphaOp(GX_TEVSTAGE1,
1086 GX_TEV_ADD,
1087 GX_TB_ZERO,
1088 GX_CS_SCALE_1,
1089 GX_ENABLE,
1090 GX_TEVPREV);
1091
1092 // Tev 2: Modulate Base Texture
1093 // No alpha in base texture, so we just pass previous alpha
1094 GXSetTevOrder(GX_TEVSTAGE2,
1095 GX_TEXCOORD0,
1096 GX_TEXMAP2,
1097 GX_COLOR_NULL);
1098 GXSetTevColorIn(GX_TEVSTAGE2,
1099 GX_CC_ZERO,
1100 GX_CC_TEXC,
1101 GX_CC_CPREV,
1102 GX_CC_ZERO);
1103 GXSetTevAlphaIn(GX_TEVSTAGE2,
1104 GX_CA_ZERO,
1105 GX_CA_ZERO,
1106 GX_CA_ZERO,
1107 GX_CA_APREV);
1108 GXSetTevColorOp(GX_TEVSTAGE2,
1109 GX_TEV_ADD,
1110 GX_TB_ZERO,
1111 GX_CS_SCALE_1,
1112 GX_ENABLE,
1113 GX_TEVPREV);
1114 GXSetTevAlphaOp(GX_TEVSTAGE2,
1115 GX_TEV_ADD,
1116 GX_TB_ZERO,
1117 GX_CS_SCALE_1,
1118 GX_ENABLE,
1119 GX_TEVPREV);
1120 break;
1121 case 4:
1122 /*-------------------------------------------------*
1123 Rasterize Color w/ Lighting => Texture Coords
1124 => Perspective Correct Texture interpolation
1125 *-------------------------------------------------*/
1126
1127 // Turn on lights. Note that 2 lights are needed for a full
1128 // RGBA light, unless you only need a monochromatic light
1129 for (i = 0 ; i < g_numHwLights ; ++i)
1130 {
1131 // Convert light position into view space
1132 MTXMultVec(g_viewMtx,
1133 &light_vtx_vec[i],
1134 &temp);
1135
1136 // RG
1137 GXInitLightPos(&g_lightObj[2 * i],
1138 temp.x,
1139 temp.y,
1140 temp.z);
1141 GXInitLightColor(&g_lightObj[2 * i],
1142 light_clr_clr[i]);
1143 // BA
1144 GXInitLightPos(&g_lightObj[2 * i + 1],
1145 temp.x,
1146 temp.y,
1147 temp.z);
1148 color.r = light_clr_clr[i].b;
1149 color.g = light_clr_clr[i].a;
1150 color.b = 0;
1151 color.a = 0;
1152 GXInitLightColor(&g_lightObj[2 * i + 1],
1153 color);
1154
1155 // Load light object into hardware
1156 GXLoadLightObjImm(&g_lightObj[2 * i],
1157 (GXLightID)lookup[2 * i]);
1158 GXLoadLightObjImm(&g_lightObj[2 * i + 1],
1159 (GXLightID)lookup[2 * i + 1]);
1160
1161 // Compute Mask
1162 mask0 |= lookup[2 * i];
1163 mask1 |= lookup[2 * i + 1];
1164 }
1165
1166 // Don't forget these!
1167 GXSetNumChans(2);
1168 GXSetNumTexGens(2);
1169 GXSetNumTevStages(2);
1170
1171 // Color Channels
1172 GXSetChanCtrl(GX_COLOR0,
1173 GX_ENABLE,
1174 GX_SRC_REG,
1175 GX_SRC_REG,
1176 mask0,
1177 GX_DF_CLAMP,
1178 GX_AF_NONE);
1179 GXSetChanCtrl(GX_COLOR1,
1180 GX_ENABLE,
1181 GX_SRC_REG,
1182 GX_SRC_REG,
1183 mask1,
1184 GX_DF_CLAMP,
1185 GX_AF_NONE);
1186 // Since we only us RG in texgen, alpha can be turned off.
1187 // Actually, you have to if you want to use 4 full color lights
1188 // (8 hardware lights total)
1189 GXSetChanCtrl (GX_ALPHA0,
1190 GX_DISABLE,
1191 GX_SRC_REG,
1192 GX_SRC_REG,
1193 GX_LIGHT_NULL,
1194 GX_DF_NONE,
1195 GX_AF_NONE);
1196 GXSetChanCtrl(GX_ALPHA1,
1197 GX_DISABLE,
1198 GX_SRC_REG,
1199 GX_SRC_REG,
1200 GX_LIGHT_NULL,
1201 GX_DF_NONE,
1202 GX_AF_NONE);
1203
1204 // set up ambient color
1205 GXSetChanAmbColor(GX_COLOR0A0,
1206 g_ambClr);
1207 GXSetChanAmbColor(GX_COLOR1A1,
1208 g_ambClr);
1209 // set up material color
1210 GXSetChanMatColor(GX_COLOR0A0,
1211 g_matClr);
1212 GXSetChanMatColor(GX_COLOR1A1,
1213 g_matClr);
1214
1215 // Tev 0: Use rasterization lookup table (RG)
1216 GXSetTevOrder(GX_TEVSTAGE0,
1217 GX_TEXCOORD_NULL,
1218 GX_TEXMAP_NULL,
1219 GX_COLOR0A0);
1220 GXSetTevColorIn(GX_TEVSTAGE0,
1221 GX_CC_ZERO,
1222 GX_CC_ZERO,
1223 GX_CC_ZERO,
1224 GX_CC_RASC);
1225 GXSetTevAlphaIn(GX_TEVSTAGE0,
1226 GX_CA_ZERO,
1227 GX_CA_ZERO,
1228 GX_CA_ZERO,
1229 GX_CA_RASA);
1230 GXSetTevColorOp(GX_TEVSTAGE0,
1231 GX_TEV_ADD,
1232 GX_TB_ZERO,
1233 GX_CS_SCALE_1,
1234 GX_ENABLE,
1235 GX_TEVPREV);
1236 GXSetTevAlphaOp(GX_TEVSTAGE0,
1237 GX_TEV_ADD,
1238 GX_TB_ZERO,
1239 GX_CS_SCALE_1,
1240 GX_ENABLE,
1241 GX_TEVPREV);
1242
1243 // Tev 1: Use rasterization lookup table (BA),
1244
1245 // then add previous tev (RG + BA)
1246 GXSetTevOrder(GX_TEVSTAGE1,
1247 GX_TEXCOORD1,
1248 GX_TEXMAP1,
1249 GX_COLOR1A1);
1250 GXSetTevColorIn(GX_TEVSTAGE1,
1251 GX_CC_ZERO,
1252 GX_CC_TEXC,
1253 GX_CC_ONE,
1254 GX_CC_CPREV);
1255 GXSetTevAlphaIn(GX_TEVSTAGE1,
1256 GX_CA_ZERO,
1257 GX_CA_TEXA,
1258 GX_CA_ONE,
1259 GX_CA_APREV);
1260 GXSetTevColorOp(GX_TEVSTAGE1,
1261 GX_TEV_ADD,
1262 GX_TB_ZERO,
1263 GX_CS_SCALE_1,
1264 GX_ENABLE,
1265 GX_TEVPREV);
1266 GXSetTevAlphaOp(GX_TEVSTAGE1,
1267 GX_TEV_ADD,
1268 GX_TB_ZERO,
1269 GX_CS_SCALE_1,
1270 GX_ENABLE,
1271 GX_TEVPREV);
1272
1273 // convert color0 to s,t for 2-D texture lookup (RG)
1274 GXSetTexCoordGen(GX_TEXCOORD0,
1275 GX_TG_SRTG,
1276 GX_TG_COLOR0,
1277 GX_IDENTITY);
1278 // convert color1 to s,t for 2-D texture lookup (BA)
1279 GXSetTexCoordGen(GX_TEXCOORD1,
1280 GX_TG_SRTG,
1281 GX_TG_COLOR1,
1282 GX_IDENTITY);
1283 break;
1284 }
1285 }
1286
1287 /*---------------------------------------------------------------------------*
1288 Name: PrintIntro
1289 Description: Prints the directions on how to use this demo.
1290 *---------------------------------------------------------------------------*/
PrintIntro(void)1291 static void PrintIntro( void )
1292 {
1293 OSReport("\n\n");
1294 OSReport("************************************************\n");
1295 OSReport("tg-clr-persp: perspective correct color demo\n");
1296 OSReport("************************************************\n");
1297 OSReport("to quit hit the start button\n");
1298 OSReport("\n");
1299 OSReport("A button : change mode\n");
1300 OSReport("X button : change size of look-up textures\n");
1301 OSReport("B button : toggle rotation\n");
1302 OSReport("C-stick : control camera\n");
1303 OSReport(" [ Followings: Mode 1 only ]\n");
1304 OSReport("Stick : control models\n");
1305 OSReport("L/R : zoom-in/out\n");
1306 OSReport("D-Up : toggle base texture\n");
1307 OSReport("D-Left : toggle alpha modes\n");
1308 OSReport("************************************************\n\n");
1309 }
1310