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