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