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