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