1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - GX - demos - UnitTours/2D_Oam_Direct
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-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 //---------------------------------------------------------------------------
19 // A sample that uses a 2D mapped bitmap OBJ
20 //
21 // This sample displays objects on the display in 2D mapped bitmap format
22 //
23 // USAGE:
24 //   UP, DOWN, LEFT, RIGHT      : Slide the OBJ
25 //   A, B                       : Scaling the OBJ
26 //   L, R                       : Rotate the OBJ
27 //   START      : Initialize status of the OBJ
28 //
29 // HOWTO:
30 // 1. Set VRAM size and mapping mode of OBJ by GX_SetOBJVRamModeBmp
31 // 2. Transfer the bitmap data by GX_LoadOBJ
32 // 3. Set GX_OAM_MODE_BITMAPOBJ to OAM attribute to use the bitmap OBJ
33 //---------------------------------------------------------------------------
34 
35 
36 #ifdef SDK_TWL
37 #include <twl.h>
38 #else
39 #include <nitro.h>
40 #endif
41 #include "DEMO.h"
42 #include "data.h"
43 //---------------------------------------------------------------------------
44 //  Summary:
45 //        OAM buffer region
46 //---------------------------------------------------------------------------
47 static GXOamAttr s_OAMBuffer[128];
48 
49 //---------------------------------------------------------------------------
50 //  Summary:
51 //        VBlank interrupt process
52 //  Description:
53 //        Enables a flag that confirms that a V-Blank interrupt has been performed.
54 //
55 //        The following steps will be performed during common initialization (DEMOInitCommon), causing this function to be called during VBlanks
56 //        * Select IRQ interrupt (OS_SetIrqMask)
57 //        * Register this function, which performs IRQ interrupts (OS_SetIRQFunction)
58 //        * Enable IRQ interrupts (OS_EnableIrq)
59 //
60 //---------------------------------------------------------------------------
VBlankIntr(void)61 void VBlankIntr(void)
62 {
63     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Sets a VBlank interrupt confirmation flag
64 }
65 
66 //---------------------------------------------------------------------------
67 //  Summary:
68 //        Displays 2D mapping bitmap OBJ
69 //  Description:
70 //        Affine conversion (rotate/scale) of the OBJ that holds the 2-dimensional mapping bitmap data and displays it
71 //
72 //  Controls:
73 //        UP, DOWN: Manipulate display position
74 //        BUTTON_A, B : Enlarge, reduce
75 //        BUTTON_L, R : rotation
76 //        START      : Initialize settings
77 //---------------------------------------------------------------------------
78 #ifdef SDK_TWL
TwlMain(void)79 void TwlMain(void)
80 #else
81 void NitroMain(void)
82 #endif
83 {
84     int     base_pos_x = 0, base_pos_y = 0;
85     int     base_pat = 0;
86     fx32    scale = FX32_ONE;
87     u16     rotate = 0;
88 
89     //---------------------
90     // Initialization
91     //---------------------
92     DEMOInitCommon();
93     DEMOInitVRAM();
94 
95     /* 2D configuration */
96     GX_SetBankForOBJ(GX_VRAM_OBJ_256_AB);       // Allocates VRAM-A, B to OBJ
97 
98     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS,    // 2D/3D mode
99                        GX_BGMODE_0,    // Set BGMODE to 0
100                        GX_BG0_AS_2D);  // Use BG 0 as 2D
101 
102     GX_SetVisiblePlane(GX_PLANEMASK_OBJ);       // Sets OBJ to visible
103     // Sets OBJ-VRAM capacity and mapping mode for bitmap OBJ
104     GX_SetOBJVRamModeBmp(GX_OBJVRAMMODE_BMP_2D_W256_32K);       // 2D mapping
105 
106     /* Load character data */
107     GX_LoadOBJ((const void *)IMAGE_DATA,        // Transfer OBJ data to VRAM
108                0, IMAGE_DATA_SIZE);
109 
110     DEMOStartDisplay();
111 
112     //---------------------
113     //  Main loop
114     //---------------------
115     while (1)
116     {
117         int     i, j;
118         int     pos_x = base_pos_x;
119         int     pos_y = base_pos_y;
120 
121         /* Obtain pad information and configure operations */
122         DEMOReadKey();
123 #ifdef SDK_AUTOTEST                    // Code for auto-test
124         {
125             const EXTKeys keys[8] =
126                 { {PAD_BUTTON_A, 10}, {PAD_BUTTON_L, 10}, {PAD_KEY_DOWN | PAD_KEY_RIGHT, 20}, {0,
127                                                                                                0}
128             };
129             EXT_AutoKeys(keys, &gKeyWork.press, &gKeyWork.trigger);
130         }
131 #endif
132 
133         if (DEMO_IS_PRESS(PAD_KEY_UP))
134         {
135             if (--base_pos_y < 0)
136             {
137                 base_pos_y = 255;
138             }
139             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
140         }
141         else if (DEMO_IS_PRESS(PAD_KEY_DOWN))
142         {
143             if (++base_pos_y > 255)
144             {
145                 base_pos_y = 0;
146             }
147             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
148         }
149         if (DEMO_IS_PRESS(PAD_KEY_RIGHT))
150         {
151             if (++base_pos_x > 511)
152             {
153                 base_pos_x = 0;
154             }
155             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
156         }
157         else if (DEMO_IS_PRESS(PAD_KEY_LEFT))
158         {
159             if (--base_pos_x < 0)
160             {
161                 base_pos_x = 511;
162             }
163             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
164         }
165         if (DEMO_IS_PRESS(PAD_BUTTON_L))
166         {
167             rotate -= 512;
168             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
169         }
170         else if (DEMO_IS_PRESS(PAD_BUTTON_R))
171         {
172             rotate += 512;
173             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
174         }
175         if (DEMO_IS_PRESS(PAD_BUTTON_A))
176         {
177             scale += 128;
178             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
179         }
180         else if (DEMO_IS_PRESS(PAD_BUTTON_B))
181         {
182             scale -= 128;
183             if (scale < 0)
184             {
185                 scale = 0;
186             }
187             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
188         }
189 
190         if (DEMO_IS_TRIG(PAD_BUTTON_START))
191         {
192             base_pos_x = 0;
193             base_pos_y = 0;
194             rotate = 0;
195             scale = FX32_ONE;
196             OS_Printf("pos=%d:%d rotate=%d scale=%d\n", base_pos_x, base_pos_y, rotate, scale);
197         }
198 
199         /* Generation and configuration of the affine transformation matrix */
200         {
201             MtxFx22 mtx;
202             fx16    sinVal = FX_SinIdx(rotate);
203             fx16    cosVal = FX_CosIdx(rotate);
204             fx32    rScale = FX_Inv(scale);
205             GXOamAffine *oamBuffp = (GXOamAffine *)&s_OAMBuffer[0];
206 
207             mtx._00 = (fx32)((cosVal * rScale) >> FX32_SHIFT);
208             mtx._01 = (fx32)((sinVal * rScale) >> FX32_SHIFT);
209             mtx._10 = -(fx32)((sinVal * rScale) >> FX32_SHIFT);
210             mtx._11 = (fx32)((cosVal * rScale) >> FX32_SHIFT);
211             // Set OBJ affine transformation
212             G2_SetOBJAffine(oamBuffp,  // OAM buffer pointer
213                             &mtx);     // 2x2 matrix for affine transformation
214         }
215 
216         /* OAM configuration (configures 16 OBJs) */
217         for (i = 0; i < 4; i++)
218         {
219             for (j = 0; j < 4; j++)
220             {
221                 int     count = (i * 4) + j;
222                 int     pattern = ((count / 4) * 0x80) + ((count % 4) * 0x08);
223 
224                 G2_SetOBJAttr(&s_OAMBuffer[count],      // Specify the location of OAM
225                               pos_x,   // x position
226                               pos_y,   // y position
227                               0,       // Priority order
228                               GX_OAM_MODE_BITMAPOBJ,    // Bitmap mode
229                               FALSE,   // Disable mosaic
230                               GX_OAM_EFFECT_AFFINE,     // Affine effect
231                               GX_OAM_SHAPE_32x32,       // OBJ size
232                               GX_OAM_COLOR_16,  // 16 colors
233                               pattern, // Character name
234                               15,      // Alpha value
235                               0);
236                 pos_x += 32;
237             }
238             pos_x = base_pos_x;
239             pos_y += 32;
240         }
241 
242 #ifdef SDK_AUTOTEST                    // Code for auto-test
243         GX_SetBankForLCDC(GX_VRAM_LCDC_C);
244         EXT_TestSetVRAMForScreenShot(GX_VRAM_LCDC_C);
245         EXT_TestScreenShot(100, 0xA407A660);
246         EXT_TestTickCounter();
247 #endif //SDK_AUTOTEST
248 
249         /* Flush the cache to main memory */
250         DC_FlushRange(s_OAMBuffer, sizeof(s_OAMBuffer));
251         /* I/O register is accessed using DMA operation, so cache wait is not needed */
252         // DC_WaitWriteBufferEmpty();
253 
254         /* V-Blank wait */
255         OS_WaitVBlankIntr();
256 
257         /* Transfer to OAM */
258         GX_LoadOAM(s_OAMBuffer,        // Transfer OAM buffer to OAM
259                    0, sizeof(s_OAMBuffer));
260         MI_DmaFill32(3,                // Clear OAM buffer
261                      s_OAMBuffer, 192, sizeof(s_OAMBuffer));
262     }
263 }
264