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