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