1 /*---------------------------------------------------------------------------*
2   Project:  RevolutionDWC Demos
3   File:     ./match_menu/src/main.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  *---------------------------------------------------------------------------*/
14 /**
15  *
16  *
17  * Brief comment:    match_menu sample
18  *
19  * This sample combines friend specified/unspecified and server-client matchmaking (including groupID), friend data registration, and other operations.
20  * This includes features to suspend matchmaking and change matchmaking configurations.
21  *
22  * When matchmaking completes, communication is used to exchange positions between oneself and other parties.
23  * One's own position can be moved by pressing Up/Down/Left/Right on the +Control Pad.
24  *
25  */
26 #include "../../common/include/common.h"
27 
28 #ifdef _REVOLUTION
29 #include <stdlib.h>
30 #endif
31 
32 #define USE_RECV_TIMEOUT // Use DWC_SetRecvTimeoutTime
33 
34 #ifdef USE_RECV_TIMEOUT
35 #define RECV_TIMEOUT_TIME (1000*30)
36 #define KEEPALIVE_INTERVAL (RECV_TIMEOUT_TIME/5)
37 #endif
38 
39 //#define USE_RELIABLE  // Perform reliable communications
40 
41 // Constant Declarations
42 //---------------------------------------------------------
43 
44 /// Enumerator that indicates the connection type
45 typedef enum{
46     SCCONNECT_NULL,
47     SCCONNECT_NORMAL,
48     SCCONNECT_GROUPID
49 }SCCONNECT;
50 
51 /// Enumerator that indicates status
52 typedef enum{
53     STATE_INIT,
54     STATE_START,
55     STATE_ONLINE,
56     STATE_MATCHMAKE,
57     STATE_COMMUNICATING,
58     STATE_ERROR
59 }MATCHMAKETESTSTATE;
60 
61 /// Enumerator that indicates the present suspension state
62 typedef enum{
63     SUSPEND_NONE,       // not suspended
64     SUSPEND_YES,        // waiting in a suspended state
65     SUSPEND_NO          // waiting in an unsuspended state
66 }SUSPEND_STATE;
67 
68 /// Current global state
69 typedef enum{
70     GLOBAL_SELECT_NONE = 0,             // delimiter
71     GLOBAL_SELECT_MATCH,                // Matchmaking type selection
72     GLOBAL_SELECT_CONFIG,               // General environment configuration
73     GLOBAL_SELECT_CONFIG_PLAYERS,       // Environment configuration (player count)
74     GLOBAL_SELECT_CONFIG_KEEPALIVE,     // Environment configuration (keep-alive time)
75     GLOBAL_SELECT_CONFIG_NETWORKTYPE,   // Environment configuration (network type)
76     GLOBAL_SELECT_CONFIG_RELIABLE,      // Use reliable communications?
77     GLOBAL_SELECT_CONFIG_ATTEMPT,       // Use attemptCallback?
78     GLOBAL_SELECT_CONFIG_ATTEMPT_TYPE,  // Type configuration when using attemptCallback
79     GLOBAL_SELECT_MAIN,                 // Actual matchmaking process
80     GLOBAL_SELECT_ANYBODY,              // anybody
81     GLOBAL_SELECT_FRIEND,               // friends
82     GLOBAL_SELECT_SERVERCLIENT,         // scsv
83     GLOBAL_SELECT_GROUPID,              // groupID
84     GLOBAL_SELECT_FRIENDDATA,           // frienddata
85     GLOBAL_SELECT_RECONNECT,            // Re-connect with the local host's group ID
86     GLOBAL_SELECT_SCSV_SV,              // scsv server
87     GLOBAL_SELECT_SCSV_CL,              // scsv client
88     GLOBAL_SELECT_GROUPID_INPUT,        // groupID input section
89     GLOBAL_SELECT_FRIENDDATA_ADD,       // Add frienddata
90     GLOBAL_SELECT_FRIENDDATA_ADD_INPUT, // Add frienddata (input)
91     GLOBAL_SELECT_FRIENDDATA_ADD_OK,    // Add frienddata (confirmation)
92     GLOBAL_SELECT_FRIENDDATA_DEL,       // Delete frienddata
93     GLOBAL_SELECT_FRIENDDATA_DEL_INPUT, // Delete frienddata (input)
94     GLOBAL_SELECT_FRIENDDATA_DEL_OK,    // Delete frienddata (confirmation)
95     GLOBAL_SELECT_FRIENDDATA_UPDATE,    // Update frienddata
96     GLOBAL_SELECT_FRIENDDATA_SAVE,      // Save frienddata
97     GLOBAL_SELECT_MATCHMAKE,            // Running matchmaking
98     GLOBAL_SELECT_COMMNICATE,           // Post-matchmaking communications processing section
99     GLOBAL_SELECT_RETURN,               // This is used only for return
100     GLOBAL_SELECT_END                   // delimiter
101 }GLOBAL_STATE;
102 
103 /// Matchmaking type
104 typedef enum{
105     MATCHMAKE_ANYBODY = 0,   // anybody
106     MATCHMAKE_FRIENDS,       // friends
107     MATCHMAKE_SCSV,          // server-client
108     MATCHMAKE_GROUPID,       // for groupID
109     MATCHMAKE_FRIENDDATA,    // frienddata
110     MATCHMAKE_RECONNECT      // Directly connect using the local host's groupID
111 }MATCHMAKE_TYPE;
112 
113 /// Return value from main
114 enum{
115     MAIN_RET_OK = 0,        // Successful completion, or continuation
116     MAIN_RET_RELOGIN,       // Re-login
117     MAIN_RET_EXIT           // Terminate demo
118 };
119 
120 
121 #define MIN_PLAYERS         2           // minimum number of connected players, including oneself
122 #define MAX_PLAYERS         64          // maximum number of connected players including oneself
123 #define FRIENDNUM           32          // Number of friends
124 #define SIZE_SEND_BUFFER    512         // Size of send buffer
125 #define SIZE_RECV_BUFFER    4 * 1024    // Size of receive buffer
126 #define USER_TYPE_MALE 1                // Type used to attempt matchmaking
127 #define USER_TYPE_FEMALE 2              // Type used to attempt matchmaking
128 #define USER_MAX_MALE 2                 // Maximum player count for the attempt type (male)
129 #define USER_MAX_FEMALE 2               // Maximum player count for the attempt type (female)
130 #define APP_CONNECTION_KEEPALIVE_TIME 30000
131 
132 #define MATCHMAKE_FILTER_KEY "DEMONAME"      // Key configured in the matchmaking filter
133 #define MATCHMAKE_FILTER_VAL "match_anybody" // Value configured in the matchmaking filter
134 
135 // Macro that sets the exit code and returns
136 #define SET_EXIT_DEMO(){\
137     GetSequenceInfo()->ret = MAIN_RET_EXIT;\
138     return;\
139 }
140 
141 // Variable Declarations
142 //---------------------------------------------------------
143 
144 // Sequence management structure
145 #define INPUT_BUF_LEN 12
146 #define INPUT_GROUPID_LEN 9         // Group ID input length
147 #define INPUT_FRIENDCODE_LEN 12     // Friend code input length
148 #define INPUT_KEEPALIVE_LEN 6       // Keep-alive input length
149 #define ERROR_BUF_LEN 255
150 typedef struct
151 {
152     // State information
153     u8 globalState;         // Global state
154     u8 globalStateOld;      // Previous global state
155     u8 matchmakeType;        // Matchmaking type
156 
157     // Key information
158     u32 padlast;            // The previous pressed state
159     u32 pad;                // The current pressed state
160     u32 padtrig;            // Keys whose state changed from the last time
161     u32 padpressed;         // Newly-pressed keys
162     u32 padreleased;        // Newly-released keys
163 
164     // Application information
165     BOOL firstTime;         // First time in that sequence?
166     u32 keepAliveTime;      // Keep-alive time
167     DWCTopologyType topologyType;           // Matchmaking network type
168     u8 matchProcessState;   // Matchmaking process state
169     u8 suspendState;        // Suspension state
170     u8 numPlayers;          // Player count
171     u8 playerIndex;         // Player index
172     u8 male;                // Gender data used by connectAttempt
173     u8 userDataNeed;        // Automatic configuration parameters for user data
174     u32 groupID;            // Current group ID
175     BOOL isReliable;        // Use reliable communications?
176     BOOL reconnectGroupID;  // Flag for re-connect using the current group ID
177     BOOL forceStop;         // Flag to forcibly halt
178     BOOL isUserdataEnabled; // Is user data enabled?
179     BOOL useConnectAttempt; // Use connectAttempt?
180     BOOL firstMatchParam;   // Was matchmaking specified when the arguments were?
181     BOOL firstConfig;       // Was the environment configured when arguments were specified?
182 
183     u8 userData[DWC_CONNECTION_USERDATA_LEN+1]; // Data passed from the application during matchmaking
184     u8 inputBuf[INPUT_BUF_LEN];     // Input buffer (group ID and friend data)
185     u8 inputBufLen;                 // Maximum buffer length to use during input
186     u8 inputCursor;                 // Input cursor
187     u64 inputCode;                  // Code that was input
188     u64 friendcode;                 // Local host's own friend code
189 
190     int ret;                        // Return value. The corresponding process will be run when this is set.
191     char errorBuf[ERROR_BUF_LEN];   // Character string shown on exit
192 
193 }
194 SequenceInfo;
195 
196 // Argument array
197 extern char* parameters[];
198 extern u8 parameter_num;
199 
200 static  SequenceInfo sequenceInfo;
201 #define GetSequenceInfo() (&sequenceInfo)   // Similar to inline functions
202 
203 static DWCFriendData            s_friends[FRIENDNUM];   // Friend data
204 
205 /// Structure that contains the player information
206 static struct tagPlayerInfo
207 {
208     DWCUserData     userdata;                       /// User data
209     DWCFriendData   friendlist[FRIEND_LIST_LEN];    /// Friend data
210 }
211 s_playerinfo ATTRIBUTE_ALIGN(32);
212 
213 // Position data structure exchanged through communications.
214 static struct Position
215 {
216     s32  xpos;
217     s32  ypos;
218 }
219 s_position[MAX_PLAYERS];  // Position data saved locally.
220 
221 static u8   s_send_buf[SIZE_SEND_BUFFER];                   // Send buffer
222 static u8   s_recv_buf[MAX_PLAYERS-1][SIZE_RECV_BUFFER];    // Receive buffer
223 
224 // Application-specific data sample to pass to the communication callback
225 typedef struct tagCommunicationData
226 {
227     s32 count;
228 }
229 CommunicationData;
230 CommunicationData s_commData;
231 
232 
233 // Function Prototype
234 //---------------------------------------------------------
235 // Internal main
236 static int inDemoMain(void);
237 
238 // Check arguments
239 static void ArgumentCheck(void);
240 
241 // Global
242 static int GlobalSelectDummy(void);
243 static int GlobalSelectMatch(void);
244 static int GlobalSelectConfig(void);
245 static int GlobalSelectMatchProcess(void);
246 static int GlobalSelectCommunicating(void);
247 static void SetGlobalState(GLOBAL_STATE state);
248 
249 // Related to environment configuration
250 static int GlobalSelectConfig_Players(void);
251 static int GlobalSelectConfig_KeepAlive(void);
252 static int GlobalSelectConfig_NetworkType(void);
253 static int GlobalSelectConfig_Reliable(void);
254 static int GlobalSelectConfig_ConnectAttempt(void);
255 static int GlobalSelectConfig_ConnectAttemptType(void);
256 
257 // Matchmaking-related
258 static int MatchAnybody(void);
259 static int MatchFriends(void);
260 static int MatchServerClient(void);
261 static int MatchFriendData(void);
262 static int MatchGroupID(void);
263 static int MatchReconnectGroupID(void);
264 static BOOL StartMatch(void);
265 
266 // Related to server-client matchmaking
267 static int MatchServerClient_Menu(void);
268 static int MatchServerClient_SetupServer(void);
269 static int MatchServerClient_ConnectToServer(void);
270 static void DispFriendList(void);
271 
272 // Related to group ID matchmaking
273 static int MatchGroupID_Input(void);
274 
275 // Related to friend data
276 static int MatchFriendData_Add(void);
277 static int MatchFriendData_Delete(void);
278 static int MatchFriendData_Update(void);
279 static int MatchFriendData_Save(void);
280 static int MatchFriendData_Add_Input(void);
281 static int MatchFriendData_Add_Confirm(void);
282 static int MatchFriendData_Delete_Input(void);
283 static int MatchFriendData_Delete_Confirm(void);
284 static int GetAvailableFriendListIndex(void);
285 
286 static void FirstUpdateUserData(void);
287 static void UpdateKeyInput(void);
288 static void InitDefaultSequence(void);
289 static void getUserData( DWCUserData * userdata );
290 static void loginCallback(DWCError error, int profileID, void * param);
291 static void matchedCallback(DWCError error, BOOL cancel, void* param );
292 static void closeCallback(DWCError error, BOOL isLocal, BOOL isServer, u8  aid, int index, void* param);
293 static void sendCallback( int size, u8 aid, void* param );
294 static void recvCallback( u8 aid, u8* buffer, int size, void* param );
295 static void suspendCallback(DWCSuspendResult result, BOOL suspend, void* data);
296 static BOOL connectAttemptCallback( u8* data, void* param );
297 static void matchedSCCallback(DWCError error, BOOL cancel, BOOL self, BOOL isServer, int index, void* param );
298 static void newClientCallback(int index, void* param );
299 static void frienddataCallback(DWCError error, BOOL isChanged, void* param);
300 static void userRecvTimeoutCallback(u8 aid, void* param);
301 static int  evalCallback( int index, void* param );
302 
303 
304 // De facto main
305 //
inDemoMain(void)306 static int inDemoMain(void)
307 {
308     int i;
309     SequenceInfo* seq = GetSequenceInfo();
310 
311     {   // test
312         for (i=0; i<parameter_num; ++i)
313         {
314             DWCDemoPrintf("parameter[%d] = %s\n", i, parameters[i]);
315         }
316     }
317 
318     // Initializes the position data.
319     //------------------------------
320     for (i=0; i<MAX_PLAYERS; i++)
321     {
322         s_position[ i ].xpos = 0;
323         s_position[ i ].ypos = 0;
324     }
325 
326     // Initialize the sequence structure
327     InitDefaultSequence();
328 
329     // Process the arguments
330     ArgumentCheck();
331 
332     // Disable argument checks when logging in again
333     parameter_num = 0;
334 
335     // Initial user data acquisition
336     FirstUpdateUserData();
337 
338     // Perform friend match initialization
339     //------------------------------
340     DWC_InitFriendsMatch(   NULL,
341                           &s_playerinfo.userdata,
342                           GAME_PRODUCTID,
343                           GAME_NAME,
344                           GAME_SECRET_KEY,
345                           0,
346                           0,
347                           seq->isUserdataEnabled ? s_playerinfo.friendlist : s_friends,
348                           seq->isUserdataEnabled ? FRIEND_LIST_LEN : FRIENDNUM);
349 
350     // Start login processing
351     //------------------------------
352     DWC_LoginAsync( (u16*)L"name",
353                     NULL,
354                     loginCallback,
355                     NULL );
356 
357 #ifdef USE_RECV_TIMEOUT
358     DWC_SetUserRecvTimeoutCallback(userRecvTimeoutCallback, &s_commData);
359 #endif
360 
361     // Main loop
362     while (1)
363     {
364         int ret = MAIN_RET_OK;
365         SequenceInfo* seq = GetSequenceInfo();
366         int (*func[])(void) =
367             {
368                 GlobalSelectDummy,
369                 GlobalSelectMatch,
370                 GlobalSelectConfig,
371                 GlobalSelectConfig_Players,
372                 GlobalSelectConfig_KeepAlive,
373                 GlobalSelectConfig_NetworkType,
374                 GlobalSelectConfig_Reliable,
375                 GlobalSelectConfig_ConnectAttempt,
376                 GlobalSelectConfig_ConnectAttemptType,
377                 GlobalSelectDummy,
378                 MatchAnybody,
379                 MatchFriends,
380                 MatchServerClient,
381                 MatchGroupID,
382                 MatchFriendData,
383                 MatchReconnectGroupID,
384                 MatchServerClient_SetupServer,
385                 MatchServerClient_ConnectToServer,
386                 MatchGroupID_Input,
387                 MatchFriendData_Add,
388                 MatchFriendData_Add_Input,
389                 MatchFriendData_Add_Confirm,
390                 MatchFriendData_Delete,
391                 MatchFriendData_Delete_Input,
392                 MatchFriendData_Delete_Confirm,
393                 MatchFriendData_Update,
394                 MatchFriendData_Save,
395                 GlobalSelectMatchProcess,
396                 GlobalSelectCommunicating,
397             };
398 
399         seq->firstTime = seq->globalState != seq->globalStateOld;
400         seq->globalStateOld = seq->globalState;
401 
402         // Update key input
403         UpdateKeyInput();
404 
405         // Processing for a forced halt
406         if ( seq->matchProcessState >= STATE_MATCHMAKE )
407         {
408             if ( seq->forceStop )
409             {
410                 if ( seq->padpressed & DWCDEMO_KEY_Z )
411                 {
412                     DWCDemoPrintf("force stop OFF.\n");
413                     seq->forceStop = 0;
414                 }
415                 else
416                     continue;
417             }
418             else
419             {
420                 if ( seq->padpressed & DWCDEMO_KEY_Z )
421                 {
422                     DWCDemoPrintf("force stop ON.\n");
423                     seq->forceStop = 1;
424                 }
425             }
426         }
427 
428         // Matchmaking update
429         DWC_ProcessFriendsMatch();
430 
431         // Error handling
432         if (DWC_GetLastErrorEx(NULL, NULL) != DWC_ERROR_NONE)
433             goto error;
434 
435         switch ( seq->matchProcessState )
436         {
437             // Processing login
438         case STATE_START:
439             // Wait until loginCallback() is invoked.
440             break;
441 
442         case STATE_ONLINE:
443         case STATE_MATCHMAKE:
444         case STATE_COMMUNICATING:
445             // Run each program
446             ret = func[GetSequenceInfo()->globalState]();
447             break;
448 
449         case STATE_ERROR:
450             goto error;
451         }
452 
453         // Processing that depends on the return value
454         if (seq->ret == MAIN_RET_RELOGIN)
455         {
456             DWCDemoPrintf("*\n*Relogin.\n*\n");
457             goto exit;
458         }
459         else if (seq->ret == MAIN_RET_EXIT)
460         {
461             goto exit;
462         }
463 
464         // Display information on the bottom-most line
465         {
466 #define FPS_COUNT_MAX (5)
467             static int cnt = 0;
468             static int frameTimeBuf = 0;
469             static int frameCnt = 0;
470             static int lastTime = 0;
471             static int msecPerFrame = 0;
472             int now = (int)DWCi_Np_TicksToMilliSeconds(DWCi_Np_GetTick());
473 
474             if (DWC_GetServerAID() != DWC_INVALID_AID)
475                 DWCDemoPrintfToFixedRow("GetServerAID=%d,IsServerMyself=%s %02d(%d)", DWC_GetServerAID(), DWC_IsServerMyself() ? "Y" : "N",
476                                         cnt%60, msecPerFrame);
477             else
478                 DWCDemoPrintfToFixedRow("Svr:unknown. %02d(%d)", cnt%60, msecPerFrame);
479 
480             cnt++;
481             frameTimeBuf += now - lastTime;
482             lastTime = now;
483 
484             frameCnt++;
485             if (frameCnt == FPS_COUNT_MAX)
486             {
487                 frameCnt = 0;
488                 msecPerFrame = frameTimeBuf / FPS_COUNT_MAX;
489                 frameTimeBuf = 0;
490             }
491         }
492 
493         // Flush the DWCDemoPrintf output.
494         DWCDemoUpdate();
495 
496         // Display information in the title bar
497 #ifdef _WIN32
498         DWCViewInfoToTitle();
499 #endif
500     }
501 
502 exit:
503     // Quit
504     DWC_ShutdownFriendsMatch();
505 
506     return MAIN_RET_OK;
507 
508 error:
509     // Error processing
510     {
511         int             errorCode;
512         DWCErrorType    errorType;
513 
514         if ( DWC_GetLastErrorEx( &errorCode, &errorType ) != DWC_ERROR_NONE )
515         {
516             DWCDemoPrintf( "DWC_GetLastErrorEx ErrorCode:%d ErrorType:%d\n",
517                            errorCode,
518                            (int)errorType );
519 
520             // Clear the errors.
521             DWC_ClearError();
522         }
523     }
524 
525     // Quit
526     DWC_ShutdownFriendsMatch();
527 
528     return MAIN_RET_OK;
529 }
530 
531 //
532 // The following are each of the callback types
533 //
534 
535 // Callback invoked after data is sent
sendCallback(int size,u8 aid,void * param)536 static void sendCallback( int size, u8 aid, void* param )
537 {
538     CommunicationData* commData = (CommunicationData*)param;
539     commData->count++;  // Add if data was sent
540     DWCDemoPrintf( "Send Callback aid:%d, size:%d mycount:%d\n", aid, size, commData->count );
541 }
542 
543 // Callback invoked when data is received
recvCallback(u8 aid,u8 * buffer,int size,void * param)544 static void recvCallback( u8 aid, u8* buffer, int size, void* param )
545 {
546     //
547     // Save the received data.
548     //
549     // Eight bytes of data were sent in; storing a 4-byte X coordinate and a 4-byte Y coordinate.
550     //
551     if ( size == 8 )
552     {
553         CommunicationData* commData = (CommunicationData*)param;
554         commData->count--;  // Subtract if data was received
555         s_position[ aid ].xpos = (s32)DWCi_LEtoHl(((u32*)buffer)[0]);
556         s_position[ aid ].ypos = (s32)DWCi_LEtoHl(((u32*)buffer)[1]);
557 
558         DWCDemoPrintf( "[aid:%d] x:% 8d y:% 8d mycount:%d\n",
559                        aid,
560                        s_position[ aid ].xpos,
561                        s_position[ aid ].ypos,
562                        commData->count);
563     }
564     else
565     {
566 
567         DWCDemoPrintf( "invalid recv data size\n" );
568 
569     }
570 }
571 
572 // Callback invoked when disconnecting
closeCallback(DWCError error,BOOL isLocal,BOOL isServer,u8 aid,int index,void * param)573 static void closeCallback(DWCError error, BOOL isLocal, BOOL isServer, u8  aid, int index, void* param)
574 {
575     (void)isLocal;
576     (void)isServer;
577     (void)param;
578 
579     DWCDemoPrintf( "Closed Callback err:%d, aid:%d, idx:%d\n",
580                    error, aid, index );
581 
582     if (isLocal)
583     {   // Return the state to ONLINE when the local host is the one that initiated disconnection
584         GetSequenceInfo()->matchProcessState = STATE_ONLINE;    // On our own
585     }
586 }
587 
588 // Friend data registration callback
frienddataCallback(DWCError error,BOOL isChanged,void * param)589 static void frienddataCallback(DWCError error, BOOL isChanged, void* param)
590 {
591     (void)param;
592     (void)isChanged;
593 
594     if ( error == DWC_ERROR_NONE )
595     {   // Successful synchronous processing of friend roster.
596         DWCDemoPrintf( "Update Servers succeeded.\n" );
597     }
598     else
599     {
600         DWCDemoPrintf("Error\n");
601     }
602 }
603 
604 // Friend roster synchronization completion callback
updateServersCallback(DWCError error,BOOL isChanged,void * param)605 static void updateServersCallback(DWCError error, BOOL isChanged, void* param)
606 {
607     SequenceInfo* seq = GetSequenceInfo();
608 
609     (void)param;
610 
611     if (error == DWC_ERROR_NONE)
612     {
613         // Successful synchronous processing of friend roster.
614         // The friend roster must be saved if it has been modified
615         if (isChanged)
616         {
617             // Save to NAND
618             DWCDemoSaveNAND("playerinfo", 0, (u8*)&s_playerinfo, sizeof(s_playerinfo));
619         }
620         seq->matchProcessState = STATE_ONLINE;
621         SetGlobalState(GLOBAL_SELECT_CONFIG);
622     }
623     else
624     {
625         DWCDemoPrintf("Update friend data Failed\n");
626         seq->matchProcessState = STATE_ERROR;
627     }
628 }
629 
630 // Friend roster delete callback
deleteFriendCallback(int deletedIndex,int srcIndex,void * param)631 static void deleteFriendCallback(int deletedIndex, int srcIndex, void* param)
632 {
633     (void)param;
634 
635     DWC_Printf(DWC_REPORTFLAG_TEST, "friend[%d] was deleted (equal friend[%d]).\n", deletedIndex, srcIndex);
636     // Save to NAND
637     DWCDemoSaveNAND("playerinfo", 0, (u8*)&s_playerinfo, sizeof(s_playerinfo));
638 }
639 
640 // Callback invoked during login
loginCallback(DWCError error,int profileID,void * param)641 static void loginCallback(DWCError error, int profileID, void * param)
642 {
643     SequenceInfo* seq = GetSequenceInfo();
644     (void)param;
645 
646     DWCDemoPrintf( "Login callback : %d\n", error );
647 
648     if ( error == DWC_ERROR_NONE )
649     {
650         // When the login is successful
651         DWCDemoPrintf( "Login Success. ProfileID=%d\n", profileID );
652 
653         // Specify the callback function.
654         DWC_SetConnectionClosedCallback( closeCallback, NULL );
655         DWC_SetUserSendCallback( sendCallback, &s_commData );
656         DWC_SetUserRecvCallback( recvCallback, &s_commData );
657 
658         // Get the local host's own friend code here
659         seq->friendcode = DWC_CreateFriendKey( &s_playerinfo.userdata );
660 
661         if (seq->isUserdataEnabled)
662         {
663             // Synchronize the local friend roster with the server friend roster
664             if (!DWC_UpdateServersAsync(    NULL,
665                                          updateServersCallback, NULL,
666                                          NULL, NULL,
667                                          deleteFriendCallback, NULL))
668             {
669                 // Failed to start synchronization
670                 DWCDemoPrintf( "DWC_UpdateServersAsync() call Failed\n" );
671                 seq->matchProcessState = STATE_ERROR;
672                 return;
673             }
674             // Do not configure globalState here; it is easier to see if it is displayed after the synchronization callback.
675             //
676         }
677         else
678         {
679             // First, configure the environment.
680             SetGlobalState(GLOBAL_SELECT_CONFIG);
681             seq->matchProcessState = STATE_ONLINE;
682         }
683     }
684     else
685     {
686         // When the login failed
687         DWCDemoPrintf( "Login Failed\n" );
688         seq->matchProcessState = STATE_ERROR;
689     }
690 }
691 
692 // Callback invoked whenever a client connection is started
newClientCallback(int index,void * param)693 static void newClientCallback(int index, void* param )
694 {
695     (void)param;
696 
697     DWCDemoPrintf( "New Client is connecting(idx %d)...\n", index);
698 }
699 
700 // Callback invoked whenever a client connection is completed
matchedSCCallback(DWCError error,BOOL cancel,BOOL self,BOOL isServer,int index,void * param)701 static void matchedSCCallback(DWCError error, BOOL cancel, BOOL self, BOOL isServer, int index, void* param )
702 {
703     SequenceInfo* seq = GetSequenceInfo();
704     (void)param;
705 
706     DWCDemoPrintf( "Match err:%d, cancel:%d, self:%d isServer:%d index:%d \n", error, cancel, self, isServer, index );
707 
708     if ( error == DWC_ERROR_NONE )
709     {
710         if (cancel == TRUE)
711         {
712             if (self == TRUE && isServer == FALSE)
713             {
714                 seq->matchProcessState = STATE_ONLINE;
715                 SetGlobalState(GLOBAL_SELECT_MATCHMAKE);
716             }
717             return;
718         }
719 
720         {
721             u8* pAidList;
722             int num = DWC_GetAIDList(&pAidList);
723             int i, j;
724             for (i = 0, j = 0; i < num; i++)
725             {
726                 if (pAidList[i] == DWC_GetMyAID())
727                 {
728                     j++;
729                     continue;
730                 }
731                 // Set a receive buffer for AIDs other than the local host's
732                 DWC_SetRecvBuffer( pAidList[i], &s_recv_buf[i-j], SIZE_RECV_BUFFER );
733 #ifdef USE_RECV_TIMEOUT
734                 DWC_SetRecvTimeoutTime(pAidList[i], RECV_TIMEOUT_TIME);
735 #endif
736             }
737             seq->matchProcessState = STATE_COMMUNICATING;
738             SetGlobalState(GLOBAL_SELECT_COMMNICATE);
739         }
740         // Use this timing to get the group ID
741         seq->groupID = DWC_GetGroupID();
742     }
743     else if ( error == DWC_ERROR_NOT_FRIEND_SERVER )
744     {
745         DWCDemoPrintf( "Server not found\n" );
746         seq->matchProcessState = STATE_ERROR;
747         SetGlobalState(GLOBAL_SELECT_MATCHMAKE);
748     }
749     else
750     {
751         DWCDemoPrintf( "Match Error\n" );
752         seq->matchProcessState = STATE_ERROR;
753         SetGlobalState(GLOBAL_SELECT_MATCHMAKE);
754     }
755 }
756 
757 // Evaluation callback
evalCallback(int index,void * param)758 static int evalCallback( int index, void* param )
759 {
760     (void)param;
761 
762     DWCDemoPrintf( "Eval Callback(idx %d)...\n", index);
763 
764     return 1;
765 }
766 
767 // Callback to suspend matchmaking
stopSCCallback(void * param)768 static void stopSCCallback(void* param)
769 {
770     (void)param;
771     DWCDemoPrintf( "stopSCCallback called.\n");
772 }
773 
774 // Callback invoked during an NN check
connectAttemptCallback(u8 * data,void * param)775 static BOOL connectAttemptCallback( u8* data, void* param )
776 {
777     // Check with the condition that there are no more than 2 males and 2 females
778     int numAid;
779     u8* aidList;
780     u8 userData[DWC_CONNECTION_USERDATA_LEN];
781     int i;
782     int maleCount = 0;    // Number of males
783     int femaleCount = 0;  // Number of females
784 
785     (void)param;
786 
787     numAid = DWC_GetAIDList(&aidList);
788     for (i = 0; i < numAid; i++)
789     {
790         DWC_GetConnectionUserData(aidList[i], userData);
791         if (userData[0] == USER_TYPE_MALE)
792             maleCount++;
793         else if (userData[0] == USER_TYPE_FEMALE)
794             femaleCount++;
795     }
796 
797     if (data[0] ==  USER_TYPE_MALE && maleCount < USER_MAX_MALE)
798         return TRUE;
799     else if (data[0] == USER_TYPE_FEMALE && femaleCount < USER_MAX_FEMALE)
800         return TRUE;
801     else
802         return FALSE;
803 }
804 
805 // Callback invoked when suspending is complete
suspendCallback(DWCSuspendResult result,BOOL suspend,void * data)806 static void suspendCallback(DWCSuspendResult result, BOOL suspend, void* data)
807 {
808     (void)data;
809     if (result == DWC_SUSPEND_SUCCESS)
810     {
811         DWCDemoPrintf("<SAMPLE> suspend successfly. suspend is (%s).\n", suspend ? "TRUE" : "FALSE");
812     }
813     else
814     {
815         DWCDemoPrintf("<SAMPLE> suspend error! result is (%d). suspend is (%s).\n", result, suspend ? "TRUE" : "FALSE");
816     }
817 }
818 
819 #ifdef USE_RECV_TIMEOUT
820 // Callback invoked upon a timeout
userRecvTimeoutCallback(u8 aid,void * param)821 static void userRecvTimeoutCallback(u8 aid, void* param)
822 {
823     CommunicationData* commData = (CommunicationData*)param;
824     DWCDemoPrintf("aid (%d) is timeout. mycount is %d\n", aid, commData->count);
825 }
826 #endif
827 
828 // Main
DWCDemoMain()829 void DWCDemoMain()
830 {
831     SequenceInfo* seq = GetSequenceInfo();
832 
833     // This basically just calls the internal main.
834     while (1)
835     {
836         (void)inDemoMain();
837         if (seq->ret != MAIN_RET_RELOGIN)
838             break;
839     }
840 }
841 
842 
843 
844 
845 //
846 // The following sections implement this sample.
847 //
848 
849 static BOOL QueryUserDataUsed(void);
850 static void InputBuffInit(u32 _init);
851 static void InputBuffUpdate(void);
852 static void InputBuffView(void);
853 
854 static BOOL LoadFromNAND(void);
855 
856 static const char* GetMatchTypeString(MATCHMAKE_TYPE _type);
857 static void SetMatchType(MATCHMAKE_TYPE _type);
858 static void SetMatchTypeProcess(MATCHMAKE_TYPE _type);
859 
860 static void SetNetworkType(DWCTopologyType _type);
861 static void SetTopologyTypeProcess(DWCTopologyType _type);
862 static const char* GetTopologyTypeString(u8 _type);
863 
864 static void SetReliableType(BOOL _useReliable);
865 static void SetReliableTypeProcess(BOOL _useReliable);
866 static const char* GetReliableTypeString(BOOL _useReliable);
867 
868 static void SetSequenceError(u8 _error);
869 static void SetSequenceErrorWithString(u8 _error, const char* _msg);
870 
871 // Automatic configuration constants for user data
872 enum
873 {
874     USERDATA_SELECT = 0,    // default
875     USERDATA_NEED,          // Required (error if it could not be read)
876     USERDATA_NONE           // Unnecessary
877 };
878 
879 // Processing when arguments were specified
880 //
ArgumentCheck(void)881 static void ArgumentCheck(void)
882 {
883     // Valid parameter table and constant table
884     enum{
885         MATCH=0, PLAYER, TIME, NETWORK, RELIABLE, CONATMPT, CONATMPT_PARAM, USERDATA, DELIM
886     };
887     char *param_tbl[] = {"-m", "-p", "-t", "-n", "-r", "-c", "-e", "-u"};
888 
889     SequenceInfo* seq = GetSequenceInfo();
890     u8 i;
891 
892     if (parameter_num == 0 || parameter_num == 1)
893         return; // do nothing when there are no parameters (or a single parameter)
894 
895     // Preparation
896     // Parse the arguments
897     for (i=0; i<parameter_num; i+=2)    // Since two are obtained at a time...
898     {
899         char* param = parameters[i];
900         int j;
901 
902         // exit if the next parameter does not exist
903         if ((i + 1) >= parameter_num) break;
904 
905         for (j=0; j<DELIM; ++j)
906         {
907             if (strcmp(param, param_tbl[j]) == 0)
908             {
909                 char* next_param = parameters[i + 1];   // Get the next parameter
910 
911                 switch (j)
912                 {
913                 case MATCH:
914                     switch (next_param[0])
915                     {
916                         // Matchmaking configuration
917                         u8 idx = 0;
918                     case 'a':
919                         idx = 0;
920                         goto MATCH_N;
921                     case 'f':
922                         idx = 1;
923                         goto MATCH_N;
924                     case 's':
925                         idx = 2;
926                         goto MATCH_N;
927                     case 'g':
928                         idx = 3;
929                         goto MATCH_N;
930                     case 'd':
931                         idx = 4;
932 MATCH_N:
933                         {
934                             seq->firstMatchParam = TRUE;
935                             SetMatchType((MATCHMAKE_TYPE)(MATCHMAKE_ANYBODY + idx));
936                             DWCDemoPrintf("set matchmake type is %s.\n", GetMatchTypeString((MATCHMAKE_TYPE)seq->matchmakeType));
937                             seq->firstConfig = TRUE;
938                         }
939                         break;
940 
941                     default:
942                         DWCDemoPrintf("*** set matchmake type(%s) is invalid!!\n", next_param);
943                     }
944                     break;
945 
946                 case PLAYER:    // Player count
947                 {
948                     int player_num = atoi(next_param);
949                     if (player_num > 2 && player_num < 100)
950                     {
951                         seq->numPlayers = (u8)player_num;
952                         seq->firstConfig = TRUE;
953                         DWCDemoPrintf("set num player is %d.\n", seq->numPlayers);
954                     }
955                     else
956                     {
957                         DWCDemoPrintf("*** set player num(%d) is invalid!!\n", player_num);
958                     }
959                 }
960                 break;
961 
962                 case TIME:  // Keep-alive time
963                 {
964                     int keep_time = atoi(next_param);
965                     if (keep_time > 0)
966                     {
967                         seq->keepAliveTime = (u32)keep_time;
968                         seq->firstConfig = TRUE;
969                         DWCDemoPrintf("set keep alive time is %d.\n", seq->keepAliveTime);
970                     }
971                     else
972                     {
973                         DWCDemoPrintf("*** set keep alive time(%d) is invalid!!\n", keep_time);
974                     }
975                 }
976                 break;
977 
978                 case NETWORK:   // Network type
979                     switch (next_param[0])
980                     {
981                         // Matchmaking configuration
982                     case 'f':
983                         seq->topologyType = DWC_TOPOLOGY_TYPE_FULLMESH;
984                         goto NETWORK_N;
985                     case 'h':
986                         seq->topologyType = DWC_TOPOLOGY_TYPE_HYBRID;
987                         goto NETWORK_N;
988                     case 's':
989                         seq->topologyType = DWC_TOPOLOGY_TYPE_STAR;
990 NETWORK_N:
991                         seq->firstConfig = TRUE;
992                         DWCDemoPrintf("set topology type is %s.\n", GetTopologyTypeString(seq->topologyType));
993                         break;
994 
995                     default:
996                         DWCDemoPrintf("*** set topology type(%s) is invalid!!\n", next_param);
997                     }
998                     break;
999 
1000                 case RELIABLE:  // Use reliable communications?
1001                 {
1002                     int ok = 1;
1003                     if (strcmp(next_param, "true") == 0) seq->isReliable = TRUE;
1004                     else if (strcmp(next_param, "false") == 0) seq->isReliable = FALSE;
1005                     else ok = -1;
1006                     if (ok)
1007                     {
1008                         seq->firstConfig = TRUE;
1009                         DWCDemoPrintf("set reliable use param is %s.\n", seq->isReliable ? "TRUE" : "FALSE");
1010                     }
1011                     else
1012                     {
1013                         DWCDemoPrintf("*** set reliable use param(%s) is invalid!!\n", next_param);
1014                     }
1015                 }
1016                 break;
1017 
1018                 case CONATMPT:  // Use connectAttempt?
1019                 {
1020                     int ok = 1;
1021                     if (strcmp(next_param, "true") == 0) seq->useConnectAttempt = TRUE;
1022                     else if (strcmp(next_param, "false") == 0) seq->useConnectAttempt = FALSE;
1023                     else ok = -1;
1024                     if (ok)
1025                     {
1026                         seq->firstConfig = TRUE;
1027                         DWCDemoPrintf("set connectAttempt used is %s.\n", seq->useConnectAttempt ? "TRUE" : "FALSE");
1028                     }
1029                     else
1030                     {
1031                         DWCDemoPrintf("*** set connectAttempt used param(%s) is invalid!!\n", next_param);
1032                     }
1033                 }
1034                 break;
1035 
1036                 case CONATMPT_PARAM:    // Configure the sample's connectAttempt parameters
1037                 {
1038                     int ok = 1;
1039                     if (strcmp(next_param, "male") == 0) seq->male = USER_TYPE_MALE;
1040                     else if (strcmp(next_param, "female") == 0) seq->male = USER_TYPE_FEMALE;
1041                     else ok = -1;
1042                     if (ok)
1043                     {
1044                         seq->firstConfig = TRUE;
1045                         DWCDemoPrintf("set connectAttempt param is %s.\n", seq->male == USER_TYPE_MALE ? "Male" : "Female");
1046                     }
1047                     else
1048                     {
1049                         DWCDemoPrintf("*** set connectAttempt param(%s) is invalid!!\n", next_param);
1050                     }
1051                 }
1052                 break;
1053 
1054                 case USERDATA:
1055                 {
1056                     int ok = 1;
1057                     if (strcmp(next_param, "true") == 0) seq->userDataNeed = USERDATA_NEED;
1058                     else if (strcmp(next_param, "false") == 0) seq->userDataNeed = USERDATA_NONE;
1059                     else ok = -1;
1060                     if (ok)
1061                     {
1062                         DWCDemoPrintf("set userdata need is %s.\n", seq->userDataNeed==USERDATA_NEED ? "TRUE" : "FALSE");
1063                     }
1064                     else
1065                     {
1066                         DWCDemoPrintf("*** set userdata need param(%s) is invalid!!\n", next_param);
1067                     }
1068                 }
1069                 break;
1070 
1071                 default:
1072                     DWCDemoPrintf("*** invlalid argument param: %s.\n", next_param);
1073                     break;
1074                 }
1075 
1076                 break;
1077             }
1078         }
1079         if ( j == DELIM)
1080         {
1081             DWCDemoPrintf("*** invlalid first argument param: %s\n", param);
1082         }
1083     }
1084 
1085 }
1086 
1087 // Initial user data acquisition
FirstUpdateUserData(void)1088 static void FirstUpdateUserData(void)
1089 {
1090     BOOL bRet = FALSE;
1091     SequenceInfo* seq = GetSequenceInfo();
1092 
1093     if (seq->userDataNeed == USERDATA_NONE)
1094     {   // User data is not read in this case, so create it by default
1095         getUserData( &s_playerinfo.userdata );
1096         seq->isUserdataEnabled = FALSE;
1097     }
1098     else
1099     {
1100         if ((bRet = LoadFromNAND()) == TRUE)
1101         {   // If user data was successfully acquired, ask if it should be used.
1102             // Create new data when the user data is not used.
1103             // (in that case, friends and sc/sv cannot be selected)
1104             if (seq->userDataNeed != USERDATA_NEED) // Use it unchanged if USERDATA_NEED has been specified.
1105                 bRet = QueryUserDataUsed();
1106         }
1107         if (bRet == FALSE)
1108         {   // On failure, create default data (can only connect to "anybody" or using groupID).
1109             if (seq->userDataNeed == USERDATA_NEED)
1110             {   // This will result in an error if user data is required.
1111                 SET_EXIT_DEMO();
1112             }
1113             getUserData( &s_playerinfo.userdata );
1114         }
1115     }
1116 
1117     // If friends or sc/sv was specified when userData is either not used or could not be read, revert settings to their original values here because they cannot be used.
1118     //
1119     if (seq->isUserdataEnabled == FALSE &&
1120             (seq->matchmakeType == MATCHMAKE_FRIENDS || seq->matchmakeType == MATCHMAKE_SCSV))
1121     {
1122         DWCDemoPrintf("*** cannot select %s with no userData!! reset.\n", GetMatchTypeString((MATCHMAKE_TYPE)seq->matchmakeType));
1123         SetMatchType(MATCHMAKE_ANYBODY);
1124         seq->firstMatchParam = FALSE;
1125         seq->firstConfig = FALSE;
1126     }
1127 }
1128 
1129 // Check if user data can be used
1130 //
QueryUserDataUsed(void)1131 static BOOL QueryUserDataUsed(void)
1132 {
1133     BOOL first = TRUE;
1134     SequenceInfo* seq = GetSequenceInfo();
1135 
1136     while (1)
1137     {
1138         // Update key input
1139         UpdateKeyInput();
1140 
1141         if (first)
1142         {
1143             DWCDemoPrintf("\n");
1144             DWCDemoPrintf("--------------------------------\n");
1145             DWCDemoPrintf("-    Is the user data used?    -\n");
1146             DWCDemoPrintf("--------------------------------\n");
1147             DWCDemoPrintf("A: used\n");
1148             DWCDemoPrintf("B: not used\n");
1149             DWCDemoPrintf("\n");
1150             DWCDemoPrintf("Select: ");
1151 
1152             first = FALSE;
1153         }
1154         if (seq->padpressed & DWCDEMO_KEY_A)
1155         {   // Go straight on to exit
1156             ;
1157         }
1158         else if (seq->padpressed & DWCDEMO_KEY_B)
1159         {   // Data is not used, so also drop the flags to create new data and to use it
1160             seq->isUserdataEnabled = FALSE;
1161         }
1162         if ( seq->padpressed & (DWCDEMO_KEY_A | DWCDEMO_KEY_B))
1163         {
1164             DWCDemoPrintf("\n*\n* data %s\n*\n\n", seq->isUserdataEnabled ? "used" : "not used");
1165             return seq->isUserdataEnabled;
1166         }
1167 
1168         DWCDemoUpdate();
1169     }
1170 
1171     return FALSE;   // This cannot be reached, but...
1172 }
1173 
1174 // Load user data
LoadFromNAND(void)1175 static BOOL LoadFromNAND(void)
1176 {
1177     SequenceInfo* seq = GetSequenceInfo();
1178 
1179     seq->isUserdataEnabled = FALSE;
1180 
1181     // Load from NAND
1182     //
1183     DWCDemoPrintf("Loading from NAND...\n");
1184 
1185     DWCDemoLoadNAND(    "playerinfo",
1186                         0,
1187                         (u8*)&s_playerinfo,
1188                         sizeof( s_playerinfo ) );
1189 
1190     // Check if user data is valid
1191     //
1192     if ( DWC_CheckUserData( &s_playerinfo.userdata ) )
1193     {
1194 
1195         // It was valid, so output the user data and return TRUE
1196         DWC_ReportUserData( &s_playerinfo.userdata );
1197         seq->isUserdataEnabled = TRUE;
1198         return TRUE;
1199 
1200     }
1201 
1202     // If valid user data had not been saved
1203     //
1204     seq->isUserdataEnabled = FALSE;
1205     DWCDemoPrintf( "No valid userdata found.\n" );
1206 
1207     return FALSE;
1208 }
1209 
1210 // Dummy function
1211 //
GlobalSelectDummy(void)1212 static int GlobalSelectDummy(void)
1213 {
1214     SequenceInfo* seq = GetSequenceInfo();
1215     if (seq->firstTime)
1216     {
1217         DWCDemoPrintf("this is dummy sequence.\n press B to return menu.\n");
1218     }
1219     if (seq->padpressed & DWCDEMO_KEY_B)
1220     {
1221         SetGlobalState(GLOBAL_SELECT_CONFIG);
1222     }
1223 
1224     return MAIN_RET_OK;
1225 }
1226 
1227 // Matchmaking selection
1228 //
GlobalSelectMatch(void)1229 static int GlobalSelectMatch(void)
1230 {
1231     SequenceInfo* seq = GetSequenceInfo();
1232     int ret = MAIN_RET_OK;
1233 
1234     // If configured to automatically jump, go there.
1235     if (seq->firstMatchParam)
1236     {
1237         SetMatchTypeProcess((MATCHMAKE_TYPE)seq->matchmakeType);
1238         seq->firstMatchParam = FALSE;
1239         return ret;
1240     }
1241 
1242     if (seq->firstTime)
1243     {
1244         DWCDemoPrintf("\n");
1245         DWCDemoPrintf("--------------------------------\n");
1246         DWCDemoPrintf("-         Match Menu        -\n");
1247         DWCDemoPrintf("--------------------------------\n");
1248         DWCDemoPrintf("A:  %s\n", GetMatchTypeString(MATCHMAKE_ANYBODY));
1249         if (seq->isUserdataEnabled)
1250         {
1251             DWCDemoPrintf("X:  %s\n", GetMatchTypeString(MATCHMAKE_FRIENDS));
1252             DWCDemoPrintf("Y:  %s\n", GetMatchTypeString(MATCHMAKE_SCSV));
1253         }
1254         DWCDemoPrintf("Z:  %s\n", GetMatchTypeString(MATCHMAKE_GROUPID));
1255         DWCDemoPrintf("L:  %s\n", GetMatchTypeString(MATCHMAKE_FRIENDDATA));
1256         DWCDemoPrintf("R:  it logs it in again\n");
1257         if (seq->groupID)
1258             DWCDemoPrintf("START:  groupID reconnect(%u)\n", seq->groupID);
1259         if (seq->isUserdataEnabled)
1260             DWCDemoPrintf("UP: view friends info\n");
1261         DWCDemoPrintf("B:  back to before sequence\n");
1262         DWCDemoPrintf("\n");
1263     }
1264     if ( seq->padpressed & DWCDEMO_KEY_A )
1265     {
1266         SetMatchTypeProcess(MATCHMAKE_ANYBODY);
1267     }
1268     if (seq->isUserdataEnabled)
1269     {
1270         if ( seq->padpressed & DWCDEMO_KEY_X )
1271         {
1272             SetMatchTypeProcess(MATCHMAKE_FRIENDS);
1273         }
1274         else if ( seq->padpressed & DWCDEMO_KEY_Y )
1275         {
1276             SetMatchTypeProcess(MATCHMAKE_SCSV);
1277         }
1278         if ( seq->padpressed & DWCDEMO_KEY_UP)
1279         {
1280             DispFriendList();
1281             seq->firstTime = TRUE;
1282             seq->globalStateOld = GLOBAL_SELECT_NONE;
1283         }
1284     }
1285     if ( seq->padpressed & DWCDEMO_KEY_Z )
1286     {
1287         SetMatchTypeProcess(MATCHMAKE_GROUPID);
1288     }
1289     else if ( seq->padpressed & DWCDEMO_KEY_L )
1290     {
1291         SetMatchTypeProcess(MATCHMAKE_FRIENDDATA);
1292     }
1293     else if ( seq->padpressed & DWCDEMO_KEY_R )
1294     {
1295         SetSequenceError(MAIN_RET_RELOGIN);
1296     }
1297     else if ( seq->padpressed & DWCDEMO_KEY_B )
1298     {
1299         SetGlobalState(GLOBAL_SELECT_CONFIG);
1300     }
1301     if (seq->groupID)
1302     {
1303         if ( seq->padpressed & DWCDEMO_KEY_START )
1304         {
1305             SetMatchTypeProcess(MATCHMAKE_RECONNECT);
1306         }
1307     }
1308 
1309     return ret;
1310 }
1311 
1312 // Matchmaking environment configuration
1313 //
GlobalSelectConfig(void)1314 static int GlobalSelectConfig(void)
1315 {
1316     SequenceInfo* seq = GetSequenceInfo();
1317     int ret = MAIN_RET_OK;
1318 
1319     // If configured to automatically jump, go there.
1320     if (seq->firstConfig)
1321     {
1322         SetGlobalState(GLOBAL_SELECT_MATCH);
1323         seq->firstConfig = FALSE;
1324         return ret;
1325     }
1326 
1327     if (seq->firstTime)
1328     {
1329         DWCDemoPrintf("\n");
1330         DWCDemoPrintf("--------------------------------\n");
1331         DWCDemoPrintf("-       Set configuration      -\n");
1332         DWCDemoPrintf("--------------------------------\n");
1333         DWCDemoPrintf("A:  set max players(%d)\n", seq->numPlayers);
1334         DWCDemoPrintf("X:  set keep alivetime(%u)\n", seq->keepAliveTime);
1335         DWCDemoPrintf("Y:  set topology type(%s)\n", GetTopologyTypeString(seq->topologyType));
1336         DWCDemoPrintf("Z:  set Reliable Use(%d)\n", seq->isReliable);
1337         DWCDemoPrintf("START:  go to matchmake select\n");
1338         DWCDemoPrintf("L:  sample connect attempt settings\n");
1339         DWCDemoPrintf("    attempt(%s) select(%s)\n", seq->useConnectAttempt ? "TRUE" : "FALSE",
1340                       seq->male == USER_TYPE_MALE ? "Male" : "Female");
1341         if (seq->isUserdataEnabled)
1342             DWCDemoPrintf("UP: view friends info\n");
1343         DWCDemoPrintf("R:  it logs it in again\n");
1344         DWCDemoPrintf("B:  exit demo\n");
1345         DWCDemoPrintf("\n");
1346     }
1347     if ( seq->padpressed & DWCDEMO_KEY_A )
1348     {
1349         SetGlobalState(GLOBAL_SELECT_CONFIG_PLAYERS);
1350     }
1351     else if ( seq->padpressed & DWCDEMO_KEY_X )
1352     {
1353         SetGlobalState(GLOBAL_SELECT_CONFIG_KEEPALIVE);
1354     }
1355     else if ( seq->padpressed & DWCDEMO_KEY_Y )
1356     {
1357         SetGlobalState(GLOBAL_SELECT_CONFIG_NETWORKTYPE);
1358     }
1359     else if ( seq->padpressed & DWCDEMO_KEY_Z )
1360     {
1361         SetGlobalState(GLOBAL_SELECT_CONFIG_RELIABLE);
1362     }
1363     else if ( seq->padpressed & DWCDEMO_KEY_START )
1364     {
1365         SetGlobalState(GLOBAL_SELECT_MATCH);
1366     }
1367     else if ( seq->padpressed & DWCDEMO_KEY_L )
1368     {
1369         SetGlobalState(GLOBAL_SELECT_CONFIG_ATTEMPT);
1370     }
1371     else if ( seq->padpressed & DWCDEMO_KEY_R )
1372     {
1373         SetSequenceError(MAIN_RET_RELOGIN);
1374     }
1375     else if ( seq->padpressed & DWCDEMO_KEY_B )
1376     {
1377         SetSequenceError(MAIN_RET_EXIT);
1378     }
1379     if (seq->isUserdataEnabled)
1380     {
1381         if ( seq->padpressed & DWCDEMO_KEY_UP)
1382         {
1383             DispFriendList();
1384             seq->firstTime = TRUE;
1385             seq->globalStateOld = GLOBAL_SELECT_NONE;
1386         }
1387     }
1388 
1389     return ret;
1390 }
1391 
1392 // Processing while matchmaking
1393 //
GlobalSelectMatchProcess(void)1394 static int GlobalSelectMatchProcess(void)
1395 {
1396     SequenceInfo* seq = GetSequenceInfo();
1397 
1398     // Cancel and return to the menu
1399     if (seq->padpressed & DWCDEMO_KEY_B)
1400     {
1401         if (DWC_CancelMatch() == TRUE)
1402         {
1403             DWCDemoPrintf("DWC_CancelMatch() called.\n");
1404         }
1405         else
1406         {
1407             DWCDemoPrintf("cannot call DWC_CancelMatch() now.\n");
1408         }
1409         seq->firstTime = TRUE;
1410         SetGlobalState(GLOBAL_SELECT_RETURN);
1411     }
1412 
1413     return MAIN_RET_OK;
1414 }
1415 
1416 // Communication processing after matchmaking has finished
1417 //
GlobalSelectCommunicating(void)1418 static int GlobalSelectCommunicating(void)
1419 {
1420     u8 me;
1421     struct Position sendPos;
1422     SequenceInfo* seq = GetSequenceInfo();
1423 
1424     // Get one's own AID.
1425     me = DWC_GetMyAID();
1426 
1427     if ( seq->pad & DWCDEMO_KEY_UP )      s_position[ me ].ypos--;
1428     if ( seq->pad & DWCDEMO_KEY_DOWN )    s_position[ me ].ypos++;
1429     if ( seq->pad & DWCDEMO_KEY_LEFT )    s_position[ me ].xpos--;
1430     if ( seq->pad & DWCDEMO_KEY_RIGHT )   s_position[ me ].xpos++;
1431 
1432     {
1433         // Forcibly send data at intervals shorter than the receive timeout interval.
1434         static int lastKeepAliveSent = 0;
1435         int now = (int)DWCi_Np_TicksToMilliSeconds(DWCi_Np_GetTick());
1436         if (lastKeepAliveSent == 0 || (now - lastKeepAliveSent) > ((int)seq->keepAliveTime/3))
1437         {
1438             seq->pad |= DWCDEMO_KEY_UP;
1439             lastKeepAliveSent = now;
1440         }
1441     }
1442     // Send a new position to the communication partner when there is input.
1443     if ( seq->pad & ( DWCDEMO_KEY_UP | DWCDEMO_KEY_DOWN |
1444                       DWCDEMO_KEY_LEFT | DWCDEMO_KEY_RIGHT ) )
1445     {
1446 
1447         sendPos.xpos = (s32)DWCi_HtoLEl((u32)s_position[ me ].xpos);
1448         sendPos.ypos = (s32)DWCi_HtoLEl((u32)s_position[ me ].ypos);
1449         // Send one's own position to all other parties.
1450         if (seq->isReliable)
1451         {
1452             DWC_SendReliableBitmap( DWC_GetAIDBitmap(),
1453                                     (const void*)&sendPos,
1454                                     sizeof( s32 ) * 2 );
1455         }
1456         else
1457         {
1458             DWC_SendUnreliableBitmap( DWC_GetAIDBitmap(),
1459                                       (const void*)&sendPos,
1460                                       sizeof( s32 ) * 2 );
1461         }
1462     }
1463 
1464     // Disconnect communications and return to ONLINE if the cancel button is pressed.
1465     //
1466     if ( seq->pad & DWCDEMO_KEY_B )
1467     {
1468         DWC_CloseAllConnectionsHard();
1469         SetGlobalState(GLOBAL_SELECT_RETURN);
1470         if (DWC_GetNumConnectionHost() == 0)
1471         {   // Return ONLINE if this was called while the local host is alone.
1472             seq->matchProcessState = STATE_ONLINE;
1473         }
1474         return MAIN_RET_OK;
1475     }
1476 
1477     // Suspend matchmaking with Y
1478     if ( seq->pad & DWCDEMO_KEY_Y )
1479     {
1480         // Temporarily suspend
1481         DWC_RequestSuspendMatchAsync(TRUE, suspendCallback, NULL);
1482     }
1483     else if ( seq->pad & DWCDEMO_KEY_X )
1484     {
1485         // Begin accepting again
1486         DWC_RequestSuspendMatchAsync(FALSE, suspendCallback, NULL);
1487     }
1488 
1489     return MAIN_RET_OK;
1490 }
1491 
1492 // Processing for peer matchmaking with friend unspecified
1493 //
MatchAnybody(void)1494 static int MatchAnybody(void)
1495 {
1496     SequenceInfo* seq = GetSequenceInfo();
1497     int ret = MAIN_RET_OK;
1498     if (seq->firstTime)
1499     {
1500         DWCDemoPrintf("\n");
1501         DWCDemoPrintf("--------------------------------\n");
1502         DWCDemoPrintf("-       Anybody matchmake       -\n");
1503         DWCDemoPrintf("--------------------------------\n");
1504         DWCDemoPrintf("\n");
1505         seq->firstTime = FALSE;
1506     }
1507 
1508     StartMatch();
1509 
1510     return ret;
1511 }
1512 
1513 // Processing for peer matchmaking with friend specified
1514 //
MatchFriends(void)1515 static int MatchFriends(void)
1516 {
1517     SequenceInfo* seq = GetSequenceInfo();
1518     int ret = MAIN_RET_OK;
1519     if (seq->firstTime)
1520     {
1521         DWCDemoPrintf("\n");
1522         DWCDemoPrintf("--------------------------------\n");
1523         DWCDemoPrintf("-        Friend matchmake       -\n");
1524         DWCDemoPrintf("--------------------------------\n");
1525         DWCDemoPrintf("\n");
1526         seq->firstTime = FALSE;
1527     }
1528 
1529     StartMatch();
1530 
1531     return ret;
1532 }
1533 
1534 // Processing for server-client matchmaking
1535 //
MatchServerClient(void)1536 static int MatchServerClient(void)
1537 {
1538     SequenceInfo* seq = GetSequenceInfo();
1539     int ret = MAIN_RET_OK;
1540     if (seq->firstTime)
1541     {
1542         DWCDemoPrintf("\n");
1543         DWCDemoPrintf("--------------------------------\n");
1544         DWCDemoPrintf("-     Server Client matchmake   -\n");
1545         DWCDemoPrintf("--------------------------------\n");
1546         DWCDemoPrintf("A:  Setup server\n");
1547         DWCDemoPrintf("X:  Connect to server\n");
1548         DWCDemoPrintf("B:  Back to before sequence\n");
1549         DWCDemoPrintf("\n");
1550     }
1551     if (seq->padpressed & DWCDEMO_KEY_A)
1552     {
1553         SetGlobalState(GLOBAL_SELECT_SCSV_SV);
1554     }
1555     else if (seq->padpressed & DWCDEMO_KEY_X)
1556     {
1557         SetGlobalState(GLOBAL_SELECT_SCSV_CL);
1558     }
1559     else if (seq->padpressed & DWCDEMO_KEY_B)
1560     {   // Return to matchmaking selection
1561         SetGlobalState(GLOBAL_SELECT_MATCH);
1562     }
1563 
1564     return ret;
1565 }
1566 // Create an SC/SV server
MatchServerClient_SetupServer(void)1567 static int MatchServerClient_SetupServer(void)
1568 {
1569     int ret = MAIN_RET_OK;
1570 
1571     DWCDemoPrintf("\n");
1572     DWCDemoPrintf("--------------------------------\n");
1573     DWCDemoPrintf("-        Setup server!!        -\n");
1574     DWCDemoPrintf("--------------------------------\n");
1575     DWCDemoPrintf("\n");
1576     DWCDemoPrintf("Waiting for clients...\n");
1577     DWCDemoPrintf("\n");
1578     StartMatch();
1579 
1580     return ret;
1581 }
1582 // Connect to a server as an SC/SV client
MatchServerClient_ConnectToServer(void)1583 static int MatchServerClient_ConnectToServer(void)
1584 {
1585     int ret = MAIN_RET_OK;
1586     SequenceInfo* seq = GetSequenceInfo();
1587 
1588     if (seq->firstTime)
1589     {
1590         DWCDemoPrintf("\n");
1591         DWCDemoPrintf("--------------------------------\n");
1592         DWCDemoPrintf("-      Connect to server       -\n");
1593         DWCDemoPrintf("--------------------------------\n");
1594         DispFriendList();
1595         DWCDemoPrintf("Arrow: select index\n");
1596         DWCDemoPrintf("A: OK\n");
1597         DWCDemoPrintf("B: Back to menu\n");
1598         DWCDemoPrintf("\n");
1599     }
1600     // Key input
1601     if (seq->padpressed & DWCDEMO_KEY_UP)
1602     {
1603         ++seq->playerIndex;
1604     }
1605     else if (seq->padpressed & DWCDEMO_KEY_DOWN && seq->playerIndex != 0)
1606     {
1607         --seq->playerIndex;
1608     }
1609     else if (seq->padpressed & DWCDEMO_KEY_A)
1610     {   // Connect now with this
1611         StartMatch();
1612     }
1613     else if (seq->padpressed & DWCDEMO_KEY_B)
1614     {   // Return to the menu
1615         SetGlobalState(GLOBAL_SELECT_SERVERCLIENT);
1616     }
1617 
1618     if (seq->firstTime || seq->padpressed & (DWCDEMO_KEY_UP | DWCDEMO_KEY_DOWN | DWCDEMO_KEY_A))
1619     {
1620         DWCDemoPrintf("server index: %d(%u:%s)\n", seq->playerIndex,
1621                       s_playerinfo.friendlist[seq->playerIndex].gs_profile_id.id,
1622                       DWCDemoGetFriendStatusString(&s_playerinfo.friendlist[seq->playerIndex]));
1623     }
1624 
1625     return ret;
1626 }
1627 
1628 
1629 // Frienddata processing
1630 //
MatchFriendData(void)1631 static int MatchFriendData(void)
1632 {
1633     int ret = MAIN_RET_OK;
1634     SequenceInfo* seq = GetSequenceInfo();
1635 
1636     if (seq->firstTime)
1637     {
1638         DWCDemoPrintf("\n");
1639         DWCDemoPrintf("--------------------------------\n");
1640         DWCDemoPrintf("- DWC Friend Data Demo         -\n");
1641         DWCDemoPrintf("--------------------------------\n");
1642         DWCDemoPrintf("A:  add friend\n");
1643         DWCDemoPrintf("X:  del friend\n");
1644         DWCDemoPrintf("Y:  update server\n");
1645         DWCDemoPrintf("Z:  save user data\n");
1646         DWCDemoPrintf("UP: view friends info\n");
1647         DWCDemoPrintf("B:  back to before sequence\n");
1648         DWCDemoPrintf("My friend code is : %012llu\n", seq->friendcode );
1649     }
1650     else if (seq->padpressed & DWCDEMO_KEY_A)
1651     {
1652         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_ADD);
1653     }
1654     else if (seq->padpressed & DWCDEMO_KEY_X)
1655     {
1656         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_DEL);
1657     }
1658     else if (seq->padpressed & DWCDEMO_KEY_Y)
1659     {
1660         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_UPDATE);
1661     }
1662     else if (seq->padpressed & DWCDEMO_KEY_Z)
1663     {
1664         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_SAVE);
1665     }
1666     else if ( seq->padpressed & DWCDEMO_KEY_UP)
1667     {
1668         DispFriendList();
1669         seq->firstTime = TRUE;
1670         seq->globalStateOld = GLOBAL_SELECT_NONE;
1671     }
1672     else if (seq->padpressed & DWCDEMO_KEY_B)
1673     {
1674         SetGlobalState(GLOBAL_SELECT_MATCH);
1675     }
1676 
1677     return MAIN_RET_OK;
1678 }
MatchFriendData_Add(void)1679 static int MatchFriendData_Add(void)
1680 {
1681     int ret = MAIN_RET_OK;
1682     SequenceInfo* seq = GetSequenceInfo();
1683 
1684     DWCDemoPrintf("Please the input friend code.\n");
1685     DWCDemoPrintf("Arrow: input number\n");
1686     DWCDemoPrintf("A: OK\n");
1687     DWCDemoPrintf("B: Cancel\n");
1688     InputBuffInit(0);
1689     SetGlobalState(GLOBAL_SELECT_FRIENDDATA_ADD_INPUT);
1690 
1691     return ret;
1692 }
MatchFriendData_Add_Input(void)1693 static int MatchFriendData_Add_Input(void)
1694 {
1695     int ret = MAIN_RET_OK;
1696     SequenceInfo* seq = GetSequenceInfo();
1697 
1698     // Get input
1699     InputBuffUpdate();
1700 
1701     // Check key input
1702     if (seq->padpressed & DWCDEMO_KEY_A)
1703     {   // Add frienddata
1704         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_ADD_OK);
1705     }
1706     else if (seq->padpressed & DWCDEMO_KEY_B)
1707     {   // Return to the menu
1708         SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1709     }
1710 
1711     return ret;
1712 }
MatchFriendData_Add_Confirm(void)1713 static int MatchFriendData_Add_Confirm(void)
1714 {
1715     SequenceInfo* seq = GetSequenceInfo();
1716 
1717     if ( DWC_CheckFriendKey( &s_playerinfo.userdata,
1718                              seq->inputCode ) )
1719     {
1720         int index;
1721         index = GetAvailableFriendListIndex();
1722         if ( index != -1 )
1723         {
1724             if ( DWC_CanChangeFriendList() )
1725             {
1726                 if (DWC_CreateFriendKey(&s_playerinfo.userdata) == seq->inputCode)
1727                 {
1728                     DWCDemoPrintf( "friend code is me.(%012llu)\n", seq->inputCode);
1729                 }
1730                 else
1731                 {
1732                     DWC_CreateFriendKeyToken(&s_playerinfo.friendlist[index], seq->inputCode);
1733                 }
1734             }
1735             else
1736             {
1737                 // If the friend roster is in an uneditable state, return to the input phase
1738                 DWCDemoPrintf( "The friends list is locked now. Retry later.\n" );
1739                 SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1740                 return MAIN_RET_OK;
1741             }
1742         }
1743         else
1744         {
1745             DWCDemoPrintf( "Too many friends!\n" );
1746         }
1747     }
1748     else
1749     {
1750         DWCDemoPrintf( "invalid friend code.\n" );
1751     }
1752 
1753     DWCDemoPrintf( "this friend code was registerd. please update server.\n" );
1754 
1755     SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1756     return MAIN_RET_OK;
1757 }
MatchFriendData_Delete(void)1758 static int MatchFriendData_Delete(void)
1759 {
1760     int ret = MAIN_RET_OK;
1761     SequenceInfo* seq = GetSequenceInfo();
1762 
1763     if (seq->firstTime)
1764     {
1765         DispFriendList();
1766         DWCDemoPrintf("Input index to delete.\n");
1767         DWCDemoPrintf("Arrow: input number\n");
1768         DWCDemoPrintf("A: OK\n");
1769         DWCDemoPrintf("B: Cancel\n");
1770         DWCDemoPrintf( "index=%d(%u)\n", seq->playerIndex, s_playerinfo.friendlist[seq->playerIndex].gs_profile_id.id );
1771     }
1772 
1773     // Key input
1774     if (seq->padpressed & DWCDEMO_KEY_UP)
1775     {
1776         seq->playerIndex = (u8)((seq->playerIndex + 1) % FRIEND_LIST_LEN);
1777     }
1778     else if (seq->padpressed & DWCDEMO_KEY_DOWN)
1779     {
1780         seq->playerIndex = (u8)(seq->playerIndex == 0 ? (FRIEND_LIST_LEN-1) : (seq->playerIndex - 1));
1781     }
1782     else if (seq->padpressed & DWCDEMO_KEY_A)
1783     {
1784         DWCDemoPrintf( "delete #%d(%u)\n", seq->playerIndex,
1785                        s_playerinfo.friendlist[seq->playerIndex].gs_profile_id.id);
1786         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_DEL_OK);
1787     }
1788     else if (seq->padpressed & DWCDEMO_KEY_B)
1789     {
1790         DWCDemoPrintf( "canceled\n" );
1791         SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1792     }
1793     else
1794         return ret;
1795 
1796     DWCDemoPrintf( "index=%d(%u)\n", seq->playerIndex, s_playerinfo.friendlist[seq->playerIndex].gs_profile_id.id );
1797 
1798     //SetGlobalState(GLOBAL_SELECT_FRIENDDATA_DEL_INPUT);
1799 
1800     return ret;
1801 }
MatchFriendData_Delete_Input(void)1802 static int MatchFriendData_Delete_Input(void)
1803 {
1804     int ret = MAIN_RET_OK;
1805     SequenceInfo* seq = GetSequenceInfo();
1806 
1807     return ret;
1808 }
MatchFriendData_Delete_Confirm(void)1809 static int MatchFriendData_Delete_Confirm(void)
1810 {
1811     int ret = MAIN_RET_OK;
1812     SequenceInfo* seq = GetSequenceInfo();
1813 
1814     if ( DWC_CanChangeFriendList() )
1815     {
1816         DWC_DeleteBuddyFriendData( &s_playerinfo.friendlist[seq->playerIndex] );
1817         DWCDemoPrintf( "delete friend data(%d).\n", seq->playerIndex );
1818     }
1819     else
1820     {
1821         // If the friend roster is in an uneditable state, return to the input phase
1822         DWCDemoPrintf( "The friends list is locked now. Retry later.\n" );
1823         SetGlobalState(GLOBAL_SELECT_FRIENDDATA_DEL);
1824         return ret;
1825     }
1826 
1827     SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1828 
1829     return ret;
1830 }
MatchFriendData_Update(void)1831 static int MatchFriendData_Update(void)
1832 {
1833     int ret = MAIN_RET_OK;
1834     SequenceInfo* seq = GetSequenceInfo();
1835 
1836     // Update the server
1837     DWC_UpdateServersAsync( NULL,
1838                             frienddataCallback, NULL,
1839                             NULL, NULL,
1840                             NULL, NULL);
1841 
1842     DWCDemoPrintf( "DWC_UpdateServersAsync\n" );
1843     SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1844 
1845     return ret;
1846 }
MatchFriendData_Save(void)1847 static int MatchFriendData_Save(void)
1848 {
1849     int ret = MAIN_RET_OK;
1850     SequenceInfo* seq = GetSequenceInfo();
1851 
1852     // Clear the change flag
1853     DWC_ClearDirtyFlag( &s_playerinfo.userdata );
1854 
1855     // Save to NAND
1856     DWCDemoSaveNAND(SAVEDATA_FILENAME,
1857                     0,
1858                     (u8*)&s_playerinfo,
1859                     sizeof( s_playerinfo ) );
1860 
1861     DWCDemoPrintf( "*\n* save friendcode successfly.\n*\n" );
1862 
1863     SetGlobalState(GLOBAL_SELECT_FRIENDDATA);
1864 
1865     return ret;
1866 }
1867 /**
1868  * Gets an empty index on the friend roster.
1869  *
1870  * Return value:   Available index in the friend roster.
1871  *          Returns -1 if there is no available index.
1872  */
GetAvailableFriendListIndex(void)1873 static int GetAvailableFriendListIndex( void )
1874 {
1875     int i;
1876 
1877     for (i=0; i<FRIEND_LIST_LEN; i++)
1878     {
1879         if (!DWC_IsValidFriendData(&s_playerinfo.friendlist[i]))
1880             return i;
1881     }
1882 
1883     return -1;
1884 }
1885 
1886 
1887 // Process GroupID connections
1888 //
MatchGroupID(void)1889 static int MatchGroupID(void)
1890 {
1891     int ret = MAIN_RET_OK;
1892     SequenceInfo* seq = GetSequenceInfo();
1893 
1894     if (seq->firstTime)
1895     {
1896         DWCDemoPrintf("\n");
1897         DWCDemoPrintf("--------------------------------\n");
1898         DWCDemoPrintf("-      Connect to GroupID      -\n");
1899         DWCDemoPrintf("--------------------------------\n");
1900         DWCDemoPrintf("Arrow: input number\n");
1901         DWCDemoPrintf("A: OK\n");
1902         DWCDemoPrintf("B: Back to before sequence\n");
1903         DWCDemoPrintf("\n");
1904     }
1905 
1906     InputBuffInit(0);
1907 
1908     SetGlobalState(GLOBAL_SELECT_GROUPID_INPUT);
1909 
1910     return MAIN_RET_OK;
1911 }
MatchGroupID_Input(void)1912 static int MatchGroupID_Input(void)
1913 {
1914     int ret = MAIN_RET_OK;
1915     SequenceInfo* seq = GetSequenceInfo();
1916 
1917     // Get input
1918     InputBuffUpdate();
1919 
1920     // Check key input
1921     if (seq->padpressed & DWCDEMO_KEY_A)
1922     {   // Connect using this input
1923         StartMatch();
1924     }
1925     else if (seq->padpressed & DWCDEMO_KEY_B)
1926     {   // Return as far as matchmaking selection
1927         SetGlobalState(GLOBAL_SELECT_MATCH);
1928     }
1929 
1930     return ret;
1931 }
1932 
1933 // Re-connect with the local host's group ID
1934 //
MatchReconnectGroupID(void)1935 static int MatchReconnectGroupID(void)
1936 {
1937     int ret = MAIN_RET_OK;
1938     SequenceInfo* seq = GetSequenceInfo();
1939 
1940     if (seq->firstTime)
1941     {
1942         DWCDemoPrintf("\n");
1943         DWCDemoPrintf("--------------------------------\n");
1944         DWCDemoPrintf("-      ReConnect to GroupID    -\n");
1945         DWCDemoPrintf("--------------------------------\n");
1946         DWCDemoPrintf("\n");
1947     }
1948 
1949     seq->reconnectGroupID = TRUE;
1950     StartMatch();
1951 
1952     return MAIN_RET_OK;
1953 }
1954 
1955 // Prepare a buffer for input
1956 //
InputBuffInit(u32 _init)1957 static void InputBuffInit(u32 _init)
1958 {
1959     SequenceInfo* seq = GetSequenceInfo();
1960     int i;
1961     char* buf = (char*)seq->inputBuf;
1962 
1963     // Default input length
1964     seq->inputBufLen = INPUT_BUF_LEN;
1965     if (seq->globalState == GLOBAL_SELECT_CONFIG_KEEPALIVE)
1966     {
1967         seq->inputBufLen = INPUT_KEEPALIVE_LEN;
1968     }
1969     else if (seq->matchmakeType == MATCHMAKE_GROUPID)
1970     {
1971         seq->inputBufLen = INPUT_GROUPID_LEN;
1972     }
1973 
1974     for (i=0; i<INPUT_BUF_LEN; ++i)
1975     {
1976         seq->inputBuf[i] = '0';
1977     }
1978     if (_init != 0)
1979     {
1980         snprintf(buf, INPUT_BUF_LEN, "%*u", seq->inputBufLen, _init);
1981     }
1982     for ( i=0; i<INPUT_BUF_LEN; i++ )
1983     {
1984         if (seq->inputBuf[i] >= '0') seq->inputBuf[i] -= '0';
1985         else if (seq->inputBuf[i] == ' ') seq->inputBuf[i] = 0; // Because this is kept short using spaces
1986     }
1987 
1988     seq->inputCursor = 0;
1989 
1990     InputBuffView();
1991 }
1992 
1993 // Input to the buffer
1994 //
InputBuffUpdate(void)1995 static void InputBuffUpdate(void)
1996 {
1997     SequenceInfo* seq = GetSequenceInfo();
1998     u8* input = seq->inputBuf;
1999     int i;
2000 
2001     if ( seq->padpressed & DWCDEMO_KEY_UP )
2002     {
2003         input[seq->inputCursor] = (u8)((input[seq->inputCursor] + 1) % 10);
2004     }
2005     else if ( seq->padpressed & DWCDEMO_KEY_DOWN )
2006     {
2007         input[seq->inputCursor] = (u8)(input[seq->inputCursor] == 0 ? 9 : (input[seq->inputCursor] - 1));
2008     }
2009     else if ( seq->padpressed & DWCDEMO_KEY_LEFT )
2010     {
2011         seq->inputCursor = (u8)(seq->inputCursor == 0 ? (seq->inputBufLen - 1) : (seq->inputCursor - 1));
2012     }
2013     else if ( seq->padpressed & DWCDEMO_KEY_RIGHT )
2014     {
2015         seq->inputCursor = (u8)((seq->inputCursor + 1) % seq->inputBufLen);
2016     }
2017     else if ( seq->padpressed & (DWCDEMO_KEY_A | DWCDEMO_KEY_B) )
2018     {
2019         seq->inputCode = 0;
2020 
2021         for ( i=0; i<seq->inputBufLen; i++ )
2022             seq->inputCode = seq->inputCode * 10 + input[i];
2023 
2024         if ( seq->padpressed & DWCDEMO_KEY_B )
2025         {
2026             DWCDemoPrintf( "canceled\n" );
2027         }
2028     }
2029     else
2030     {
2031         return;
2032     }
2033 
2034     InputBuffView();
2035 }
2036 
2037 // Display buffer input information
InputBuffView(void)2038 static void InputBuffView(void)
2039 {
2040     SequenceInfo* seq = GetSequenceInfo();
2041     char tmpbuf[0xff];
2042     u8* input = seq->inputBuf;
2043     int i;
2044 
2045     sprintf( tmpbuf, "" );
2046 
2047     for ( i=0; i<seq->inputBufLen; i++ )
2048         sprintf( tmpbuf, "%s%d", tmpbuf, input[i] );
2049     sprintf( tmpbuf, "%s\n", tmpbuf );
2050 
2051     for ( i=0; i<seq->inputBufLen; i++ )
2052         sprintf( tmpbuf, "%s%c", tmpbuf, " ~"[seq->inputCursor==i] );
2053     sprintf( tmpbuf, "%s\n", tmpbuf );
2054 
2055     DWCDemoPrintf( tmpbuf );
2056 }
2057 
2058 // Configure the player count
2059 //
GlobalSelectConfig_Players(void)2060 static int GlobalSelectConfig_Players(void)
2061 {
2062     SequenceInfo* seq = GetSequenceInfo();
2063     int ret = MAIN_RET_OK;
2064     static u8 players;
2065 
2066     if (seq->firstTime)
2067     {
2068         DWCDemoPrintf("\n");
2069         DWCDemoPrintf("--------------------------------\n");
2070         DWCDemoPrintf("-       Set entry players      -\n");
2071         DWCDemoPrintf("--------------------------------\n");
2072         DWCDemoPrintf("Arrow: update entry players\n");
2073         DWCDemoPrintf("A: OK\n");
2074         DWCDemoPrintf("B: Cancel\n");
2075         DWCDemoPrintf("\n");
2076         players = seq->numPlayers;
2077     }
2078 
2079     // Key input
2080     if (seq->padpressed & DWCDEMO_KEY_UP)    ++players;
2081     if (seq->padpressed & DWCDEMO_KEY_DOWN)  --players;
2082     if (seq->padpressed & DWCDEMO_KEY_A)
2083     {   // For now, return to general environment configuration
2084         seq->numPlayers = players;
2085         SetGlobalState(GLOBAL_SELECT_CONFIG);
2086     }
2087     else if (seq->padpressed & DWCDEMO_KEY_B)
2088     {
2089         SetGlobalState(GLOBAL_SELECT_CONFIG);
2090     }
2091 
2092     // Adjust the player count
2093     if (players < MIN_PLAYERS) players = MIN_PLAYERS;
2094     else if (players > MAX_PLAYERS) players = MAX_PLAYERS;
2095 
2096     if (seq->firstTime || seq->padpressed & (DWCDEMO_KEY_UP | DWCDEMO_KEY_DOWN | DWCDEMO_KEY_A))
2097     {
2098         DWCDemoPrintf("Players: %d\n", players);
2099     }
2100 
2101     return ret;
2102 }
2103 
2104 // Configure the keep-alive time
2105 //
GlobalSelectConfig_KeepAlive(void)2106 static int GlobalSelectConfig_KeepAlive(void)
2107 {
2108     SequenceInfo* seq = GetSequenceInfo();
2109     int ret = MAIN_RET_OK;
2110 
2111     if (seq->firstTime)
2112     {
2113         DWCDemoPrintf("\n");
2114         DWCDemoPrintf("--------------------------------\n");
2115         DWCDemoPrintf("-      Set keepalive Time      -\n");
2116         DWCDemoPrintf("--------------------------------\n");
2117         DWCDemoPrintf("Arrow: input number\n");
2118         DWCDemoPrintf("A: OK\n");
2119         DWCDemoPrintf("B: Cancel\n");
2120         InputBuffInit(seq->keepAliveTime);
2121     }
2122 
2123     InputBuffUpdate();
2124     if (seq->padpressed & DWCDEMO_KEY_A)
2125     {   // Set the keep-alive time with this value.
2126         // You cannot specify 0.
2127         if ((u32)seq->inputCode == 0)
2128         {
2129             DWCDemoPrintf("*** Set keepalive time: ignore value!!(%u)\n", (u32)seq->inputCode);
2130         }
2131         else
2132         {
2133             seq->keepAliveTime = (u32)seq->inputCode;
2134             DWCDemoPrintf("*\n*Set keepalive time:%u\n*\n", seq->keepAliveTime);
2135         }
2136         SetGlobalState(GLOBAL_SELECT_CONFIG);
2137     }
2138     else if (seq->padpressed & DWCDEMO_KEY_B)
2139     {
2140         SetGlobalState(GLOBAL_SELECT_CONFIG);
2141     }
2142 
2143     return MAIN_RET_OK;
2144 }
2145 
2146 // Configure the network type
2147 //
GlobalSelectConfig_NetworkType(void)2148 static int GlobalSelectConfig_NetworkType(void)
2149 {
2150     SequenceInfo* seq = GetSequenceInfo();
2151     int ret = MAIN_RET_OK;
2152 
2153     if (seq->firstTime)
2154     {
2155         DWCDemoPrintf("\n");
2156         DWCDemoPrintf("--------------------------------\n");
2157         DWCDemoPrintf("-       Set topology type       -\n");
2158         DWCDemoPrintf("--------------------------------\n");
2159         DWCDemoPrintf("A: %s\n", GetTopologyTypeString(DWC_TOPOLOGY_TYPE_HYBRID));
2160         DWCDemoPrintf("X: %s\n", GetTopologyTypeString(DWC_TOPOLOGY_TYPE_FULLMESH));
2161         DWCDemoPrintf("Y: %s\n", GetTopologyTypeString(DWC_TOPOLOGY_TYPE_STAR));
2162         DWCDemoPrintf("B: cancel\n");
2163         DWCDemoPrintf("Current: %s\n", GetTopologyTypeString(seq->topologyType));
2164         DWCDemoPrintf("\n");
2165     }
2166 
2167     // Key input
2168     if (seq->padpressed & DWCDEMO_KEY_A)     SetTopologyTypeProcess(DWC_TOPOLOGY_TYPE_HYBRID);
2169     if (seq->padpressed & DWCDEMO_KEY_X)     SetTopologyTypeProcess(DWC_TOPOLOGY_TYPE_FULLMESH);
2170     if (seq->padpressed & DWCDEMO_KEY_Y)     SetTopologyTypeProcess(DWC_TOPOLOGY_TYPE_STAR);
2171     if (seq->padpressed & DWCDEMO_KEY_B)  SetGlobalState(GLOBAL_SELECT_CONFIG);
2172 
2173     return ret;
2174 }
2175 
2176 // Configure reliable communications
2177 //
GlobalSelectConfig_Reliable(void)2178 static int GlobalSelectConfig_Reliable(void)
2179 {
2180     SequenceInfo* seq = GetSequenceInfo();
2181     int ret = MAIN_RET_OK;
2182 
2183     if (seq->firstTime)
2184     {
2185         DWCDemoPrintf("\n");
2186         DWCDemoPrintf("--------------------------------\n");
2187         DWCDemoPrintf("-       Set Use Reliable       -\n");
2188         DWCDemoPrintf("--------------------------------\n");
2189         DWCDemoPrintf("X: %s\n", GetReliableTypeString(TRUE));
2190         DWCDemoPrintf("Y: %s\n", GetReliableTypeString(FALSE));
2191         DWCDemoPrintf("B: Cencel\n");
2192         DWCDemoPrintf("Current: %s\n", GetReliableTypeString(seq->isReliable));
2193     }
2194 
2195     if (seq->padpressed & DWCDEMO_KEY_X)     SetReliableTypeProcess(TRUE);
2196     if (seq->padpressed & DWCDEMO_KEY_Y)     SetReliableTypeProcess(FALSE);
2197     if (seq->padpressed & DWCDEMO_KEY_B)  SetReliableTypeProcess(seq->isReliable);
2198 
2199     return MAIN_RET_OK;
2200 }
2201 
2202 // Configure whether connectAttempt should be used
2203 //
GlobalSelectConfig_ConnectAttempt(void)2204 static int GlobalSelectConfig_ConnectAttempt(void)
2205 {
2206     SequenceInfo* seq = GetSequenceInfo();
2207     int ret = MAIN_RET_OK;
2208 
2209     if (seq->firstTime)
2210     {
2211         DWCDemoPrintf("\n");
2212         DWCDemoPrintf("--------------------------------\n");
2213         DWCDemoPrintf("-  connect attempt setting     -\n");
2214         DWCDemoPrintf("--------------------------------\n");
2215         DWCDemoPrintf("A: use\n");
2216         DWCDemoPrintf("B: not use\n");
2217         DWCDemoPrintf("Current: %s\n", seq->useConnectAttempt ? "use" : "not use");
2218     }
2219 
2220     if (seq->padpressed & DWCDEMO_KEY_A)
2221     {
2222         seq->useConnectAttempt = TRUE;
2223         SetGlobalState(GLOBAL_SELECT_CONFIG_ATTEMPT_TYPE);
2224     }
2225     if (seq->padpressed & DWCDEMO_KEY_B)
2226     {
2227         seq->useConnectAttempt = FALSE;
2228         SetGlobalState(GLOBAL_SELECT_CONFIG);
2229     }
2230     if (seq->padpressed & (DWCDEMO_KEY_A | DWCDEMO_KEY_B))
2231     {
2232         DWCDemoPrintf("*\n*use connect attempt: %s\n*\n", seq->useConnectAttempt ? "use" : "not use");
2233     }
2234 
2235     return ret;
2236 }
2237 // Configure connectAttempt parameters for test use
2238 //
GlobalSelectConfig_ConnectAttemptType(void)2239 static int GlobalSelectConfig_ConnectAttemptType(void)
2240 {
2241     SequenceInfo* seq = GetSequenceInfo();
2242     int ret = MAIN_RET_OK;
2243 
2244     if (seq->firstTime)
2245     {
2246         DWCDemoPrintf("\n");
2247         DWCDemoPrintf("--------------------------------\n");
2248         DWCDemoPrintf("-    set sample male type      -\n");
2249         DWCDemoPrintf("--------------------------------\n");
2250         DWCDemoPrintf("A: male\n");
2251         DWCDemoPrintf("B: female\n");
2252         DWCDemoPrintf("Current: %s\n", seq->male == USER_TYPE_MALE ? "male" : "female");
2253     }
2254 
2255     if (seq->padpressed & DWCDEMO_KEY_A)
2256     {
2257         seq->male = USER_TYPE_MALE;
2258         SetGlobalState(GLOBAL_SELECT_CONFIG);
2259     }
2260     if (seq->padpressed & DWCDEMO_KEY_B)
2261     {
2262         seq->male = USER_TYPE_FEMALE;
2263         SetGlobalState(GLOBAL_SELECT_CONFIG);
2264     }
2265     if (seq->padpressed & (DWCDEMO_KEY_A | DWCDEMO_KEY_B))
2266     {
2267         DWCDemoPrintf("*\n*set male type: %s\n*\n", seq->male == USER_TYPE_MALE ? "Male" : "Female");
2268     }
2269 
2270     return ret;
2271 }
2272 
2273 // Set the matchmaking type
2274 //
SetMatchType(MATCHMAKE_TYPE _type)2275 static void SetMatchType(MATCHMAKE_TYPE _type)
2276 {
2277     GetSequenceInfo()->matchmakeType = _type;
2278 }
2279 
2280 // Set the matchmaking type and advance the sequence
2281 //
SetMatchTypeProcess(MATCHMAKE_TYPE _type)2282 static void SetMatchTypeProcess(MATCHMAKE_TYPE _type)
2283 {
2284     SetMatchType(_type);
2285     SetGlobalState(GLOBAL_SELECT_MAIN);
2286     DWCDemoPrintf("Selected Match!!\n");
2287     DWCDemoPrintf("*\n* %s\n*\n", GetMatchTypeString(_type));
2288 }
2289 
2290 // Get the matchmaking type as a string
2291 //
GetMatchTypeString(MATCHMAKE_TYPE _type)2292 static const char* GetMatchTypeString(MATCHMAKE_TYPE _type)
2293 {
2294     switch (_type)
2295     {
2296     case MATCHMAKE_ANYBODY:
2297         return "Anybody Match";
2298     case MATCHMAKE_FRIENDS:
2299         return "Friends Match";
2300     case MATCHMAKE_SCSV:
2301         return "Server/Client Match";
2302     case MATCHMAKE_FRIENDDATA:
2303         return "Set frienddata";
2304     case MATCHMAKE_GROUPID:
2305         return "Connect to server from groupID";
2306     case MATCHMAKE_RECONNECT:
2307         return "ReConnect to server from groupID";
2308     }
2309     return "Unknown Match";  // It would be strange if this was reached, but...
2310 }
2311 
2312 // Set the network type
2313 //
SetNetworkType(DWCTopologyType _type)2314 static void SetNetworkType(DWCTopologyType _type)
2315 {
2316     if (_type != DWC_TOPOLOGY_TYPE_HYBRID &&
2317             _type != DWC_TOPOLOGY_TYPE_STAR &&
2318             _type != DWC_TOPOLOGY_TYPE_FULLMESH)
2319     {
2320         DWCDemoPrintf("SetNetworkType: illegal type!! (%d)", _type);
2321         SET_EXIT_DEMO();
2322     }
2323 
2324     GetSequenceInfo()->topologyType = _type;
2325 }
2326 
2327 // Set the network type and advance the sequence
2328 //
SetTopologyTypeProcess(DWCTopologyType _type)2329 static void SetTopologyTypeProcess(DWCTopologyType _type)
2330 {
2331     SetNetworkType(_type);
2332     GetSequenceInfo()->globalState = GLOBAL_SELECT_CONFIG;  // For now, this is a fixed value
2333     DWCDemoPrintf("Set topology type!!\n");
2334     DWCDemoPrintf("*\n* %s\n*\n", GetTopologyTypeString(_type));
2335 }
2336 
SetReliableType(BOOL _useReliable)2337 static void SetReliableType(BOOL _useReliable)
2338 {
2339     GetSequenceInfo()->isReliable = _useReliable;
2340 }
2341 
SetReliableTypeProcess(BOOL _useReliable)2342 static void SetReliableTypeProcess(BOOL _useReliable)
2343 {
2344     SetReliableType(_useReliable);
2345     GetSequenceInfo()->globalState = GLOBAL_SELECT_CONFIG;  // For now, this is a fixed value
2346     DWCDemoPrintf("Set Reliable!!\n");
2347     DWCDemoPrintf("*\n* %s\n*\n", GetReliableTypeString(_useReliable));
2348 }
2349 
GetReliableTypeString(BOOL _useReliable)2350 static const char* GetReliableTypeString(BOOL _useReliable)
2351 {
2352     return _useReliable ? "Reliable is used" : "Reliable is not used";
2353 }
2354 
2355 
2356 // Get the matchmaking type as a string
2357 //
GetTopologyTypeString(u8 _type)2358 static const char* GetTopologyTypeString(u8 _type)
2359 {
2360     switch (_type)
2361     {
2362     case DWC_TOPOLOGY_TYPE_HYBRID:
2363         return "Hybrid Network";
2364     case DWC_TOPOLOGY_TYPE_STAR:
2365         return "Star Network";
2366     case DWC_TOPOLOGY_TYPE_FULLMESH:
2367         return "Fullmesh Network";
2368     }
2369     return "Unknown Network type";  // It would be strange if this was reached, but...
2370 }
2371 
2372 // Set errors
2373 //
SetSequenceError(u8 _error)2374 static void SetSequenceError(u8 _error)
2375 {
2376     GetSequenceInfo()->ret = _error;
2377 }
2378 
2379 // Set errors and strings
2380 //
SetSequenceErrorWithString(u8 _error,const char * _msg)2381 static void SetSequenceErrorWithString(u8 _error, const char* _msg)
2382 {
2383     SetSequenceError(_error);
2384     if (_msg)
2385     {
2386         strncpy(GetSequenceInfo()->errorBuf, _msg, ERROR_BUF_LEN);
2387     }
2388 }
2389 
2390 // Set the global state
2391 //
SetGlobalState(GLOBAL_STATE state)2392 static void SetGlobalState(GLOBAL_STATE state)
2393 {
2394     SequenceInfo* seq = GetSequenceInfo();
2395     if (state < 0 || state >= GLOBAL_SELECT_END)
2396     {
2397         DWCDemoPanic("SetGlobalState: illegal state!!");
2398         SET_EXIT_DEMO();
2399     }
2400 
2401     if (state == GLOBAL_SELECT_RETURN)
2402     {   // When returned, sort the return positions by matchmaking type
2403         if (seq->matchmakeType == MATCHMAKE_ANYBODY ||
2404                 seq->matchmakeType == MATCHMAKE_FRIENDS ||
2405                 seq->matchmakeType == MATCHMAKE_GROUPID ||
2406                 seq->matchmakeType == MATCHMAKE_RECONNECT )
2407         {   // Go to matchmaking selection
2408             state = GLOBAL_SELECT_MATCH;
2409         }
2410         else
2411         {   // As-is
2412             state = GLOBAL_SELECT_MAIN;
2413         }
2414     }
2415 
2416     seq->globalState = state;
2417 
2418     if (state == GLOBAL_SELECT_MAIN)
2419     {   // Sort by the selected matchmaking type
2420         seq->globalState = (GLOBAL_STATE)(GLOBAL_SELECT_ANYBODY + seq->matchmakeType);
2421     }
2422 }
2423 
2424 // Initialize the application information to safe values
2425 //
InitDefaultSequence(void)2426 static void InitDefaultSequence(void)
2427 {
2428     SequenceInfo* seq = GetSequenceInfo();
2429     memset(seq, 0, sizeof(SequenceInfo));
2430     seq->keepAliveTime = APP_CONNECTION_KEEPALIVE_TIME;
2431     seq->topologyType = DWC_TOPOLOGY_TYPE_HYBRID;
2432     seq->matchProcessState = STATE_START;
2433     seq->numPlayers = 4;
2434     seq->male = USER_TYPE_MALE;
2435 }
2436 
2437 // Update key processing.
2438 //
UpdateKeyInput(void)2439 static void UpdateKeyInput(void)
2440 {
2441     SequenceInfo* seq = GetSequenceInfo();
2442     seq->padlast = seq->pad;
2443     seq->pad = DWCDemoPadRead();
2444     seq->padtrig = seq->padlast ^ seq->pad;
2445     seq->padpressed = seq->padtrig & seq->pad;
2446     seq->padreleased = seq->padtrig & ~seq->pad;
2447 }
2448 
2449 // Start matchmaking
2450 //
StartMatch(void)2451 static BOOL StartMatch(void)
2452 {
2453     char* filterString;
2454     char addFilter[128];
2455     u8* userData;
2456     BOOL bRet;
2457     SequenceInfo* seq = GetSequenceInfo();
2458 
2459     filterString = FILTER_STRING;
2460 
2461     snprintf(addFilter, sizeof(addFilter), "str_key='%s'", filterString);
2462 
2463     // To Do
2464     // Set user data values below.
2465     // First, initialize.
2466     seq->userData[0] = 0;
2467     seq->userData[1] = 0;
2468     seq->userData[2] = 0;
2469     seq->userData[3] = 0;
2470 
2471     // If connectAttempt is enabled, configure
2472     if (seq->useConnectAttempt)
2473     {
2474         seq->userData[0] = seq->male;
2475     }
2476     userData = seq->userData;
2477 
2478     // Keep-alive timeout
2479     DWC_SetConnectionKeepAliveTime(seq->keepAliveTime);
2480 
2481     // Set the network type
2482     SetNetworkType(seq->topologyType);
2483 
2484     // Begin matchmaking according to the selected matchmaking type.
2485     // If it's a re-connection using group ID, do it there
2486     if (seq->reconnectGroupID)
2487     {
2488         DWCDemoPrintf("Try reconnect to server by groupID.\n");
2489 
2490         seq->reconnectGroupID = FALSE;
2491 
2492         bRet = DWC_ConnectToGameServerByGroupID( seq->topologyType,
2493                 seq->groupID,
2494                 matchedSCCallback,
2495                 NULL,
2496                 newClientCallback,
2497                 NULL,
2498                 seq->useConnectAttempt ? connectAttemptCallback : NULL,
2499                 userData,
2500                 NULL );
2501     }
2502     else
2503     {
2504         switch (seq->matchmakeType)
2505         {
2506         case MATCHMAKE_ANYBODY:
2507             DWCDemoPrintf("*\n*DWC_ConnectToAnybodyAsync\n*\n");
2508 
2509             // Set the index key.
2510             DWC_AddMatchKeyString( 0, "str_key", filterString );
2511 
2512             // Begin matchmaking
2513             bRet = DWC_ConnectToAnybodyAsync( seq->topologyType,
2514                                               seq->numPlayers,
2515                                               addFilter,
2516                                               matchedSCCallback,
2517                                               NULL,
2518                                               newClientCallback,
2519                                               NULL,
2520                                               evalCallback,
2521                                               NULL,
2522                                               seq->useConnectAttempt ? connectAttemptCallback : NULL,
2523                                               userData,
2524                                               NULL );
2525 
2526             break;
2527 
2528         case MATCHMAKE_FRIENDS:
2529             DWCDemoPrintf("*\n*DWC_ConnectToFriendsAsync\n*\n");
2530 
2531             bRet = DWC_ConnectToFriendsAsync( seq->topologyType,
2532                                               NULL,
2533                                               0,
2534                                               seq->numPlayers,
2535                                               matchedSCCallback,
2536                                               NULL,
2537                                               newClientCallback,
2538                                               NULL,
2539                                               evalCallback,
2540                                               NULL,
2541                                               seq->useConnectAttempt ? connectAttemptCallback : NULL,
2542                                               userData,
2543                                               NULL );
2544             break;
2545 
2546         case MATCHMAKE_SCSV:
2547             if (seq->globalState == GLOBAL_SELECT_SCSV_SV)
2548             {   // Server setup
2549                 DWCDemoPrintf("*\n*DWC_SetupGameServer\n*\n");
2550 
2551                 bRet = DWC_SetupGameServer( seq->topologyType,
2552                                             seq->numPlayers,
2553                                             matchedSCCallback,
2554                                             NULL,
2555                                             newClientCallback,
2556                                             NULL,
2557                                             seq->useConnectAttempt ? connectAttemptCallback : NULL,
2558                                             userData,
2559                                             NULL );
2560             }
2561             else
2562             {   // Connect to the server as a client
2563                 DWCDemoPrintf("*\n*DWC_ConnectToGameServerAsync\n*\n");
2564 
2565                 bRet = DWC_ConnectToGameServerAsync( seq->topologyType,
2566                                                      seq->playerIndex,
2567                                                      matchedSCCallback,
2568                                                      NULL,
2569                                                      newClientCallback,
2570                                                      NULL,
2571                                                      seq->useConnectAttempt ? connectAttemptCallback : NULL,
2572                                                      userData,
2573                                                      NULL );
2574             }
2575             break;
2576 
2577         case MATCHMAKE_GROUPID:
2578             DWCDemoPrintf("*\n*DWC_ConnectToGameServerByGroupID\n*\n");
2579 
2580             bRet = DWC_ConnectToGameServerByGroupID( seq->topologyType,
2581                     (u32)seq->inputCode,
2582                     matchedSCCallback,
2583                     NULL,
2584                     newClientCallback,
2585                     NULL,
2586                     seq->useConnectAttempt ? connectAttemptCallback : NULL,
2587                     userData,
2588                     NULL );
2589             break;
2590         }
2591     }
2592 
2593     // If the call succeeded, matchmaking is in progress. If the call failed, return to environment configuration for the moment.
2594     if (bRet)
2595     {
2596         seq->matchProcessState = STATE_MATCHMAKE;    // Transition to matchmaking
2597         SetGlobalState(GLOBAL_SELECT_MATCHMAKE);
2598     }
2599     else
2600     {
2601         DWCDemoPrintf("*** matchmake start failed!!\n");
2602         SetGlobalState(GLOBAL_SELECT_CONFIG);
2603     }
2604 
2605     return bRet;
2606 }
2607 
2608 // Displays the friend roster.
DispFriendList(void)2609 static void DispFriendList(void)
2610 {
2611     int  i;
2612 
2613     DWCDemoPrintf( "\nFriend list\n");
2614 
2615     for ( i = 0; i < FRIEND_LIST_LEN; i++ )
2616     {
2617         if ( !DWC_IsValidFriendData( &s_playerinfo.friendlist[i] ) )
2618             continue;
2619 
2620         // It is convenient to also display the profile ID
2621         DWCDemoPrintf( "Index: %d (%s) => ", i, DWCDemoGetFriendStatusString(&s_playerinfo.friendlist[i]) );
2622         DWC_ReportFriendData( &s_playerinfo.userdata, &s_playerinfo.friendlist[i] );
2623     }
2624     DWCDemoPrintf( "\n");
2625 }
2626 
2627 /**
2628  * Creates user data.
2629  *
2630  * Once created, user data is usually saved in NAND flash memory and loaded at the next startup, but for simplicity user data is created each time the system starts in this sample.
2631  *
2632  *
2633  *
2634  * Refer to the demos located in "userdata" for saving user data to and loading user data from NAND flash memory.
2635  *
2636  */
getUserData(DWCUserData * userdata)2637 static void getUserData( DWCUserData * userdata )
2638 {
2639     // Create user data.
2640     DWC_CreateUserData( userdata );
2641     DWC_ClearDirtyFlag( userdata );
2642 }
2643 
2644 
2645 
2646