1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - demos - multiboot-wfs - parent
3   File:     parent.c
4 
5   Copyright 2005-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-08#$
14   $Rev: 9555 $
15   $Author: kitase_hirotake $
16  *---------------------------------------------------------------------------*/
17 
18 
19 #ifdef SDK_TWL
20 #include    <twl.h>
21 #else
22 #include    <nitro.h>
23 #endif
24 #include <nitro/wm.h>
25 #include <nitro/wbt.h>
26 #include <nitro/fs.h>
27 
28 #include    "wfs.h"
29 #include    "wh.h"
30 
31 #include    "util.h"
32 #include    "common.h"
33 
34 
35 /*---------------------------------------------------------------------------*
36     Internal Variable Definitions
37  *---------------------------------------------------------------------------*/
38 
39 /* Transfer configuration adjustment */
40 static BOOL is_parent_sync = FALSE;
41 static int parent_packet_size = parent_packet_max;
42 
43 
44 /*---------------------------------------------------------------------------*
45     Function Definitions
46  *---------------------------------------------------------------------------*/
47 
48 
49 /*---------------------------------------------------------------------------*
50   Name:         ModeSelect
51 
52   Description:  Process in parent/child selection screen.
53 
54   Arguments:    None.
55 
56   Returns:      None.
57  *---------------------------------------------------------------------------*/
ModeSelect(void)58 void ModeSelect(void)
59 {
60     KeyInfo key[1];
61     int     i;
62     int     file_mode = 0;
63 
64     enum
65     {
66         mode_default, mode_shared, mode_max
67     };
68     static const char *(mode_name[]) =
69     {
70     "use child's own FS", "share parent's FS",};
71 
72     InitFrameLoop(key);
73     while (WH_GetSystemState() == WH_SYSSTATE_IDLE)
74     {
75         WaitForNextFrame(key);
76 
77         PrintString(3, 10, COLOR_WHITE, "Press A to connect as PARENT");
78         PrintString(2, 3, COLOR_GREEN, "<UP & DOWN key>");
79         PrintString(2, 4, COLOR_WHITE, "child's FS mode:");
80         for (i = 0; i < mode_max; ++i)
81         {
82             const BOOL focused = (i == file_mode);
83             PrintString(5, 5 + i, focused ? COLOR_YELLOW : COLOR_WHITE,
84                         "%c%s", focused ? '>' : ' ', mode_name[i]);
85         }
86         PrintString(5, 5 + mode_max, COLOR_GRAY, " (overlay is always own.)");
87 
88         /*
89          * Press Up and Down on the +Control Pad to select one of the following file system modes.
90          *   - File system of the child program for DS Download Play
91          *   - File system of the parent program
92          * The former is considered to be the normal mode, but the latter can be used to efficiently reduce ROM usage for applications that share most data resources between the parent and children.
93          *
94          *
95          *
96          * Note: In either case, however, the overlay information is always provided by the child program.
97          *
98          *   Applications that share overlays must be configured to clone boot.
99          *
100          */
101         if ((key->trg & PAD_KEY_DOWN) && (++file_mode >= mode_max))
102         {
103             file_mode -= mode_max;
104         }
105         if ((key->trg & PAD_KEY_UP) && (--file_mode < 0))
106         {
107             file_mode += mode_max;
108         }
109 
110         /*
111          * Use the A button to start wireless processing as a parent.
112          * In order for the WFS library to run using WM_SetPortCallback, call WFS_Init after WM_Initialize.
113          *
114          */
115         if (key->trg & PAD_BUTTON_A)
116         {
117             /*
118              * Loading a table is only effective for a parent.
119              * For children, the parent's file system table information is held by dynamically-allocated memory in the WFS library, so there is no reason to load this table again.
120              *
121              *
122              */
123             static BOOL table_loaded = FALSE;
124             if (!table_loaded)
125             {
126                 u32     need_size = FS_GetTableSize();
127                 void   *p_table = OS_Alloc(need_size);
128                 SDK_ASSERT(p_table != NULL);
129                 table_loaded = FS_LoadTable(p_table, need_size);
130                 if (!table_loaded && p_table)
131                 {
132                     OS_Free(p_table);
133                 }
134             }
135 
136             (void)WH_ParentConnect(WH_CONNECTMODE_MP_PARENT, 0x0000, 1);
137             /*
138              * The parent starts the WFS library and becomes the file server.
139              * The files and overlays requested by children during DS Download Play are all provided automatically by the parent through the WFS library.
140              *
141              */
142             {
143                 FSFile  file[1];
144                 FS_InitFile(file);
145                 if (!FS_OpenFileEx(file, "data/main.srl", FS_FILEMODE_R))
146                 {
147                     OS_TPanic("failed to open DS-downloaded program file!");
148                 }
149                 WFS_InitParent(port_wbt, StateCallbackForWFS, AllocatorForWFS,
150                                NULL, parent_packet_max, file, (file_mode == mode_shared));
151                 WFS_EnableSync(0);
152                 (void)FS_CloseFile(file);
153             }
154         }
155     }
156 }
157 
158 /*---------------------------------------------------------------------------*
159   Name:         ModeParent
160 
161   Description:  Processing in parent communications screen.
162 
163   Arguments:    None.
164 
165   Returns:      None.
166  *---------------------------------------------------------------------------*/
ModeParent(void)167 void ModeParent(void)
168 {
169     KeyInfo key[1];
170 
171     InitFrameLoop(key);
172     while (WH_GetSystemState() == WH_SYSSTATE_CONNECTED && WH_GetConnectMode() == WH_CONNECTMODE_MP_PARENT)
173     {
174 
175         int     parent_packet_size = WFS_GetPacketSize();
176         BOOL    is_parent_sync = ((WFS_GetSyncBitmap() & ~1) == (WFS_GetCurrentBitmap() & ~1));
177 
178         WaitForNextFrame(key);
179 
180         PrintString(8, 1, COLOR_WHITE, "Parent mode");
181         PrintString(2, 20, COLOR_WHITE, "Press START to disconnect.");
182 
183 
184         {
185             /*
186              * Switch the packet size by pressing Up and Down.
187              *
188              * This simply affects the transfer speed.
189              * Note: When a change is made, it will not be applied to any processes in the middle of accessing data.
190              */
191             int     new_packet_size = parent_packet_size;
192 
193             if (key->trg & PAD_KEY_UP)
194             {
195                 new_packet_size += 2;
196                 if (new_packet_size > parent_packet_max)
197                     new_packet_size = WBT_PACKET_SIZE_MIN + 2;
198             }
199             if (key->trg & PAD_KEY_DOWN)
200             {
201                 new_packet_size -= 2;
202                 if (new_packet_size < WBT_PACKET_SIZE_MIN + 2)
203                     new_packet_size = (parent_packet_max & ~1);
204             }
205             if (parent_packet_size != new_packet_size)
206             {
207                 parent_packet_size = new_packet_size;
208                 WFS_SetPacketSize(parent_packet_size);
209             }
210         }
211 
212         /*
213          * Press the A button to switch to synchronous mode.
214          *
215          * This will cause access to be blocked for the first child if even one of the children specified to be synchronous does not receive the request.
216          *
217          * This setting can make communications more efficient if it is clear that the same combination of files will be requested in the same order.
218          *
219          *
220          * This setting will be reset automatically and a warning message will be sent to debug output when a group of children has conflicting access requests.
221          *
222          */
223         if (key->trg & PAD_BUTTON_A)
224         {
225             is_parent_sync = !is_parent_sync;
226             WFS_EnableSync(is_parent_sync ? WFS_GetCurrentBitmap() : 0);
227         }
228 
229         if (key->trg & PAD_BUTTON_START)
230         {
231             WH_Finalize();
232             while (WH_GetSystemState() != WH_SYSSTATE_IDLE) {}
233         }
234 
235         /* Display the current configuration and connection state */
236         PrintString(3, 4, COLOR_GREEN, "<UP & DOWN key>");
237         PrintString(3, 5, COLOR_WHITE, "parent packet ... %d BYTE", parent_packet_size);
238 
239         PrintString(3, 7, COLOR_GREEN, "<toggle A button>");
240         PrintString(3, 8, COLOR_WHITE, "sync mode     ... %s",
241                     is_parent_sync ? "ENABLE" : "DISABLE");
242 
243         PrintString(3, 10, COLOR_GREEN, "bitmap status");
244         PrintString(5, 11, COLOR_GREEN, "-  not connected");
245         PrintString(5, 12, COLOR_GREEN, "+  idle");
246         PrintString(5, 13, COLOR_GREEN, "*  busy");
247         PrintString(5, 14, COLOR_GREEN, "!  sync-blocking");
248 
249         PrintString(12, 15, COLOR_BLUE, "0123456789ABCDEF");
250         {
251             int     i;
252             const int cur_bitmap = WFS_GetCurrentBitmap();
253             const int busy_bitmap = WFS_GetBusyBitmap();
254             const int sync_bitmap = WFS_GetSyncBitmap();
255             for (i = 0; i < sizeof(u16) * 8; ++i)
256             {
257                 char    c;
258                 const int bit = (1 << i);
259                 if ((bit & busy_bitmap) != 0)
260                     c = '*';
261                 else if ((bit & cur_bitmap) != 0)
262                     c = '+';
263                 else
264                     c = '-';
265                 PrintString(12 + i, 16, COLOR_WHITE, "%c", c);
266                 if ((bit & sync_bitmap) != 0)
267                     PrintString(12 + i, 17, COLOR_WHITE, "!");
268             }
269         }
270     }
271 }
272 
273 
274 /*---------------------------------------------------------------------------*
275   End of file
276  *---------------------------------------------------------------------------*/
277