1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WBT - demos - wbt-1
3   File:     main.c
4 
5   Copyright 2006-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-28#$
14   $Rev: 11027 $
15   $Author: tominaga_masafumi $
16  *---------------------------------------------------------------------------*/
17 
18 /*---------------------------------------------------------------------------*
19     A simple functional sample of wireless communication using the WM library.
20     Automatically connects to any wbt-1 demos in the surrounding area.
21 
22     HOWTO:
23         1. Press the A Button to start communications as a parent.
24            As soon as a nearby child that has the same wbt-1 demo is found, communication is automatically started with that child.
25            Communication with up to 15 children is possible at the same time.
26 
27         2. Press the B Button to start communications as a child.
28 		   As soon as a nearby parent that has the same wbt-1 demo is found, communication is automatically started with that parent.
29 
30         3. If the START button is pressed during a busy screen while a connection is being established, or during a communication screen after a connection is established, the connection is reset, and the display returns to the initial screen.
31  *---------------------------------------------------------------------------*/
32 
33 #ifdef SDK_TWL
34 #include <twl.h>
35 #else
36 #include <nitro.h>
37 #endif
38 
39 #include <nitro/wm.h>
40 #include <nitro/wbt.h>
41 
42 #include    "font.h"
43 #include    "text.h"
44 #include    "wh.h"
45 #include    "bt.h"
46 
47 
48 #define MIYA_PRINT 1
49 
50 
51 /*---------------------------------------------------------------------------*
52     Constant definitions
53  *---------------------------------------------------------------------------*/
54 #define     KEY_REPEAT_START    25     // Number of frames until key repeat starts
55 #define     KEY_REPEAT_SPAN     10     // Number of frames between key repeats
56 
57 // Game information
58 /* Constants related to MP communications */
59 #define     DEFAULT_GGID            0x003fff30
60 
61 /*---------------------------------------------------------------------------*
62     Structure definitions
63  *---------------------------------------------------------------------------*/
64 // Key input data
65 typedef struct KeyInfo
66 {
67     u16     cnt;                       // Unprocessed input value
68     u16     trg;                       // Push trigger input
69     u16     up;                        // Release trigger input
70     u16     rep;                       // Press and hold repeat input
71 
72 }
73 KeyInfo;
74 
75 
76 /*---------------------------------------------------------------------------*
77     Internal Function Definitions
78  *---------------------------------------------------------------------------*/
79 static void ModeSelect(void);          // Parent/child select screen
80 static void ModeStartParent(void);     // State after calculation of the channel(s) with the lowest usage rate has finished
81 static void ModeError(void);           // Error display screen
82 static void ModeWorking(void);         // Busy screen
83 static void ModeParent(void);          // Parent communications screen
84 static void ModeChild(void);           // Child communications screen
85 static void VBlankIntr(void);          // V-Blank interrupt handler
86 
87 // Functions called when receiving data
88 static void ParentReceiveCallback(u16 aid, u16 *data, u16 length);
89 static void ChildReceiveCallback(u16 aid, u16 *data, u16 length);
90 
91 // Function called when data is sent
92 void    ParentSendCallback(void);
93 void    ChildSendCallback(void);
94 
95 // Block transfer status notification function
96 static void BlockTransferCallback(void *arg);
97 static void SendCallback(BOOL result);
98 
99 // General purpose subroutines
100 static void KeyRead(KeyInfo * pKey);
101 static void ClearString(int vram_num);
102 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...);
103 static void InitializeAllocateSystem(void);
104 
105 
106 /*---------------------------------------------------------------------------*
107     Internal Variable Definitions
108  *---------------------------------------------------------------------------*/
109 static KeyInfo gKey;                   // Key input
110 static s32 gFrame;                     // Frame counter
111 
112 // Send/receive buffer for display
113 static u8 gSendBuf[256] ATTRIBUTE_ALIGN(32);
114 static BOOL gRecvFlag[1 + WM_NUM_MAX_CHILD];
115 
116 static int send_counter[16];
117 static int recv_counter[16];
118 
119 static BOOL gFirstSendAtChild = TRUE;
120 
121 #define PRINTF mprintf
122 
123 #define VRAM_SIZE 2*32*32
124 static u8 g_screen[NUM_OF_SCREEN][VRAM_SIZE] ATTRIBUTE_ALIGN(32);
125 
126 
127 static TEXT_CTRL textctrl[NUM_OF_SCREEN];
128 TEXT_CTRL *tc[NUM_OF_SCREEN];
129 
130 static int vram_num[2];
131 static int screen_toggle = 0;
132 
133 static u32 v_blank_intr_counter = 0;
134 #define TEXT_HEAPBUF_SIZE 0x8000
135 static u8 text_heap_buffer[TEXT_HEAPBUF_SIZE];
136 
137 static BOOL wbt_available = FALSE;
138 static u16 connected_bitmap = 0;
139 
140 
141 /*---------------------------------------------------------------------------*
142   Name:         InitWireless
143 
144   Description:  Initializes and re-initializes wireless processing.
145 
146   Arguments:    None.
147 
148   Returns:      None.
149  *---------------------------------------------------------------------------*/
InitWireless(void)150 static void InitWireless(void)
151 {
152     //********************************
153     // Initialize wireless
154     connected_bitmap = 0;
155 
156     if (!WH_Initialize())
157     {
158         OS_Panic("WH_Initialize failed.");
159     }
160     WH_SetSessionUpdateCallback(BlockTransferCallback);
161     while(WH_GetSystemState()==WH_SYSSTATE_BUSY){}
162 
163     //********************************
164     if (wbt_available)
165     {
166         bt_stop();
167         WBT_End();
168         wbt_available = FALSE;
169     }
170 }
171 
172 /*---------------------------------------------------------------------------*
173   Name:         EndWireless
174 
175   Description:  Wireless shutdown processing.
176 
177   Arguments:    None.
178 
179   Returns:      None.
180  *---------------------------------------------------------------------------*/
EndWireless(void)181 static void EndWireless(void)
182 {
183     //********************************
184     // End communication.
185     WH_Finalize();
186     while(WH_GetSystemState()==WH_SYSSTATE_BUSY){}
187     (void)WH_End();
188     while(WH_GetSystemState()==WH_SYSSTATE_BUSY){}
189 }
190 
191 /*---------------------------------------------------------------------------*
192   Name:         NitroMain / TwlMain
193 
194   Description:  Initialization and main loop.
195 
196   Arguments:    None.
197 
198   Returns:      None.
199  *---------------------------------------------------------------------------*/
200 #ifdef SDK_TWL
TwlMain(void)201 void TwlMain(void)
202 #else
203 void NitroMain(void)
204 #endif
205 {
206     int     i;
207 
208     // Various types of initialization
209     OS_Init();
210     OS_InitTick();
211 
212     // Memory allocation
213     (void)init_text_buf_sys((void *)&(text_heap_buffer[0]),
214                             (void *)&(text_heap_buffer[TEXT_HEAPBUF_SIZE]));
215 
216     for (i = 0; i < NUM_OF_SCREEN; i++)
217     {
218         tc[i] = &(textctrl[i]);
219         init_text(tc[i], (u16 *)&(g_screen[i]), 4 /* Pal no. */ );
220     }
221 
222     FX_Init();
223     GX_Init();
224     GX_DispOff();
225     GXS_DispOff();
226 
227     // Initializes display settings
228 
229     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
230     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
231     (void)GX_DisableBankForLCDC();
232     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
233     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
234     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
235     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
236 
237 
238     /* BG0 display configuration */
239     GX_SetBankForBG(GX_VRAM_BG_128_A);
240     G2_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16, GX_BG_SCRBASE_0xf000,      // SCR base block 31
241                      GX_BG_CHARBASE_0x00000,    // CHR base block 0
242                      GX_BG_EXTPLTT_01);
243     G2_SetBG0Priority(0);
244     G2_BG0Mosaic(FALSE);
245     // 2D display settings
246     GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BG0_AS_2D);
247     GX_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
248     GX_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
249 
250     // OBJ display settings
251     GX_SetBankForOBJ(GX_VRAM_OBJ_128_B);
252     GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_2D);
253 
254     GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
255 
256     /* Sub BG0 display configuration */
257     GX_SetBankForSubBG(GX_VRAM_SUB_BG_48_HI);
258     G2S_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16, GX_BG_SCRBASE_0xb800,     // SCR base block 23
259                       GX_BG_CHARBASE_0x00000,   // CHR base block 0
260                       GX_BG_EXTPLTT_01);
261     G2S_SetBG0Priority(0);
262     G2S_BG0Mosaic(FALSE);
263     GXS_SetGraphicsMode(GX_BGMODE_0);
264     GXS_LoadBG0Char(d_CharData, 0, sizeof(d_CharData));
265     GXS_LoadBGPltt(d_PaletteData, 0, sizeof(d_PaletteData));
266 
267     GX_SetBankForSubOBJ(GX_VRAM_SUB_OBJ_128_D);
268     GXS_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_2D);
269 
270     GXS_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
271 
272     G2_SetBG0Offset(0, 0);
273     G2S_SetBG0Offset(0, 0);
274 
275 
276     InitializeAllocateSystem();
277 
278     // LCD display start
279     GX_DispOn();
280     GXS_DispOn();
281 
282     // For V-Blank
283     (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
284     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
285     (void)OS_EnableIrq();
286     (void)OS_EnableInterrupts();
287     (void)GX_VBlankIntr(TRUE);
288 
289 
290     // Debug string output
291     PRINTF("ARM9: WBT-1 demo started.\n");
292     vram_num[0] = 1;
293     vram_num[1] = 0;
294 
295     // Initialize wireless (use the WH library)
296     WH_SetGgid(DEFAULT_GGID);
297 
298     // Main loop
299 
300     for (gFrame = 0; TRUE; gFrame++)
301     {
302         text_buf_to_vram(tc[vram_num[0]]);
303         text_buf_to_vram(tc[vram_num[1]]);
304 
305         if (gKey.trg & PAD_BUTTON_SELECT)
306         {
307             screen_toggle ^= 1;
308         }
309         if (gKey.trg & PAD_BUTTON_L)
310         {
311             vram_num[screen_toggle]--;
312             if (vram_num[screen_toggle] < 0)
313             {
314                 vram_num[screen_toggle] = (NUM_OF_SCREEN - 1);
315             }
316         }
317         else if (gKey.trg & PAD_BUTTON_R)
318         {
319             vram_num[screen_toggle]++;
320             if (vram_num[screen_toggle] > (NUM_OF_SCREEN - 1))
321             {
322                 vram_num[screen_toggle] = 0;
323             }
324         }
325 
326         // Get key input data
327         KeyRead(&gKey);
328 
329         // Branch processing based on communication status
330         switch (WH_GetSystemState())
331         {
332         case WH_SYSSTATE_STOP:
333             ModeSelect();
334             break;
335         case WH_SYSSTATE_MEASURECHANNEL:
336             ModeStartParent();
337             break;
338         case WH_SYSSTATE_IDLE:
339         case WH_SYSSTATE_ERROR:
340         case WH_SYSSTATE_CONNECT_FAIL:
341             EndWireless();
342             break;
343         case WH_SYSSTATE_FATAL:
344             ModeError();
345             break;
346         case WH_SYSSTATE_SCANNING:
347         case WH_SYSSTATE_BUSY:
348             ModeWorking();
349             break;
350         case WH_SYSSTATE_CONNECTED:
351             // Branch again based on whether this is a parent or child device
352             switch (WH_GetConnectMode())
353             {
354             case WH_CONNECTMODE_MP_PARENT:
355                 ModeParent();
356                 break;
357             case WH_CONNECTMODE_MP_CHILD:
358                 ModeChild();
359                 break;
360             }
361             break;
362         }
363 
364         // Waiting for the V-Blank
365         OS_WaitVBlankIntr();
366     }
367 }
368 
369 /*---------------------------------------------------------------------------*
370   Name:         ModeSelect
371 
372   Description:  Processing in parent/child selection screen.
373 
374   Arguments:    None.
375 
376   Returns:      None.
377  *---------------------------------------------------------------------------*/
ModeSelect(void)378 static void ModeSelect(void)
379 {
380     // Clear counters
381     MI_CpuClear(send_counter, sizeof(send_counter));
382     MI_CpuClear(recv_counter, sizeof(recv_counter));
383 
384     gFirstSendAtChild = TRUE;
385 
386     connected_bitmap = 0;
387     if (wbt_available)
388     {
389         bt_stop();
390         WBT_End();
391         wbt_available = FALSE;
392     }
393 
394 
395     PrintString(3, 10, 0xf, "Push A to connect as PARENT");
396     PrintString(3, 12, 0xf, "Push B to connect as CHILD");
397 
398     if (gKey.trg & PAD_BUTTON_A)
399     {
400         // Initialize wireless
401         InitWireless();
402 
403         //********************************
404         WBT_InitParent(BT_PARENT_PACKET_SIZE, BT_CHILD_PACKET_SIZE, bt_callback);
405         WH_SetReceiver(ParentReceiveCallback);
406         bt_register_blocks();
407         (void)WH_StartMeasureChannel();
408         wbt_available = TRUE;
409         //********************************
410     }
411     else if (gKey.trg & PAD_BUTTON_B)
412     {
413         static const u8 ANY_PARENT[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
414 
415         // Initialize wireless
416         InitWireless();
417 
418         //********************************
419         WBT_InitChild(bt_callback);
420         WH_SetReceiver(ChildReceiveCallback);
421         (void)WH_ChildConnectAuto(WH_CONNECTMODE_MP_CHILD, ANY_PARENT, 0);
422         wbt_available = TRUE;
423         //********************************
424         vram_num[1] = 2;
425     }
426 }
427 
428 /*---------------------------------------------------------------------------*
429   Name:         ModeStartParent
430 
431   Description:  Processing run when calculation of the channel(s) with a low usage rate is done.
432 
433   Arguments:    None.
434 
435   Returns:      None.
436  *---------------------------------------------------------------------------*/
ModeStartParent(void)437 static void ModeStartParent(void)
438 {
439     (void)WH_ParentConnect(WH_CONNECTMODE_MP_PARENT, 0x0000, WH_GetMeasureChannel());
440 }
441 
442 /*---------------------------------------------------------------------------*
443   Name:         ModeError
444 
445   Description:  Processing in error display screen.
446 
447   Arguments:    None.
448 
449   Returns:      None.
450  *---------------------------------------------------------------------------*/
ModeError(void)451 static void ModeError(void)
452 {
453     PrintString(5, 10, 0x1, "======= ERROR! =======");
454     PrintString(5, 13, 0xf, " Fatal error occured.");
455     PrintString(5, 14, 0xf, "Please reboot program.");
456 }
457 
458 /*---------------------------------------------------------------------------*
459   Name:         ModeWorking
460 
461   Description:  Processing in busy screen.
462 
463   Arguments:    None.
464 
465   Returns:      None.
466  *---------------------------------------------------------------------------*/
ModeWorking(void)467 static void ModeWorking(void)
468 {
469     PrintString(9, 11, 0xf, "Now working...");
470 
471     if (gKey.trg & PAD_BUTTON_START)
472     {
473         //********************************
474         // Wireless shutdown
475         EndWireless();
476         //********************************
477     }
478 }
479 
480 /*---------------------------------------------------------------------------*
481   Name:         ModeParent
482 
483   Description:  Processing in parent communications screen.
484 
485   Arguments:    None.
486 
487   Returns:      None.
488  *---------------------------------------------------------------------------*/
ModeParent(void)489 static void ModeParent(void)
490 {
491     PrintString(8, 1, 0x2, "Parent mode");
492     PrintString(4, 3, 0x4, "Send:     %08X", send_counter[0]);
493 
494     PrintString(4, 5, 0x4, "Receive:");
495     {
496         s32     i;
497 
498         for (i = 1; i < (WM_NUM_MAX_CHILD + 1); i++)
499         {
500             if (gRecvFlag[i])
501             {
502                 PrintString(5, (s16)(6 + i), 0x4, "Child%02d: %08X", i, recv_counter[i]);
503             }
504             else
505             {
506                 PrintString(5, (s16)(6 + i), 0x7, "No child");
507             }
508         }
509     }
510 
511     if (gKey.trg & PAD_BUTTON_START)
512     {
513         //********************************
514         // Wireless shutdown
515         EndWireless();
516         //********************************
517     }
518 }
519 
520 /*---------------------------------------------------------------------------*
521   Name:         ModeChild
522 
523   Description:  Processing in child communications screen.
524 
525   Arguments:    None.
526 
527   Returns:      None.
528  *---------------------------------------------------------------------------*/
ModeChild(void)529 static void ModeChild(void)
530 {
531     PrintString(8, 1, 0x2, "Child mode");
532     PrintString(4, 3, 0x4, "Send:     %08X", send_counter[0]);
533     PrintString(4, 5, 0x4, "Receive:");
534     PrintString(5, 7, 0x4, "Parent:  %08X", recv_counter[0]);
535 
536     if (gFirstSendAtChild)
537     {
538         // First cycle's data transmission
539         ChildSendCallback();
540         gFirstSendAtChild = FALSE;
541     }
542 
543     if (gKey.trg & PAD_BUTTON_START)
544     {
545         //********************************
546         // Wireless shutdown
547         EndWireless();
548         //********************************
549     }
550     else if (gKey.trg & PAD_BUTTON_Y)
551     {
552         bt_start();
553     }
554     else if (gKey.trg & PAD_BUTTON_X)
555     {
556         bt_stop();
557     }
558 }
559 
560 /*---------------------------------------------------------------------------*
561   Name:         VBlankIntr
562 
563   Description:  V-Blank interrupt vector.
564 
565   Arguments:    None.
566 
567   Returns:      None.
568  *---------------------------------------------------------------------------*/
VBlankIntr(void)569 static void VBlankIntr(void)
570 {
571     vu16   *ptr;
572     int     i;
573 
574     DC_FlushRange((void *)&(g_screen[vram_num[0]]), VRAM_SIZE);
575     /* I/O register is accessed using DMA operation, so cache wait is not needed */
576     // DC_WaitWriteBufferEmpty();
577     GX_LoadBG0Scr(&(g_screen[vram_num[0]]), 0, VRAM_SIZE);
578 
579     DC_FlushRange((void *)&(g_screen[vram_num[1]]), VRAM_SIZE);
580     /* I/O register is accessed using DMA operation, so cache wait is not needed */
581     // DC_WaitWriteBufferEmpty();
582     GXS_LoadBG0Scr(&(g_screen[vram_num[1]]), 0, VRAM_SIZE);
583 
584     if (screen_toggle)
585         ptr = (u16 *)G2S_GetBG0ScrPtr();
586     else
587         ptr = (u16 *)G2_GetBG0ScrPtr();
588 
589     for (i = 0; i < 32; i++)
590     {
591         *ptr = (u16)((2 << 12) | (0x00ff & '='));
592         ptr++;
593     }
594 
595 
596     v_blank_intr_counter++;
597     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
598 }
599 
600 /*---------------------------------------------------------------------------*
601   Name:         ParentReceiveCallback
602 
603   Description:  Function that is called when a parent receives data from a child.
604 
605   Arguments:    aid: AID of send origin child
606                 data: Pointer to received data (NULL is disconnection notification)
607                 length: Size of received data
608 
609   Returns:      None.
610  *---------------------------------------------------------------------------*/
ParentReceiveCallback(u16 aid,u16 * data,u16 length)611 static void ParentReceiveCallback(u16 aid, u16 *data, u16 length)
612 {
613 	recv_counter[aid]++;
614     if (data != NULL)
615     {
616         gRecvFlag[aid] = TRUE;
617         // Copy source is aligned to 2 bytes (not 4 bytes)
618 //        recv_counter[aid]++;
619         WBT_MpParentRecvHook((u8 *)data, length, aid);
620     }
621     else
622     {
623         gRecvFlag[aid] = FALSE;
624     }
625 }
626 
627 
628 /*---------------------------------------------------------------------------*
629   Name:         ChildReceiveCallback
630 
631   Description:  Function that is called when a child receives data from a parent.
632 
633   Arguments:    aid: AID of sending source parent (always 0)
634                 data: Pointer to received data (NULL is disconnection notification)
635                 length: Size of received data
636 
637   Returns:      None.
638  *---------------------------------------------------------------------------*/
ChildReceiveCallback(u16 aid,u16 * data,u16 length)639 static void ChildReceiveCallback(u16 aid, u16 *data, u16 length)
640 {
641     (void)aid;
642     recv_counter[0]++;
643     if (data != NULL)
644     {
645         gRecvFlag[0] = TRUE;
646         // Copy source is aligned to 2 bytes (not 4 bytes)
647         WBT_MpChildRecvHook((u8 *)data, length);
648     }
649     else
650     {
651         gRecvFlag[0] = FALSE;
652     }
653 }
654 
655 /*---------------------------------------------------------------------------*
656   Name:         BlockTransferCallback
657 
658   Description:  Function that notifies of block transfer status.
659 
660   Arguments:    arg: Callback pointer for the notification source WM function.
661 
662   Returns:      None.
663  *---------------------------------------------------------------------------*/
BlockTransferCallback(void * arg)664 static void BlockTransferCallback(void *arg)
665 {
666     int connectMode = WH_GetConnectMode();
667 
668     switch (((WMCallback*)arg)->apiid)
669     {
670     case WM_APIID_START_MP:
671         {                              /* Begin MP state */
672            WMStartMPCallback *cb = (WMStartMPCallback *)arg;
673             switch (cb->state)
674             {
675             case WM_STATECODE_MP_START:
676                 if (connectMode == WH_CONNECTMODE_MP_PARENT)
677                 {
678                     ParentSendCallback();
679                 }
680                 else if (connectMode == WH_CONNECTMODE_MP_CHILD)
681                 {
682                     WBT_SetOwnAid(WH_GetCurrentAid());
683                     mfprintf(tc[2], "aid = %d\n", WH_GetCurrentAid());
684                     bt_start();
685                     ChildSendCallback();
686                 }
687                 break;
688             }
689         }
690         break;
691     case WM_APIID_SET_MP_DATA:
692         {                              /* A single MP communication is complete */
693             if (connectMode == WH_CONNECTMODE_MP_PARENT)
694             {
695                 if (connected_bitmap != 0)
696                 {
697                     ParentSendCallback();
698                 }
699             }
700             else if (connectMode == WH_CONNECTMODE_MP_CHILD)
701             {
702                 ChildSendCallback();
703             }
704         }
705         break;
706     case WM_APIID_START_PARENT:
707         {                              /* Connect to a new child */
708             WMStartParentCallback *cb = (WMStartParentCallback *)arg;
709             if (connectMode == WH_CONNECTMODE_MP_PARENT)
710             {
711                 switch (cb->state)
712                 {
713                 case WM_STATECODE_CONNECTED:
714                     if (connected_bitmap == 0)
715                     {
716                         ParentSendCallback();
717                     }
718                     connected_bitmap |= (1 << cb->aid);
719                     break;
720                 case WM_STATECODE_DISCONNECTED:
721                     connected_bitmap &= ~(1 << cb->aid);
722                     break;
723                 }
724             }
725         }
726         break;
727     }
728 }
729 
730 
731 /*---------------------------------------------------------------------------*
732   Name:         ParentSendCallback
733 
734   Description:  Function that is called when a parent sends data to a child.
735 
736   Arguments:    None.
737 
738   Returns:      None.
739  *---------------------------------------------------------------------------*/
ParentSendCallback(void)740 void ParentSendCallback(void)
741 {
742     const u16 size = (u16)WBT_MpParentSendHook(gSendBuf, WC_PARENT_DATA_SIZE_MAX);
743     send_counter[0]++;
744     (void)WH_SendData(gSendBuf, size, NULL);
745 }
746 
747 
748 /*---------------------------------------------------------------------------*
749   Name:         ChildSendCallback
750 
751   Description:  Function that is called when a child receives data from a parent.
752 
753   Arguments:    None.
754 
755   Returns:      None.
756  *---------------------------------------------------------------------------*/
ChildSendCallback(void)757 void ChildSendCallback(void)
758 {
759     const u16 size = (u16)WBT_MpChildSendHook(gSendBuf, WC_CHILD_DATA_SIZE_MAX);
760     send_counter[0]++;
761     (void)WH_SendData(gSendBuf, size, NULL);
762 }
763 
764 /*---------------------------------------------------------------------------*
765   Name:         KeyRead
766 
767   Description:  Edits key input data
768                 Detects press trigger, release trigger, and press-and-hold repeat.
769 
770   Arguments:    pKey: Structure that holds key input data to be edited
771 
772   Returns:      None.
773  *---------------------------------------------------------------------------*/
KeyRead(KeyInfo * pKey)774 static void KeyRead(KeyInfo * pKey)
775 {
776     static u16 repeat_count[12];
777     int     i;
778     u16     r;
779 
780     r = PAD_Read();
781     pKey->trg = 0x0000;
782     pKey->up = 0x0000;
783     pKey->rep = 0x0000;
784 
785     for (i = 0; i < 12; i++)
786     {
787         if (r & (0x0001 << i))
788         {
789             if (!(pKey->cnt & (0x0001 << i)))
790             {
791                 pKey->trg |= (0x0001 << i);     // Press trigger
792                 repeat_count[i] = 1;
793             }
794             else
795             {
796                 if (repeat_count[i] > KEY_REPEAT_START)
797                 {
798                     pKey->rep |= (0x0001 << i); // Press-and-hold repeat
799                     repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
800                 }
801                 else
802                 {
803                     repeat_count[i]++;
804                 }
805             }
806         }
807         else
808         {
809             if (pKey->cnt & (0x0001 << i))
810             {
811                 pKey->up |= (0x0001 << i);      // Release trigger
812             }
813         }
814     }
815     pKey->cnt = r;                     // Unprocessed key input
816 }
817 
818 /*---------------------------------------------------------------------------*
819   Name:         ClearString
820 
821   Description:  Clears the virtual screen.
822 
823   Arguments:    None.
824 
825   Returns:      None.
826  *---------------------------------------------------------------------------*/
ClearString(int vram_num)827 static void ClearString(int vram_num)
828 {
829     MI_DmaClear32(0, (void *)&(g_screen[vram_num]), VRAM_SIZE);
830 }
831 
832 
833 /*---------------------------------------------------------------------------*
834   Name:         PrintString
835 
836   Description:  Positions the text string on the virtual screen. The string can be up to 32 chars.
837 
838   Arguments:    x: X-coordinate where character string starts (x 8 pixels).
839                 y: Y-coordinate where character string starts (x 8 pixels).
840                 palette: Specify text color by palette number.
841                 text: Text string to position. Null-terminated.
842                 ...: Virtual argument.
843 
844   Returns:      None.
845  *---------------------------------------------------------------------------*/
PrintString(s16 x,s16 y,u8 palette,char * text,...)846 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...)
847 {
848     va_list vlist;
849     char    temp[32 + 2];
850     s32     i;
851 
852     va_start(vlist, text);
853     (void)OS_VSNPrintf(temp, 32, text, vlist);
854     va_end(vlist);
855     *(u16 *)(&temp[31]) = 0x0000;
856     for (i = 0;; i++)
857     {
858         if (temp[i] == 0x00)
859         {
860             break;
861         }
862         tc[1]->screen[(y * 32) + x + i] = (u16)((palette << 12) | temp[i]);
863     }
864 }
865 
866 
867 /*---------------------------------------------------------------------------*
868   Name:         InitializeAllocateSystem
869 
870   Description:  Initializes the memory allocation system within the main memory arena.
871 
872   Arguments:    None.
873 
874   Returns:      None.
875  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)876 static void InitializeAllocateSystem(void)
877 {
878     void   *tempLo;
879     OSHeapHandle hh;
880 
881     mprintf(" arena lo = %08x\n", OS_GetMainArenaLo());
882     mprintf(" arena hi = %08x\n", OS_GetMainArenaHi());
883 
884     // Based on the premise that OS_Init has been already called
885     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
886     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
887     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
888     if (hh < 0)
889     {
890         OS_Panic("ARM9: Fail to create heap...\n");
891     }
892     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
893 }
894 
895 
896 /*---------------------------------------------------------------------------*
897   End of file
898  *---------------------------------------------------------------------------*/
899