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