1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CHT - demos - catch-1
3   File:     main.c
4 
5   Copyright 2003-2009 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:: 2009-08-31#$
14   $Rev: 11030 $
15   $Author: tominaga_masafumi $
16  *---------------------------------------------------------------------------*/
17 
18 /*---------------------------------------------------------------------------*
19     This demo uses the PictoChat search feature to detect the beacon from the PictoChat parent.
20  *---------------------------------------------------------------------------*/
21 
22 /*
23  * This demo uses the WH library for wireless communications, but does not perform wireless shutdown processing.
24  *
25  * For details on WH library wireless shutdown processing, see the comments at the top of the WH library source code or the wm/dataShare-Model demo.
26  *
27  *
28  */
29 
30 #include    <nitro.h>
31 #include    <nitro/wm.h>
32 #include    <nitro/cht.h>
33 
34 #include    "font.h"
35 #include    "icon.h"
36 #include    "wh.h"
37 
38 /*---------------------------------------------------------------------------*
39     Constant Definitions
40  *---------------------------------------------------------------------------*/
41 #define     KEY_REPEAT_START    25     // Number of frames until key repeat starts
42 #define     KEY_REPEAT_SPAN     10     // Number of frames between key repeats
43 
44 #define     DEFAULT_GGID        0x003fff61
45 
46 #define     PICTO_CATCH_LIFETIME    300 // 5 seconds
47 
48 /*---------------------------------------------------------------------------*
49     Structure Definitions
50  *---------------------------------------------------------------------------*/
51 // Key input data
52 typedef struct KeyInfo
53 {
54     u16     cnt;                       // Unprocessed input value
55     u16     trg;                       // Push trigger input
56     u16     up;                        // Release trigger input
57     u16     rep;                       // Press and hold repeat input
58 
59 }
60 KeyInfo;
61 
62 typedef struct PictoCatchInfo
63 {
64     int     lifeTime;
65     int     clientNum;
66 
67 }
68 PictoCatchInfo;
69 
70 
71 /*---------------------------------------------------------------------------*
72     Internal Function Definitions
73  *---------------------------------------------------------------------------*/
74 // Parent discovery callback
75 static void FoundParentCallback(WMBssDesc *pBssDesc);
76 
77 // V-Blank interrupt handler
78 static void VBlankIntr(void);
79 
80 // General purpose subroutines
81 static void KeyRead(KeyInfo * pKey);
82 static void ClearString(void);
83 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...);
84 static void ColorString(s16 x, s16 y, s16 length, u8 palette);
85 static void InitializeAllocateSystem(void);
86 static void DrawIcon(u8 index, int charName, int x, int y);
87 
88 
89 /*---------------------------------------------------------------------------*
90     Internal Variable Definitions
91  *---------------------------------------------------------------------------*/
92 static u16 gScreen[32 * 32] ATTRIBUTE_ALIGN(32);
93 static GXOamAttr gOam[128] ATTRIBUTE_ALIGN(32);
94 static KeyInfo gKey;                   // Key input
95 static s32 gFrame;                     // Frame counter
96 
97 static PictoCatchInfo gRoom[4];
98 
99 
100 /*---------------------------------------------------------------------------*
101   Name:         NitroMain
102 
103   Description:  Initialization and main loop.
104 
105   Arguments:    None.
106 
107   Returns:      None.
108  *---------------------------------------------------------------------------*/
NitroMain(void)109 void NitroMain(void)
110 {
111     // Various types of initialization
112     OS_Init();
113     FX_Init();
114     GX_Init();
115     GX_DispOff();
116     GXS_DispOff();
117 
118     // Initializes display settings
119     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
120     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
121     (void)GX_DisableBankForLCDC();
122     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
123     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
124     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
125     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
126 
127     // 2D display settings for text string display
128     GX_SetBankForBG(GX_VRAM_BG_128_A);
129     G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16, GX_BG_SCRBASE_0xf800,      // SCR base block 31
130                      GX_BG_CHARBASE_0x00000,    // CHR base block 0
131                      GX_BG_EXTPLTT_01);
132     GX_SetBankForOBJ(GX_VRAM_OBJ_16_F);
133     GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_32K);
134     G2_SetBG0Priority(0);
135     G2_BG0Mosaic(FALSE);
136     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D);
137     GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
138     GX_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
139     GX_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
140     GX_LoadOBJ(icons_character, 0, sizeof(icons_character));
141     GX_LoadOBJPltt(icons_palette, 0, sizeof(icons_palette));
142     MI_CpuFillFast((void *)gScreen, 0, sizeof(gScreen));
143     DC_FlushRange(gScreen, sizeof(gScreen));
144     /* I/O register is accessed using DMA operation, so cache wait is not needed */
145     // DC_WaitWriteBufferEmpty();
146     GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
147 
148     // Interrupt settings
149     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
150     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
151     (void)GX_VBlankIntr(TRUE);
152     (void)OS_EnableIrq();
153     (void)OS_EnableInterrupts();
154 
155     // Memory allocation
156     InitializeAllocateSystem();
157 
158     //********************************
159     // Initialize wireless
160     if (!WH_Initialize())
161     {
162         OS_TPanic("WH_Initialize failed.\n");
163     }
164     WH_SetGgid(DEFAULT_GGID);
165     WH_TurnOnPictoCatch();
166     {
167         const u8 mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
168         s32     i;
169 
170         for (i = 0; i < 4; i++)
171         {
172             gRoom[i].lifeTime = 0;
173         }
174         // Wait for initialization to complete
175         while (WH_GetSystemState() != WH_SYSSTATE_IDLE)
176         {
177         }
178         // Start search for parent
179         if (!WH_StartScan(FoundParentCallback, mac, 0))
180         {
181             OS_TPanic("WH_StartScan failed.\n");
182         }
183     }
184     //********************************
185 
186     // LCD display start
187     GX_DispOn();
188     GXS_DispOn();
189 
190     // Debug string output
191     OS_Printf("ARM9: CHT catch-1 demo started.\n");
192 
193     // Empty call for getting key input data (strategy for pressing A Button in the IPL)
194     KeyRead(&gKey);
195 
196     // Main loop
197     for (gFrame = 0; TRUE; gFrame++)
198     {
199         // Get key input data
200         KeyRead(&gKey);
201 
202         // Clear the screen
203         ClearString();
204 
205         // Display
206         PrintString(1, 1, 0xf, "frame: %d", gFrame);
207         {
208             s32     i;
209 
210             for (i = 0; i < 4; i++)
211             {
212                 if (gRoom[i].lifeTime > 0)
213                 {
214                     gRoom[i].lifeTime--;
215                     PrintString(1, (s16)(6 + (3 * i)), 0xf, "Discover pictochat room%d", i);
216                     PrintString(2, (s16)(7 + (3 * i)), 0x2, "%d members", gRoom[i].clientNum);
217                     // Display icon
218                     DrawIcon((u8)i, 9, 208, (s16)(48 + (24 * i)));
219                 }
220                 else
221                 {
222                     PrintString(10, (s16)(6 + (3 * i)), 0xe, "pictochat room%d", i);
223                 }
224             }
225         }
226 
227         // Waiting for the V-Blank
228         OS_WaitVBlankIntr();
229         // Output ARM7 debug print
230     }
231 }
232 
233 /*---------------------------------------------------------------------------*
234   Name:         FoundParentCallback
235 
236   Description:  The callback function that is invoked when a parent is found.
237 
238   Arguments:    pBssDesc:      Pointer to beacon information of found parent.
239 
240   Returns:      None.
241  *---------------------------------------------------------------------------*/
FoundParentCallback(WMBssDesc * pBssDesc)242 static void FoundParentCallback(WMBssDesc *pBssDesc)
243 {
244     if (CHT_IsPictochatParent(pBssDesc))
245     {
246         int     clientNum;
247         int     roomNumber;
248 
249         clientNum = CHT_GetPictochatClientNum(pBssDesc);
250         roomNumber = CHT_GetPictochatRoomNumber(pBssDesc);
251         if (roomNumber < 4)
252         {
253             if (gRoom[roomNumber].lifeTime == 0)
254             {
255                 /* SE should start here */
256             }
257             gRoom[roomNumber].clientNum = clientNum;
258             gRoom[roomNumber].lifeTime = PICTO_CATCH_LIFETIME;
259         }
260     }
261 }
262 
263 /*---------------------------------------------------------------------------*
264   Name:         VBlankIntr
265 
266   Description:  V-Blank interrupt vector.
267 
268   Arguments:    None.
269 
270   Returns:      None.
271  *---------------------------------------------------------------------------*/
VBlankIntr(void)272 static void VBlankIntr(void)
273 {
274     // Reflect virtual screen in VRAM
275     DC_FlushRange(gScreen, sizeof(gScreen));
276     /* I/O register is accessed using DMA operation, so cache wait is not needed */
277     // DC_WaitWriteBufferEmpty();
278     GX_LoadBG0Scr(gScreen, 0, sizeof(gScreen));
279 
280     // Reflect virtual OAM in OAM
281     DC_FlushRange(gOam, sizeof(gOam));
282     /* I/O register is accessed using DMA operation, so cache wait is not needed */
283     // DC_WaitWriteBufferEmpty();
284     GX_LoadOAM(gOam, 0, sizeof(gOam));
285 
286     // Sets the IRQ check flag
287     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
288 }
289 
290 /*---------------------------------------------------------------------------*
291   Name:         KeyRead
292 
293   Description:  Edits key input data
294                 Detects press trigger, release trigger, and press-and-hold repeat.
295 
296   Arguments:    pKey: Structure that holds key input data to be edited
297 
298   Returns:      None.
299  *---------------------------------------------------------------------------*/
KeyRead(KeyInfo * pKey)300 static void KeyRead(KeyInfo * pKey)
301 {
302     static u16 repeat_count[12];
303     int     i;
304     u16     r;
305 
306     r = PAD_Read();
307     pKey->trg = 0x0000;
308     pKey->up = 0x0000;
309     pKey->rep = 0x0000;
310 
311     for (i = 0; i < 12; i++)
312     {
313         if (r & (0x0001 << i))
314         {
315             if (!(pKey->cnt & (0x0001 << i)))
316             {
317                 pKey->trg |= (0x0001 << i);     // Press trigger
318                 repeat_count[i] = 1;
319             }
320             else
321             {
322                 if (repeat_count[i] > KEY_REPEAT_START)
323                 {
324                     pKey->rep |= (0x0001 << i); // Press-and-hold repeat
325                     repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
326                 }
327                 else
328                 {
329                     repeat_count[i]++;
330                 }
331             }
332         }
333         else
334         {
335             if (pKey->cnt & (0x0001 << i))
336             {
337                 pKey->up |= (0x0001 << i);      // Release trigger
338             }
339         }
340     }
341     pKey->cnt = r;                     // Unprocessed key input
342 }
343 
344 /*---------------------------------------------------------------------------*
345   Name:         ClearString
346 
347   Description:  Clears the virtual screen.
348 
349   Arguments:    None.
350 
351   Returns:      None.
352  *---------------------------------------------------------------------------*/
ClearString(void)353 static void ClearString(void)
354 {
355     s32     i;
356 
357     MI_CpuClearFast((void *)gScreen, sizeof(gScreen));
358     for (i = 0; i < 128; i++)
359     {
360         G2_SetOBJPosition(&gOam[i], 256, 192);
361     }
362 }
363 
364 /*---------------------------------------------------------------------------*
365   Name:         PrintString
366 
367   Description:  Positions the text string on the virtual screen. The string can be up to 32 chars.
368 
369   Arguments:    x: X-coordinate where character string starts (x 8 dots)
370                 y: Y-coordinate where character string starts (x 8 dots)
371                 palette: Specify text color by palette number
372                 text: Text string to position. Null-terminated.
373                 ...: Virtual argument
374 
375   Returns:      None.
376  *---------------------------------------------------------------------------*/
PrintString(s16 x,s16 y,u8 palette,char * text,...)377 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...)
378 {
379     va_list vlist;
380     char    temp[32 + 2];
381     s32     i;
382 
383     va_start(vlist, text);
384     (void)vsnprintf(temp, 33, text, vlist);
385     va_end(vlist);
386 
387     *(u16 *)(&temp[32]) = 0x0000;
388     for (i = 0;; i++)
389     {
390         if (temp[i] == 0x00)
391         {
392             break;
393         }
394         gScreen[((y * 32) + x + i) % (32 * 32)] = (u16)((palette << 12) | temp[i]);
395     }
396 }
397 
398 /*---------------------------------------------------------------------------*
399   Name:         ColorString
400 
401   Description:  Changes the color of character strings printed on the virtual screen.
402 
403   Arguments:    x:         X-coordinate (x 8 dots ) from which to start color change.
404                 y:         Y-coordinate (x 8 dots ) from which to start color change.
405                 length:   Number of characters to continue the color change for.
406                 palette: Specify text color by palette number
407 
408   Returns:      None.
409  *---------------------------------------------------------------------------*/
ColorString(s16 x,s16 y,s16 length,u8 palette)410 static void ColorString(s16 x, s16 y, s16 length, u8 palette)
411 {
412     s32     i;
413     u16     temp;
414     s32     index;
415 
416     if (length < 0)
417         return;
418 
419     for (i = 0; i < length; i++)
420     {
421         index = ((y * 32) + x + i) % (32 * 32);
422         temp = gScreen[index];
423         temp &= 0x0fff;
424         temp |= (palette << 12);
425         gScreen[index] = temp;
426     }
427 }
428 
429 /*---------------------------------------------------------------------------*
430   Name:         DrawIcon
431 
432   Description:  Display icon.
433 
434   Arguments:    index:        Virtual OAM array index.
435                 charName:    Icon number.
436                                 0 - 3 : Icons of signal strength against white background.
437                                 4 - 7 : Icons of signal strength against black background.
438                                 8      : Communications icon
439                                 9      : PictoChat icon
440                 x:            X-coordinate position in dots
441                 y:             Y-coordinate position in dots
442 
443   Returns:      None.
444  *---------------------------------------------------------------------------*/
DrawIcon(u8 index,int charName,int x,int y)445 static void DrawIcon(u8 index, int charName, int x, int y)
446 {
447     G2_SetOBJAttr(&gOam[index],        // Pointer to OAM structure to edit
448                   x,                   // X position
449                   y,                   // Y position
450                   0,                   // Highest display priority
451                   GX_OAM_MODE_NORMAL,  // Normal OBJ
452                   FALSE,               // No mosaic
453                   GX_OAM_EFFECT_NONE,  // No effects
454                   GX_OAM_SHAPE_16x16,  // 2 x 2 character
455                   GX_OAM_COLORMODE_16, // 16-color palette
456                   charName * 4,        // Character number
457                   0,                   // Palette number 0
458                   0                    // Affine transformation index (disabled)
459         );
460 }
461 
462 /*---------------------------------------------------------------------------*
463   Name:         InitializeAllocateSystem
464 
465   Description:  Initializes the memory allocation system within the main memory arena.
466 
467   Arguments:    None.
468 
469   Returns:      None.
470  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)471 static void InitializeAllocateSystem(void)
472 {
473     void   *tempLo;
474     OSHeapHandle hh;
475 
476     // Based on the premise that OS_Init has been already called
477     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
478     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
479     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
480     if (hh < 0)
481     {
482         OS_Panic("ARM9: Fail to create heap...\n");
483     }
484     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
485 }
486 
487 /*---------------------------------------------------------------------------*
488   End of file
489  *---------------------------------------------------------------------------*/
490