1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: lit-tx-alpha.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 lit-tx-alpha
15 Texture with lighting. One color channel/one alpha channel.
16 *---------------------------------------------------------------------------*/
17
18
19 /*---------------------------------------------------------------------------*
20 Header files
21 *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24
25 /*---------------------------------------------------------------------------*
26 Macro definitions
27 *---------------------------------------------------------------------------*/
28 #define PI 3.14159265358979323846F
29 #define NUM_LIGHTS 2
30 #define NUM_PANELTYPE 6
31 #define PANEL_ARRAY_SIZE ( 16 * 16 * 3 )
32
33 /*---------------------------------------------------------------------------*
34 Structure definitions
35 *---------------------------------------------------------------------------*/
36 // for camera
37 typedef struct
38 {
39 Vec location;
40 Vec up;
41 Vec target;
42 f32 left;
43 f32 top;
44 f32 znear;
45 f32 zfar;
46 } CameraConfig;
47
48 typedef struct
49 {
50 CameraConfig cfg;
51 Mtx view;
52 Mtx44 proj;
53 } MyCameraObj;
54
55 // for lighting
56 typedef struct
57 {
58 GXLightObj lobj;
59 s32 theta;
60 s32 phi;
61 u32 color;
62 u32 enable;
63 } MyLightObj;
64
65 // for model object
66 typedef struct
67 {
68 u32 type;
69 f32* posArray;
70 f32* normArray;
71 } MyTessPanelObj;
72
73 // for entire scene control
74 typedef struct
75 {
76 MyCameraObj cam;
77 MyLightObj lightCtrl[NUM_LIGHTS];
78 MyTessPanelObj panel;
79 } MySceneCtrlObj;
80
81 /*---------------------------------------------------------------------------*
82 Forward references
83 *---------------------------------------------------------------------------*/
84 void main ( void );
85 static void DrawInit ( MySceneCtrlObj* sc );
86 static void DrawTick ( MySceneCtrlObj* sc );
87 static void AnimTick ( MySceneCtrlObj* sc );
88 static void CreateTessPanel ( MyTessPanelObj* pnl );
89 static void DrawTessPanel ( MyTessPanelObj* pnl );
90 static void DrawBackGround ( void );
91 static void SetCamera ( MyCameraObj* cam );
92 static void SetLight ( MyLightObj* lightCtrl );
93 static void PrintIntro ( void );
94
95 /*---------------------------------------------------------------------------*
96 Lighting and model parameters
97 *---------------------------------------------------------------------------*/
98 #define REG_MATERIAL MyColors[2]
99 #define REG_AMBIENT MyColors[3]
100
101 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
102 {
103 {0xff, 0xff, 0xff, 0x00}, // white
104 {0x00, 0x00, 0x00, 0xff}, // alpha
105 {0xff, 0xff, 0xff, 0xff}, // material
106 {0x40, 0x40, 0x40, 0x40} // ambient
107 };
108
109 static s16 DefaultLightPos[2][3] =
110 {
111 { 150, 150, 300 },
112 { -150, -150, 300 }
113 };
114
115 static char* CtrlMsg[] =
116 {
117 "RGB Light",
118 "Alpha Light",
119 };
120
121 #define ANGLE_ATN0 -39.0F
122 #define ANGLE_ATN1 40.0F
123 #define ANGLE_ATN2 0.0F
124
125 /*---------------------------------------------------------------------------*
126 Camera configuration
127 *---------------------------------------------------------------------------*/
128 static CameraConfig DefaultCamera =
129 {
130 { 0.0F, 0.0F, 1200.0F }, // location
131 { 0.0F, 1.0F, 0.0F }, // up
132 { 0.0F, 0.0F, 0.0F }, // target
133 -320.0F, // left
134 240.0F, // top
135 500.0F, // near
136 2000.0F // far
137 };
138
139 /*---------------------------------------------------------------------------*
140 Global variables
141 *---------------------------------------------------------------------------*/
142 static MySceneCtrlObj SceneCtrl;
143 static TPLPalettePtr MyTplObj = NULL;
144 static GXTexObj MyTexObj0, MyTexObj1;
145
146 /*---------------------------------------------------------------------------*
147 Application main loop
148 *---------------------------------------------------------------------------*/
main(void)149 void main ( void )
150 {
151 DEMOInit(NULL);
152
153 DrawInit(&SceneCtrl); // Initialize vertex formats, array
154 // and default scene settings
155
156 PrintIntro(); // Print demo directions
157
158 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
159 {
160 DEMOBeforeRender();
161 DrawTick(&SceneCtrl); // Draw the model.
162 DEMODoneRender();
163 DEMOPadRead(); // Update pad status.
164 AnimTick(&SceneCtrl); // Update animation.
165 }
166
167 OSHalt("End of demo");
168 }
169
170 /*---------------------------------------------------------------------------*
171 Functions
172 *---------------------------------------------------------------------------*/
173 /*---------------------------------------------------------------------------*
174 Name: DrawInit
175
176 Description: Initializes the vertex attribute format and allocates
177 the array memory for the indexed data.
178 This function also initializes scene control parameters.
179
180 Arguments: sc : pointer to the structure of scene control parameters
181
182 Returns: none
183 *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)184 static void DrawInit( MySceneCtrlObj* sc )
185 {
186 u32 i;
187
188 // vertex attribute
189 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
190 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
191 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
192 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
193
194 // textures from tpl
195 TPLGetPalette(&MyTplObj, "gxTextrs.tpl");
196 TPLGetGXTexObjFromPalette(MyTplObj, &MyTexObj0, 3); // Water
197 TPLGetGXTexObjFromPalette(MyTplObj, &MyTexObj1, 6); // Floor board
198 // invalidate data existing in texture cache
199 GXInvalidateTexAll();
200
201
202 // Scene control parameter settings
203 // (This default is also used as single frame test.)
204
205 // camera
206 sc->cam.cfg = DefaultCamera;
207 SetCamera(&sc->cam); // never changes in this test
208
209 // light parameters
210 for ( i = 0 ; i < NUM_LIGHTS ; ++i )
211 {
212 sc->lightCtrl[i].theta = 0;
213 sc->lightCtrl[i].phi = 0;
214 sc->lightCtrl[i].color = i;
215 sc->lightCtrl[i].enable = 1;
216 }
217
218 // allocate arrays
219 sc->panel.posArray = MEMAllocFromAllocator(&DemoAllocator1, PANEL_ARRAY_SIZE * sizeof(f32));
220 ASSERT( sc->panel.posArray != 0 );
221 sc->panel.normArray = MEMAllocFromAllocator(&DemoAllocator1, PANEL_ARRAY_SIZE * sizeof(f32));
222 ASSERT( sc->panel.normArray != 0 );
223 sc->panel.type = 0;
224
225 // create default panel
226 CreateTessPanel(&sc->panel);
227 }
228
229 /*---------------------------------------------------------------------------*
230 Name: DrawTick
231
232 Description: Draws models specified by given scene control parameters.
233
234 Arguments: sc : pointer to the structure of scene control parameters
235
236 Returns: none
237 *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)238 static void DrawTick( MySceneCtrlObj* sc )
239 {
240 Mtx ms; // Scale matrix.
241 Mtx mt; // Translation matrix
242 Mtx mv; // Modelview matrix.
243 Mtx mvi; // Modelview matrix.
244 s32 ix, iy;
245
246 //
247 // Draw the background wall
248 //
249 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
250 GXSetNumTexGens(1);
251
252 // Tev mode = no color / one texture
253 GXSetNumTexGens(1);
254 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
255 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
256 GXSetNumChans(0); // no color required
257
258 // load texture
259 GXLoadTexObj(&MyTexObj1, GX_TEXMAP0);
260 // set up blend mode
261 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_COPY);
262
263 MTXCopy(sc->cam.view, mv);
264 GXLoadPosMtxImm(mv, GX_PNMTX0);
265 MTXInverse(mv, mvi);
266 MTXTranspose(mvi, mv);
267 GXLoadNrmMtxImm(mv, GX_PNMTX0);
268 DrawBackGround();
269
270
271 //
272 // Draw the front wall
273 //
274
275 // Tev mode = one color / one texture
276 GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
277 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
278 SetLight(sc->lightCtrl);
279
280 // load texture
281 GXLoadTexObj(&MyTexObj0, GX_TEXMAP0);
282 // set up blend mode
283 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
284
285 // draw 2x2=4 panels
286 MTXScale(ms, 400.0F, 400.0F, 120.0F);
287 for ( iy = 0 ; iy < 2 ; ++iy )
288 {
289 for ( ix = 0 ; ix < 2 ; ++ix )
290 {
291 MTXTrans(mt, (f32)(ix * 400 - 400), (f32)(iy * 400 - 400), 0);
292
293 MTXConcat(sc->cam.view, mt, mv);
294 MTXConcat(mv, ms, mv);
295
296 GXLoadPosMtxImm(mv, GX_PNMTX0);
297 MTXInverse(mv, mvi);
298 MTXTranspose(mvi, mv);
299 GXLoadNrmMtxImm(mv, GX_PNMTX0);
300
301 DrawTessPanel(&sc->panel);
302 }
303 }
304 }
305
306 /*---------------------------------------------------------------------------*
307 Name: AnimTick
308
309 Description: Changes scene control parameters by using pad input.
310
311 Arguments: sc : pointer to the structure of scene control parameters.
312
313 Returns: none
314 *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)315 static void AnimTick( MySceneCtrlObj* sc )
316 {
317 static u32 cur = 0;
318 static u16 counter = 0;
319 u32 i;
320 u16 down;
321
322 // PAD
323 down = DEMOPadGetButtonDown(0);
324
325 // Frame counter
326 ++counter;
327
328 // Light Blinking Control
329 for ( i = 0 ; i < NUM_LIGHTS ; ++i )
330 {
331 sc->lightCtrl[i].enable = 1;
332 }
333 if ( ( counter % 64 ) > 56 )
334 {
335 sc->lightCtrl[cur].enable = 0;
336 }
337
338 // Light Position Calculation
339 sc->lightCtrl[cur].theta += ( DEMOPadGetStickX(0) / 24 );
340 if ( sc->lightCtrl[cur].theta < -90 )
341 sc->lightCtrl[cur].theta = -90;
342 if ( sc->lightCtrl[cur].theta > 90 )
343 sc->lightCtrl[cur].theta = 90;
344
345 sc->lightCtrl[cur].phi += ( DEMOPadGetStickY(0) / 24 );
346 if ( sc->lightCtrl[cur].phi < -90 )
347 sc->lightCtrl[cur].phi = -90;
348 if ( sc->lightCtrl[cur].phi > 90 )
349 sc->lightCtrl[cur].phi = 90;
350
351 // Reset Light Angle
352 if ( down & PAD_BUTTON_Y )
353 {
354 sc->lightCtrl[cur].theta = 0;
355 sc->lightCtrl[cur].phi = 0;
356 }
357
358 // Select Tessellated wall type
359 if ( down & PAD_BUTTON_A )
360 {
361 sc->panel.type = ( sc->panel.type + 1 ) % NUM_PANELTYPE;
362 CreateTessPanel(&sc->panel);
363 }
364
365 // Select Light
366 if ( down & PAD_BUTTON_B )
367 {
368 cur = 1 - cur;
369 OSReport("%s \n", CtrlMsg[cur]);
370 }
371 }
372
373 /*---------------------------------------------------------------------------*
374 Name: CreateTessPanel
375
376 Description: Creates tesselated vertex data
377
378 Arguments: pnl : pointer to a MyTessPanelObj structure
379
380 Returns: none
381 *---------------------------------------------------------------------------*/
CreateTessPanel(MyTessPanelObj * pnl)382 static void CreateTessPanel( MyTessPanelObj* pnl )
383 {
384 u8 ix, iy;
385 u32 in;
386 f32 px, py, pz, nx, ny, nz;
387 f32 theta, phi, s;
388
389 in = 0;
390
391 for ( iy = 0 ; iy <= 15 ; ++iy )
392 {
393 py = (f32)iy / 15;
394
395 for ( ix = 0 ; ix <= 15 ; ++ix )
396 {
397 px = (f32)ix / 15;
398
399 switch(pnl->type)
400 {
401 case 0 : // Z = 0
402 {
403 pz = 0.0F;
404 nx = 0.0F;
405 ny = 0.0F;
406 nz = 1.0F;
407 } break;
408 case 1 : // Z = sinX
409 {
410 theta = (f32)ix * 2.0F * PI / 15.0F;
411 s = sqrtf( 1 + cosf(theta) * cosf(theta) );
412 pz = sinf(theta);
413 nx = - cosf(theta) / s;
414 ny = 0.0F;
415 nz = 1.0F / s;
416 } break;
417 case 2 : // Z = sin2X
418 {
419 theta = (f32)ix * 4.0F * PI / 15.0F;
420 s = sqrtf( 1.0F + cosf(theta) * cosf(theta) );
421 pz = sinf(theta);
422 nx = - cosf(theta) / s;
423 ny = 0.0F;
424 nz = 1.0F / s;
425 } break;
426 case 3 : // Z = cos2X * sinY
427 {
428 theta = (f32)ix * 4.0F * PI / 15.0F;
429 phi = (f32)iy * 2.0F * PI / 15.0F;
430 s = sqrtf( 1.0F + cosf(theta) * cosf(theta) * sinf(phi) * sinf(phi) )
431 * sqrtf( 1.0F + sinf(theta) * sinf(theta) * cosf(phi) * cosf(phi) );
432 pz = cosf(theta) * cosf(phi);
433 nx = sinf(theta) * cosf(phi) / s;
434 ny = cosf(theta) * sinf(phi) / s;
435 nz = 1.0F / s;
436 } break;
437 case 4 : // Z = (X - 0.5)^2
438 {
439 theta = (f32)ix / 15.0F - 0.5F;
440 pz = 4.0F * theta * theta;
441 s = sqrtf( 1.0F + 64.0F * theta * theta );
442 nx = - (f32)theta * 8.0F / s;
443 ny = 0.0F;
444 nz = 1.0F / s;
445 } break;
446 case 5 : // Z = - (Y - 0.5)^2
447 {
448 theta = (f32)iy / 15.0F - 0.5F;
449 pz = 0.25F - 4.0F * theta * theta;
450 s = sqrtf( 1.0F + 64.0F * theta * theta );
451 nx = 0.0F;
452 ny = (f32)theta * 8.0F / s;
453 nz = 1.0F / s;
454 } break;
455 }
456
457 pnl->posArray[in] = px;
458 pnl->posArray[in+1] = py;
459 pnl->posArray[in+2] = pz;
460 pnl->normArray[in] = nx;
461 pnl->normArray[in+1] = ny;
462 pnl->normArray[in+2] = nz;
463
464 in += 3;
465 }
466 }
467
468 // flushes all data into main memory from D-cache
469 DCFlushRange(pnl->posArray, PANEL_ARRAY_SIZE * sizeof(f32));
470 DCFlushRange(pnl->normArray, PANEL_ARRAY_SIZE * sizeof(f32));
471 // invalidates previous data existing in vertex cache
472 GXInvalidateVtxCache();
473
474 }
475
476 /*---------------------------------------------------------------------------*
477 Name: DrawTessPanel
478
479 Description: Draws panel by using tesselated vertices
480
481 Arguments: pnl : pointer to a MyTessPanelObj structure
482
483 Returns: none
484 *---------------------------------------------------------------------------*/
DrawTessPanel(MyTessPanelObj * pnl)485 static void DrawTessPanel( MyTessPanelObj* pnl )
486 {
487 static f32 s = 0.0F;
488 u32 i, x, y;
489 f32 xt, yt0, yt1;
490
491 // set up vertex descriptors
492 // since GX_INDEX8 can handle up to 255 (not 256) vertices,
493 // GX_INDEX16 is used here.
494 GXClearVtxDesc();
495 GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
496 GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
497 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
498
499 // set up array pointers and strides
500 GXSetArray(GX_VA_POS, pnl->posArray, 3 * sizeof(f32));
501 GXSetArray(GX_VA_NRM, pnl->normArray, 3 * sizeof(f32));
502
503 // texture coord animation
504 s += 0.005F;
505 if ( s >= 1.0F )
506 {
507 s -= 1.0F;
508 }
509
510 // drawing loop
511 for ( y = 0 ; y < 15 ; ++y )
512 {
513 i = y * 16;
514 yt0 = (f32)( y / 7.5F );
515 yt1 = (f32)((y+1) / 7.5F );
516
517 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 32);
518 for ( x = 0 ; x < 16 ; ++x )
519 {
520 xt = (f32)( x / 7.5F ) + s;
521
522 GXPosition1x16((u16)i);
523 GXNormal1x16((u16)i);
524 GXTexCoord2f32(xt, yt0);
525 GXPosition1x16((u16)(i+16));
526 GXNormal1x16((u16)(i+16));
527 GXTexCoord2f32(xt, yt1);
528 ++i;
529 }
530 GXEnd();
531 }
532 }
533
534 /*---------------------------------------------------------------------------*
535 Name: DrawBackGround
536
537 Description: Draws a background wall
538
539 Arguments: none
540
541 Returns: none
542 *---------------------------------------------------------------------------*/
DrawBackGround(void)543 static void DrawBackGround( void )
544 {
545 // set up vertex descriptors
546 GXClearVtxDesc();
547 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
548 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
549
550 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
551 GXPosition3f32(-500.0F, -500.0F, -150.0F);
552 GXTexCoord2f32( 0.0F, 0.0F );
553 GXPosition3f32(-500.0F, 500.0F, -150.0F);
554 GXTexCoord2f32( 2.0F, 0.0F );
555 GXPosition3f32( 500.0F, 500.0F, -150.0F);
556 GXTexCoord2f32( 2.0F, 2.0F );
557 GXPosition3f32( 500.0F, -500.0F, -150.0F);
558 GXTexCoord2f32( 0.0F, 2.0F );
559 GXEnd();
560 }
561
562 /*---------------------------------------------------------------------------*
563 Name: SetCamera
564
565 Description: Sets view matrix and loads projection matrix into hardware
566
567 Arguments: cam : pointer to the MyCameraObj structure
568
569 Returns: none
570 *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)571 static void SetCamera( MyCameraObj* cam )
572 {
573 MTXLookAt(
574 cam->view,
575 &cam->cfg.location,
576 &cam->cfg.up,
577 &cam->cfg.target );
578
579 MTXFrustum(
580 cam->proj,
581 cam->cfg.top,
582 - (cam->cfg.top),
583 cam->cfg.left,
584 - (cam->cfg.left),
585 cam->cfg.znear,
586 cam->cfg.zfar );
587 GXSetProjection(cam->proj, GX_PERSPECTIVE);
588 }
589
590 /*---------------------------------------------------------------------------*
591 Name: SetLight
592
593 Description: Sets light objects and color channels
594
595 Arguments: lightCtrl : pointer to the array of MyLightObj structures
596
597 Returns: none
598 *---------------------------------------------------------------------------*/
SetLight(MyLightObj * lightCtrl)599 static void SetLight( MyLightObj* lightCtrl )
600 {
601 GXLightID rgbMask, alphaMask;
602 f32 theta, phi, dx, dy, dz;
603 s16 lx, ly, lz;
604 u32 i;
605
606 // set up light objects
607 for ( i = 0 ; i < NUM_LIGHTS ; ++i )
608 {
609 // direction is already calculated in the view space
610 theta = (f32)lightCtrl[i].theta * PI / 180.0F;
611 phi = (f32)lightCtrl[i].phi * PI / 180.0F;
612 dx = cosf(phi) * sinf(theta);
613 dy = sinf(phi);
614 dz = - cosf(phi) * cosf(theta);
615
616 // position is fixed and already in the view space
617 lx = DefaultLightPos[i][0];
618 ly = DefaultLightPos[i][1];
619 lz = DefaultLightPos[i][2];
620
621 GXInitLightDir(&lightCtrl[i].lobj, dx, dy, dz);
622 GXInitLightPos(&lightCtrl[i].lobj, lx, ly, lz);
623 GXInitLightColor(
624 &lightCtrl[i].lobj,
625 MyColors[lightCtrl[i].color] );
626 GXInitLightAttn(
627 &lightCtrl[i].lobj,
628 ANGLE_ATN0,
629 ANGLE_ATN1,
630 ANGLE_ATN2,
631 1.0F,
632 0.0F,
633 0.0F );
634 }
635
636 // loads each light object
637 GXLoadLightObjImm(&lightCtrl[0].lobj, GX_LIGHT0);
638 GXLoadLightObjImm(&lightCtrl[1].lobj, GX_LIGHT1);
639
640 // light mask control
641 rgbMask = ( lightCtrl[0].enable ) ? GX_LIGHT0 : (GXLightID)0;
642 alphaMask = ( lightCtrl[1].enable ) ? GX_LIGHT1 : (GXLightID)0;
643
644 // color channel setting
645 GXSetNumChans(1); // number of active color channels
646 GXSetChanCtrl(
647 GX_COLOR0,
648 GX_ENABLE, // enable channel
649 GX_SRC_REG, // amb source
650 GX_SRC_REG, // mat source
651 rgbMask, // light mask
652 GX_DF_CLAMP, // diffuse function
653 GX_AF_SPOT);
654 GXSetChanCtrl(
655 GX_ALPHA0,
656 GX_ENABLE, // disable channel
657 GX_SRC_REG, // amb source
658 GX_SRC_REG, // mat source
659 alphaMask, // light mask
660 GX_DF_CLAMP, // diffuse function
661 GX_AF_SPOT);
662 // set up ambient color
663 GXSetChanAmbColor(GX_COLOR0A0, REG_AMBIENT);
664 // set up material color
665 GXSetChanMatColor(GX_COLOR0A0, REG_MATERIAL);
666
667 }
668
669 /*---------------------------------------------------------------------------*
670 Name: PrintIntro
671
672 Description: Prints the directions on how to use this demo.
673
674 Arguments: none
675
676 Returns: none
677 *---------------------------------------------------------------------------*/
PrintIntro(void)678 static void PrintIntro( void )
679 {
680 OSReport("\n\n");
681 OSReport("******************************************************\n");
682 OSReport("lit-tx-alpha: one RGB and one Alpha light with texture\n");
683 OSReport("******************************************************\n");
684 OSReport("to quit hit the start button\n");
685 OSReport("\n");
686 OSReport("Stick : Move selected Light\n");
687 OSReport("B Button : Select Light\n");
688 OSReport("A Button : Change front wall type\n");
689 OSReport("******************************************************\n");
690 OSReport("\n");
691 }
692
693 /*============================================================================*/
694