1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WBT - demos - wbt-1
3 File: main.c
4
5 Copyright 2006-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-12-16#$
14 $Rev: 9665 $
15 $Author: kitase_hirotake $
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 if (wbt_available)
367 {
368 bt_stop();
369 WBT_End();
370 wbt_available = FALSE;
371 }
372
373
374 PrintString(3, 10, 0xf, "Push A to connect as PARENT");
375 PrintString(3, 12, 0xf, "Push B to connect as CHILD");
376
377 if (gKey.trg & PAD_BUTTON_A)
378 {
379 //********************************
380 WBT_InitParent(BT_PARENT_PACKET_SIZE, BT_CHILD_PACKET_SIZE, bt_callback);
381 WH_SetReceiver(ParentReceiveCallback);
382 bt_register_blocks();
383 (void)WH_StartMeasureChannel();
384 wbt_available = TRUE;
385 //********************************
386 }
387 else if (gKey.trg & PAD_BUTTON_B)
388 {
389 static const u8 ANY_PARENT[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
390 //********************************
391 WBT_InitChild(bt_callback);
392 WH_SetReceiver(ChildReceiveCallback);
393 (void)WH_ChildConnectAuto(WH_CONNECTMODE_MP_CHILD, ANY_PARENT, 0);
394 wbt_available = TRUE;
395 //********************************
396 vram_num[1] = 2;
397 }
398 }
399
400 /*---------------------------------------------------------------------------*
401 Name: ModeStartParent
402
403 Description: This process is run when the channel with a low usage rate is done being calculated.
404
405 Arguments: None.
406
407 Returns: None.
408 *---------------------------------------------------------------------------*/
ModeStartParent(void)409 static void ModeStartParent(void)
410 {
411 (void)WH_ParentConnect(WH_CONNECTMODE_MP_PARENT, 0x0000, WH_GetMeasureChannel());
412 }
413
414 /*---------------------------------------------------------------------------*
415 Name: ModeError
416
417 Description: Processing in error display screen.
418
419 Arguments: None.
420
421 Returns: None.
422 *---------------------------------------------------------------------------*/
ModeError(void)423 static void ModeError(void)
424 {
425 PrintString(5, 10, 0x1, "======= ERROR! =======");
426 PrintString(5, 13, 0xf, " Fatal error occured.");
427 PrintString(5, 14, 0xf, "Please reboot program.");
428 }
429
430 /*---------------------------------------------------------------------------*
431 Name: ModeWorking
432
433 Description: Processing in busy screen.
434
435 Arguments: None.
436
437 Returns: None.
438 *---------------------------------------------------------------------------*/
ModeWorking(void)439 static void ModeWorking(void)
440 {
441 PrintString(9, 11, 0xf, "Now working...");
442
443 if (gKey.trg & PAD_BUTTON_START)
444 {
445 //********************************
446 WH_Finalize();
447 //********************************
448 }
449 }
450
451 /*---------------------------------------------------------------------------*
452 Name: ModeParent
453
454 Description: Processing in parent communications screen.
455
456 Arguments: None.
457
458 Returns: None.
459 *---------------------------------------------------------------------------*/
ModeParent(void)460 static void ModeParent(void)
461 {
462 PrintString(8, 1, 0x2, "Parent mode");
463 PrintString(4, 3, 0x4, "Send: %08X", send_counter[0]);
464
465 PrintString(4, 5, 0x4, "Receive:");
466 {
467 s32 i;
468
469 for (i = 1; i < (WM_NUM_MAX_CHILD + 1); i++)
470 {
471 if (gRecvFlag[i])
472 {
473 PrintString(5, (s16)(6 + i), 0x4, "Child%02d: %08X", i, recv_counter[i]);
474 }
475 else
476 {
477 PrintString(5, (s16)(6 + i), 0x7, "No child");
478 }
479 }
480 }
481
482 if (gKey.trg & PAD_BUTTON_START)
483 {
484 //********************************
485 WH_Finalize();
486 //********************************
487 }
488 }
489
490 /*---------------------------------------------------------------------------*
491 Name: ModeChild
492
493 Description: Processing in child communications screen.
494
495 Arguments: None.
496
497 Returns: None.
498 *---------------------------------------------------------------------------*/
ModeChild(void)499 static void ModeChild(void)
500 {
501 PrintString(8, 1, 0x2, "Child mode");
502 PrintString(4, 3, 0x4, "Send: %08X", send_counter[0]);
503 PrintString(4, 5, 0x4, "Receive:");
504 PrintString(5, 7, 0x4, "Parent: %08X", recv_counter[0]);
505
506 if (gFirstSendAtChild)
507 {
508 // First data transmission
509 ChildSendCallback();
510 gFirstSendAtChild = FALSE;
511 }
512
513 if (gKey.trg & PAD_BUTTON_START)
514 {
515 //********************************
516 WH_Finalize();
517 //********************************
518 }
519 else if (gKey.trg & PAD_BUTTON_Y)
520 {
521 bt_start();
522 }
523 else if (gKey.trg & PAD_BUTTON_X)
524 {
525 bt_stop();
526 }
527 }
528
529 /*---------------------------------------------------------------------------*
530 Name: VBlankIntr
531
532 Description: V-Blank interrupt vector.
533
534 Arguments: None.
535
536 Returns: None.
537 *---------------------------------------------------------------------------*/
VBlankIntr(void)538 static void VBlankIntr(void)
539 {
540 vu16 *ptr;
541 int i;
542
543 DC_FlushRange((void *)&(g_screen[vram_num[0]]), VRAM_SIZE);
544 /* I/O register is accessed using DMA operation, so cache wait is not needed */
545 // DC_WaitWriteBufferEmpty();
546 GX_LoadBG0Scr(&(g_screen[vram_num[0]]), 0, VRAM_SIZE);
547
548 DC_FlushRange((void *)&(g_screen[vram_num[1]]), VRAM_SIZE);
549 /* I/O register is accessed using DMA operation, so cache wait is not needed */
550 // DC_WaitWriteBufferEmpty();
551 GXS_LoadBG0Scr(&(g_screen[vram_num[1]]), 0, VRAM_SIZE);
552
553 if (screen_toggle)
554 ptr = (u16 *)G2S_GetBG0ScrPtr();
555 else
556 ptr = (u16 *)G2_GetBG0ScrPtr();
557
558 for (i = 0; i < 32; i++)
559 {
560 *ptr = (u16)((2 << 12) | (0x00ff & '='));
561 ptr++;
562 }
563
564
565 v_blank_intr_counter++;
566 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
567 }
568
569 /*---------------------------------------------------------------------------*
570 Name: ParentReceiveCallback
571
572 Description: Function that is called when a parent receives data from a child.
573
574 Arguments: aid: AID of send origin child
575 data: Pointer to received data (NULL is disconnection notification)
576 length: Size of received data
577
578 Returns: None.
579 *---------------------------------------------------------------------------*/
ParentReceiveCallback(u16 aid,u16 * data,u16 length)580 static void ParentReceiveCallback(u16 aid, u16 *data, u16 length)
581 {
582 recv_counter[aid]++;
583 if (data != NULL)
584 {
585 gRecvFlag[aid] = TRUE;
586 // Copy source is aligned to 2 bytes (not 4 bytes)
587 // recv_counter[aid]++;
588 WBT_MpParentRecvHook((u8 *)data, length, aid);
589 }
590 else
591 {
592 gRecvFlag[aid] = FALSE;
593 }
594 }
595
596
597 /*---------------------------------------------------------------------------*
598 Name: ChildReceiveCallback
599
600 Description: Function that is called when a child receives data from a parent.
601
602 Arguments: aid: AID of sending source parent (always 0)
603 data: Pointer to received data (NULL is disconnection notification)
604 length: Size of received data
605
606 Returns: None.
607 *---------------------------------------------------------------------------*/
ChildReceiveCallback(u16 aid,u16 * data,u16 length)608 static void ChildReceiveCallback(u16 aid, u16 *data, u16 length)
609 {
610 (void)aid;
611 recv_counter[0]++;
612 if (data != NULL)
613 {
614 gRecvFlag[0] = TRUE;
615 // Copy source is aligned to 2 bytes (not 4 bytes)
616 WBT_MpChildRecvHook((u8 *)data, length);
617 }
618 else
619 {
620 gRecvFlag[0] = FALSE;
621 }
622 }
623
624 /*---------------------------------------------------------------------------*
625 Name: BlockTransferCallback
626
627 Description: Block transfer status notification function
628
629 Arguments: arg: Callback pointer for the notification source WM function
630
631 Returns: None.
632 *---------------------------------------------------------------------------*/
BlockTransferCallback(void * arg)633 static void BlockTransferCallback(void *arg)
634 {
635 int connectMode = WH_GetConnectMode();
636
637 switch (((WMCallback*)arg)->apiid)
638 {
639 case WM_APIID_START_MP:
640 { /* Begin MP state */
641 WMStartMPCallback *cb = (WMStartMPCallback *)arg;
642 switch (cb->state)
643 {
644 case WM_STATECODE_MP_START:
645 if (connectMode == WH_CONNECTMODE_MP_PARENT)
646 {
647 ParentSendCallback();
648 }
649 else if (connectMode == WH_CONNECTMODE_MP_CHILD)
650 {
651 WBT_SetOwnAid(WH_GetCurrentAid());
652 mfprintf(tc[2], "aid = %d\n", WH_GetCurrentAid());
653 bt_start();
654 ChildSendCallback();
655 }
656 break;
657 }
658 }
659 break;
660 case WM_APIID_SET_MP_DATA:
661 { /* Complete single MP communication */
662 if (connectMode == WH_CONNECTMODE_MP_PARENT)
663 {
664 if (connected_bitmap != 0)
665 {
666 ParentSendCallback();
667 }
668 }
669 else if (connectMode == WH_CONNECTMODE_MP_CHILD)
670 {
671 ChildSendCallback();
672 }
673 }
674 break;
675 case WM_APIID_START_PARENT:
676 { /* Connect to a new child */
677 WMStartParentCallback *cb = (WMStartParentCallback *)arg;
678 if (connectMode == WH_CONNECTMODE_MP_PARENT)
679 {
680 switch (cb->state)
681 {
682 case WM_STATECODE_CONNECTED:
683 if (connected_bitmap == 0)
684 {
685 ParentSendCallback();
686 }
687 connected_bitmap |= (1 << cb->aid);
688 break;
689 case WM_STATECODE_DISCONNECTED:
690 connected_bitmap &= ~(1 << cb->aid);
691 break;
692 }
693 }
694 }
695 break;
696 }
697 }
698
699
700 /*---------------------------------------------------------------------------*
701 Name: ParentSendCallback
702
703 Description: Function that is called when a parent sends data to a child.
704
705 Arguments: None.
706
707 Returns: None.
708 *---------------------------------------------------------------------------*/
ParentSendCallback(void)709 void ParentSendCallback(void)
710 {
711 const u16 size = (u16)WBT_MpParentSendHook(gSendBuf, WC_PARENT_DATA_SIZE_MAX);
712 send_counter[0]++;
713 (void)WH_SendData(gSendBuf, size, NULL);
714 }
715
716
717 /*---------------------------------------------------------------------------*
718 Name: ChildSendCallback
719
720 Description: Function that is called when a child receives data from a parent.
721
722 Arguments: None.
723
724 Returns: None.
725 *---------------------------------------------------------------------------*/
ChildSendCallback(void)726 void ChildSendCallback(void)
727 {
728 const u16 size = (u16)WBT_MpChildSendHook(gSendBuf, WC_CHILD_DATA_SIZE_MAX);
729 send_counter[0]++;
730 (void)WH_SendData(gSendBuf, size, NULL);
731 }
732
733 /*---------------------------------------------------------------------------*
734 Name: KeyRead
735
736 Description: Edits key input data.
737 Detects press trigger, release trigger, and press-and-hold repeat.
738
739 Arguments: pKey: Structure that holds key input data to be edited.
740
741 Returns: None.
742 *---------------------------------------------------------------------------*/
KeyRead(KeyInfo * pKey)743 static void KeyRead(KeyInfo * pKey)
744 {
745 static u16 repeat_count[12];
746 int i;
747 u16 r;
748
749 r = PAD_Read();
750 pKey->trg = 0x0000;
751 pKey->up = 0x0000;
752 pKey->rep = 0x0000;
753
754 for (i = 0; i < 12; i++)
755 {
756 if (r & (0x0001 << i))
757 {
758 if (!(pKey->cnt & (0x0001 << i)))
759 {
760 pKey->trg |= (0x0001 << i); // Press trigger
761 repeat_count[i] = 1;
762 }
763 else
764 {
765 if (repeat_count[i] > KEY_REPEAT_START)
766 {
767 pKey->rep |= (0x0001 << i); // Press-and-hold repeat
768 repeat_count[i] = KEY_REPEAT_START - KEY_REPEAT_SPAN;
769 }
770 else
771 {
772 repeat_count[i]++;
773 }
774 }
775 }
776 else
777 {
778 if (pKey->cnt & (0x0001 << i))
779 {
780 pKey->up |= (0x0001 << i); // Release trigger
781 }
782 }
783 }
784 pKey->cnt = r; // Unprocessed key input
785 }
786
787 /*---------------------------------------------------------------------------*
788 Name: ClearString
789
790 Description: Clears the virtual screen.
791
792 Arguments: None.
793
794 Returns: None.
795 *---------------------------------------------------------------------------*/
ClearString(int vram_num)796 static void ClearString(int vram_num)
797 {
798 MI_DmaClear32(0, (void *)&(g_screen[vram_num]), VRAM_SIZE);
799 }
800
801
802 /*---------------------------------------------------------------------------*
803 Name: PrintString
804
805 Description: Positions the text string on the virtual screen. The string can be up to 32 chars.
806
807 Arguments: x: X-coordinate where character string starts (x 8 dots)
808 y: Y-coordinate where character string starts (x 8 dots)
809 palette: Specify text color by palette number
810 text: Text string to position. Null-terminated.
811 ...: Virtual argument
812
813 Returns: None.
814 *---------------------------------------------------------------------------*/
PrintString(s16 x,s16 y,u8 palette,char * text,...)815 static void PrintString(s16 x, s16 y, u8 palette, char *text, ...)
816 {
817 va_list vlist;
818 char temp[32 + 2];
819 s32 i;
820
821 va_start(vlist, text);
822 (void)OS_VSNPrintf(temp, 32, text, vlist);
823 va_end(vlist);
824 *(u16 *)(&temp[31]) = 0x0000;
825 for (i = 0;; i++)
826 {
827 if (temp[i] == 0x00)
828 {
829 break;
830 }
831 tc[1]->screen[(y * 32) + x + i] = (u16)((palette << 12) | temp[i]);
832 }
833 }
834
835
836 /*---------------------------------------------------------------------------*
837 Name: InitializeAllocateSystem
838
839 Description: Initializes the memory allocation system within the main memory arena.
840
841 Arguments: None.
842
843 Returns: None.
844 *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)845 static void InitializeAllocateSystem(void)
846 {
847 void *tempLo;
848 OSHeapHandle hh;
849
850 mprintf(" arena lo = %08x\n", OS_GetMainArenaLo());
851 mprintf(" arena hi = %08x\n", OS_GetMainArenaHi());
852
853 // Based on the premise that OS_Init has been already called
854 tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
855 OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
856 hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
857 if (hh < 0)
858 {
859 OS_Panic("ARM9: Fail to create heap...\n");
860 }
861 hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
862 }
863
864
865 /*---------------------------------------------------------------------------*
866 End of file
867 *---------------------------------------------------------------------------*/
868