1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MB - libraries
3 File: mb_gameinfo.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-11-27#$
14 $Rev: 9425 $
15 $Author: yosizaki $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19 #include "mb_gameinfo.h"
20 #include "mb_common.h"
21 #include "mb_private.h" // for MB_SCAN_TIME_NORMAL & MB_SCAN_TIME_LOKING & MB_OUTPUT, MB_DEBUG_OUTPUT
22
23
24 /*
25
26 ********** PRECAUTIONS **********
27 - During a scan lock, the scan time should be set to be greater than the parent's beacon interval. (200ms or greater)
28 However, if this is done the scan time will change dynamically, so what will be done about values that have already been counted, and the maximum value of LifetimeCount and LockTimeCount?
29
30
31 */
32
33
34 /*
35 * The wmDEMOlib functions that are being used:
36 * - none
37 *
38 * The WM API that is being used:
39 * - WM_SetGameInfo (MBi_SendFixedBeacon, MBi_SendVolatBeacon)
40 *
41 *
42 *
43 *
44 */
45
46 // define data---------------------------------------------
47
48 #define MB_GAME_INFO_LIFETIME_SEC 60 // Lifetime of the received game information (deleted if a beacon is not received in this time period (seconds))
49 #define MB_SCAN_LOCK_SEC 8 // Maximum time for locking a specific parent and scanning
50 #define MB_SAME_BEACON_RECV_MAX_COUNT 3 // The maximum number of times that a parent's beacon can be continuously received when the parent repeatedly sends out the same beacon.
51
52 #define MB_BEACON_DATA_SIZE (WM_SIZE_USER_GAMEINFO - 8)
53 #define MB_BEACON_FIXED_DATA_SIZE (MB_BEACON_DATA_SIZE - 6) // The data size of the fixed region for the parent device's game information in the beacon.
54 #define MB_BEACON_VOLAT_DATA_SIZE (MB_BEACON_DATA_SIZE - 8) // The data size of the volatile region for the parent device's game information in the beacon.
55 #define MB_SEND_MEMBER_MAX_NUM (MB_BEACON_VOLAT_DATA_SIZE / sizeof(MBUserInfo)) // The maximum amount of member information that can be send at one time in the beacon.
56
57 #define FIXED_NORMAL_SIZE sizeof(MBGameInfoFixed) // The normal size of the game information's fixed region.
58 #define FIXED_NO_ICON_SIZE (sizeof(MBGameInfoFixed) - sizeof(MBIconInfo)) // The size of the game information's fixed region without icons.
59 #define FIXED_FLAGMENT_MAX(size) ( ( size / MB_BEACON_FIXED_DATA_SIZE) + ( size % MB_BEACON_FIXED_DATA_SIZE ? 1 : 0 ) )
60 // The number of beacon fragments of the game information's fixed region.
61
62 #define MB_LIFETIME_MAX_COUNT ( MB_GAME_INFO_LIFETIME_SEC * 1000 / MB_SCAN_TIME_NORMAL + 1 )
63 #define MB_LOCKTIME_MAX_COUNT ( MB_SCAN_LOCK_SEC * 1000 / MB_SCAN_TIME_NORMAL + 1 )
64 // This is the parent's game information lifetime converted into ScanTime units.
65 // This is the scan lock time converted into ScanTime units.
66 #define MB_SCAN_COUNT_UNIT_NORMAL ( 1 )
67 #define MB_SCAN_COUNT_UNIT_LOCKING ( MB_SCAN_TIME_LOCKING / MB_SCAN_TIME_NORMAL )
68
69
70
71 typedef enum MbBeaconState
72 {
73 MB_BEACON_STATE_STOP = 0,
74 MB_BEACON_STATE_READY,
75 MB_BEACON_STATE_FIXED_START,
76 MB_BEACON_STATE_FIXED,
77 MB_BEACON_STATE_VOLAT_START,
78 MB_BEACON_STATE_VOLAT,
79 MB_BEACON_STATE_NEXT_GAME
80 }
81 MbBeaconState;
82
83
84 /* Beacon Format Structure */
85 typedef struct MbBeacon
86 {
87 u32 ggid; // GGID
88 u8 dataAttr:2; // Data attributes (designated by MbBeaconDataAttr)
89 u8 fileNo:6; // File Number
90 u8 seqNoFixed; // Fixed data sequence number (will be added if there was an update to the data contents)
91 u8 seqNoVolat; // Volat data sequence number (will be added if there was an update to the data contents)
92 u8 beaconNo; // Beacon number (increments for each beacon transmission)
93 /* Original MbBeaconData */
94 union
95 {
96 struct
97 { // When sending MbGameInfoFixed
98 u16 sum; // 16-bit checksum
99 u8 flagmentNo; // The current number of the fragmented data.
100 u8 flagmentMaxNum; // The maximum number of the fragmented data.
101 u8 size; // Data size.
102 u8 rsv;
103 u8 data[MB_BEACON_FIXED_DATA_SIZE]; // The data itself.
104 }
105 fixed;
106 struct
107 { // When sending MbGameInfoVolatile
108 u16 sum; // 16-bit checksum
109 u8 nowPlayerNum; // Current number of players
110 u8 pad[1];
111 u16 nowPlayerFlag; // Shows in bits the player numbers of all the current players.
112 u16 changePlayerFlag; // Shows in bits the numbers of the player information that changed at this update. (Used for judgment only at the instant when the sequence number has changed.)
113 MBUserInfo member[MB_SEND_MEMBER_MAX_NUM]; // Send the user information of each child device in increments of MB_SEND_MEMBER_MAX_NUM (end if the PlayerNo == 15 (parent device))
114 u8 userVolatData[MB_USER_VOLAT_DATA_SIZE]; // The data that can be set by the user
115 }
116 volat;
117 }
118 data;
119
120 }
121 MbBeacon;
122
123 /* The parent-side structure for the beacon-transmission status */
124 typedef struct MbBeaconSendStatus
125 {
126 MBGameInfo *gameInfoListTop; // Pointer to the top of the game information list (a one-way list)
127 MBGameInfo *nowGameInfop; // Pointer to the game information that is currently being sent.
128 u8 *srcp; // Pointer to the source of the game information that is currently being sent.
129 u8 state; // The beacon transmission state. (Transmission of fixed data part, dynamic status part. The state changes when each kind of data is completely sent.)
130 u8 seqNoFixed; // Fixed region's sequence number
131 u8 seqNoVolat; // Volatile region's sequence number
132 u8 flagmentNo; // �@ Fragment number of a region (if a fixed region)
133 u8 flagmentMaxNum; // �@ Fragment count of a region (if a fixed region)
134 u8 beaconNo;
135 u8 pad[2];
136 }
137 MbBeaconSendStatus;
138
139
140
141 // function's prototype------------------------------------
142 static BOOL MBi_ReadIconInfo(const char *filePathp, MBIconInfo *iconp, BOOL char_flag);
143 static void MBi_ClearSendStatus(void);
144 static BOOL MBi_ReadyBeaconSendStatus(void);
145 static void MBi_InitSendFixedBeacon(void);
146 static void MBi_SendFixedBeacon(u32 ggid, u16 tgid, u8 attribute);
147 static void MBi_InitSendVolatBeacon(void);
148 static void MBi_SendVolatBeacon(u32 ggid, u16 tgid, u8 attribute);
149
150 static void MBi_SetSSIDToBssDesc(WMBssDesc *bssDescp, u32 ggid);
151 static int MBi_GetStoreElement(WMBssDesc *bssDescp, MBBeaconMsgCallback Callbackp);
152 static void MBi_CheckCompleteGameInfoFlagments(int index, MBBeaconMsgCallback Callbackp);
153 static void MBi_AnalyzeBeacon(WMBssDesc *bssDescp, int index, u16 linkLevel);
154 static void MBi_CheckTGID(WMBssDesc *bssDescp, int inex);
155 static void MBi_CheckSeqNoFixed(int index);
156 static void MBi_CheckSeqNoVolat(int index);
157 static void MBi_InvalidateGameInfoBssID(u8 *bssidp);
158 static void MBi_RecvFixedBeacon(int index);
159 static void MBi_RecvVolatBeacon(int index);
160
161 static void MBi_LockScanTarget(int index);
162 static void MBi_UnlockScanTarget(void);
163 static int mystrlen(u16 *str);
164
165
166 // const data----------------------------------------------
167
168 // global variables----------------------------------------
169
170 static MbBeaconSendStatus mbss; // Beacon send status.
171
172 static MbBeaconRecvStatus mbrs; // Beacon receive status
173 static MbBeaconRecvStatus *mbrsp = NULL; // Beacon receive status
174
175 // static variables----------------------------------------
176 static MbScanLockFunc sLockFunc = NULL; // Pointer to the function for setting a scan lock.
177 static MbScanUnlockFunc sUnlockFunc = NULL; // Pointer to the function for releasing a scan lock.
178
179 static MbBeacon bsendBuff ATTRIBUTE_ALIGN(32); // Beacon send buffer.
180 static MbBeacon *brecvBuffp; // Beacon receive buffer.
181 static WMBssDesc bssDescbuf ATTRIBUTE_ALIGN(32); // BssDesc temporary buffer.
182
183 static MBSendVolatCallbackFunc sSendVolatCallback = NULL; // User data transmission callback
184 static u32 sSendVolatCallbackTimming; // Timing at which the transmission callback is issued.
185
186 // function's description-----------------------------------------------
187
188
189 //=========================================================
190 // Operations for the work buffer that receives beacons
191 //=========================================================
192 // Obtains the work buffer that is set.
MB_GetBeaconRecvStatus(void)193 const MbBeaconRecvStatus *MB_GetBeaconRecvStatus(void)
194 {
195 return mbrsp;
196 }
197
198 // Sets the work buffer from a static variable (for compatibility with older versions).
MBi_SetBeaconRecvStatusBufferDefault(void)199 void MBi_SetBeaconRecvStatusBufferDefault(void)
200 {
201 mbrsp = &mbrs;
202 }
203
204 // Sets the work buffer for receiving beacons.
MBi_SetBeaconRecvStatusBuffer(MbBeaconRecvStatus * buf)205 void MBi_SetBeaconRecvStatusBuffer(MbBeaconRecvStatus * buf)
206 {
207 mbrsp = buf;
208 }
209
210
211 // Sets the function for scan lock
MBi_SetScanLockFunc(MbScanLockFunc lock,MbScanUnlockFunc unlock)212 void MBi_SetScanLockFunc(MbScanLockFunc lock, MbScanUnlockFunc unlock)
213 {
214 sLockFunc = lock;
215 sUnlockFunc = unlock;
216 }
217
218
219
220 //=========================================================
221 // Beacon transmission of game information by the parent device
222 //=========================================================
223
224 // Generate the parent device's game information to be sent by a beacon.
MBi_MakeGameInfo(MBGameInfo * gameInfop,const MBGameRegistry * mbGameRegp,const MBUserInfo * parent)225 void MBi_MakeGameInfo(MBGameInfo *gameInfop,
226 const MBGameRegistry *mbGameRegp, const MBUserInfo *parent)
227 {
228 BOOL icon_disable;
229
230 // Clear all for the time being.
231 MI_CpuClear16(gameInfop, sizeof(MBGameInfo));
232
233 // Register the icon data.
234 gameInfop->dataAttr = MB_BEACON_DATA_ATTR_FIXED_NORMAL;
235 icon_disable = !MBi_ReadIconInfo(mbGameRegp->iconCharPathp, &gameInfop->fixed.icon, TRUE);
236 icon_disable |= !MBi_ReadIconInfo(mbGameRegp->iconPalettePathp, &gameInfop->fixed.icon, FALSE);
237
238 if (icon_disable)
239 {
240 gameInfop->dataAttr = MB_BEACON_DATA_ATTR_FIXED_NO_ICON;
241 MI_CpuClearFast(&gameInfop->fixed.icon, sizeof(MBIconInfo));
242 }
243
244 // GGID
245 gameInfop->ggid = mbGameRegp->ggid;
246
247 // Register the parent's user information.
248 if (parent != NULL)
249 {
250 MI_CpuCopy16(parent, &gameInfop->fixed.parent, sizeof(MBUserInfo));
251 }
252
253 // Register the maximum number of players.
254 gameInfop->fixed.maxPlayerNum = mbGameRegp->maxPlayerNum;
255
256 // Register the game name and a description of the game content.
257 {
258 int len;
259
260 #define COPY_GAME_INFO_STRING MI_CpuCopy16
261
262 len = mystrlen(mbGameRegp->gameNamep) << 1;
263 COPY_GAME_INFO_STRING((u8 *)mbGameRegp->gameNamep, gameInfop->fixed.gameName, (u16)len);
264 // Data after the NULL character is also sent so that data can be packed in after the game content explanation.
265 len = MB_GAME_INTRO_LENGTH * 2;
266 COPY_GAME_INFO_STRING((u8 *)mbGameRegp->gameIntroductionp,
267 gameInfop->fixed.gameIntroduction, (u16)len);
268 }
269
270 // Register the parent device's portion of the player information.
271 gameInfop->volat.nowPlayerNum = 1;
272 gameInfop->volat.nowPlayerFlag = 0x0001; // The player number of the parent device is 0.
273 gameInfop->broadcastedPlayerFlag = 0x0001;
274
275 // NOTE: There is no registration at multiboot startup since there are no play members.
276 }
277
278
279 // Read icon data.
MBi_ReadIconInfo(const char * filePathp,MBIconInfo * iconp,BOOL char_flag)280 static BOOL MBi_ReadIconInfo(const char *filePathp, MBIconInfo *iconp, BOOL char_flag)
281 {
282 FSFile file;
283 s32 size = char_flag ? MB_ICON_DATA_SIZE : MB_ICON_PALETTE_SIZE;
284 u16 *dstp = char_flag ? iconp->data : iconp->palette;
285
286 if (filePathp == NULL)
287 { // Returns FALSE if there is no file designation.
288 return FALSE;
289 }
290
291 FS_InitFile(&file);
292
293 if (FS_OpenFileEx(&file, filePathp, FS_FILEMODE_R) == FALSE)
294 { // Returns FALSE if the file could not be opened.
295 MB_DEBUG_OUTPUT("\t%s : file open error.\n", filePathp);
296 return FALSE;
297 }
298 else if ((u32)size != FS_GetFileLength(&file))
299 {
300 MB_DEBUG_OUTPUT("\t%s : different file size.\n", filePathp);
301 (void)FS_CloseFile(&file);
302 return FALSE;
303 }
304
305 (void)FS_ReadFile(&file, dstp, size);
306 (void)FS_CloseFile(&file);
307 return TRUE;
308 }
309
310
311 // Update the volatile portion of the game information.
MB_UpdateGameInfoMember(MBGameInfo * gameInfop,const MBUserInfo * member,u16 nowPlayerFlag,u16 changePlayerFlag)312 void MB_UpdateGameInfoMember(MBGameInfo *gameInfop,
313 const MBUserInfo *member, u16 nowPlayerFlag, u16 changePlayerFlag)
314 {
315 int i;
316 u8 playerNum = 1;
317
318 MI_CpuCopy16(member, &gameInfop->volat.member[0], sizeof(MBUserInfo) * MB_MEMBER_MAX_NUM);
319 /* Count the number of child devices */
320 for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
321 {
322 if (nowPlayerFlag & (0x0002 << i))
323 {
324 playerNum++;
325 }
326 }
327 gameInfop->volat.nowPlayerNum = playerNum;
328 gameInfop->volat.nowPlayerFlag = (u16)(nowPlayerFlag | 0x0001);
329 gameInfop->volat.changePlayerFlag = changePlayerFlag;
330 gameInfop->seqNoVolat++;
331 }
332
333
334 // Calculate the length of a character string.
mystrlen(u16 * str)335 static int mystrlen(u16 *str)
336 {
337 int len = 0;
338 while (*str++)
339 len++;
340 return len;
341 }
342
343
344 // Adds the game information to the send list.
MB_AddGameInfo(MBGameInfo * newGameInfop)345 void MB_AddGameInfo(MBGameInfo *newGameInfop)
346 {
347 MBGameInfo *gInfop = mbss.gameInfoListTop;
348
349 if (!gInfop)
350 { // If the top of mbss is NULL, register at the top.
351 mbss.gameInfoListTop = newGameInfop;
352 }
353 else
354 { // Otherwise, follow the list and add to the end.
355 while (gInfop->nextp != NULL)
356 {
357 gInfop = gInfop->nextp;
358 }
359 gInfop->nextp = newGameInfop;
360 }
361 newGameInfop->nextp = NULL; // 'next' of the added game information is the end.
362 }
363
364
365 // Deletes the game information from the send list.
MB_DeleteGameInfo(MBGameInfo * gameInfop)366 BOOL MB_DeleteGameInfo(MBGameInfo *gameInfop)
367 {
368 MBGameInfo *gInfop = mbss.gameInfoListTop;
369 MBGameInfo *before;
370
371 while (gInfop != NULL)
372 {
373 if (gInfop != gameInfop)
374 {
375 before = gInfop;
376 gInfop = gInfop->nextp;
377 continue;
378 }
379
380 // It matched, so it is deleted from the list.
381 if ((u32)gInfop == (u32)mbss.gameInfoListTop)
382 { // when deleting the top of the list
383 mbss.gameInfoListTop = mbss.gameInfoListTop->nextp;
384 }
385 else
386 {
387 before->nextp = gInfop->nextp;
388 }
389
390 if ((u32)gameInfop == (u32)mbss.nowGameInfop) // If the game information to delete is currently being transmitted, re-set that game information from the rebuilt list.
391 { //
392 mbss.nowGameInfop = NULL;
393 if (!MBi_ReadyBeaconSendStatus())
394 {
395 mbss.state = MB_BEACON_STATE_READY; // If the game information has been completely deleted, the status shifts to READY.
396 }
397 }
398 return TRUE;
399 }
400
401 // When there is no game information
402 return FALSE;
403 }
404
405
406 // Initializes the game information send configuration.
MB_InitSendGameInfoStatus(void)407 void MB_InitSendGameInfoStatus(void)
408 {
409 mbss.gameInfoListTop = NULL; // Delete the entire game information list.
410 mbss.nowGameInfop = NULL; // Also delete the current transmitted game.
411 mbss.state = MB_BEACON_STATE_READY;
412 sSendVolatCallback = NULL;
413 MBi_ClearSendStatus(); // Also clear the send status.
414 }
415
416
417 // Clears the send status.
MBi_ClearSendStatus(void)418 static void MBi_ClearSendStatus(void)
419 {
420 mbss.seqNoFixed = 0;
421 mbss.seqNoVolat = 0;
422 mbss.flagmentNo = 0;
423 mbss.flagmentMaxNum = 0;
424 mbss.beaconNo = 0;
425 }
426
427
428 // Sends a beacon.
MB_SendGameInfoBeacon(u32 ggid,u16 tgid,u8 attribute)429 void MB_SendGameInfoBeacon(u32 ggid, u16 tgid, u8 attribute)
430 {
431 while (1)
432 {
433 switch (mbss.state)
434 {
435 case MB_BEACON_STATE_STOP:
436 case MB_BEACON_STATE_READY:
437 if (!MBi_ReadyBeaconSendStatus())
438 { // Preparations for sending game information.
439 return;
440 }
441 break;
442 case MB_BEACON_STATE_FIXED_START:
443 MBi_InitSendFixedBeacon();
444 break;
445 case MB_BEACON_STATE_FIXED:
446 MBi_SendFixedBeacon(ggid, tgid, attribute);
447 return;
448 case MB_BEACON_STATE_VOLAT_START:
449 MBi_InitSendVolatBeacon();
450 break;
451 case MB_BEACON_STATE_VOLAT:
452 MBi_SendVolatBeacon(ggid, tgid, attribute);
453 return;
454 case MB_BEACON_STATE_NEXT_GAME:
455 break;
456 }
457 }
458 }
459
460
461 // Prepare the beacon send status so that it is sendable.
MBi_ReadyBeaconSendStatus(void)462 static BOOL MBi_ReadyBeaconSendStatus(void)
463 {
464 MBGameInfo *nextGameInfop;
465
466 // Return an error if the game information has not been registered.
467 if (!mbss.gameInfoListTop)
468 {
469 /* The MB flag and ENTRY flag are dropped here. */
470 (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, MBi_GetGgid(),
471 MBi_GetTgid(), WM_ATTR_FLAG_CS);
472 return FALSE;
473 }
474
475 // Select the GameInfo to send next.
476 if (!mbss.nowGameInfop || !mbss.nowGameInfop->nextp)
477 {
478 // If there is no game information still being sent, or if at the end of the list, prepare to send the top of the list.
479 nextGameInfop = mbss.gameInfoListTop;
480 }
481 else
482 {
483 // Otherwise, prepare to send the next game in the list.
484 nextGameInfop = mbss.nowGameInfop->nextp;
485 }
486
487 mbss.nowGameInfop = nextGameInfop;
488
489 MBi_ClearSendStatus();
490 mbss.seqNoVolat = mbss.nowGameInfop->seqNoVolat;
491
492 mbss.state = MB_BEACON_STATE_FIXED_START;
493
494 return TRUE;
495 }
496
497
498 // Initialize transmission of the fixed data portion of the game information.
MBi_InitSendFixedBeacon(void)499 static void MBi_InitSendFixedBeacon(void)
500 {
501 if (mbss.state != MB_BEACON_STATE_FIXED_START)
502 {
503 return;
504 }
505
506 if (mbss.nowGameInfop->dataAttr == MB_BEACON_DATA_ATTR_FIXED_NORMAL)
507 {
508 mbss.flagmentMaxNum = FIXED_FLAGMENT_MAX(FIXED_NORMAL_SIZE);
509 mbss.srcp = (u8 *)&mbss.nowGameInfop->fixed;
510 }
511 else
512 {
513 mbss.flagmentMaxNum = FIXED_FLAGMENT_MAX(FIXED_NO_ICON_SIZE);
514 mbss.srcp = (u8 *)&mbss.nowGameInfop->fixed.parent;
515 }
516 mbss.state = MB_BEACON_STATE_FIXED;
517 }
518
519
520 // Split up the fixed data portion of the game information and send a beacon.
MBi_SendFixedBeacon(u32 ggid,u16 tgid,u8 attribute)521 static void MBi_SendFixedBeacon(u32 ggid, u16 tgid, u8 attribute)
522 {
523 u32 lastAddr = (u32)mbss.nowGameInfop + sizeof(MBGameInfoFixed);
524
525 if ((u32)mbss.srcp + MB_BEACON_FIXED_DATA_SIZE <= lastAddr)
526 {
527 bsendBuff.data.fixed.size = MB_BEACON_FIXED_DATA_SIZE;
528 }
529 else
530 {
531 bsendBuff.data.fixed.size = (u8)(lastAddr - (u32)mbss.srcp);
532 MI_CpuClear16((void *)((u8 *)bsendBuff.data.fixed.data + bsendBuff.data.fixed.size),
533 (u32)(MB_BEACON_FIXED_DATA_SIZE - bsendBuff.data.fixed.size));
534 }
535
536 // Set to the beacon send buffer.
537 MB_DEBUG_OUTPUT("send flagment= %2d adr = 0x%x\n", mbss.flagmentNo, mbss.srcp);
538 MI_CpuCopy16(mbss.srcp, bsendBuff.data.fixed.data, bsendBuff.data.fixed.size);
539 bsendBuff.data.fixed.flagmentNo = mbss.flagmentNo;
540 bsendBuff.data.fixed.flagmentMaxNum = mbss.flagmentMaxNum;
541 bsendBuff.dataAttr = mbss.nowGameInfop->dataAttr;
542 bsendBuff.seqNoFixed = mbss.nowGameInfop->seqNoFixed;
543 bsendBuff.seqNoVolat = mbss.seqNoVolat;
544 bsendBuff.ggid = mbss.nowGameInfop->ggid;
545 bsendBuff.fileNo = mbss.nowGameInfop->fileNo;
546 bsendBuff.beaconNo = mbss.beaconNo++;
547 bsendBuff.data.fixed.sum = 0;
548 bsendBuff.data.fixed.sum = MBi_calc_cksum((u16 *)&bsendBuff.data, MB_BEACON_DATA_SIZE);
549
550 // Update the send status.
551 mbss.flagmentNo++;
552 if (mbss.flagmentNo < mbss.flagmentMaxNum)
553 {
554 mbss.srcp += MB_BEACON_FIXED_DATA_SIZE;
555 }
556 else
557 {
558 mbss.state = MB_BEACON_STATE_VOLAT_START;
559 }
560
561 /* Register the GGID of the parent program itself. */
562 (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, ggid, tgid,
563 (u8)(attribute | WM_ATTR_FLAG_MB | WM_ATTR_FLAG_ENTRY));
564 // The multiboot flag is activated here.
565 }
566
567
568 // Initialize transmission of the volatile data portion of the game information.
MBi_InitSendVolatBeacon(void)569 static void MBi_InitSendVolatBeacon(void)
570 {
571 mbss.nowGameInfop->broadcastedPlayerFlag = 0x0001;
572 mbss.seqNoVolat = mbss.nowGameInfop->seqNoVolat;
573 mbss.state = MB_BEACON_STATE_VOLAT;
574 }
575
576
577 // Split up the volatile data portion of the game information and send a beacon.
MBi_SendVolatBeacon(u32 ggid,u16 tgid,u8 attribute)578 static void MBi_SendVolatBeacon(u32 ggid, u16 tgid, u8 attribute)
579 {
580 int i;
581 int setPlayerNum;
582 u16 remainPlayerFlag;
583
584 if (mbss.seqNoVolat != mbss.nowGameInfop->seqNoVolat)
585 { // Resend if the data is updated during a send.
586 MBi_InitSendVolatBeacon();
587 }
588
589 // Set the beacon information.
590 bsendBuff.dataAttr = MB_BEACON_DATA_ATTR_VOLAT;
591 bsendBuff.seqNoFixed = mbss.nowGameInfop->seqNoFixed;
592 bsendBuff.seqNoVolat = mbss.seqNoVolat;
593 bsendBuff.ggid = mbss.nowGameInfop->ggid;
594 bsendBuff.fileNo = mbss.nowGameInfop->fileNo;
595 bsendBuff.beaconNo = mbss.beaconNo++;
596
597 // Set the state of the current player information.
598 bsendBuff.data.volat.nowPlayerNum = mbss.nowGameInfop->volat.nowPlayerNum;
599 bsendBuff.data.volat.nowPlayerFlag = mbss.nowGameInfop->volat.nowPlayerFlag;
600 bsendBuff.data.volat.changePlayerFlag = mbss.nowGameInfop->volat.changePlayerFlag;
601
602 // Set the application configuration data.
603 if (sSendVolatCallbackTimming == MB_SEND_VOLAT_CALLBACK_TIMMING_BEFORE
604 && sSendVolatCallback != NULL)
605 {
606 sSendVolatCallback(mbss.nowGameInfop->ggid);
607 }
608
609 for (i = 0; i < MB_USER_VOLAT_DATA_SIZE; i++)
610 {
611 bsendBuff.data.volat.userVolatData[i] = mbss.nowGameInfop->volat.userVolatData[i];
612 }
613
614 MB_DEBUG_OUTPUT("send PlayerFlag = %x\n", mbss.nowGameInfop->volat.nowPlayerFlag);
615
616 // Set the player information to send this time.
617 MI_CpuClear16(&bsendBuff.data.volat.member[0], sizeof(MBUserInfo) * MB_SEND_MEMBER_MAX_NUM);
618 setPlayerNum = 0;
619 remainPlayerFlag =
620 (u16)(mbss.nowGameInfop->broadcastedPlayerFlag ^ mbss.nowGameInfop->volat.nowPlayerFlag);
621 for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
622 {
623 if ((remainPlayerFlag & (0x0002 << i)) == 0)
624 {
625 continue;
626 }
627
628 MB_DEBUG_OUTPUT(" member %d set.\n", i);
629
630 MI_CpuCopy16(&mbss.nowGameInfop->volat.member[i],
631 &bsendBuff.data.volat.member[setPlayerNum], sizeof(MBUserInfo));
632 mbss.nowGameInfop->broadcastedPlayerFlag |= 0x0002 << i;
633 if (++setPlayerNum == MB_SEND_MEMBER_MAX_NUM)
634 {
635 break;
636 }
637 }
638 if (setPlayerNum < MB_SEND_MEMBER_MAX_NUM)
639 { // Terminate when the maximum number of sends was not reached.
640 bsendBuff.data.volat.member[setPlayerNum].playerNo = 0;
641 }
642
643 // Set the checksum.
644 bsendBuff.data.volat.sum = 0;
645 bsendBuff.data.volat.sum = MBi_calc_cksum((u16 *)&bsendBuff.data, MB_BEACON_DATA_SIZE);
646
647
648 // check for send end
649 if (mbss.nowGameInfop->broadcastedPlayerFlag == mbss.nowGameInfop->volat.nowPlayerFlag)
650 {
651 mbss.state = MB_BEACON_STATE_READY; // When sending of all information is complete, moves to a ready state in order to send the next game information.
652 }
653
654 /* Register the GGID of the parent program itself. */
655
656 (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, ggid, tgid,
657 (u8)(attribute | WM_ATTR_FLAG_MB | WM_ATTR_FLAG_ENTRY));
658 // The multiboot flag is activated here.
659
660 if (sSendVolatCallbackTimming == MB_SEND_VOLAT_CALLBACK_TIMMING_AFTER
661 && sSendVolatCallback != NULL)
662 {
663 sSendVolatCallback(mbss.nowGameInfop->ggid);
664 }
665
666 }
667
668
669 //=========================================================
670 // Beacon reception of the game information by the child device.
671 //=========================================================
672
673 // Initializes the game information receive status.
MB_InitRecvGameInfoStatus(void)674 void MB_InitRecvGameInfoStatus(void)
675 {
676 MI_CpuClearFast(mbrsp, sizeof(MbBeaconRecvStatus));
677
678 mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_NORMAL;
679 }
680
681
682 // Receives a beacon.
MB_RecvGameInfoBeacon(MBBeaconMsgCallback Callbackp,u16 linkLevel,WMBssDesc * bssDescp)683 BOOL MB_RecvGameInfoBeacon(MBBeaconMsgCallback Callbackp, u16 linkLevel, WMBssDesc *bssDescp)
684 {
685 int index;
686
687 // Determine whether or not the beacon obtained this time is a multiboot parent device.
688 if (!MBi_CheckMBParent(bssDescp))
689 {
690 return FALSE;
691 }
692
693 /* Copy the obtained bssDesc to a temporary buffer */
694 MI_CpuCopy16(bssDescp, &bssDescbuf, sizeof(WMBssDesc));
695
696 /* Switch bssDescp to a local buffer. */
697 bssDescp = &bssDescbuf;
698
699 brecvBuffp = (MbBeacon *) bssDescp->gameInfo.userGameInfo;
700
701 // Confirm checksum.
702 if (MBi_calc_cksum((u16 *)&brecvBuffp->data, MB_BEACON_DATA_SIZE))
703 {
704 MB_DEBUG_OUTPUT("Beacon checksum error!\n");
705 return FALSE;
706 }
707
708 // Determines the location for storing the parent's game information (if the same parent data has already been received, continue to store at that location)
709 index = MBi_GetStoreElement(bssDescp, Callbackp);
710 if (index < 0)
711 {
712 return FALSE; // Returns an error because there is no storage location
713 }
714 MB_DEBUG_OUTPUT("GameInfo Index:%6d\n", index);
715
716 // Beacon analysis
717 MBi_AnalyzeBeacon(bssDescp, index, linkLevel);
718
719 // Determines whether all the parent's game data fragments are gathered together and makes a notification with a callback
720 MBi_CheckCompleteGameInfoFlagments(index, Callbackp);
721
722 return TRUE;
723 }
724
725
726 // Determines whether the beacon that was obtained this time is a multiboot parent device.
MBi_CheckMBParent(WMBssDesc * bssDescp)727 BOOL MBi_CheckMBParent(WMBssDesc *bssDescp)
728 {
729 // Determines whether it is a multiboot parent device.
730 if ((bssDescp->gameInfo.magicNumber != WM_GAMEINFO_MAGIC_NUMBER)
731 || !(bssDescp->gameInfo.attribute & WM_ATTR_FLAG_MB))
732 {
733 MB_DEBUG_OUTPUT("not MB parent : %x%x\n",
734 *(u16 *)(&bssDescp->bssid[4]), *(u32 *)bssDescp->bssid);
735 return FALSE;
736 }
737 else
738 {
739
740 MB_DEBUG_OUTPUT("MB parent : %x%x",
741 *(u16 *)(&bssDescp->bssid[4]), *(u32 *)bssDescp->bssid);
742 return TRUE;
743 }
744 }
745
746
747 // Sets an SSID to bssDesc.
MBi_SetSSIDToBssDesc(WMBssDesc * bssDescp,u32 ggid)748 static void MBi_SetSSIDToBssDesc(WMBssDesc *bssDescp, u32 ggid)
749 {
750 /*
751 SSID settings
752
753 The SSID is generated from the download application specific GGID and the multiboot parent's TGID.
754
755 The child reconnects with the parent application using this SSID.
756 */
757 bssDescp->ssidLength = 32;
758 ((u16 *)bssDescp->ssid)[0] = (u16)(ggid & 0x0000ffff);
759 ((u16 *)bssDescp->ssid)[1] = (u16)((ggid & 0xffff0000) >> 16);
760 ((u16 *)bssDescp->ssid)[2] = bssDescp->gameInfo.tgid;
761 }
762
763
764 // Based on bssDesc, gets where in the receive list elements to perform a store.
MBi_GetStoreElement(WMBssDesc * bssDescp,MBBeaconMsgCallback Callbackp)765 static int MBi_GetStoreElement(WMBssDesc *bssDescp, MBBeaconMsgCallback Callbackp)
766 {
767 int i;
768
769 // Determines whether the same game information has already been received from this parent (if "GGID", "BSSID" and "fileNo" all match, the game information is determined to be the same)
770 for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
771 {
772 MBGameInfoRecvList *info = &mbrsp->list[i];
773
774 if ((mbrsp->usingGameInfoFlag & (0x01 << i)) == 0)
775 {
776 continue;
777 }
778 // Does GGID match?
779 if (info->gameInfo.ggid != brecvBuffp->ggid)
780 {
781 continue;
782 }
783 // Does the MAC address match?
784 if (!WM_IsBssidEqual(info->bssDesc.bssid, bssDescp->bssid))
785 {
786 continue;
787 }
788 // Does the file number match?
789 if (mbrsp->list[i].gameInfo.fileNo != brecvBuffp->fileNo)
790 {
791 continue;
792 }
793
794 // =========================================
795 // Determined that a reception location for this parent device information has already been allocated.
796 // =========================================
797 if (!(mbrsp->validGameInfoFlag & (0x01 << i)))
798 {
799 MBi_LockScanTarget(i); // If information for the appropriate Parent Device is not ready, scan lock.
800 }
801 return i;
802 }
803
804 // It has not yet been received, so search for the NULL position in the list and make that the storage location.
805 for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
806 {
807 if (mbrsp->usingGameInfoFlag & (0x01 << i))
808 {
809 continue;
810 }
811
812 MI_CpuCopy16(bssDescp, &mbrsp->list[i].bssDesc, sizeof(WMBssDesc));
813 // Copies BssDesc
814 mbrsp->list[i].gameInfo.seqNoFixed = brecvBuffp->seqNoFixed;
815 mbrsp->usingGameInfoFlag |= (u16)(0x01 << i);
816
817 MB_DEBUG_OUTPUT("\n");
818 // Only this parent device should be locked to the scan target.
819 MBi_LockScanTarget(i);
820 return i;
821 }
822
823 // If all the storage locations are full, an error is returned with a callback notification
824 if (Callbackp != NULL)
825 {
826 Callbackp(MB_BC_MSG_GINFO_LIST_FULL, NULL, 0);
827 }
828 return -1;
829 }
830
831
832 // Determines whether all the parent's game data fragments are gathered together and makes a notification with a callback
MBi_CheckCompleteGameInfoFlagments(int index,MBBeaconMsgCallback Callbackp)833 static void MBi_CheckCompleteGameInfoFlagments(int index, MBBeaconMsgCallback Callbackp)
834 {
835 MBGameInfoRecvList *info = &mbrsp->list[index];
836
837 /* In any case, notify the application that a parent was discovered. */
838 if (Callbackp != NULL)
839 {
840 Callbackp(MB_BC_MSG_GINFO_BEACON, info, index);
841 }
842 if ((info->getFlagmentFlag == info->allFlagmentFlag) && (info->getFlagmentFlag) // If the new parent game information is complete
843 && (info->gameInfo.volat.nowPlayerFlag)
844 && (info->getPlayerFlag == info->gameInfo.volat.nowPlayerFlag))
845 {
846 if (mbrsp->validGameInfoFlag & (0x01 << index))
847 {
848 return;
849 }
850 mbrsp->validGameInfoFlag |= 0x01 << index;
851 mbrsp->usefulGameInfoFlag |= 0x01 << index;
852 MBi_UnlockScanTarget(); // Releases the lock on the scan target
853 MB_DEBUG_OUTPUT("validated ParentInfo = %d\n", index);
854 if (Callbackp != NULL)
855 {
856 Callbackp(MB_BC_MSG_GINFO_VALIDATED, info, index);
857 }
858 }
859 else
860 { // If the parent's game information that was already obtained is updated and becomes incomplete
861 if ((mbrsp->validGameInfoFlag & (0x01 << index)) == 0)
862 {
863 return;
864 }
865 mbrsp->validGameInfoFlag ^= (0x01 << index);
866 MB_DEBUG_OUTPUT("Invaldated ParentInfo = %d\n", index);
867 if (Callbackp != NULL)
868 {
869 Callbackp(MB_BC_MSG_GINFO_INVALIDATED, info, index);
870 }
871 }
872 }
873
874
875 // The parent's game information lifetime count (while doing so, also counts the scan lock time)
MB_CountGameInfoLifetime(MBBeaconMsgCallback Callbackp,BOOL found_parent)876 void MB_CountGameInfoLifetime(MBBeaconMsgCallback Callbackp, BOOL found_parent)
877 {
878 int i;
879 BOOL unlock = FALSE;
880
881 // Determines the lifetime of the game information receiving list and confirms the presence of a new lock target.
882 for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
883 {
884 MBGameInfoRecvList *info = &mbrsp->list[i];
885 u16 mask = (u16)(0x0001 << i);
886 if ((mbrsp->usingGameInfoFlag & mask) == 0)
887 {
888 continue;
889 }
890 // Lifetime determination
891 info->lifetimeCount -= mbrsp->scanCountUnit;
892 if (info->lifetimeCount >= 0)
893 {
894 continue;
895 }
896 info->lifetimeCount = 0;
897 if (mbrsp->validGameInfoFlag & mask)
898 {
899 if (Callbackp != NULL)
900 {
901 Callbackp(MB_BC_MSG_GINFO_LOST, info, i);
902 }
903 }
904 if (mbrsp->nowScanTargetFlag & mask)
905 {
906 unlock = TRUE;
907 }
908 mbrsp->usingGameInfoFlag &= ~mask;
909 MB_DeleteRecvGameInfo(i); // Deletes game information after callback notification.
910 MB_DEBUG_OUTPUT("gameInfo %2d : lifetime end.\n", i);
911 }
912
913 // Scan lock time count
914 if (mbrsp->nowScanTargetFlag && mbrsp->nowLockTimeCount > 0)
915 {
916 mbrsp->nowLockTimeCount -= mbrsp->scanCountUnit; // Releases the lock and searches for the next lock target if the scan lock times out.
917 if (mbrsp->nowLockTimeCount < 0)
918 {
919 MB_DEBUG_OUTPUT("scan lock time up!\n");
920 unlock = TRUE;
921 }
922 else if (!found_parent)
923 {
924 if (++mbrsp->notFoundLockTargetCount > 4)
925 {
926 MB_DEBUG_OUTPUT("scan lock target not found!\n");
927 unlock = TRUE;
928 }
929 }
930 else
931 {
932 mbrsp->notFoundLockTargetCount = 0;
933 }
934 }
935
936 // Scan unlock processing.
937 if (unlock)
938 {
939 mbrsp->nowLockTimeCount = 0;
940 MBi_UnlockScanTarget();
941 }
942 }
943
944
945 // Beacon analysis
MBi_AnalyzeBeacon(WMBssDesc * bssDescp,int index,u16 linkLevel)946 static void MBi_AnalyzeBeacon(WMBssDesc *bssDescp, int index, u16 linkLevel)
947 {
948 MBi_CheckTGID(bssDescp, index); // Checks the TGID
949 MBi_CheckSeqNoFixed(index); // Checks seqNoFixed
950 MBi_CheckSeqNoVolat(index); // Checks seqNoVolat
951
952 // Obtains data for the shared portion of the received beacon
953 {
954 MBGameInfoRecvList *info = &mbrsp->list[index];
955
956 // Excludes parents that are in an abnormal state, repeatedly sending out the same beacon.
957 if (info->beaconNo == brecvBuffp->beaconNo)
958 {
959 if (++info->sameBeaconRecvCount > MB_SAME_BEACON_RECV_MAX_COUNT)
960 {
961 info->lifetimeCount = 0; // Sets the lifetime of the parent information to zero so it gets deleted.
962 MB_OUTPUT("The parent broadcast same beacon.: %d\n", index);
963 MBi_InvalidateGameInfoBssID(&info->bssDesc.bssid[0]);
964 return; // If this parent has distributed other game information, that is deleted as well.
965 }
966 }
967 else
968 {
969 info->sameBeaconRecvCount = 0;
970 }
971 // Data reception for normal parents.
972 info->beaconNo = brecvBuffp->beaconNo;
973 info->lifetimeCount = MB_LIFETIME_MAX_COUNT; // Extends the lifetime of the parent's information.
974 info->gameInfo.ggid = brecvBuffp->ggid; // Gets ggid.
975 info->gameInfo.fileNo = brecvBuffp->fileNo; // Gets fileNo.
976 info->linkLevel = linkLevel; // Gets the signal strength.
977 // Sets an SSID to bssDesc.
978 MBi_SetSSIDToBssDesc(&info->bssDesc, info->gameInfo.ggid);
979 }
980
981 // Gets data for each data type in the received beacon.
982 if (brecvBuffp->dataAttr == MB_BEACON_DATA_ATTR_VOLAT)
983 {
984 MBi_RecvVolatBeacon(index);
985 }
986 else
987 {
988 MBi_RecvFixedBeacon(index);
989 }
990 }
991
992
993 // Checks tgid
MBi_CheckTGID(WMBssDesc * bssDescp,int index)994 static void MBi_CheckTGID(WMBssDesc *bssDescp, int index)
995 {
996 if (mbrsp->list[index].bssDesc.gameInfo.tgid == bssDescp->gameInfo.tgid)
997 {
998 return;
999 }
1000
1001 // If tgid is updated, that parent device is assumed to be restarting; all data is cleared and re-obtained.
1002 MB_DEBUG_OUTPUT("\ntgid updated! : %x%x", *(u16 *)(&bssDescp->bssid[4]),
1003 *(u32 *)bssDescp->bssid);
1004 MB_DeleteRecvGameInfoWithoutBssdesc(index);
1005 MI_CpuCopy16(bssDescp, &mbrsp->list[index].bssDesc, sizeof(WMBssDesc));
1006 // A new bssDesc is copied in the event of a tgid update.
1007 MBi_LockScanTarget(index); // Scan-locks the appropriate parent.
1008 }
1009
1010
1011 // Checks the SeqNo of the fixed data
MBi_CheckSeqNoFixed(int index)1012 static void MBi_CheckSeqNoFixed(int index)
1013 {
1014 // Handles the situation where the sequence number has been updated
1015 if (mbrsp->list[index].gameInfo.seqNoFixed == brecvBuffp->seqNoFixed)
1016 {
1017 return;
1018 }
1019 // Clears the data received thus far if the sequence number has been updated.
1020 MB_DEBUG_OUTPUT("\n seqNoFixed updated!");
1021 MB_DeleteRecvGameInfoWithoutBssdesc(index);
1022 MBi_LockScanTarget(index); // Scan-locks the appropriate parent.
1023 mbrsp->list[index].gameInfo.seqNoFixed = brecvBuffp->seqNoFixed;
1024 }
1025
1026
1027 // Checks the SeqNo of the volatile data.
MBi_CheckSeqNoVolat(int index)1028 static void MBi_CheckSeqNoVolat(int index)
1029 {
1030 MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1031
1032 // Handles the situation where the sequence number has been updated
1033 if (mbrsp->list[index].gameInfo.seqNoVolat != brecvBuffp->seqNoVolat)
1034 {
1035 MB_DEBUG_OUTPUT("\n seqNoVolat updated!");
1036 MBi_LockScanTarget(index); // Checks whether a scan lock is possible, then does so.
1037 }
1038 }
1039
1040
1041 // Invalidates all the parent game information of the target BSSID.
MBi_InvalidateGameInfoBssID(u8 * bssidp)1042 static void MBi_InvalidateGameInfoBssID(u8 *bssidp)
1043 {
1044 int i;
1045 for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
1046 {
1047 if ((mbrsp->usingGameInfoFlag & (0x01 << i)) == 0)
1048 {
1049 continue;
1050 }
1051
1052 if (!WM_IsBssidEqual(bssidp, mbrsp->list[i].bssDesc.bssid))
1053 {
1054 continue;
1055 }
1056
1057 // Determined to be data that is targeted for deletion.
1058 mbrsp->list[i].lifetimeCount = 0; // Sets the lifetime of the parent information to zero so it gets deleted.
1059 MB_OUTPUT("The parent broadcast same beacon.: %d\n", i);
1060 }
1061 }
1062
1063
1064 // Splits up the fixed data portion of the game information and receives the beacon.
MBi_RecvFixedBeacon(int index)1065 static void MBi_RecvFixedBeacon(int index)
1066 {
1067 MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1068 u32 lastAddr = (u32)&grecvp->gameInfo + sizeof(MBGameInfoFixed);
1069 u8 *dstp;
1070
1071 // Do not receive if the sequence number has not been updated, and the beacon has already been obtained.
1072 if (grecvp->gameInfo.seqNoFixed == brecvBuffp->seqNoFixed)
1073 {
1074 if (grecvp->getFlagmentFlag & (0x01 << brecvBuffp->data.fixed.flagmentNo))
1075 {
1076 return;
1077 }
1078 }
1079
1080 // Checks whether the received beacon exceeds the receive buffer.
1081 if (brecvBuffp->dataAttr == MB_BEACON_DATA_ATTR_FIXED_NORMAL)
1082 {
1083 dstp = (u8 *)&grecvp->gameInfo.fixed;
1084 }
1085 else
1086 {
1087 dstp = (u8 *)&grecvp->gameInfo.fixed.parent;
1088 }
1089 dstp += MB_BEACON_FIXED_DATA_SIZE * brecvBuffp->data.fixed.flagmentNo;
1090 // Calculates the receiving address for the game information buffer.
1091
1092 if ((u32)dstp + brecvBuffp->data.fixed.size > lastAddr)
1093 {
1094 MB_DEBUG_OUTPUT("recv beacon gInfoFixed Buffer over!\n");
1095 // Ignores beacon data that overflows the buffer.
1096 return;
1097 }
1098
1099 // Sets the received beacon to the target game information buffer
1100 MB_DEBUG_OUTPUT("recv flagment= %2d adr = 0x%x", brecvBuffp->data.fixed.flagmentNo, dstp);
1101 MI_CpuCopy16(brecvBuffp->data.fixed.data, dstp, brecvBuffp->data.fixed.size);
1102 grecvp->gameInfo.dataAttr = brecvBuffp->dataAttr;
1103 grecvp->getFlagmentFlag |= 0x01 << brecvBuffp->data.fixed.flagmentNo;
1104 grecvp->allFlagmentFlag = (u32)((0x01 << brecvBuffp->data.fixed.flagmentMaxNum) - 1);
1105 MB_DEBUG_OUTPUT("\t now flagment = 0x%x \t all flagment = 0x%x\n",
1106 grecvp->getFlagmentFlag, grecvp->allFlagmentFlag);
1107 }
1108
1109
1110 // Splits up the volatile data portion of the game information and receives the beacon.
MBi_RecvVolatBeacon(int index)1111 static void MBi_RecvVolatBeacon(int index)
1112 {
1113 int i;
1114 MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1115
1116 /* Always receive user-defined data. */
1117 for (i = 0; i < MB_USER_VOLAT_DATA_SIZE; i++)
1118 {
1119 grecvp->gameInfo.volat.userVolatData[i] = brecvBuffp->data.volat.userVolatData[i];
1120 }
1121 MI_CpuCopy16(brecvBuffp, &grecvp->bssDesc.gameInfo.userGameInfo, WM_SIZE_USER_GAMEINFO);
1122
1123 // Processing when a member information update is detected.
1124 if (grecvp->gameInfo.seqNoVolat != brecvBuffp->seqNoVolat)
1125 {
1126 if ((u8)(grecvp->gameInfo.seqNoVolat + 1) == brecvBuffp->seqNoVolat)
1127 { // Transfer of non-updated member information if seqNoVolat is off by one
1128 for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
1129 {
1130 if (brecvBuffp->data.volat.changePlayerFlag & (0x02 << i))
1131 {
1132 MI_CpuClear16(&grecvp->gameInfo.volat.member[i], sizeof(MBUserInfo));
1133 }
1134 }
1135 grecvp->getPlayerFlag &= ~brecvBuffp->data.volat.changePlayerFlag;
1136 mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1137 }
1138 else
1139 { // Clears all the member information received thus far if seqNoVolat is further off.
1140 MI_CpuClear16(&grecvp->gameInfo.volat.member[0],
1141 sizeof(MBUserInfo) * MB_MEMBER_MAX_NUM);
1142 grecvp->getPlayerFlag = 0;
1143 mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1144 }
1145 grecvp->gameInfo.seqNoVolat = brecvBuffp->seqNoVolat;
1146 }
1147 else if (grecvp->getPlayerFlag == brecvBuffp->data.volat.nowPlayerFlag)
1148 {
1149 return; // Do not receive if the sequence number has not been updated, and the beacon has already been obtained.
1150 }
1151
1152 // Reads the player information
1153 grecvp->gameInfo.volat.nowPlayerNum = brecvBuffp->data.volat.nowPlayerNum;
1154 grecvp->gameInfo.volat.nowPlayerFlag = brecvBuffp->data.volat.nowPlayerFlag;
1155 grecvp->gameInfo.volat.changePlayerFlag = brecvBuffp->data.volat.changePlayerFlag;
1156 grecvp->getPlayerFlag |= 0x0001;
1157
1158 // Reads the user information for each member
1159 for (i = 0; i < MB_SEND_MEMBER_MAX_NUM; i++)
1160 {
1161 int playerNo = (int)brecvBuffp->data.volat.member[i].playerNo;
1162 if (playerNo == 0)
1163 {
1164 continue;
1165 }
1166 MB_DEBUG_OUTPUT("member %d recv.\n", playerNo);
1167 MI_CpuCopy16(&brecvBuffp->data.volat.member[i],
1168 &grecvp->gameInfo.volat.member[playerNo - 1], sizeof(MBUserInfo));
1169 grecvp->getPlayerFlag |= 0x01 << playerNo;
1170 }
1171 }
1172
1173
1174 // Locks the scan target to a single parent
MBi_LockScanTarget(int index)1175 static void MBi_LockScanTarget(int index)
1176 {
1177 /* Ignore if there is already a locked target */
1178 if (mbrsp->nowScanTargetFlag)
1179 {
1180 return;
1181 }
1182
1183 if (sLockFunc != NULL)
1184 {
1185 sLockFunc(mbrsp->list[index].bssDesc.bssid);
1186 }
1187 mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_LOCKING;
1188
1189 mbrsp->nowScanTargetFlag = (u16)(0x01 << index); // Shows new scan lock targets in bits.
1190 mbrsp->nowLockTimeCount = MB_LOCKTIME_MAX_COUNT; // Initializes the scan lock time
1191 MB_DEBUG_OUTPUT("scan target locked. : %x %x %x %x %x %x\n",
1192 mbrsp->list[index].bssDesc.bssid[0],
1193 mbrsp->list[index].bssDesc.bssid[1],
1194 mbrsp->list[index].bssDesc.bssid[2],
1195 mbrsp->list[index].bssDesc.bssid[3],
1196 mbrsp->list[index].bssDesc.bssid[4], mbrsp->list[index].bssDesc.bssid[5]);
1197 }
1198
1199
1200 // Releases the scan target lock.
MBi_UnlockScanTarget(void)1201 static void MBi_UnlockScanTarget(void)
1202 {
1203 if (mbrsp->nowScanTargetFlag == 0)
1204 {
1205 return;
1206 }
1207
1208 if (sUnlockFunc != NULL)
1209 {
1210 sUnlockFunc();
1211 }
1212 mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_NORMAL;
1213 mbrsp->nowScanTargetFlag = 0;
1214 mbrsp->notFoundLockTargetCount = 0;
1215
1216 MB_DEBUG_OUTPUT(" unlock target\n");
1217 }
1218
1219
1220 // Completely deletes the received game information (also deletes the valid game information flag)
MB_DeleteRecvGameInfo(int index)1221 void MB_DeleteRecvGameInfo(int index)
1222 {
1223 mbrsp->usefulGameInfoFlag &= ~(0x0001 << index);
1224 mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1225 MI_CpuClear16(&mbrsp->list[index], sizeof(MBGameInfoRecvList));
1226 }
1227
1228
1229 // Deletes the received game information, except for bssDesc.
MB_DeleteRecvGameInfoWithoutBssdesc(int index)1230 void MB_DeleteRecvGameInfoWithoutBssdesc(int index)
1231 {
1232 mbrsp->usefulGameInfoFlag &= ~(0x0001 << index);
1233 mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1234 mbrsp->list[index].getFlagmentFlag = 0;
1235 mbrsp->list[index].allFlagmentFlag = 0;
1236 mbrsp->list[index].getPlayerFlag = 0;
1237 mbrsp->list[index].linkLevel = 0;
1238 MI_CpuClear16(&(mbrsp->list[index].gameInfo), sizeof(MBGameInfo));
1239 }
1240
1241 // Gets a pointer to a received parent information structure.
MB_GetGameInfoRecvList(int index)1242 MBGameInfoRecvList *MB_GetGameInfoRecvList(int index)
1243 {
1244 // Returns NULL if there is no valid data
1245 if ((mbrsp->usefulGameInfoFlag & (0x01 << index)) == 0)
1246 {
1247 return NULL;
1248 }
1249
1250 return &mbrsp->list[index];
1251 }
1252
1253
1254 //=========================================================
1255 // User volatile data settings
1256 //=========================================================
1257
1258 /*---------------------------------------------------------------------------*
1259 Name: MB_SetSendVolatileCallback
1260
1261 Description: Sets the multiboot beacon-transmission callback.
1262
1263 Arguments: callback: The callback function for a completed transmission.
1264 The callback is invoked whenever data is sent.
1265 timing: The timing for issuing the callback.
1266
1267 Returns: None.
1268 *---------------------------------------------------------------------------*/
MB_SetSendVolatCallback(MBSendVolatCallbackFunc callback,u32 timming)1269 void MB_SetSendVolatCallback(MBSendVolatCallbackFunc callback, u32 timming)
1270 {
1271 OSIntrMode enabled = OS_DisableInterrupts();
1272
1273 sSendVolatCallback = callback;
1274 sSendVolatCallbackTimming = timming;
1275
1276 (void)OS_RestoreInterrupts(enabled);
1277 }
1278
1279
1280
1281 /*---------------------------------------------------------------------------*
1282 Name: MB_SetUserVolatData
1283
1284 Description: Sets user data in an available region of a multiboot beacon.
1285
1286 Arguments: ggid: Specifies the ggid of the program that was set by MB_RegisterFile, and attaches user data to this file's beacon.
1287
1288 userData: Pointer to the user data being set.
1289 size: Size of the user data being set. (8 bytes maximum)
1290
1291 Returns: None.
1292 *---------------------------------------------------------------------------*/
MB_SetUserVolatData(u32 ggid,const u8 * userData,u32 size)1293 void MB_SetUserVolatData(u32 ggid, const u8 *userData, u32 size)
1294 {
1295 MBGameInfo *gameInfo;
1296
1297 SDK_ASSERT(size <= MB_USER_VOLAT_DATA_SIZE);
1298 SDK_NULL_ASSERT(userData);
1299
1300 gameInfo = mbss.gameInfoListTop;
1301 if (gameInfo == NULL)
1302 {
1303 return;
1304 }
1305
1306 while (gameInfo->ggid != ggid)
1307 {
1308 if (gameInfo == NULL)
1309 {
1310 return;
1311 }
1312 gameInfo = gameInfo->nextp;
1313 }
1314
1315 {
1316 u32 i;
1317
1318 OSIntrMode enabled = OS_DisableInterrupts();
1319
1320 for (i = 0; i < size; i++)
1321 {
1322 gameInfo->volat.userVolatData[i] = userData[i];
1323 }
1324
1325 (void)OS_RestoreInterrupts(enabled);
1326 }
1327 }
1328
1329 /*---------------------------------------------------------------------------*
1330 Name: MB_GetUserVolatData
1331
1332 Description: Gets the user data in an available region of a beacon.
1333
1334 Arguments: gameInfo: Pointer to the gameInfo parameter that will be obtained at Scan time.
1335
1336 Returns: Pointer to the user data.
1337 *---------------------------------------------------------------------------*/
MB_GetUserVolatData(const WMGameInfo * gameInfo)1338 void *MB_GetUserVolatData(const WMGameInfo *gameInfo)
1339 {
1340 MbBeacon *beacon;
1341
1342 SDK_NULL_ASSERT(gameInfo);
1343
1344 if (!(gameInfo->attribute & WM_ATTR_FLAG_MB))
1345 {
1346 return NULL;
1347 }
1348
1349 beacon = (MbBeacon *) (gameInfo->userGameInfo);
1350
1351 if (beacon->dataAttr != MB_BEACON_DATA_ATTR_VOLAT)
1352 {
1353 return NULL;
1354 }
1355
1356 return beacon->data.volat.userVolatData;
1357 }
1358