1 /*---------------------------------------------------------------------------*
2 Project: RevolutionDWC Demos
3 File: ./frienddata/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: Friend data demo
18 *
19 * This demo builds a friend relationship by exchanging friend codes.
20 * Formed friendships are saved in NAND memory and restored at the next startup.
21 *
22 * Procedure for forming a friend relationship using this demo
23 *
24 * 1. Run the demo on each of two consoles
25 * 2. Press "A" on each and enter the other one's friend code
26 * 3. Press "X" to save and exit
27 * 4. Startup again (the friend relationship will be formed during login)
28 * 5. Press "X" to save and exit
29 *
30 * Version: 1.4.16 Revised program to check for duplicate friend codes.
31 *
32 */
33 #include "../../common/include/common.h"
34
35 // Constant Declarations
36 //---------------------------------------------------------
37
38 // Variable Declarations
39 //---------------------------------------------------------
40
41 /// Structure that contains the player information
42 static struct tagPlayerInfo
43 {
44
45 /// User data
46 DWCUserData userdata;
47
48 /// Friend data
49 DWCFriendData friendlist[FRIEND_LIST_LEN];
50
51 }
52 s_playerinfo ATTRIBUTE_ALIGN(32);
53
54
55 // Function Prototype
56 //---------------------------------------------------------
57 static int GetAvailableFriendListIndex( void );
58 static BOOL CheckForDuplicatedFriendData( DWCFriendData* data );
59 static void DispFriendList( void );
60 static BOOL update( void );
61 static void loginCallback(DWCError error, int profileID, void * param);
62 static void updateCallback(DWCError error, BOOL isChanged, void* param);
63
64
65 /**
66 * Gets an empty index on the friend roster.
67 *
68 * Return value: Available index in the friend roster.
69 * Returns -1 if there is no available index.
70 */
GetAvailableFriendListIndex(void)71 static int GetAvailableFriendListIndex( void )
72 {
73 int i;
74
75 for ( i = 0; i < FRIEND_LIST_LEN; i++ )
76 {
77
78 if ( !DWC_IsValidFriendData( &s_playerinfo.friendlist[i] ) )
79 return i;
80
81 }
82
83 return -1;
84 }
85
86
87 /**
88 * Check through the friend roster to see if the friend is already registered.
89 *
90 * Param: data - The friend data to check
91 *
92 * Return value: TRUE: Does not exist in the roster
93 * Return value: FALSE: Already exists in the roster
94 */
CheckForDuplicatedFriendData(DWCFriendData * data)95 static BOOL CheckForDuplicatedFriendData( DWCFriendData* data )
96 {
97 int i;
98
99 for ( i = 0; i < FRIEND_LIST_LEN; i++ )
100 {
101
102 if ( DWC_IsEqualFriendData( &s_playerinfo.friendlist[i], data ) )
103 return FALSE;
104
105 }
106
107 return TRUE;
108 }
109
110
111 /**
112 * Display the friend roster.
113 */
DispFriendList(void)114 static void DispFriendList( void )
115 {
116 int i;
117
118 for ( i = 0; i < FRIEND_LIST_LEN; i++ )
119 {
120
121 if ( !DWC_IsValidFriendData( &s_playerinfo.friendlist[i] ) )
122 continue;
123
124 DWCDemoPrintf( " #%02d: ", i );
125 DWC_ReportFriendData( &s_playerinfo.userdata,
126 &s_playerinfo.friendlist[i] );
127 }
128
129 DWCDemoPrintf( "\n");
130
131 }
132
133 /**
134 * The callback function called during login
135 */
loginCallback(DWCError error,int profileID,void * param)136 static void loginCallback(DWCError error, int profileID, void * param)
137 {
138 DWCDemoPrintf( "Login callback : %d\n", error );
139
140 if ( error == DWC_ERROR_NONE )
141 {
142
143 // When the login is successful
144 //
145 DWCDemoPrintf( "Login Success. ProfileID=%d\n", profileID );
146
147 }
148 else
149 {
150
151 // When the login failed
152 //
153 DWCDemoPanic( "Login Failed\n" );
154 }
155
156 // Set the loop ended flag
157 *((BOOL*)param) = TRUE;
158
159 }
160
update(void)161 static BOOL update( void )
162 {
163
164 static u32 padlast = 0; // The previous pressed state
165 u32 pad; // The current pressed state
166 u32 padtrig; // Keys whose state changed from the last time
167 u32 padpressed; // Newly-pressed keys
168 u32 padreleased; // Newly-released keys
169
170 static u32 cursor = 0;
171 static u8 cfriendcode[12];
172 static u64 friendcode;
173
174 static u8 delindex = 0;
175
176 static enum
177 {
178 STATE_MENU,
179 STATE_SELECT,
180 STATE_ADD_FRIEND,
181 STATE_ADD_FRIEND_INPUT,
182 STATE_ADD_FRIEND_PROCESS,
183 STATE_DEL_FRIEND,
184 STATE_DEL_FRIEND_INPUT,
185 STATE_DEL_FRIEND_PROCESS
186 }
187 state = STATE_MENU;
188
189 int i;
190
191
192 // Read key input
193 pad = DWCDemoPadRead();
194 padtrig = padlast ^ pad;
195 padpressed = padtrig & pad;
196 padreleased = padtrig & ~pad;
197
198
199 switch ( state )
200 {
201
202 case STATE_MENU:
203 DWCDemoPrintf("\n");
204 DWCDemoPrintf("--------------------------------\n");
205 DWCDemoPrintf("- DWC Friend Data Demo -\n");
206 DWCDemoPrintf("--------------------------------\n");
207 DWCDemoPrintf("A: add friend\n");
208 DWCDemoPrintf("B: del friend\n");
209 DWCDemoPrintf("Y: update server\n");
210 DWCDemoPrintf("X: save & exit\n");
211 state = STATE_SELECT;
212 break;
213
214 case STATE_SELECT:
215
216 if ( padpressed & DWCDEMO_KEY_A )
217 {
218
219 state = STATE_ADD_FRIEND;
220 break;
221
222 }
223 else if ( padpressed & DWCDEMO_KEY_B )
224 {
225
226 state = STATE_DEL_FRIEND;
227 break;
228
229 }
230 else if ( padpressed & DWCDEMO_KEY_Y )
231 {
232
233 // By calling this asynchronous function, friend information stored locally and on the server are synchronized.
234 //
235 DWC_UpdateServersAsync( NULL,
236 updateCallback, NULL,
237 NULL, NULL,
238 NULL, NULL);
239
240 DWCDemoPrintf( "DWC_UpdateServersAsync\n" );
241 state = STATE_MENU;
242 break;
243
244 }
245 else if ( padpressed & DWCDEMO_KEY_X )
246 {
247
248 // Quit
249 return FALSE;
250
251 }
252 break;
253
254 case STATE_ADD_FRIEND:
255
256 DWCDemoPrintf("Please the input friend code.\n");
257 DWCDemoPrintf("Arrow: input number\n");
258 DWCDemoPrintf("A: OK\n");
259 DWCDemoPrintf("B: Cancel\n");
260 state = STATE_ADD_FRIEND_INPUT;
261
262 break;
263
264 case STATE_ADD_FRIEND_INPUT:
265
266 if ( padpressed & DWCDEMO_KEY_UP )
267 {
268 cfriendcode[cursor] = (u8)((cfriendcode[cursor] + 1) % 10);
269 }
270 else if ( padpressed & DWCDEMO_KEY_DOWN )
271 {
272 cfriendcode[cursor] = (u8)(cfriendcode[cursor] == 0 ? 9 : (cfriendcode[cursor] - 1));
273 }
274 else if ( padpressed & DWCDEMO_KEY_LEFT )
275 {
276 cursor = cursor == 0 ? 11 : (cursor - 1);
277 }
278 else if ( padpressed & DWCDEMO_KEY_RIGHT )
279 {
280 cursor = (cursor + 1) % 12;
281 }
282 else if ( padpressed & DWCDEMO_KEY_A )
283 {
284
285 friendcode = 0;
286
287 for ( i=0; i<12; i++ )
288 friendcode = friendcode * 10 + cfriendcode[i];
289
290 DWCDemoPrintf( "Add friend(%012llu)\n", friendcode );
291
292 state = STATE_ADD_FRIEND_PROCESS;
293
294 break;
295
296 }
297 else if ( padpressed & DWCDEMO_KEY_B )
298 {
299 DWCDemoPrintf( "canceled\n" );
300 state = STATE_MENU;
301 }
302 else
303 break;
304
305 {
306 char tmpbuf[0xff];
307
308 sprintf( tmpbuf, "" );
309
310 for ( i=0; i<12; i++ )
311 sprintf( tmpbuf, "%s%d", tmpbuf, cfriendcode[i] );
312 sprintf( tmpbuf, "%s\n", tmpbuf );
313
314 for ( i=0; i<12; i++ )
315 sprintf( tmpbuf, "%s%c", tmpbuf, " ~"[cursor==i] );
316 sprintf( tmpbuf, "%s\n", tmpbuf );
317
318 DWCDemoPrintf( tmpbuf );
319 }
320
321 break;
322
323 case STATE_ADD_FRIEND_PROCESS:
324
325 if ( DWC_CheckFriendKey( &s_playerinfo.userdata,
326 friendcode ) )
327 {
328 int index;
329
330 index = GetAvailableFriendListIndex();
331
332 if ( index != -1 )
333 {
334
335 if ( DWC_CanChangeFriendList() )
336 {
337 DWCFriendData newdata;
338
339 DWC_CreateFriendKeyToken( &newdata, friendcode );
340
341 // Checks if the friend is already present in the friend roster, and if not, adds the friend
342 if ( CheckForDuplicatedFriendData( &newdata ) )
343 {
344 s_playerinfo.friendlist[index] = newdata;
345 }
346 else
347 {
348 DWCDemoPrintf( "dupulicating friend code\n" );
349 }
350
351 }
352 else
353 {
354 // If the friend roster is in an uneditable state, return to the input phase
355 DWCDemoPrintf( "The friends list is locked now. Retry later.\n" );
356 state = STATE_ADD_FRIEND_INPUT;
357 break;
358
359 }
360
361 }
362 else
363 {
364
365 DWCDemoPrintf( "Too many friends:)\n" );
366
367 }
368
369 }
370 else
371 {
372
373 DWCDemoPrintf( "invalid friend code\n" );
374
375 }
376
377 state = STATE_MENU;
378
379 break;
380
381 case STATE_DEL_FRIEND:
382
383 DWCDemoPrintf("Input index to delete.\n");
384 DWCDemoPrintf("Arrow: input number\n");
385 DWCDemoPrintf("A: OK\n");
386 DWCDemoPrintf("B: Cancel\n");
387 DWCDemoPrintf( "index=%d\n", delindex );
388 DispFriendList();
389 state = STATE_DEL_FRIEND_INPUT;
390 break;
391
392 case STATE_DEL_FRIEND_INPUT:
393
394 if ( padpressed & DWCDEMO_KEY_UP )
395 {
396 delindex = (u8)((delindex + 1) % FRIEND_LIST_LEN);
397 }
398 else if ( padpressed & DWCDEMO_KEY_DOWN )
399 {
400 delindex = (u8)(delindex == 0 ? (FRIEND_LIST_LEN-1) : (delindex - 1));
401 }
402 else if ( padpressed & DWCDEMO_KEY_A )
403 {
404
405 DWCDemoPrintf( "delete #%d\n", delindex );
406 state = STATE_DEL_FRIEND_PROCESS;
407
408 }
409 else if ( padpressed & DWCDEMO_KEY_B )
410 {
411
412 DWCDemoPrintf( "canceled\n" );
413 state = STATE_MENU;
414
415 }
416 else
417 break;
418
419 DWCDemoPrintf( "index=%d\n", delindex );
420
421 break;
422
423 case STATE_DEL_FRIEND_PROCESS:
424
425 if ( DWC_CanChangeFriendList() )
426 {
427 DWC_DeleteBuddyFriendData( &s_playerinfo.friendlist[delindex] );
428 }
429 else
430 {
431 // If the friend roster is in an uneditable state, return to the input phase
432 DWCDemoPrintf( "The friends list is locked now. Retry later.\n" );
433 state = STATE_DEL_FRIEND;
434 break;
435
436 }
437
438 state = STATE_MENU;
439
440 break;
441
442 }
443
444
445
446 // Save the current state
447 padlast = pad;
448
449 return TRUE;
450 }
451
updateCallback(DWCError error,BOOL isChanged,void * param)452 static void updateCallback(DWCError error, BOOL isChanged, void* param)
453 {
454 (void)param;
455 (void)isChanged;
456
457 if ( error == DWC_ERROR_NONE )
458 {
459 // Successful synchronous processing of friend roster.
460 DWCDemoPrintf( "Update Servers succeeded.\n" );
461
462 }
463 else
464 {
465 DWCDemoPrintf("Error\n");
466 }
467 }
468
469 //=============================================================================
470 /*!
471 * @brief Main
472 */
473 //=============================================================================
DWCDemoMain()474 void DWCDemoMain()
475 {
476
477 u64 friendcode;
478 BOOL exitflag = FALSE;
479
480
481 // Load user data from NAND
482 //
483 DWCDemoPrintf("Loading userdata from NAND...\n");
484 DWCDemoUpdate();
485
486 DWCDemoLoadNAND( SAVEDATA_FILENAME,
487 0,
488 (u8*)&s_playerinfo,
489 sizeof( s_playerinfo ) );
490
491
492 // Check if user data is valid
493 //
494 if ( !DWC_CheckUserData( &s_playerinfo.userdata ) )
495 {
496
497 // If valid user data had not been saved
498 //
499
500 // Create user data.
501 DWCDemoPrintf("Creating new UserData\n");
502 DWCDemoUpdate();
503
504 DWC_CreateUserData( &s_playerinfo.userdata );
505
506 // Initialize the friend roster
507 DWCi_Np_CpuClear32( &s_playerinfo.friendlist,
508 sizeof( s_playerinfo.friendlist ) );
509
510 }
511
512 DWC_ReportUserData( &s_playerinfo.userdata );
513
514 // Perform friend match initialization
515 //
516 DWC_InitFriendsMatch( NULL,
517 &s_playerinfo.userdata,
518 GAME_PRODUCTID,
519 GAME_NAME,
520 GAME_SECRET_KEY,
521 0,
522 0,
523 s_playerinfo.friendlist,
524 FRIEND_LIST_LEN );
525
526 // Start login processing
527 //
528 DWC_LoginAsync( (u16*)L"name",
529 NULL,
530 loginCallback,
531 &exitflag );
532
533 // Wait until login has completed
534 //
535 while ( !exitflag )
536 {
537
538 DWC_ProcessFriendsMatch();
539
540 DWCDemoUpdate();
541
542 }
543
544 // Get your own friend code
545 //
546 // If login completed normally, the profile ID was probably acquired
547 // If it failed, 0 is returned
548 //
549 friendcode = DWC_CreateFriendKey( &s_playerinfo.userdata );
550 DWCDemoPrintf("My friend code is : %012llu\n", friendcode );
551 DWCDemoUpdate();
552
553 // Main loop
554 //
555 //
556 //
557 //
558 while ( update() )
559 {
560
561 DWC_ProcessFriendsMatch();
562
563 DWCDemoUpdate();
564
565 }
566
567 // Shut down communications
568 //
569 DWC_ShutdownFriendsMatch();
570
571
572 // Save user data to NAND.
573 //
574
575 // Clear the change flag
576 DWC_ClearDirtyFlag( &s_playerinfo.userdata );
577
578 // Save to NAND
579 DWCDemoSaveNAND( SAVEDATA_FILENAME,
580 0,
581 (u8*)&s_playerinfo,
582 sizeof( s_playerinfo ) );
583
584 }
585