1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MB - demos - multiboot
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:: 2009-03-02#$
14 $Rev: 10122 $
15 $Author: kitase_hirotake $
16 *---------------------------------------------------------------------------*/
17
18
19 #include <nitro.h>
20 #include <nitro/wm.h>
21 #include <nitro/mb.h>
22
23
24 #include "common.h"
25 #include "dispfunc.h"
26
27 /*
28 * For BeaconPeriod randomization (rand)
29 */
30 #include <stdlib.h>
31
32 /*
33 * A simple example of a multiboot parent
34 *
35 * Because the MB library samples use the multiboot functionality, multiple development units with the same communications environment (wired or wireless) are required
36 *
37 * The mb_child_NITRO.srl and mb_child_TWL.srl sample programs in the $TwlSDK/bin/ARM9-TS/Rom/ directory provide the same features as a multiboot child for final retail units. Load these binaries on other hardware as with any sample program, and run them together.
38 *
39 *
40 *
41 *
42 */
43
44
45 /*---------------------------------------------------------------------------*/
46 /* Functions */
47
48 static void Menu(void);
49
50 /* V-Blank interrupt process */
VBlankIntr(void)51 static void VBlankIntr(void)
52 {
53 //---- OAM updating
54 DC_FlushRange(oamBak, sizeof(oamBak));
55 /* I/O register is accessed using DMA operation, so cache wait is not needed */
56 // DC_WaitWriteBufferEmpty();
57 MI_DmaCopy32(3, oamBak, (void *)HW_OAM, sizeof(oamBak));
58
59 //---- BG screen update
60 BgScrSetVblank();
61
62 (void)rand();
63
64 //---- Interrupt check flag
65 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
66 }
67
68 /* Main */
NitroMain()69 void NitroMain()
70 {
71 /* OS initialization */
72 OS_Init();
73 OS_InitTick();
74 OS_InitAlarm();
75 FX_Init();
76
77 /* GX initialization */
78 GX_Init();
79 GX_DispOff();
80 GXS_DispOff();
81
82 { /* Memory allocation initialization */
83 OSHeapHandle heapHandle; // Heap handle
84 enum
85 { MAIN_HEAP_SIZE = 0x80000 };
86 void *heapStart, *nstart;
87 nstart = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 16);
88 OS_SetMainArenaLo(nstart);
89 heapStart = OS_AllocFromMainArenaLo((u32)MAIN_HEAP_SIZE, 32);
90 heapHandle =
91 OS_CreateHeap(OS_ARENA_MAIN, heapStart, (void *)((u32)heapStart + MAIN_HEAP_SIZE));
92 if (heapHandle < 0)
93 {
94 OS_Panic("ARM9: Fail to create heap...\n");
95 }
96 heapHandle = OS_SetCurrentHeap(OS_ARENA_MAIN, heapHandle);
97 }
98
99 (void)OS_EnableIrq();
100 (void)OS_EnableInterrupts();
101
102 /* FS initialization */
103 FS_Init(FS_DMA_NOT_USE);
104 {
105 u32 need_size = FS_GetTableSize();
106 void *p_table = OS_Alloc(need_size);
107 SDK_ASSERT(p_table != NULL);
108 (void)FS_LoadTable(p_table, need_size);
109 }
110
111 { /* Initialize drawing setting */
112 GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
113 MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
114 (void)GX_DisableBankForLCDC();
115 MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);
116 MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);
117 MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);
118 MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);
119 BgInitForPrintStr();
120 GX_SetBankForOBJ(GX_VRAM_OBJ_128_B);
121 GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_2D);
122 GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
123 GXS_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
124 GX_LoadOBJ(sampleCharData, 0, sizeof(sampleCharData));
125 GX_LoadOBJPltt(samplePlttData, 0, sizeof(samplePlttData));
126 MI_DmaFill32(3, oamBak, 0xc0, sizeof(oamBak));
127 }
128
129 /* V-Blank interrupt configuration */
130 (void)OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
131 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
132 (void)OS_EnableIrqMask(OS_IE_FIFO_RECV);
133
134 (void)GX_VBlankIntr(TRUE);
135
136 // RTC initialization
137 RTC_Init();
138
139 /* Start display */
140 GX_DispOn();
141 GXS_DispOn();
142 G2_SetBG0Offset(0, 0);
143 G2S_SetBG0Offset(0, 0);
144
145 /* Initialization of the pointer to the file buffer */
146 InitFileBuffer();
147
148 /* Main loop */
149 prog_state = STATE_MENU;
150 for (;;)
151 {
152 OS_WaitVBlankIntr();
153
154 switch (prog_state)
155 {
156 case STATE_MENU:
157 Menu();
158 break;
159 case STATE_MB_PARENTINIT:
160 ParentInit();
161 break;
162 case STATE_MB_PARENT:
163 ParentMain();
164 break;
165 default:
166 break;
167 }
168 }
169
170 }
171
172 /*
173 * -------------------------------------------------------------
174 * Menu processing functions
175 * -------------------------------------------------------------
176 */
177
178 enum
179 {
180 MENU_SENDSIZE,
181 MENU_MAX_CHILDREN,
182 MENU_AUTO_ACCEPT,
183 MENU_AUTO_SENDFILE,
184 MENU_AUTO_BOOTREQUEST,
185 MENU_NUM
186 };
187
188 /* Send size table */
189 u16 sendsize_table[] = {
190 256, 384, 510,
191 };
192
193 /* Work for the menu */
194 typedef struct
195 {
196 u8 item_no;
197 u8 size_index;
198 u8 channel;
199 u8 auto_accept_flag;
200 u8 auto_send_flag;
201 u8 auto_boot_flag;
202 }
203 MenuData;
204
205 /* Menu */
Menu(void)206 static void Menu(void)
207 {
208 const u16 keyData = ReadKeySetTrigger(PAD_Read());
209 static MenuData menu;
210 enum
211 { DISP_OX = 5, DISP_OY = 5 };
212
213 /* Change cursor number */
214 if (keyData & PAD_KEY_DOWN)
215 {
216 (void)RotateU8(&menu.item_no, 0, MENU_NUM - 1, 1);
217 }
218 else if (keyData & PAD_KEY_UP)
219 {
220 (void)RotateU8(&menu.item_no, 0, MENU_NUM - 1, -1);
221 }
222 else if (keyData & (PAD_BUTTON_A | PAD_BUTTON_START))
223 {
224 prog_state = STATE_MB_PARENTINIT;
225 }
226
227 /* Start display */
228 BgClear();
229 BgPutString((s16)(DISP_OX + 3), (s16)(DISP_OY - 3), WHITE, "Multiboot Sample");
230
231 BgPrintf((s16)(DISP_OX), (s16)(DISP_OY), WHITE,
232 "Send Size(Bytes) [%3d]", GetParentSendSize());
233 BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 1), WHITE, "Children Entry Max [%2d]", GetMaxEntry());
234 BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 2), WHITE,
235 "Auto Accept Entries %s", (menu.auto_accept_flag) ? "[Yes]" : "[No ]");
236 BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 3), WHITE,
237 "Auto Send Start %s", (menu.auto_send_flag) ? "[Yes]" : "[No ]");
238 BgPrintf((s16)(DISP_OX), (s16)(DISP_OY + 4), WHITE,
239 "Auto Boot %s", (menu.auto_boot_flag) ? "[Yes]" : "[No ]");
240 /* Cursor display */
241 BgPutChar((s16)(DISP_OX - 2), (s16)(DISP_OY + menu.item_no), RED, '*');
242 /* Wait for A button */
243 BgPutString(DISP_OX, DISP_OY + 14, WHITE, " Push A or START Button");
244
245 switch (menu.item_no)
246 {
247 /* MP send size configuration */
248 case MENU_SENDSIZE:
249 if (keyData & PAD_KEY_RIGHT)
250 {
251 (void)RotateU8(&menu.size_index, 0, sizeof(sendsize_table) / sizeof(u16) - 1, 1);
252 }
253 else if (keyData & PAD_KEY_LEFT)
254 {
255 (void)RotateU8(&menu.size_index, 0, sizeof(sendsize_table) / sizeof(u16) - 1, -1);
256 }
257 SetParentSendSize(sendsize_table[menu.size_index]);
258 break;
259
260 /* Set the maximum number of child connections */
261 case MENU_MAX_CHILDREN:
262 {
263 u8 entry = GetMaxEntry();
264 if (keyData & PAD_KEY_RIGHT)
265 {
266 (void)RotateU8(&entry, 1, MB_MAX_CHILD, 1);
267 }
268 else if (keyData & PAD_KEY_LEFT)
269 {
270 (void)RotateU8(&entry, 1, MB_MAX_CHILD, -1);
271 }
272 SetMaxEntry(entry);
273 }
274 break;
275
276 /* AUTO ACCEPT configuration */
277 case MENU_AUTO_ACCEPT:
278 if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
279 {
280 menu.auto_accept_flag ^= 1;
281 }
282 break;
283
284 /* AUTO SEND configuration */
285 case MENU_AUTO_SENDFILE:
286 if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
287 {
288 menu.auto_send_flag ^= 1;
289 }
290 break;
291
292 /* AUTO BOOT configuration */
293 case MENU_AUTO_BOOTREQUEST:
294 if (keyData & (PAD_KEY_RIGHT | PAD_KEY_LEFT))
295 {
296 menu.auto_boot_flag ^= 1;
297 }
298 break;
299 default:
300 break;
301 }
302
303 SetAutoOperation(menu.auto_accept_flag, menu.auto_send_flag, menu.auto_boot_flag);
304
305 }
306