1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WVR - demos - switchover
3   File:     graphic_main.c
4 
5   Copyright 2005-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 /*---------------------------------------------------------------------------
20  * This demo dynamically switches WVR library use on and off.
21  * Buttons are used to switch the dual-screen 3D display mode and the wireless communications mode.
22  *
23  * This demo is simply a combination of the following two samples.
24  * For details on operation in the individual modes, see the related source code.
25  *    /build/demos/wvr/simple
26  *    /build/demos/gx/UnitTours/Sub_Double3D
27  *---------------------------------------------------------------------------*/
28 
29 
30 #include <nitro.h>
31 #include    "common.h"
32 
33 
34 /*****************************************************************************/
35 /* Constants */
36 
37 /* Cube vertex coordinates */
38 static const s16 gCubeGeometry[3 * 8] = {
39     FX16_ONE, FX16_ONE, FX16_ONE,
40     FX16_ONE, FX16_ONE, -FX16_ONE,
41     FX16_ONE, -FX16_ONE, FX16_ONE,
42     FX16_ONE, -FX16_ONE, -FX16_ONE,
43     -FX16_ONE, FX16_ONE, FX16_ONE,
44     -FX16_ONE, FX16_ONE, -FX16_ONE,
45     -FX16_ONE, -FX16_ONE, FX16_ONE,
46     -FX16_ONE, -FX16_ONE, -FX16_ONE
47 };
48 
49 /* Cube vertex color */
50 static const GXRgb gCubeColor[8] = {
51     GX_RGB(31, 31, 31),
52     GX_RGB(31, 31, 0),
53     GX_RGB(31, 0, 31),
54     GX_RGB(31, 0, 0),
55     GX_RGB(0, 31, 31),
56     GX_RGB(0, 31, 0),
57     GX_RGB(0, 0, 31),
58     GX_RGB(0, 0, 0)
59 };
60 
61 
62 /*****************************************************************************/
63 /* Variables */
64 
65 /* OAM information used to display the captured screen as a bitmap OBJ */
66 static GXOamAttr sOamBak[128];
67 
68 
69 /*****************************************************************************/
70 /* Functions */
71 
72 /*---------------------------------------------------------------------------*
73   Name:         GetPadTrigger
74 
75   Description:  Updates key input information and returns the latest press trigger bit.
76                 Detects press trigger, release trigger, and press-and-hold repeat.
77 
78   Arguments:    None.
79 
80   Returns:      None.
81  *---------------------------------------------------------------------------*/
GetPadTrigger(void)82 static int GetPadTrigger(void)
83 {
84     static u16 pad_bak = 0;
85     const u16 pad_cur = PAD_Read();
86     const int trig = (u16)(~pad_bak & pad_cur);
87     return (pad_bak = pad_cur), trig;
88 }
89 
90 /*---------------------------------------------------------------------------*
91   Name:         VBlankIntr
92 
93   Description:  V-Blank interrupt handler (set by DEMO library).
94 
95   Arguments:    None.
96 
97   Returns:      None.
98  *---------------------------------------------------------------------------*/
VBlankIntr(void)99 static void VBlankIntr(void)
100 {
101     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
102 }
103 
104 /*---------------------------------------------------------------------------*
105   Name:         Color
106 
107   Description:  Sets specified vertex color of cube.
108 
109   Arguments:    idx: Vertex index
110 
111   Returns:      None.
112  *---------------------------------------------------------------------------*/
Color(int idx)113 static inline void Color(int idx)
114 {
115     G3_Color(gCubeColor[idx]);
116 }
117 
118 /*---------------------------------------------------------------------------*
119   Name:         Vtx
120 
121   Description:  Sets specified vertex coordinate of cube.
122 
123   Arguments:    idx: Vertex index
124 
125   Returns:      None.
126  *---------------------------------------------------------------------------*/
Vtx(int idx)127 static inline void Vtx(int idx)
128 {
129     G3_Vtx(gCubeGeometry[idx * 3], gCubeGeometry[idx * 3 + 1], gCubeGeometry[idx * 3 + 2]);
130 }
131 
132 /*---------------------------------------------------------------------------*
133   Name:         ColVtxQuad
134 
135   Description:  Creates a rectangle by specifying coordinates for the vertices and color in series.
136 
137   Arguments:    idx0: Index of Vertex 0
138                 idx1: Index of Vertex 1
139                 idx2: Index of Vertex 2
140                 idx3: Index of Vertex 3
141                 bOwnIndexColor: If TRUE, use the colors of each index.
142                                 If FALSE, use color of idx0 for all.
143 
144   Returns:      None.
145  *---------------------------------------------------------------------------*/
ColVtxQuad(int idx0,int idx1,int idx2,int idx3,BOOL bOwnIndexColor)146 static void ColVtxQuad(int idx0, int idx1, int idx2, int idx3, BOOL bOwnIndexColor)
147 {
148     if (bOwnIndexColor)
149     {
150         Color(idx0);
151         Vtx(idx0);
152         Color(idx1);
153         Vtx(idx1);
154         Color(idx2);
155         Vtx(idx2);
156         Color(idx3);
157         Vtx(idx3);
158     }
159     else
160     {
161         Color(idx0);
162         Vtx(idx0);
163         Vtx(idx1);
164         Vtx(idx2);
165         Vtx(idx3);
166     }
167 }
168 
169 /*---------------------------------------------------------------------------*
170   Name:         drawCube
171 
172   Description:  Draws cube on left side of screen.
173 
174   Arguments:    Rotate: Angle of rotation
175                 bIsRight: If right, TRUE; if left, FALSE
176 
177   Returns:      None.
178  *---------------------------------------------------------------------------*/
drawCube(u16 Rotate,BOOL bIsRight)179 static void drawCube(u16 Rotate, BOOL bIsRight)
180 {
181     G3_PushMtx();
182     {
183         const int pos = bIsRight ? +3 : -3;
184 
185         /* Parallel movement and rotational movement */
186         G3_Translate(pos << (FX32_SHIFT - 1), 0, 0);
187         {
188             const fx16 s = FX_SinIdx(Rotate);
189             const fx16 c = FX_CosIdx(Rotate);
190             G3_RotX(s, c);
191             G3_RotY(s, c);
192             G3_RotZ(s, c);
193         }
194 
195         /*
196          * Specify the material and polygon properties with the following settings.
197          *   Diffuse reflection color = GX_RGB(31, 31, 31) (not used as vertex color)
198          *   Ambient reflection color = GX_RGB(16, 16, 16)
199          *   Specular reflection color = GX_RGB(16, 16, 16) (not using a table)
200          *   Emission color = GX_RGB(0, 0, 0)
201          *   Light = All disabled
202          *   Mode = Modulation
203          *   Culling = Hide back surface
204          *   Polygon ID = 0
205          *   Opacity = 31
206          *   Other = None
207          */
208         G3_MaterialColorDiffAmb(GX_RGB(31, 31, 31), GX_RGB(16, 16, 16), FALSE);
209         G3_MaterialColorSpecEmi(GX_RGB(16, 16, 16), GX_RGB(0, 0, 0), FALSE);
210         G3_PolygonAttr(GX_LIGHTMASK_NONE, GX_POLYGONMODE_MODULATE, GX_CULL_BACK,
211                        0, 31, GX_POLYGON_ATTR_MISC_NONE);
212 
213         /* Render the cube */
214         G3_Begin(GX_BEGIN_QUADS);
215         {
216             ColVtxQuad(2, 0, 4, 6, bIsRight);
217             ColVtxQuad(7, 5, 1, 3, bIsRight);
218             ColVtxQuad(6, 4, 5, 7, bIsRight);
219             ColVtxQuad(3, 1, 0, 2, bIsRight);
220             ColVtxQuad(5, 4, 0, 1, bIsRight);
221             ColVtxQuad(6, 7, 3, 2, bIsRight);
222         }
223         G3_End();
224 
225     }
226     G3_PopMtx(1);
227 }
228 
229 /*---------------------------------------------------------------------------*
230   Name:         setupFrame
231 
232   Description:  Initializes settings for frame drawing.
233 
234   Arguments:    bIsRight: If right, TRUE; if left, FALSE
235 
236   Returns:      None.
237  *---------------------------------------------------------------------------*/
setupFrame(BOOL bIsRight)238 static void setupFrame(BOOL bIsRight)
239 {
240     /*
241      * Alternate use of the 3D engine for each picture frame on two screens.
242      * When the 3D engine cannot be used in the current frame, use captured results from the previous frame.
243      * VRAM-C captures the left cube and VRAM-D captures the right cube. Each VRAM can be used for only BGs or OBJs, however, so VRAM-C is displayed with a direct bitmap and VRAM-D is displayed with a texture OBJ.
244      *
245      *
246      */
247 
248     /*
249      * Initialize the LCDs with the following settings.
250      *   Main BG mode: 0
251      *     BG-0: 3D (Priority 0)
252      *     BG-1: -
253      *     BG-2: -
254      *     BG-3: -
255      *     OBJ: -
256      */
257     (void)GX_ResetBankForSubOBJ();
258     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_3D);
259     GX_SetVisiblePlane(GX_PLANEMASK_BG0);
260     G2_SetBG0Priority(0);
261     GXS_SetGraphicsMode(GX_BGMODE_5);
262 
263     if (bIsRight)
264     {
265         /*
266          *   Show the main LCD above and the sub LCD below.
267          *   Sub BG mode: 5
268          *     BG-0: -
269          *     BG-1: -
270          *     BG-2: Direct bitmap
271          *     BG-3: -
272          *     OBJ: -
273          *   Capture mode: (256, 192), 3D only 100%
274          *   VRAM-A: -
275          *   VRAM-B: -
276          *   VRAM-C: Sub OBJ
277          *   VRAM-D: LCDC
278          */
279         (void)GX_DisableBankForLCDC();
280         (void)GX_DisableBankForSubOBJ();
281         GX_SetBankForSubBG(GX_VRAM_SUB_BG_128_C);
282         GX_SetBankForLCDC(GX_VRAM_LCDC_D);
283         GX_SetCapture(GX_CAPTURE_SIZE_256x192,
284                       GX_CAPTURE_MODE_A, GX_CAPTURE_SRCA_3D, (GXCaptureSrcB)0,
285                       GX_CAPTURE_DEST_VRAM_D_0x00000, 16, 0);
286         GXS_SetVisiblePlane(GX_PLANEMASK_BG2);
287         G2S_SetBG2Priority(0);
288         G2S_SetBG2ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256,
289                                GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
290         G2S_BG2Mosaic(FALSE);
291     }
292     else
293     {
294         /*
295          *   Show the main LCD below and the sub LCD above.
296          *   Sub BG mode: 5
297          *     BG-0: -
298          *     BG-1: -
299          *     BG-2: -
300          *     BG-3: -
301          *     OBJ: ON
302          *   Capture mode: (256, 192), 3D only 100%
303          *   VRAM-A: -
304          *   VRAM-B: -
305          *   VRAM-C: LCDC
306          *   VRAM-D: Sub OBJ
307          */
308         (void)GX_DisableBankForLCDC();
309         (void)GX_DisableBankForSubBG();
310         GX_SetBankForSubOBJ(GX_VRAM_SUB_OBJ_128_D);
311         GX_SetBankForLCDC(GX_VRAM_LCDC_C);
312         GX_SetCapture(GX_CAPTURE_SIZE_256x192,
313                       GX_CAPTURE_MODE_A, GX_CAPTURE_SRCA_3D, (GXCaptureSrcB)0,
314                       GX_CAPTURE_DEST_VRAM_C_0x00000, 16, 0);
315         GXS_SetVisiblePlane(GX_PLANEMASK_OBJ);
316     }
317 
318     G3X_Reset();
319 
320     /* Configure the camera matrix */
321     {
322         const VecFx32 Eye = { 0, 0, FX32_ONE * 5 };
323         const VecFx32 at = { 0, 0, 0 };
324         const VecFx32 vUp = { 0, FX32_ONE, 0 };
325         G3_LookAt(&Eye, &vUp, &at, NULL);
326     }
327 }
328 
329 /*---------------------------------------------------------------------------*
330   Name:         setupSubOAM
331 
332   Description:  Arranges OAM into grid for display of VRAM-D on subscreen.
333 
334   Arguments:    None.
335 
336   Returns:      None.
337  *---------------------------------------------------------------------------*/
setupSubOAM(void)338 static void setupSubOAM(void)
339 {
340     int     i;
341     int     x, y;
342     int     idx = 0;
343 
344     GXS_SetOBJVRamModeBmp(GX_OBJVRAMMODE_BMP_2D_W256);
345 
346     for (i = 0; i < 128; ++i)
347     {
348         sOamBak[i].attr01 = 0;
349         sOamBak[i].attr23 = 0;
350     }
351 
352     for (y = 0; y < 192; y += 64)
353     {
354         for (x = 0; x < 256; x += 64, idx++)
355         {
356             G2_SetOBJAttr(&sOamBak[idx], x, y, 0,
357                           GX_OAM_MODE_BITMAPOBJ, FALSE,
358                           GX_OAM_EFFECT_NONE, GX_OAM_SHAPE_64x64, GX_OAM_COLOR_16,
359                           (y / 8) * 32 + (x / 8), 15, 0);
360         }
361     }
362     DC_FlushRange(&sOamBak[0], sizeof(sOamBak));
363     /* I/O register is accessed using DMA operation, so cache wait is not needed */
364     // DC_WaitWriteBufferEmpty();
365     GXS_LoadOAM(&sOamBak[0], 0, sizeof(sOamBak));
366 }
367 
368 /*---------------------------------------------------------------------------*
369   Name:         GraphicMain
370 
371   Description:  Initialization and main loop for two-screen 3D display mode.
372 
373   Arguments:    None.
374 
375   Returns:      None.
376  *---------------------------------------------------------------------------*/
GraphicMain(void)377 void GraphicMain(void)
378 {
379     GX_DispOff();
380     GXS_DispOff();
381 
382     /* Clear all VRAM, OAM, and palette RAM */
383     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
384     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
385     (void)GX_DisableBankForLCDC();
386     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
387     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
388     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
389     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
390 
391     /* V-Blank interrupt handler configuration */
392     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
393     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
394     (void)GX_VBlankIntr(TRUE);
395     (void)OS_EnableIrq();
396     (void)OS_EnableInterrupts();
397 
398     /* GX initialization */
399     G3X_Init();
400     G3X_InitTable();
401     G3X_InitMtxStack();
402 
403     /* Initialization of the necessary render configurations only at startup */
404     G3X_AntiAlias(TRUE);
405     setupSubOAM();
406     G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
407     G3X_SetClearColor(GX_RGB(0, 0, 0), 0, 0x7fff, 63, FALSE);
408     G3_ViewPort(0, 0, 255, 191);
409 
410     /* Initialization of the projection matrix */
411     {
412         const fx32 right = FX32_ONE;
413         const fx32 top = FX32_ONE * 3 / 4;
414         const fx32 near = FX32_ONE;
415         const fx32 far = FX32_ONE * 400;
416         G3_Perspective(FX32_SIN30, FX32_COS30, FX32_ONE * 4 / 3, near, far, NULL);
417         G3_StoreMtx(0);
418     }
419 
420     /* Start render loop */
421     OS_WaitVBlankIntr();
422     GX_DispOn();
423     GXS_DispOn();
424     {
425         u16     Rotate = 0;
426         BOOL    bIsRight;
427 
428         (void)GetPadTrigger();
429         for (bIsRight = TRUE;; bIsRight = !bIsRight)
430         {
431             if (GetPadTrigger() & PAD_BUTTON_START)
432             {
433                 break;
434             }
435             /* Frame render */
436             setupFrame(bIsRight);
437             drawCube(Rotate, bIsRight);
438 
439             Rotate += 256;
440 
441             G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
442             OS_WaitVBlankIntr();
443             /*
444              * Rendering results will be applied from the V-Blank after the buffers are swapped, so the LCD intended for the display is set at this time.
445              *
446              * Specify that the cube on the right will appear in the lower screen.
447              */
448             GX_SetDispSelect(bIsRight ? GX_DISP_SELECT_SUB_MAIN : GX_DISP_SELECT_MAIN_SUB);
449 
450         }
451     }
452 }
453