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