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