1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - GX - demos - UnitTours/3D_Shininess
3   File:     main.c
4 
5   Copyright 2003-2008 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   $Date:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 //---------------------------------------------------------------------------
19 // A sample that uses the shininess table:
20 //
21 // There are nine spheres displayed. Each of them displayed with different shininess adjustment
22 // by the shininess table.
23 //
24 // HOWTO:
25 // 1. Set up the shininess table by G3_Shininess().
26 // 2. Prepare to use the shininess table by G3_MaterialColorSpecEmi(..., TRUE).
27 //---------------------------------------------------------------------------
28 
29 #ifdef SDK_TWL
30 #include <twl.h>
31 #else
32 #include <nitro.h>
33 #endif
34 #include "DEMO.h"
35 #include "commandList.h"
36 
37 #define NUM_SHININESS_TYPES     9
38 static u32 shininess_table[NUM_SHININESS_TYPES][32];
39 
40 
drawSphere(BOOL shininess)41 static void drawSphere(BOOL shininess)
42 {
43     //---------------------------------------------------------------------------
44     // GX_RGB(0, 0, 0) set except specular color for comparison
45     //---------------------------------------------------------------------------
46     G3_MaterialColorDiffAmb(GX_RGB(23, 0, 0),   // diffuse
47                             GX_RGB(8, 0, 0),    // ambient
48                             FALSE      // use diffuse as vtx color if TRUE
49         );
50 
51     G3_MaterialColorSpecEmi(GX_RGB(31, 31, 31), // specular
52                             GX_RGB(0, 0, 0),    // emission
53                             shininess  // use shininess table if TRUE
54         );
55 
56 
57     G3_PolygonAttr(GX_LIGHTMASK_0,     // lighting
58                    GX_POLYGONMODE_MODULATE,     // modulation mode
59                    GX_CULL_BACK,       // cull back
60                    0,                  // polygon ID(0 - 63)
61                    31,                 // alpha(0 - 31)
62                    0                   // OR of GXPolygonAttrMisc's value
63         );
64 
65     // Transfer by DMA
66     G3_Begin(GX_BEGIN_TRIANGLES);
67     MI_SendGXCommand(3, sphere1, sphere_size);
68     G3_End();
69 
70 }
71 
72 // Power fixed point format( 0.8 ) number
powFixedPoint8_(u8 base,u8 exponent)73 static inline u8 powFixedPoint8_(u8 base, u8 exponent)
74 {
75     u16     result = (u16)base;
76     const u16 LIGHTING_L_DOT_H_SHIFT = 8;
77 
78     if (exponent == 0)
79         return base;
80 
81     while (exponent - 1 > 0)
82     {
83         result *= (u16)base;
84         result = (u16)(result >> LIGHTING_L_DOT_H_SHIFT);
85         exponent--;
86     }
87 
88     return (u8)result;
89 }
90 
91 #include <nitro/code32.h>              // avoid byte access problems
92 // Initialize the shininess table.
InitShininessTables_()93 static void InitShininessTables_()
94 {
95     u8      i, j;
96     u8     *pShininess = NULL;
97     const u8 tableLength = 32 * sizeof(u32);
98 
99     for (i = 0; i < NUM_SHININESS_TYPES; i++)
100     {
101         pShininess = (u8 *)&shininess_table[i][0];
102 
103         for (j = 0; j < tableLength - 1; j++)
104         {
105             pShininess[j] = powFixedPoint8_((u8)(j * 2 + 1), i);
106         }
107 
108         // set the max value specially
109         pShininess[tableLength - 1] = 0xFF;
110     }
111 }
112 
113 
114 #ifdef SDK_TWL
TwlMain(void)115 void TwlMain(void)
116 #else
117 void NitroMain(void)
118 #endif
119 {
120     u8      count = 0;
121     u16     Rotate = 0;                // for rotating cubes(0-65535)
122 
123     //---------------------------------------------------------------------------
124     // Initialize:
125     // They enable IRQ interrupts, initialize VRAM, and set BG #0 for 3D mode.
126     //---------------------------------------------------------------------------
127     DEMOInitCommon();
128     DEMOInitVRAM();
129     DEMOInitDisplay3D();
130 
131     // Initialize shininess tables
132     InitShininessTables_();
133 
134     DEMOStartDisplay();
135     while (1)
136     {
137         G3X_Reset();
138         count++;
139         Rotate += 256;
140 
141         //---------------------------------------------------------------------------
142         // Set up the camera matrix
143         //---------------------------------------------------------------------------
144         {
145             VecFx32 Eye = { 0, 0, FX32_ONE };   // Eye position
146             VecFx32 at = { 0, 0, 0 };  // Viewpoint
147             VecFx32 vUp = { 0, FX32_ONE, 0 };   // Up
148 
149             G3_LookAt(&Eye, &vUp, &at, NULL);
150         }
151 
152         //---------------------------------------------------------------------------
153         // Set up light colors and direction.
154         // Notice that light vector is transformed by the current vector matrix
155         // immediately after LightVector command is issued.
156         //---------------------------------------------------------------------------
157         {
158             const fx32 XY_R = FX_Mul(FX32_SQRT1_3, FX32_SQRT2);
159 
160             G3_LightVector(GX_LIGHTID_0,
161                            (fx16)FX_Mul(XY_R, FX_SinIdx(Rotate)),
162                            (fx16)FX_Mul(XY_R, FX_CosIdx(Rotate)), (fx16)(FX32_SQRT1_3 * -1));
163 
164             G3_LightColor(GX_LIGHTID_0, GX_RGB(31, 31, 31));
165         }
166 
167         G3_PushMtx();
168 
169         //---------------------------------------------------------------------------
170         // Draw spheres , changing its shininess table.
171         //---------------------------------------------------------------------------
172         G3_Translate(0, 0, -15 * FX32_ONE);
173         {
174             u8      i = 0;
175             const fx32 step = FX32_ONE * 5;
176             const u8 num_row = 3;
177             const u8 num_cor = NUM_SHININESS_TYPES / num_row;
178             for (i = 0; i < NUM_SHININESS_TYPES; i++)
179             {
180                 int     ix = i % num_row;
181                 int     iy = i / num_row;
182                 //---------------------------------------------------------------------------
183                 // Set up the shininess table
184                 //---------------------------------------------------------------------------
185                 G3_Shininess(&shininess_table[i][0]);
186 
187 
188                 G3_PushMtx();
189                 G3_Translate(step * ix - step * (num_row / 2), -step * iy + step * (num_cor / 2),
190                              0);
191                 drawSphere(TRUE);
192                 G3_PopMtx(1);
193             }
194         }
195 
196         G3_PopMtx(1);
197 
198         // swapping the polygon list RAM, the vertex RAM, etc.
199         G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
200 
201 #ifdef SDK_AUTOTEST
202         GX_SetBankForLCDC(GX_VRAM_LCDC_C);
203         EXT_TestSetVRAMForScreenShot(GX_VRAM_LCDC_C);
204         EXT_TestScreenShot(100, 0x445FBD00);
205         EXT_TestTickCounter();
206 #endif //SDK_AUTOTEST
207 
208         OS_WaitVBlankIntr();           // Waiting the end of VBlank interrupt
209     }
210 }
211 
212 #include <nitro/codereset.h>
213 
214 //---------------------------------------------------------------------------
215 // VBlank interrupt function:
216 //
217 // Interrupt handlers are registered on the interrupt table by OS_SetIRQFunction.
218 // OS_EnableIrqMask selects IRQ interrupts to enable, and
219 // OS_EnableIrq enables IRQ interrupts.
220 // Notice that you have to call 'OS_SetIrqCheckFlag' to check a VBlank interrupt.
221 //---------------------------------------------------------------------------
VBlankIntr(void)222 void VBlankIntr(void)
223 {
224     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // checking VBlank interrupt
225 }
226