1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WM - demos - wireless-all
3   File:     common.c
4 
5   Copyright 2006-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 #ifdef SDK_TWL
19 #include <twl.h>
20 #else
21 #include <nitro.h>
22 #endif
23 
24 #include "common.h"
25 
26 
27 /*****************************************************************************/
28 /* Constants */
29 
30 #define BGSTR_MAX_LENGTH        32
31 
32 /* Text rendering data */
33 extern const u16 _binary_bg_plt_dat[16][16];
34 extern const u32 _binary_bg_chr_dat[8 * 0x100];
35 
36 
37 /*****************************************************************************/
38 /* Variables */
39 
40 /* Channel */
41 static u16 current_channel = 0;
42 
43 /* Key input */
44 static int own_aid;
45 static GShareData current_input[WH_PLAYER_MAX] ATTRIBUTE_ALIGN(32);
46 static BOOL valid_input[WH_PLAYER_MAX];
47 static GShareData next_input;
48 static u16 padPress;
49 static u16 padTrig;
50 
51 /* Rendering variables */
52 static u16 vscr[32 * 32];
53 static GXOamAttr oamBak[128];
54 
55 
56 /*****************************************************************************/
57 /* Functions */
58 
59 /*---------------------------------------------------------------------------*
60   Name:         IS_PAD_PRESS
61 
62   Description:  Determines own key status.
63 
64   Arguments:    The key flag for determination
65 
66   Returns:      TRUE if the specified key is being pressed; FALSE otherwise.
67 
68  *---------------------------------------------------------------------------*/
IS_PAD_PRESS(u16 flag)69 BOOL IS_PAD_PRESS(u16 flag)
70 {
71     return (padPress & flag) == flag;
72 }
73 
74 /*---------------------------------------------------------------------------*
75   Name:         IS_PAD_TRIGGER
76 
77   Description:  Determines own key trigger status.
78 
79   Arguments:    The key flag for determination
80 
81   Returns:      If the specified key trigger is enabled, TRUE.
82                 If disabled, FALSE
83  *---------------------------------------------------------------------------*/
IS_PAD_TRIGGER(u16 flag)84 BOOL IS_PAD_TRIGGER(u16 flag)
85 {
86     return (padTrig & flag) == flag;
87 }
88 
89 /*---------------------------------------------------------------------------*
90   Name:         UpdateInput
91 
92   Description:  Updates key input.
93                 Attempts data sharing when a wireless connection is established; otherwise, updates only its own key input.
94 
95 
96   Arguments:    None.
97 
98   Returns:      Returns TRUE if key input updates are successful.
99  *---------------------------------------------------------------------------*/
UpdateInput(void)100 static BOOL UpdateInput(void)
101 {
102     BOOL    retval = FALSE;
103 
104     {
105         OSIntrMode bak_cpsr = OS_DisableInterrupts();
106         next_input.key = PAD_Read();
107         next_input.count = next_input.count + 1;
108         /* Sets own key input for cases other than data sharing */
109         if (WH_GetSystemState() != WH_SYSSTATE_DATASHARING)
110         {
111             own_aid = 0;
112             current_input[0] = next_input;
113             valid_input[0] = TRUE;
114             retval = TRUE;
115         }
116         /* For other cases, attempts data sharing */
117         else if (WH_StepDS(&next_input))
118         {
119             /* If successful, reflects everyone's input data */
120             u16     i;
121             for (i = 0; i < WH_PLAYER_MAX; ++i)
122             {
123                 void   *adr = WH_GetSharedDataAdr(i);
124                 if (adr)
125                 {
126                     MI_CpuCopy8(adr, &current_input[i], sizeof(current_input[i]));
127                     valid_input[i] = TRUE;
128                 }
129                 else
130                 {
131                     valid_input[i] = FALSE;
132                 }
133             }
134             retval = TRUE;
135             own_aid = WH_GetCurrentAid();
136         }
137         (void)OS_RestoreInterrupts(bak_cpsr);
138     }
139 
140     /* When input is updated, the key trigger is also updated */
141     if (retval && valid_input[own_aid])
142     {
143         padTrig = (u16)(~padPress & current_input[own_aid].key);
144         padPress = current_input[own_aid].key;
145     }
146 
147     return retval;
148 }
149 
150 /*---------------------------------------------------------------------------*
151   Name:         GetCurrentInput
152 
153   Description:  Gets current key input of the specified player.
154 
155   Arguments:    aid: The player getting the key input
156 
157   Returns:      Returns a valid address if the latest data sharing succeeds; otherwise, returns NULL.
158 
159  *---------------------------------------------------------------------------*/
GetCurrentInput(int aid)160 GShareData *GetCurrentInput(int aid)
161 {
162     return valid_input[aid] ? &current_input[aid] : NULL;
163 }
164 
165 /*---------------------------------------------------------------------------*
166   Name:         VBlankIntr
167 
168   Description:  Gets key trigger.
169 
170   Arguments:    None.
171 
172   Returns:      None.
173  *---------------------------------------------------------------------------*/
VBlankIntr(void)174 static void VBlankIntr(void)
175 {
176     /* OAM update */
177     DC_FlushRange(oamBak, sizeof(oamBak));
178     MI_DmaCopy32(3, oamBak, (void *)HW_OAM, sizeof(oamBak));
179     /* BG update */
180     DC_FlushRange(vscr, sizeof(vscr));
181     GX_LoadBG0Scr(vscr, 0, sizeof(vscr));
182 
183     /* Interrupt check flag */
184     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
185 }
186 
187 /*---------------------------------------------------------------------------*
188   Name:         InitCommon
189 
190   Description:  Common initialization functions.
191 
192   Arguments:    None.
193 
194   Returns:      None.
195  *---------------------------------------------------------------------------*/
InitCommon(void)196 void InitCommon(void)
197 {
198     /* OS initialization */
199     OS_Init();
200     OS_InitTick();
201     OS_InitAlarm();
202     FX_Init();
203     {
204         void   *tempLo;
205         OSHeapHandle hh;
206         tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
207         OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
208         hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
209         if (hh < 0)
210         {
211             OS_TPanic("ARM9: Fail to create heap...\n");
212         }
213         hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
214     }
215 
216     /* Initializes key input */
217     MI_CpuClear8(&next_input, sizeof(next_input));
218     MI_CpuClear8(&current_input, sizeof(current_input));
219     own_aid = 0;
220     (void)UpdateInput();
221 
222     /* GX initialization */
223     GX_Init();
224     GX_DispOff();
225     GXS_DispOff();
226     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
227     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
228     (void)GX_DisableBankForLCDC();
229     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
230     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
231     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
232     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
233     /* OBJ (VRAM-B) */
234     GX_SetBankForOBJ(GX_VRAM_OBJ_128_B);
235     GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_32K);
236     MI_DmaFill32(3, oamBak, 0xC0, sizeof(oamBak));
237     GX_LoadOBJ(_binary_bg_chr_dat, 0, sizeof(_binary_bg_chr_dat));
238     GX_LoadOBJPltt(_binary_bg_plt_dat, 0, sizeof(_binary_bg_plt_dat));
239     /* BG (VRAM-C) */
240     GX_SetBankForBG(GX_VRAM_BG_128_C);
241     G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16, GX_BG_SCRBASE_0xf800,      /* SCR base block 31 */
242                      GX_BG_CHARBASE_0x00000,    /* CHR base block 0 */
243                      GX_BG_EXTPLTT_01);
244     G2_SetBG0Priority(0);
245     G2_BG0Mosaic(FALSE);
246     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D);
247     G2_SetBG0Offset(0, 0);
248     GX_LoadBG0Char(_binary_bg_chr_dat, 0, sizeof(_binary_bg_chr_dat));
249     GX_LoadBGPltt(_binary_bg_plt_dat, 0, sizeof(_binary_bg_plt_dat));
250     MI_CpuFillFast((void *)vscr, 0, sizeof(vscr));
251     DC_FlushRange(vscr, sizeof(vscr));
252     DC_WaitWriteBufferEmpty();
253     GX_LoadBG0Scr(vscr, 0, sizeof(vscr));
254     GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
255     GX_DispOn();
256     GXS_DispOn();
257 
258     /* V-Blank interrupt configuration */
259     (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
260     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
261     (void)GX_VBlankIntr(TRUE);
262     (void)OS_EnableIrq();
263     (void)OS_EnableInterrupts();
264 
265     /* FS initialization */
266     if (!MB_IsMultiBootChild())
267     {
268         static u8 fs_tablework[0x100] ATTRIBUTE_ALIGN(32);
269         FS_Init(FS_DMA_NOT_USE);
270         (void)FS_LoadTable(fs_tablework, sizeof(fs_tablework));
271     }
272 }
273 
274 /*---------------------------------------------------------------------------*
275   Name:         GetCurrentChannel
276 
277   Description:  Gets the currently selected wireless channel.
278 
279   Arguments:    None.
280 
281   Returns:      Returns the currently selected wireless channel.
282  *---------------------------------------------------------------------------*/
GetCurrentChannel(void)283 u16 GetCurrentChannel(void)
284 {
285     return current_channel;
286 }
287 
288 /*---------------------------------------------------------------------------*
289   Name:         SetCurrentChannel
290 
291   Description:  Sets the current wireless channel.
292 
293   Arguments:    channel: Channel to be set
294 
295   Returns:      None.
296  *---------------------------------------------------------------------------*/
SetCurrentChannel(u16 channel)297 void SetCurrentChannel(u16 channel)
298 {
299     current_channel = channel;
300 }
301 
302 /*---------------------------------------------------------------------------*
303   Name:         LoadLinkIcon
304 
305   Description:  Loads the link icon into VRAM.
306 
307   Arguments:    id: The load target's character ID
308                 palette: The load target's palette
309                 level: The link strength
310 
311   Returns:      None.
312  *---------------------------------------------------------------------------*/
LoadLinkIcon(int id,int palette,int level)313 void LoadLinkIcon(int id, int palette, int level)
314 {
315     /* *INDENT-OFF* */
316     typedef struct Icon16Format
317     {
318         GXRgb   palette[16];
319         u8      image[16 * 16 / 2];
320     }
321     IconFormat;
322     extern const IconFormat _binary_linkimg0_dat[];
323     extern const IconFormat _binary_linkimg1_dat[];
324     extern const IconFormat _binary_linkimg2_dat[];
325     extern const IconFormat _binary_linkimg3_dat[];
326     static const IconFormat * const table[4] =
327     { _binary_linkimg0_dat, _binary_linkimg1_dat, _binary_linkimg2_dat, _binary_linkimg3_dat, };
328     /* *INDENT-ON* */
329     GX_LoadOBJ(table[level]->image, (u32)(32 * id), 16 * 16 / 2);
330     GX_LoadOBJPltt(table[level]->palette, sizeof(GXRgb) * 16 * palette,
331                    sizeof(table[level]->palette));
332 }
333 
334 /*---------------------------------------------------------------------------*
335   Name:         PrintString
336 
337   Description:  Draws BG text.
338 
339   Arguments:    x: The rendering x grid position
340                 y: The rendering y grid position
341                 palette: The palette index
342                 format: The format string
343 
344   Returns:      None.
345  *---------------------------------------------------------------------------*/
PrintString(int x,int y,int palette,const char * format,...)346 void PrintString(int x, int y, int palette, const char *format, ...)
347 {
348     int     i;
349     char    tmp[BGSTR_MAX_LENGTH + 1] = { 0, };
350     va_list vlist;
351     va_start(vlist, format);
352     (void)OS_VSNPrintf(tmp, sizeof(tmp), format, vlist);
353     va_end(vlist);
354     y = y * 32 + x;
355     for (i = 0; (i < BGSTR_MAX_LENGTH) && tmp[i]; ++i)
356     {
357         vscr[(y + i) & ((32 * 32) - 1)] = (u16)((palette << 12) | tmp[i]);
358     }
359 }
360 
361 /*---------------------------------------------------------------------------*
362   Name:         WaitNextFrame
363 
364   Description:  Initializes rendering while waiting for the next picture frame.
365 
366   Arguments:    None.
367 
368   Returns:      Returns TRUE when key input is updated.
369  *---------------------------------------------------------------------------*/
WaitNextFrame(void)370 BOOL WaitNextFrame(void)
371 {
372     BOOL    retval;
373     /* Standby for next picture frame */
374     OS_WaitVBlankIntr();
375     /* Updates key input */
376     retval = UpdateInput();
377     /* Clears the text */
378     MI_CpuClearFast(vscr, sizeof(vscr));
379     /* Displays the link strength icon */
380     LoadLinkIcon(512, PLTT_LINK_ICON, WM_GetLinkLevel());
381     G2_SetOBJAttr(&oamBak[64], 3, 3, 0,
382                   GX_OAM_MODE_NORMAL, FALSE, GX_OAM_EFFECT_NONE,
383                   GX_OAM_SHAPE_16x16, GX_OAM_COLOR_16, 512, PLTT_LINK_ICON, 0);
384     return retval;
385 }
386 
387 /*---------------------------------------------------------------------------*
388   Name:         WaitWHState
389 
390   Description:  Waits until entering the specified WH state.
391 
392   Arguments:    state: The state whose transition is awaited
393 
394   Returns:      None.
395  *---------------------------------------------------------------------------*/
WaitWHState(int state)396 void WaitWHState(int state)
397 {
398     while (WH_GetSystemState() != state)
399     {
400         (void)WaitNextFrame();
401         PrintString(3, 10, PLTT_WHITE, "WH working...");
402         PrintString(10, 16, PLTT_WHITE, "( to state %d )", state);
403     }
404 }
405