Finish remaining symbols in link_rfu_2

This commit is contained in:
GriffinR 2021-10-07 14:55:15 -04:00
parent 6aaf50ee27
commit 846942ce48
8 changed files with 248 additions and 220 deletions

View File

@ -293,7 +293,7 @@ void SetBerryBlenderLinkCallback(void);
void SetSuppressLinkErrorMessage(bool8 flag); void SetSuppressLinkErrorMessage(bool8 flag);
void ConvertLinkPlayerName(struct LinkPlayer *linkPlayer); void ConvertLinkPlayerName(struct LinkPlayer *linkPlayer);
void ClearSavedLinkPlayers(void); void ClearSavedLinkPlayers(void);
void BufferLinkErrorInfo(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 disconnected); void SetLinkErrorBuffer(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 disconnected);
void LocalLinkPlayerToBlock(void); void LocalLinkPlayerToBlock(void);
void LinkPlayerFromBlock(u32 who); void LinkPlayerFromBlock(u32 who);
bool32 Link_AnyPartnersPlayingFRLG_JP(void); bool32 Link_AnyPartnersPlayingFRLG_JP(void);

View File

@ -68,6 +68,21 @@ enum {
RFU_ERROR_STATE_IGNORE, RFU_ERROR_STATE_IGNORE,
}; };
// These error flags are set in errorInfo, and given as
// the uppermost 16 bits of 'status' for sLinkErrorBuffer.
// The first 8 bits are reserved for the link manager msg
// when the error occurred, and the last 8 bits are this
// sequence of presumably meaningful error flags, but
// ultimately sLinkErrorBuffer's status is never read.
#define F_RFU_ERROR_1 (1 << 8)
#define F_RFU_ERROR_2 (1 << 9) // Never set
#define F_RFU_ERROR_3 (1 << 10) // Never set
#define F_RFU_ERROR_4 (1 << 11) // Never set
#define F_RFU_ERROR_5 (1 << 12)
#define F_RFU_ERROR_6 (1 << 13)
#define F_RFU_ERROR_7 (1 << 14)
#define F_RFU_ERROR_8 (1 << 15)
struct RfuGameCompatibilityData struct RfuGameCompatibilityData
{ {
u16 language:4; u16 language:4;
@ -157,14 +172,14 @@ struct RfuManager
{ {
/* 0x000 */ void (*callback)(void); /* 0x000 */ void (*callback)(void);
/* 0x004 */ u16 state; /* 0x004 */ u16 state;
/* 0x006 */ u8 filler_06[4]; /* 0x006 */ u8 unused1[4];
/* 0x00a */ u16 linkmanMsg; /* 0x00a */ u16 errorInfo;
/* 0x00c */ u8 parentChild; /* 0x00c */ u8 parentChild;
/* 0x00d */ u8 playerCount; /* 0x00d */ u8 playerCount;
/* 0x00e */ bool8 unk_0e; /* 0x00e */ bool8 runParentMain2;
/* 0x00f */ u8 unk_0f; /* 0x00f */ u8 unused2;
/* 0x010 */ u16 unk_10; /* 0x010 */ u16 errorParam0;
/* 0x012 */ u16 unk_12; /* 0x012 */ u16 errorParam1;
/* 0x014 */ u8 childRecvBuffer[RFU_CHILD_MAX][CHILD_DATA_LENGTH]; /* 0x014 */ u8 childRecvBuffer[RFU_CHILD_MAX][CHILD_DATA_LENGTH];
/* 0x04c */ u8 childSendBuffer[CHILD_DATA_LENGTH]; /* 0x04c */ u8 childSendBuffer[CHILD_DATA_LENGTH];
/* 0x05a */ u8 blockRequestType; /* 0x05a */ u8 blockRequestType;
@ -173,7 +188,7 @@ struct RfuManager
/* 0x061 */ bool8 numBlocksReceived[MAX_RFU_PLAYERS]; /* 0x061 */ bool8 numBlocksReceived[MAX_RFU_PLAYERS];
/* 0x066 */ u8 idleTaskId; /* 0x066 */ u8 idleTaskId;
/* 0x067 */ u8 searchTaskId; /* 0x067 */ u8 searchTaskId;
/* 0x068 */ u8 filler_68[4]; /* 0x068 */ u8 unused3[4];
/* 0x06c */ struct RfuBlockSend sendBlock; /* 0x06c */ struct RfuBlockSend sendBlock;
/* 0x080 */ struct RfuBlockSend recvBlock[MAX_RFU_PLAYERS]; /* 0x080 */ struct RfuBlockSend recvBlock[MAX_RFU_PLAYERS];
/* 0x0e4 */ bool8 readyCloseLink[MAX_RFU_PLAYERS]; /* 0x0e4 */ bool8 readyCloseLink[MAX_RFU_PLAYERS];
@ -185,8 +200,8 @@ struct RfuManager
/* 0x0f2 */ u16 packet[RFU_PACKET_SIZE]; /* 0x0f2 */ u16 packet[RFU_PACKET_SIZE];
/* 0x0fe */ u16 resendExitStandbyTimer; /* 0x0fe */ u16 resendExitStandbyTimer;
/* 0x100 */ u16 allReadyNum; /* 0x100 */ u16 allReadyNum;
/* 0x102 */ u8 unk_102; /* 0x102 */ u8 childSendCmdId;
/* 0x103 */ u8 filler_103[7]; /* 0x103 */ u8 unused4[7];
/* 0x10A */ struct RfuGameData parent; /* 0x10A */ struct RfuGameData parent;
u8 filler_; u8 filler_;
u8 parentName[RFU_USER_NAME_LENGTH]; u8 parentName[RFU_USER_NAME_LENGTH];
@ -194,12 +209,12 @@ struct RfuManager
/* 0x9e8 */ struct RfuSendQueue sendQueue; /* 0x9e8 */ struct RfuSendQueue sendQueue;
/* 0xc1c */ struct RfuBackupQueue backupQueue; /* 0xc1c */ struct RfuBackupQueue backupQueue;
/* 0xc3c */ vu8 linkRecovered; /* 0xc3c */ vu8 linkRecovered;
/* 0xc3d */ u8 unk_c3d; /* 0xc3d */ u8 reconnectParentId;
/* 0xc3e */ vu8 childSlot; /* 0xc3e */ vu8 childSlot;
/* 0xc3f */ u8 unk_c3f[70]; /* 0xc3f */ u8 childRecvQueue[RECV_QUEUE_SLOT_LENGTH];
/* 0xc85 */ u8 leaveGroupStatus; /* 0xc85 */ u8 leaveGroupStatus;
/* 0xc86 */ u8 recvStatus; /* 0xc86 */ u8 childRecvStatus;
/* 0xc87 */ u8 recvCmds[5][7][2]; /* 0xc87 */ u8 recvCmds[MAX_RFU_PLAYERS][CMD_LENGTH - 1][2];
/* 0xccd */ u8 parentId; /* 0xccd */ u8 parentId;
/* 0xcce */ u8 multiplayerId; /* 0xcce */ u8 multiplayerId;
/* 0xccf */ u8 connectParentFailures; /* 0xccf */ u8 connectParentFailures;
@ -207,21 +222,21 @@ struct RfuManager
/* 0xcd1 */ u8 partnerSendStatuses[RFU_CHILD_MAX]; /* 0xcd1 */ u8 partnerSendStatuses[RFU_CHILD_MAX];
/* 0xcd5 */ u8 partnerRecvStatuses[RFU_CHILD_MAX]; /* 0xcd5 */ u8 partnerRecvStatuses[RFU_CHILD_MAX];
/* 0xcd9 */ bool8 stopNewConnections; /* 0xcd9 */ bool8 stopNewConnections;
/* 0xcda */ u8 unk_cda; /* 0xcda */ u8 parentSendSlot;
/* 0xcdb */ vbool8 unk_cdb; /* 0xcdb */ vbool8 parentFinished;
/* 0xcdc */ vbool8 unk_cdc; /* 0xcdc */ vbool8 parentMain2Failed;
/* 0xcdd */ u8 unk_cdd; /* 0xcdd */ u8 unused5;
/* 0xcde */ u8 linkPlayerIdx[RFU_CHILD_MAX]; /* 0xcde */ u8 linkPlayerIdx[RFU_CHILD_MAX];
/* 0xce2 */ u8 unk_ce2; /* 0xce2 */ u8 parentSlots;
/* 0xce2 */ u8 disconnectSlots; /* 0xce2 */ u8 disconnectSlots;
/* 0xce4 */ u8 disconnectMode; /* 0xce4 */ u8 disconnectMode;
/* 0xce5 */ u8 nextChildBits; /* 0xce5 */ u8 nextChildBits;
/* 0xce5 */ u8 newChildQueue; /* 0xce5 */ u8 newChildQueue;
/* 0xce7 */ u8 acceptSlot_flag; /* 0xce7 */ u8 acceptSlot_flag;
/* 0xce8 */ bool8 unk_ce8; /* 0xce8 */ bool8 playerExchangeActive;
/* 0xce9 */ u8 incomingChild; /* 0xce9 */ u8 incomingChild;
/* 0xcea */ u8 unk_cea[4]; /* 0xcea */ u8 numChildRecvErrors[RFU_CHILD_MAX];
/* 0xcee */ u8 unk_cee[4]; /* 0xcee */ u8 childRecvIds[RFU_CHILD_MAX];
}; // size = 0xcf4 }; // size = 0xcf4
extern struct RfuGameData gHostRfuGameData; extern struct RfuGameData gHostRfuGameData;
@ -260,8 +275,8 @@ void RfuSetIgnoreError(bool32 enable);
u8 RfuGetStatus(void); u8 RfuGetStatus(void);
struct RfuGameData *GetHostRfuGameData(void); struct RfuGameData *GetHostRfuGameData(void);
void UpdateGameData_GroupLockedIn(u8 startedActivity); void UpdateGameData_GroupLockedIn(u8 startedActivity);
void GetLinkmanErrorParams(u32 msg); void RfuSetErrorParams(u32 errorInfo);
void RfuSetStatus(u8 status, u16 msg); void RfuSetStatus(u8 status, u16 errorInfo);
u8 Rfu_SetLinkRecovery(bool32 enable); u8 Rfu_SetLinkRecovery(bool32 enable);
void CopyHostRfuGameDataAndUsername(struct RfuGameData *buff1, u8 *buff2); void CopyHostRfuGameDataAndUsername(struct RfuGameData *buff1, u8 *buff2);
void SetHostRfuGameData(u8 activity, u32 partnerInfo, bool32 startedActivity); void SetHostRfuGameData(u8 activity, u32 partnerInfo, bool32 startedActivity);
@ -293,7 +308,7 @@ void Rfu_SendPacket(void *data);
bool32 PlayerHasMetTrainerBefore(u16 id, u8 *name); bool32 PlayerHasMetTrainerBefore(u16 id, u8 *name);
void Rfu_DisconnectPlayerById(u32 playerIdx); void Rfu_DisconnectPlayerById(u32 playerIdx);
u8 GetLinkPlayerInfoFlags(s32 playerId); u8 GetLinkPlayerInfoFlags(s32 playerId);
void sub_800EF7C(void); void StopUnionRoomLinkManager(void);
bool8 Rfu_GetCompatiblePlayerData(struct RfuGameData *player, u8 *username, u8 idx); bool8 Rfu_GetCompatiblePlayerData(struct RfuGameData *player, u8 *username, u8 idx);
bool8 Rfu_GetWonderDistributorPlayerData(struct RfuGameData *player, u8 *username, u8 idx); bool8 Rfu_GetWonderDistributorPlayerData(struct RfuGameData *player, u8 *username, u8 idx);
s32 Rfu_GetIndexOfNewestChild(u8 bits); s32 Rfu_GetIndexOfNewestChild(u8 bits);
@ -301,7 +316,7 @@ void CreateTask_RfuIdle(void);
void DestroyTask_RfuIdle(void); void DestroyTask_RfuIdle(void);
void ClearRecvCommands(void); void ClearRecvCommands(void);
void LinkRfu_FatalError(void); void LinkRfu_FatalError(void);
bool32 sub_8011A9C(void); bool32 Rfu_IsPlayerExchangeActive(void);
void Rfu_StopPartnerSearch(void); void Rfu_StopPartnerSearch(void);
void RfuSetNormalDisconnectMode(void); void RfuSetNormalDisconnectMode(void);
void SetUnionRoomChatPlayerData(u32 numPlayers); void SetUnionRoomChatPlayerData(u32 numPlayers);

View File

@ -987,8 +987,8 @@ static u32 QuitBerryCrush(MainCallback exitCallback)
#define ERROR_EXIT(exitCallback) \ #define ERROR_EXIT(exitCallback) \
{ \ { \
SetMainCallback2(exitCallback); \ SetMainCallback2(exitCallback); \
gRfu.unk_10 = 0; \ gRfu.errorParam0 = 0; \
gRfu.unk_12 = 0; \ gRfu.errorParam1 = 0; \
gRfu.errorState = RFU_ERROR_STATE_1; \ gRfu.errorState = RFU_ERROR_STATE_1; \
} }

View File

@ -204,7 +204,7 @@ static void Task_ReturnToFieldWirelessLink(u8 taskId)
if (!IsLinkTaskFinished()) if (!IsLinkTaskFinished())
{ {
if (++task->data[1] > 1800) if (++task->data[1] > 1800)
GetLinkmanErrorParams(0x6000); RfuSetErrorParams(F_RFU_ERROR_6 | F_RFU_ERROR_7);
} }
else else
{ {

View File

@ -108,7 +108,7 @@ static EWRAM_DATA u16 sTimeOutCounter = 0;
EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {}; EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {};
EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {}; EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {};
static EWRAM_DATA struct LinkPlayer sSavedLinkPlayers[MAX_RFU_PLAYERS] = {}; static EWRAM_DATA struct LinkPlayer sSavedLinkPlayers[MAX_RFU_PLAYERS] = {};
EWRAM_DATA struct { static EWRAM_DATA struct {
u32 status; u32 status;
u8 lastRecvQueueCount; u8 lastRecvQueueCount;
u8 lastSendQueueCount; u8 lastSendQueueCount;
@ -140,7 +140,7 @@ static void LinkCB_WaitCloseLinkWithJP(void);
static void LinkCB_Standby(void); static void LinkCB_Standby(void);
static void LinkCB_StandbyForAll(void); static void LinkCB_StandbyForAll(void);
static void CheckErrorStatus(void); static void TrySetLinkErrorBuffer(void);
static void CB2_PrintErrorMessage(void); static void CB2_PrintErrorMessage(void);
static bool8 IsSioMultiMaster(void); static bool8 IsSioMultiMaster(void);
static void SetWirelessCommType0_Internal(void); static void SetWirelessCommType0_Internal(void);
@ -394,9 +394,7 @@ void CloseLink(void)
{ {
gReceivedRemoteLinkPlayers = FALSE; gReceivedRemoteLinkPlayers = FALSE;
if (gWirelessCommType) if (gWirelessCommType)
{
LinkRfu_Shutdown(); LinkRfu_Shutdown();
}
sLinkOpen = FALSE; sLinkOpen = FALSE;
DisableSerial(); DisableSerial();
} }
@ -496,7 +494,7 @@ u16 LinkMain2(const u16 *heldKeys)
ProcessRecvCmds(SIO_MULTI_CNT->id); ProcessRecvCmds(SIO_MULTI_CNT->id);
if (gLinkCallback != NULL) if (gLinkCallback != NULL)
gLinkCallback(); gLinkCallback();
CheckErrorStatus(); TrySetLinkErrorBuffer();
} }
return gLinkStatus; return gLinkStatus;
} }
@ -1559,10 +1557,13 @@ static void LinkCB_StandbyForAll(void)
} }
} }
static void CheckErrorStatus(void) static void TrySetLinkErrorBuffer(void)
{ {
// Check if a link error has occurred
if (sLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus)) if (sLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus))
{ {
// Link error has occurred, handle message details if
// necessary, then stop the link.
if (!gSuppressLinkErrorMessage) if (!gSuppressLinkErrorMessage)
{ {
sLinkErrorBuffer.status = gLinkStatus; sLinkErrorBuffer.status = gLinkStatus;
@ -1575,7 +1576,7 @@ static void CheckErrorStatus(void)
} }
} }
void BufferLinkErrorInfo(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 disconnected) void SetLinkErrorBuffer(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 disconnected)
{ {
sLinkErrorBuffer.status = status; sLinkErrorBuffer.status = status;
sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount; sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount;
@ -1778,10 +1779,10 @@ void LinkPlayerFromBlock(u32 who)
SetMainCallback2(CB2_LinkError); SetMainCallback2(CB2_LinkError);
} }
// When this function returns TRUE the callbacks are skipped
bool8 HandleLinkConnection(void) bool8 HandleLinkConnection(void)
{ {
bool32 r4; bool32 main1Failed, main2Failed;
bool32 r5;
if (gWirelessCommType == 0) if (gWirelessCommType == 0)
{ {
@ -1792,11 +1793,13 @@ bool8 HandleLinkConnection(void)
} }
else else
{ {
r4 = RfuMain1(); main1Failed = RfuMain1(); // Always returns FALSE
r5 = RfuMain2(); main2Failed = RfuMain2();
if (IsSendingKeysOverCable() == TRUE) if (IsSendingKeysOverCable() == TRUE)
{ {
if (r4 == TRUE || IsRfuRecvQueueEmpty() || r5) // This will never be reached.
// IsSendingKeysOverCable is always FALSE for wireless communication
if (main1Failed == TRUE || IsRfuRecvQueueEmpty() || main2Failed)
return TRUE; return TRUE;
} }
} }

View File

@ -33,11 +33,12 @@ enum {
RFUSTATE_CHILD_TRY_JOIN, RFUSTATE_CHILD_TRY_JOIN,
RFUSTATE_CHILD_JOINED, RFUSTATE_CHILD_JOINED,
RFUSTATE_UR_PLAYER_EXCHANGE, RFUSTATE_UR_PLAYER_EXCHANGE,
RFUSTATE_14, RFUSTATE_UR_STOP_MANAGER,
RFUSTATE_15, RFUSTATE_UR_STOP_MANAGER_END,
RFUSTATE_UR_FINALIZE, RFUSTATE_UR_FINALIZE,
}; };
// These states are re-used for different purposes // These states are used for different purposes
// depending on the link mode (parent, child, union room)
#define RFUSTATE_17 17 #define RFUSTATE_17 17
#define RFUSTATE_PARENT_RECONNECT 18 #define RFUSTATE_PARENT_RECONNECT 18
@ -67,16 +68,16 @@ struct SioInfo
// its fields was largely removed before release // its fields was largely removed before release
struct RfuDebug struct RfuDebug
{ {
u8 filler0[6]; u8 unused0[6];
u16 unk_06; u16 recvCount;
u8 filler1[6]; u8 unused1[6];
vu8 unk_0e; vu8 unkFlag;
u8 childJoinCount; u8 childJoinCount;
u8 filler2[84]; u8 unused2[84];
u16 blockSendFailures; u16 blockSendFailures;
u8 filler3[29]; u8 unused3[29];
u8 blockSendTime; u8 blockSendTime;
u8 filler4[88]; u8 unused4[88];
}; };
u32 gRfuAPIBuffer[RFU_API_BUFF_SIZE_RAM / 4]; u32 gRfuAPIBuffer[RFU_API_BUFF_SIZE_RAM / 4];
@ -93,9 +94,9 @@ static EWRAM_DATA struct RfuDebug sRfuDebug = {};
static void ResetSendDataManager(struct RfuBlockSend *); static void ResetSendDataManager(struct RfuBlockSend *);
static void InitChildRecvBuffers(void); static void InitChildRecvBuffers(void);
static void sub_800EAFC(void); static void InitParentSendData(void);
static void LinkManagerCB_MSC(u16); static void MSCCallback_Child(u16);
static void sub_800EDBC(u16); static void MSCCallback_Parent(u16);
static void UpdateBackupQueue(void); static void UpdateBackupQueue(void);
static void Task_PlayerExchange(u8); static void Task_PlayerExchange(u8);
static void Task_PlayerExchangeUpdate(u8); static void Task_PlayerExchangeUpdate(u8);
@ -111,7 +112,7 @@ static void UpdateChildStatuses(void);
static s32 GetJoinGroupStatus(void); static s32 GetJoinGroupStatus(void);
static void ClearSelectedLinkPlayerIds(u16); static void ClearSelectedLinkPlayerIds(u16);
static void ValidateAndReceivePokemonSioInfo(void *); static void ValidateAndReceivePokemonSioInfo(void *);
static void sub_80115EC(s32); static void ParentResetChildRecvMetadata(s32);
static void CB2_RfuIdle(void); static void CB2_RfuIdle(void);
static void RfuReqDisconnectSlot(u32); static void RfuReqDisconnectSlot(u32);
static void SendDisconnectCommand(u32, u32); static void SendDisconnectCommand(u32, u32);
@ -170,7 +171,7 @@ static const u32 sAllBlocksReceived[] = {
}; };
#undef BLOCK_MASK #undef BLOCK_MASK
static const u8 sUnknown_082ED68C[] = { static const u8 sSlotToLinkPlayerTableId[] = {
0, 0, 1, 0, 0, 1,
1, 2, 2, 1, 2, 2,
2, 2, 3 2, 2, 3
@ -366,10 +367,10 @@ static void Task_ParentSearchForChildren(u8 taskId)
case RFUSTATE_STOP_MANAGER_END: case RFUSTATE_STOP_MANAGER_END:
break; break;
case RFUSTATE_PARENT_FINALIZE: case RFUSTATE_PARENT_FINALIZE:
gRfu.unk_cdb = FALSE; gRfu.parentFinished = FALSE;
rfu_LMAN_setMSCCallback(sub_800EDBC); rfu_LMAN_setMSCCallback(MSCCallback_Parent);
InitChildRecvBuffers(); InitChildRecvBuffers();
sub_800EAFC(); InitParentSendData();
gRfu.state = RFUSTATE_FINALIZED; gRfu.state = RFUSTATE_FINALIZED;
gTasks[taskId].data[1] = 8; gTasks[taskId].data[1] = 8;
CreateTask(Task_PlayerExchange, 5); CreateTask(Task_PlayerExchange, 5);
@ -383,40 +384,47 @@ s32 Rfu_GetIndexOfNewestChild(u8 bits)
return sPlayerBitsToNewChildIdx[bits]; return sPlayerBitsToNewChildIdx[bits];
} }
void sub_800E88C(s32 r2, s32 r5) static void SetLinkPlayerIdsFromSlots(s32 baseSlots, s32 addSlots)
{ {
u8 i; u8 i;
u8 r4 = 1; u8 baseId = 1;
s32 r1 = r2; s32 baseSlotsCopy = baseSlots;
s32 r6 = 0; s32 newId = 0;
if (r5 == -1) if (addSlots == -1)
{ {
for (i = 0; i < RFU_CHILD_MAX; r2 >>= 1, i++) // Initialize
for (i = 0; i < RFU_CHILD_MAX; baseSlots >>= 1, i++)
{ {
if (r2 & 1) if (baseSlots & 1)
{ {
gRfu.linkPlayerIdx[i] = r4; gRfu.linkPlayerIdx[i] = baseId;
r4++; baseId++;
} }
} }
} }
else else
{ {
for (i = 0; i < RFU_CHILD_MAX; r1 >>= 1, i++) // Clear id for any empty slot
for (i = 0; i < RFU_CHILD_MAX; baseSlotsCopy >>= 1, i++)
{ {
if (!(r1 & 1)) if (!(baseSlotsCopy & 1))
gRfu.linkPlayerIdx[i] = 0; gRfu.linkPlayerIdx[i] = 0;
} }
for (r4 = RFU_CHILD_MAX; r4 != 0; r4--)
// Get starting id by checking existing slots
for (baseId = RFU_CHILD_MAX; baseId != 0; baseId--)
{ {
for (i = 0; i < RFU_CHILD_MAX && gRfu.linkPlayerIdx[i] != r4; i++); for (i = 0; i < RFU_CHILD_MAX && gRfu.linkPlayerIdx[i] != baseId; i++)
;
if (i == RFU_CHILD_MAX) if (i == RFU_CHILD_MAX)
r6 = r4; newId = baseId;
} }
for (r5 &= ~r2, i = 0; i < RFU_CHILD_MAX; r5 >>= 1, i++)
// Set id for new slots
for (addSlots &= ~baseSlots, i = 0; i < RFU_CHILD_MAX; addSlots >>= 1, i++)
{ {
if (r5 & 1) if (addSlots & 1)
gRfu.linkPlayerIdx[i] = r6++; gRfu.linkPlayerIdx[i] = newId++;
} }
} }
} }
@ -460,7 +468,7 @@ static void Task_ChildSearchForParent(u8 taskId)
{ {
u8 bmChildSlot = 1 << gRfu.childSlot; u8 bmChildSlot = 1 << gRfu.childSlot;
rfu_clearSlot(TYPE_NI_SEND | TYPE_NI_RECV, gRfu.childSlot); rfu_clearSlot(TYPE_NI_SEND | TYPE_NI_RECV, gRfu.childSlot);
rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.unk_c3f, sizeof(gRfu.unk_c3f)); rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.childRecvQueue, sizeof(gRfu.childRecvQueue));
rfu_UNI_setSendData(bmChildSlot, gRfu.childSendBuffer, sizeof(gRfu.childSendBuffer)); rfu_UNI_setSendData(bmChildSlot, gRfu.childSendBuffer, sizeof(gRfu.childSendBuffer));
gTasks[taskId].data[1] = 8; gTasks[taskId].data[1] = 8;
DestroyTask(taskId); DestroyTask(taskId);
@ -490,13 +498,13 @@ static void InitChildRecvBuffers(void)
} }
} }
static void sub_800EAFC(void) static void InitParentSendData(void)
{ {
u8 acceptSlot = lman.acceptSlot_flag; u8 acceptSlot = lman.acceptSlot_flag;
rfu_UNI_setSendData(acceptSlot, gRfu.recvCmds, 70); rfu_UNI_setSendData(acceptSlot, gRfu.recvCmds, sizeof(gRfu.recvCmds));
gRfu.unk_cda = Rfu_GetIndexOfNewestChild(acceptSlot); gRfu.parentSendSlot = Rfu_GetIndexOfNewestChild(acceptSlot);
gRfu.unk_ce2 = acceptSlot; gRfu.parentSlots = acceptSlot;
sub_800E88C(acceptSlot, -1); SetLinkPlayerIdsFromSlots(acceptSlot, -1);
gRfu.parentChild = MODE_PARENT; gRfu.parentChild = MODE_PARENT;
} }
@ -521,7 +529,7 @@ static void Task_UnionRoomListen(u8 taskId)
break; break;
case RFUSTATE_UR_CONNECT: case RFUSTATE_UR_CONNECT:
rfu_LMAN_establishConnection(MODE_P_C_SWITCH, 0, 240, (u16 *)sAcceptedSerialNos); rfu_LMAN_establishConnection(MODE_P_C_SWITCH, 0, 240, (u16 *)sAcceptedSerialNos);
rfu_LMAN_setMSCCallback(LinkManagerCB_MSC); rfu_LMAN_setMSCCallback(MSCCallback_Child);
gRfu.state = RFUSTATE_UR_CONNECT_END; gRfu.state = RFUSTATE_UR_CONNECT_END;
break; break;
case RFUSTATE_UR_CONNECT_END: case RFUSTATE_UR_CONNECT_END:
@ -537,23 +545,23 @@ static void Task_UnionRoomListen(u8 taskId)
CreateTask(Task_PlayerExchange, 5); CreateTask(Task_PlayerExchange, 5);
} }
break; break;
case RFUSTATE_14: case RFUSTATE_UR_STOP_MANAGER:
rfu_LMAN_stopManager(0); rfu_LMAN_stopManager(FALSE);
gRfu.state = RFUSTATE_15; gRfu.state = RFUSTATE_UR_STOP_MANAGER_END;
break; break;
case RFUSTATE_15: case RFUSTATE_UR_STOP_MANAGER_END:
break; break;
case RFUSTATE_UR_FINALIZE: case RFUSTATE_UR_FINALIZE:
gRfu.unk_cdb = FALSE; gRfu.parentFinished = FALSE;
rfu_LMAN_setMSCCallback(sub_800EDBC); rfu_LMAN_setMSCCallback(MSCCallback_Parent);
UpdateGameData_GroupLockedIn(TRUE); UpdateGameData_GroupLockedIn(TRUE);
InitChildRecvBuffers(); InitChildRecvBuffers();
sub_800EAFC(); InitParentSendData();
gRfu.state = RFUSTATE_FINALIZED; gRfu.state = RFUSTATE_FINALIZED;
gTasks[taskId].data[1] = 8; gTasks[taskId].data[1] = 8;
gRfu.parentChild = MODE_PARENT; gRfu.parentChild = MODE_PARENT;
CreateTask(Task_PlayerExchange, 5); CreateTask(Task_PlayerExchange, 5);
gRfu.unk_ce8 = TRUE; gRfu.playerExchangeActive = TRUE;
DestroyTask(taskId); DestroyTask(taskId);
break; break;
} }
@ -569,7 +577,8 @@ void LinkRfu_StopManagerBeforeEnteringChat(void)
rfu_LMAN_stopManager(FALSE); rfu_LMAN_stopManager(FALSE);
} }
static void LinkManagerCB_MSC(u16 unused) // Argument is provided by the RFU and is unused.
static void MSCCallback_Child(u16 REQ_commandID)
{ {
s32 i; s32 i;
@ -581,8 +590,8 @@ static void LinkManagerCB_MSC(u16 unused)
if (gRfuSlotStatusUNI[gRfu.childSlot]->recv.newDataFlag) if (gRfuSlotStatusUNI[gRfu.childSlot]->recv.newDataFlag)
{ {
gRfu.childSendCount++; gRfu.childSendCount++;
RfuRecvQueue_Enqueue(&gRfu.recvQueue, gRfu.unk_c3f); RfuRecvQueue_Enqueue(&gRfu.recvQueue, gRfu.childRecvQueue);
sRfuDebug.unk_06++; sRfuDebug.recvCount++;
UpdateBackupQueue(); UpdateBackupQueue();
rfu_UNI_readySendData(gRfu.childSlot); rfu_UNI_readySendData(gRfu.childSlot);
rfu_UNI_clearRecvNewDataFlag(gRfu.childSlot); rfu_UNI_clearRecvNewDataFlag(gRfu.childSlot);
@ -590,9 +599,10 @@ static void LinkManagerCB_MSC(u16 unused)
rfu_LMAN_REQ_sendData(TRUE); rfu_LMAN_REQ_sendData(TRUE);
} }
static void sub_800EDBC(u16 unused) // Argument is provided by the RFU and is unused.
static void MSCCallback_Parent(u16 REQ_commandID)
{ {
gRfu.unk_cdb = TRUE; gRfu.parentFinished = TRUE;
} }
void LinkRfu_Shutdown(void) void LinkRfu_Shutdown(void)
@ -651,7 +661,7 @@ static bool8 CanTryReconnectParent(void)
static bool32 TryReconnectParent(void) static bool32 TryReconnectParent(void)
{ {
if (gRfu.state == RFUSTATE_CHILD_CONNECT_END && !rfu_LMAN_CHILD_connectParent(gRfuLinkStatus->partner[gRfu.unk_c3d].id, 240)) if (gRfu.state == RFUSTATE_CHILD_CONNECT_END && !rfu_LMAN_CHILD_connectParent(gRfuLinkStatus->partner[gRfu.reconnectParentId].id, 240))
{ {
gRfu.state = RFUSTATE_RECONNECTED; gRfu.state = RFUSTATE_RECONNECTED;
return TRUE; return TRUE;
@ -687,9 +697,9 @@ bool32 WaitRfuState(bool32 force)
return FALSE; return FALSE;
} }
void sub_800EF7C(void) void StopUnionRoomLinkManager(void)
{ {
gRfu.state = RFUSTATE_14; gRfu.state = RFUSTATE_UR_STOP_MANAGER;
} }
// Unused // Unused
@ -708,7 +718,7 @@ static void ReadySendDataForSlots(u8 slots)
} }
} }
static void sub_800EFB0(void) static void ReadAllPlayerRecvCmds(void)
{ {
s32 i, j; s32 i, j;
@ -779,10 +789,10 @@ static bool32 RfuMain1_Parent(void)
} }
else else
{ {
gRfu.unk_cdb = FALSE; gRfu.parentFinished = FALSE;
if ((gRfu.unk_ce2 & gRfuLinkStatus->connSlotFlag) == gRfu.unk_ce2 && (gRfu.unk_ce2 & gRfuLinkStatus->connSlotFlag)) if ((gRfu.parentSlots & gRfuLinkStatus->connSlotFlag) == gRfu.parentSlots && (gRfu.parentSlots & gRfuLinkStatus->connSlotFlag))
{ {
if (!gRfu.unk_cdc) if (!gRfu.parentMain2Failed)
{ {
if (gRfu.disconnectSlots) if (gRfu.disconnectSlots)
{ {
@ -790,8 +800,8 @@ static bool32 RfuMain1_Parent(void)
gRfu.disconnectSlots = 0; gRfu.disconnectSlots = 0;
if (gRfu.disconnectMode == RFU_DISCONNECT_ERROR) if (gRfu.disconnectMode == RFU_DISCONNECT_ERROR)
{ {
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x8000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_8);
GetLinkmanErrorParams(0x8000); RfuSetErrorParams(F_RFU_ERROR_8);
return FALSE; return FALSE;
} }
if (!lman.acceptSlot_flag) if (!lman.acceptSlot_flag)
@ -801,15 +811,15 @@ static bool32 RfuMain1_Parent(void)
return FALSE; return FALSE;
} }
} }
sub_800EFB0(); ReadAllPlayerRecvCmds();
rfu_UNI_readySendData(gRfu.unk_cda); rfu_UNI_readySendData(gRfu.parentSendSlot);
rfu_LMAN_REQ_sendData(TRUE); rfu_LMAN_REQ_sendData(TRUE);
} }
else else
{ {
rfu_REQ_PARENT_resumeRetransmitAndChange(); rfu_REQ_PARENT_resumeRetransmitAndChange();
} }
gRfu.unk_0e = TRUE; gRfu.runParentMain2 = TRUE;
} }
} }
return FALSE; return FALSE;
@ -821,22 +831,22 @@ static bool32 RfuMain2_Parent(void)
u16 flags; u16 flags;
u8 r0; u8 r0;
u16 j; u16 j;
u8 retval; bool8 failed;
if (gRfu.state >= RFUSTATE_FINALIZED && gRfu.unk_0e == TRUE) if (gRfu.state >= RFUSTATE_FINALIZED && gRfu.runParentMain2 == TRUE)
{ {
rfu_waitREQComplete(); rfu_waitREQComplete();
while (gRfu.unk_cdb == FALSE) while (gRfu.parentFinished == FALSE)
{ {
if (gRfu.errorState != RFU_ERROR_STATE_NONE) if (gRfu.errorState != RFU_ERROR_STATE_NONE)
return FALSE; return FALSE;
} }
rfu_REQ_recvData(); rfu_REQ_recvData();
rfu_waitREQComplete(); rfu_waitREQComplete();
if ((lman.parentAck_flag & gRfu.unk_ce2) == gRfu.unk_ce2) if ((lman.parentAck_flag & gRfu.parentSlots) == gRfu.parentSlots)
{ {
gRfu.unk_cdc = FALSE; gRfu.parentMain2Failed = FALSE;
sRfuDebug.unk_06++; sRfuDebug.recvCount++;
flags = lman.acceptSlot_flag; flags = lman.acceptSlot_flag;
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
@ -844,15 +854,15 @@ static bool32 RfuMain2_Parent(void)
{ {
if (gRfu.childRecvBuffer[i][1]) if (gRfu.childRecvBuffer[i][1])
{ {
if (gRfu.unk_cee[i] != 0xFF && (gRfu.childRecvBuffer[i][0] >> 5) != ((gRfu.unk_cee[i] + 1) & 7)) if (gRfu.childRecvIds[i] != 0xFF && (gRfu.childRecvBuffer[i][0] >> 5) != ((gRfu.childRecvIds[i] + 1) & 7))
{ {
if (++gRfu.unk_cea[i] > 4) if (++gRfu.numChildRecvErrors[i] > 4)
GetLinkmanErrorParams(0x8000 | 0x100); RfuSetErrorParams(F_RFU_ERROR_8 | F_RFU_ERROR_1);
} }
else else
{ {
gRfu.unk_cee[i] = gRfu.childRecvBuffer[i][0] / 32; gRfu.childRecvIds[i] = gRfu.childRecvBuffer[i][0] / 32;
gRfu.unk_cea[i] = 0; gRfu.numChildRecvErrors[i] = 0;
gRfu.childRecvBuffer[i][0] &= 0x1f; gRfu.childRecvBuffer[i][0] &= 0x1f;
r0 = gRfu.linkPlayerIdx[i]; r0 = gRfu.linkPlayerIdx[i];
for (j = 0; j < CMD_LENGTH - 1; j++) for (j = 0; j < CMD_LENGTH - 1; j++)
@ -872,51 +882,51 @@ static bool32 RfuMain2_Parent(void)
CallRfuFunc(); CallRfuFunc();
if (gRfu.nextChildBits && !gRfu.stopNewConnections) if (gRfu.nextChildBits && !gRfu.stopNewConnections)
{ {
sRfuDebug.unk_0e = FALSE; sRfuDebug.unkFlag = FALSE;
rfu_clearSlot(TYPE_UNI_SEND | TYPE_UNI_RECV, gRfu.unk_cda); rfu_clearSlot(TYPE_UNI_SEND | TYPE_UNI_RECV, gRfu.parentSendSlot);
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
if ((gRfu.nextChildBits >> i) & 1) if ((gRfu.nextChildBits >> i) & 1)
rfu_setRecvBuffer(TYPE_UNI, i, gRfu.childRecvBuffer[i], sizeof(gRfu.childRecvBuffer[0])); rfu_setRecvBuffer(TYPE_UNI, i, gRfu.childRecvBuffer[i], sizeof(gRfu.childRecvBuffer[0]));
} }
sub_800E88C(gRfu.unk_ce2, gRfu.unk_ce2 | gRfu.nextChildBits); SetLinkPlayerIdsFromSlots(gRfu.parentSlots, gRfu.parentSlots | gRfu.nextChildBits);
gRfu.incomingChild = gRfu.nextChildBits; gRfu.incomingChild = gRfu.nextChildBits;
gRfu.unk_ce2 |= gRfu.nextChildBits; gRfu.parentSlots |= gRfu.nextChildBits;
gRfu.nextChildBits = 0; gRfu.nextChildBits = 0;
rfu_UNI_setSendData(gRfu.unk_ce2, gRfu.recvCmds, 70); rfu_UNI_setSendData(gRfu.parentSlots, gRfu.recvCmds, sizeof(gRfu.recvCmds));
gRfu.unk_cda = Rfu_GetIndexOfNewestChild(gRfu.unk_ce2); gRfu.parentSendSlot = Rfu_GetIndexOfNewestChild(gRfu.parentSlots);
CreateTask(Task_PlayerExchangeUpdate, 0); CreateTask(Task_PlayerExchangeUpdate, 0);
} }
} }
else else
{ {
gRfu.unk_cdc = TRUE; gRfu.parentMain2Failed = TRUE;
gRfu.unk_0e = FALSE; gRfu.runParentMain2 = FALSE;
} }
gRfu.unk_0e = FALSE; gRfu.runParentMain2 = FALSE;
} }
retval = gRfu.unk_cdc; failed = gRfu.parentMain2Failed;
return gRfuLinkStatus->sendSlotUNIFlag ? retval & 1 : FALSE; return gRfuLinkStatus->sendSlotUNIFlag ? failed & 1 : FALSE;
} }
static void sub_800F498(u16 *sendCmd, u8 *buffer) static void ChildBuildSendCmd(u16 *sendCmd, u8 *dst)
{ {
s32 i; s32 i;
if (sendCmd[0]) if (sendCmd[0])
{ {
sendCmd[0] |= (gRfu.unk_102 << 5); sendCmd[0] |= (gRfu.childSendCmdId << 5);
gRfu.unk_102 = (gRfu.unk_102 + 1) & 7; gRfu.childSendCmdId = (gRfu.childSendCmdId + 1) & 7;
for (i = 0; i < CMD_LENGTH - 1; i++) for (i = 0; i < CMD_LENGTH - 1; i++)
{ {
buffer[2 * i + 1] = sendCmd[i] >> 8; dst[2 * i + 1] = sendCmd[i] >> 8;
buffer[2 * i + 0] = sendCmd[i]; dst[2 * i + 0] = sendCmd[i];
} }
} }
else else
{ {
for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++) for (i = 0; i < SEND_QUEUE_SLOT_LENGTH; i++)
buffer[i] = 0; dst[i] = 0;
} }
} }
@ -942,14 +952,14 @@ static bool32 RfuMain1_Child(void)
rfu_waitREQComplete(); rfu_waitREQComplete();
status = RfuGetStatus(); status = RfuGetStatus();
if (status != RFU_STATUS_FATAL_ERROR && status != RFU_STATUS_JOIN_GROUP_NO && status != RFU_STATUS_LEAVE_GROUP) if (status != RFU_STATUS_FATAL_ERROR && status != RFU_STATUS_JOIN_GROUP_NO && status != RFU_STATUS_LEAVE_GROUP)
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x9000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_8);
rfu_clearAllSlot(); rfu_clearAllSlot();
gReceivedRemoteLinkPlayers = FALSE; gReceivedRemoteLinkPlayers = FALSE;
gRfu.callback = NULL; gRfu.callback = NULL;
if (gRfu.disconnectMode == RFU_DISCONNECT_ERROR) if (gRfu.disconnectMode == RFU_DISCONNECT_ERROR)
{ {
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x9000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_8);
GetLinkmanErrorParams(0x9000); RfuSetErrorParams(F_RFU_ERROR_5 | F_RFU_ERROR_8);
} }
lman.state = lman.next_state = 0; lman.state = lman.next_state = 0;
gRfu.disconnectMode = RFU_DISCONNECT_NONE; gRfu.disconnectMode = RFU_DISCONNECT_NONE;
@ -958,7 +968,7 @@ static bool32 RfuMain1_Child(void)
{ {
gRfu.childSendCount--; gRfu.childSendCount--;
CallRfuFunc(); CallRfuFunc();
sub_800F498(gSendCmd, send); ChildBuildSendCmd(gSendCmd, send);
RfuSendQueue_Enqueue(&gRfu.sendQueue, send); RfuSendQueue_Enqueue(&gRfu.sendQueue, send);
for (i = 0; i < CMD_LENGTH - 1; i++) for (i = 0; i < CMD_LENGTH - 1; i++)
gSendCmd[i] = 0; gSendCmd[i] = 0;
@ -1241,7 +1251,7 @@ static void RfuPrepareSendBuffer(u16 command)
break; break;
case RFUCMD_SEND_PLAYER_IDS: case RFUCMD_SEND_PLAYER_IDS:
case RFUCMD_SEND_PLAYER_IDS_NEW: case RFUCMD_SEND_PLAYER_IDS_NEW:
tmp = gRfu.unk_ce2 ^ gRfu.disconnectSlots; tmp = gRfu.parentSlots ^ gRfu.disconnectSlots;
gRfu.playerCount = sPlayerBitsToCount[tmp] + 1; gRfu.playerCount = sPlayerBitsToCount[tmp] + 1;
gSendCmd[1] = gRfu.playerCount; gSendCmd[1] = gRfu.playerCount;
buff = (u8 *)&gSendCmd[2]; buff = (u8 *)&gSendCmd[2];
@ -1445,7 +1455,7 @@ static void WaitAllReadyToCloseLink(void)
static void SendReadyCloseLink(void) static void SendReadyCloseLink(void)
{ {
if (gSendCmd[0] == 0 && !gRfu.unk_ce8) if (gSendCmd[0] == 0 && !gRfu.playerExchangeActive)
{ {
RfuPrepareSendBuffer(RFUCMD_READY_CLOSE_LINK); RfuPrepareSendBuffer(RFUCMD_READY_CLOSE_LINK);
gRfu.callback = WaitAllReadyToCloseLink; gRfu.callback = WaitAllReadyToCloseLink;
@ -1729,8 +1739,8 @@ static s32 GetJoinGroupStatus(void)
|| gRfuSlotStatusNI[gRfu.childSlot]->recv.state == SLOT_STATE_RECV_SUCCESS_AND_SENDSIDE_UNKNOWN) || gRfuSlotStatusNI[gRfu.childSlot]->recv.state == SLOT_STATE_RECV_SUCCESS_AND_SENDSIDE_UNKNOWN)
{ {
rfu_clearSlot(TYPE_NI_RECV, gRfu.childSlot); rfu_clearSlot(TYPE_NI_RECV, gRfu.childSlot);
RfuSetStatus(gRfu.recvStatus, 0); RfuSetStatus(gRfu.childRecvStatus, 0);
status = gRfu.recvStatus; status = gRfu.childRecvStatus;
} }
else if (gRfuSlotStatusNI[gRfu.childSlot]->recv.state == SLOT_STATE_RECV_FAILED) else if (gRfuSlotStatusNI[gRfu.childSlot]->recv.state == SLOT_STATE_RECV_FAILED)
{ {
@ -1748,7 +1758,7 @@ static void Task_PlayerExchange(u8 taskId)
if (gRfu.status == RFU_STATUS_FATAL_ERROR || gRfu.status == RFU_STATUS_CONNECTION_ERROR) if (gRfu.status == RFU_STATUS_FATAL_ERROR || gRfu.status == RFU_STATUS_CONNECTION_ERROR)
{ {
gRfu.unk_ce8 = FALSE; gRfu.playerExchangeActive = FALSE;
DestroyTask(taskId); DestroyTask(taskId);
} }
switch (gTasks[taskId].tState) switch (gTasks[taskId].tState)
@ -1809,7 +1819,7 @@ static void Task_PlayerExchange(u8 taskId)
case 6: case 6:
DestroyTask(taskId); DestroyTask(taskId);
gReceivedRemoteLinkPlayers = TRUE; gReceivedRemoteLinkPlayers = TRUE;
gRfu.unk_ce8 = FALSE; gRfu.playerExchangeActive = FALSE;
rfu_LMAN_setLinkRecovery(1, 600); rfu_LMAN_setLinkRecovery(1, 600);
if (gRfu.newChildQueue) if (gRfu.newChildQueue)
{ {
@ -1866,10 +1876,10 @@ static void Task_PlayerExchangeUpdate(u8 taskId)
s32 i; s32 i;
struct LinkPlayerBlock *playerBlock; struct LinkPlayerBlock *playerBlock;
struct SioInfo *sio; struct SioInfo *sio;
u8 playerId = gRfu.linkPlayerIdx[sUnknown_082ED68C[gRfu.incomingChild]]; u8 playerId = gRfu.linkPlayerIdx[sSlotToLinkPlayerTableId[gRfu.incomingChild]];
if (gRfu.status == RFU_STATUS_FATAL_ERROR || gRfu.status == RFU_STATUS_CONNECTION_ERROR) if (gRfu.status == RFU_STATUS_FATAL_ERROR || gRfu.status == RFU_STATUS_CONNECTION_ERROR)
{ {
gRfu.unk_ce8 = FALSE; gRfu.playerExchangeActive = FALSE;
DestroyTask(taskId); DestroyTask(taskId);
} }
switch (gTasks[taskId].tState) switch (gTasks[taskId].tState)
@ -1919,7 +1929,7 @@ static void Task_PlayerExchangeUpdate(u8 taskId)
{ {
CpuFill16(0, gBlockRecvBuffer, sizeof(struct SioInfo)); CpuFill16(0, gBlockRecvBuffer, sizeof(struct SioInfo));
ResetBlockReceivedFlag(0); ResetBlockReceivedFlag(0);
gRfu.unk_ce8 = FALSE; gRfu.playerExchangeActive = FALSE;
if (gRfu.newChildQueue) if (gRfu.newChildQueue)
{ {
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
@ -1928,7 +1938,7 @@ static void Task_PlayerExchangeUpdate(u8 taskId)
{ {
gRfu.nextChildBits = 1 << i; gRfu.nextChildBits = 1 << i;
gRfu.newChildQueue ^= (1 << i); gRfu.newChildQueue ^= (1 << i);
gRfu.unk_ce8 = TRUE; gRfu.playerExchangeActive = TRUE;
break; break;
} }
} }
@ -1978,7 +1988,7 @@ static void RfuCheckErrorStatus(void)
gWirelessCommType = 2; gWirelessCommType = 2;
SetMainCallback2(CB2_LinkError); SetMainCallback2(CB2_LinkError);
gMain.savedCallback = CB2_LinkError; gMain.savedCallback = CB2_LinkError;
BufferLinkErrorInfo((gRfu.linkmanMsg << 16) | (gRfu.unk_10 << 8) | gRfu.unk_12, gRfu.recvQueue.count, gRfu.sendQueue.count, RfuGetStatus() == RFU_STATUS_CONNECTION_ERROR); SetLinkErrorBuffer((gRfu.errorInfo << 16) | (gRfu.errorParam0 << 8) | gRfu.errorParam1, gRfu.recvQueue.count, gRfu.sendQueue.count, RfuGetStatus() == RFU_STATUS_CONNECTION_ERROR);
gRfu.errorState = RFU_ERROR_STATE_2; gRfu.errorState = RFU_ERROR_STATE_2;
CloseLink(); CloseLink();
} }
@ -1986,8 +1996,8 @@ static void RfuCheckErrorStatus(void)
{ {
if (lman.childClockSlave_flag) if (lman.childClockSlave_flag)
rfu_LMAN_requestChangeAgbClockMaster(); rfu_LMAN_requestChangeAgbClockMaster();
RfuSetStatus(RFU_STATUS_FATAL_ERROR, 0x7000); RfuSetStatus(RFU_STATUS_FATAL_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
GetLinkmanErrorParams(0x7000); RfuSetErrorParams(F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
} }
} }
@ -2108,7 +2118,7 @@ void SetUnionRoomChatPlayerData(u32 numPlayers)
{ {
numConnectedChildren = 0; numConnectedChildren = 0;
partnerInfo = 0; partnerInfo = 0;
slots = gRfu.unk_ce2 ^ gRfu.disconnectSlots; slots = gRfu.parentSlots ^ gRfu.disconnectSlots;
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
if ((slots >> i) & 1) if ((slots >> i) & 1)
@ -2127,13 +2137,13 @@ void SetUnionRoomChatPlayerData(u32 numPlayers)
} }
} }
void GetLinkmanErrorParams(u32 msg) void RfuSetErrorParams(u32 errorInfo)
{ {
if (gRfu.errorState == RFU_ERROR_STATE_NONE) if (gRfu.errorState == RFU_ERROR_STATE_NONE)
{ {
gRfu.unk_10 = lman.param[0]; gRfu.errorParam0 = lman.param[0];
gRfu.unk_12 = lman.param[1]; gRfu.errorParam1 = lman.param[1];
gRfu.linkmanMsg = msg; gRfu.errorInfo = errorInfo;
gRfu.errorState = RFU_ERROR_STATE_1; gRfu.errorState = RFU_ERROR_STATE_1;
} }
} }
@ -2174,7 +2184,7 @@ static void LinkManagerCB_Parent(u8 msg, u8 paramCount)
case LMAN_MSG_NEW_CHILD_CONNECT_DETECTED: case LMAN_MSG_NEW_CHILD_CONNECT_DETECTED:
break; break;
case LMAN_MSG_NEW_CHILD_CONNECT_ACCEPTED: case LMAN_MSG_NEW_CHILD_CONNECT_ACCEPTED:
sub_80115EC(lman.param[0]); ParentResetChildRecvMetadata(lman.param[0]);
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
if ((lman.param[0] >> i) & 1) if ((lman.param[0] >> i) & 1)
@ -2219,11 +2229,11 @@ static void LinkManagerCB_Parent(u8 msg, u8 paramCount)
case LMAN_MSG_LINK_LOSS_DETECTED_AND_DISCONNECTED: case LMAN_MSG_LINK_LOSS_DETECTED_AND_DISCONNECTED:
case LMAN_MSG_LINK_RECOVERY_FAILED_AND_DISCONNECTED: case LMAN_MSG_LINK_RECOVERY_FAILED_AND_DISCONNECTED:
gRfu.linkLossRecoveryState = 4; gRfu.linkLossRecoveryState = 4;
gRfu.unk_ce2 &= ~lman.param[0]; gRfu.parentSlots &= ~lman.param[0];
if (gReceivedRemoteLinkPlayers == 1) if (gReceivedRemoteLinkPlayers == 1)
{ {
if (gRfu.unk_ce2 == 0) if (gRfu.parentSlots == 0)
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
else else
StartDisconnectNewChild(); StartDisconnectNewChild();
} }
@ -2236,16 +2246,16 @@ static void LinkManagerCB_Parent(u8 msg, u8 paramCount)
break; break;
case LMAN_MSG_LMAN_API_ERROR_RETURN: case LMAN_MSG_LMAN_API_ERROR_RETURN:
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
gRfu.isShuttingDown = TRUE; gRfu.isShuttingDown = TRUE;
break; break;
case LMAN_MSG_REQ_API_ERROR: case LMAN_MSG_REQ_API_ERROR:
case LMAN_MSG_WATCH_DOG_TIMER_ERROR: case LMAN_MSG_WATCH_DOG_TIMER_ERROR:
case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA: case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA:
case LMAN_MSG_RFU_FATAL_ERROR: case LMAN_MSG_RFU_FATAL_ERROR:
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
gRfu.unk_cdb = TRUE; gRfu.parentFinished = TRUE;
break; break;
} }
} }
@ -2271,25 +2281,25 @@ static void LinkManagerCB_Child(u8 msg, u8 unused1)
case LMAN_MSG_CHILD_NAME_SEND_COMPLETED: case LMAN_MSG_CHILD_NAME_SEND_COMPLETED:
gRfu.state = RFUSTATE_CHILD_TRY_JOIN; gRfu.state = RFUSTATE_CHILD_TRY_JOIN;
gRfu.leaveGroupStatus = RFU_STATUS_OK; gRfu.leaveGroupStatus = RFU_STATUS_OK;
gRfu.recvStatus = RFU_STATUS_OK; gRfu.childRecvStatus = RFU_STATUS_OK;
rfu_setRecvBuffer(TYPE_NI, gRfu.childSlot, &gRfu.recvStatus, sizeof(gRfu.recvStatus)); rfu_setRecvBuffer(TYPE_NI, gRfu.childSlot, &gRfu.childRecvStatus, sizeof(gRfu.childRecvStatus));
rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.unk_c3f, sizeof(gRfu.unk_c3f)); rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.childRecvQueue, sizeof(gRfu.childRecvQueue));
break; break;
case LMAN_MSG_CHILD_NAME_SEND_FAILED_AND_DISCONNECTED: case LMAN_MSG_CHILD_NAME_SEND_FAILED_AND_DISCONNECTED:
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg);
break; break;
case LMAN_MSG_LINK_LOSS_DETECTED_AND_DISCONNECTED: case LMAN_MSG_LINK_LOSS_DETECTED_AND_DISCONNECTED:
gRfu.linkLossRecoveryState = 2; gRfu.linkLossRecoveryState = 2;
if (gRfu.recvStatus == RFU_STATUS_JOIN_GROUP_NO) if (gRfu.childRecvStatus == RFU_STATUS_JOIN_GROUP_NO)
break; break;
case LMAN_MSG_LINK_RECOVERY_FAILED_AND_DISCONNECTED: case LMAN_MSG_LINK_RECOVERY_FAILED_AND_DISCONNECTED:
if (gRfu.linkLossRecoveryState != 2) if (gRfu.linkLossRecoveryState != 2)
gRfu.linkLossRecoveryState = 4; gRfu.linkLossRecoveryState = 4;
if (gRfu.recvStatus != RFU_STATUS_LEAVE_GROUP) if (gRfu.childRecvStatus != RFU_STATUS_LEAVE_GROUP)
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg);
Debug_PrintString(sASCII_LinkLossDisconnect, 5, 5); Debug_PrintString(sASCII_LinkLossDisconnect, 5, 5);
if (gReceivedRemoteLinkPlayers == 1) if (gReceivedRemoteLinkPlayers == 1)
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
break; break;
case LMAN_MSG_LINK_LOSS_DETECTED_AND_START_RECOVERY: case LMAN_MSG_LINK_LOSS_DETECTED_AND_START_RECOVERY:
gRfu.linkLossRecoveryState = 1; gRfu.linkLossRecoveryState = 1;
@ -2307,7 +2317,7 @@ static void LinkManagerCB_Child(u8 msg, u8 unused1)
break; break;
case LMAN_MSG_LMAN_API_ERROR_RETURN: case LMAN_MSG_LMAN_API_ERROR_RETURN:
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
gRfu.isShuttingDown = TRUE; gRfu.isShuttingDown = TRUE;
break; break;
case LMAN_MSG_REQ_API_ERROR: case LMAN_MSG_REQ_API_ERROR:
@ -2315,22 +2325,22 @@ static void LinkManagerCB_Child(u8 msg, u8 unused1)
case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA: case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA:
case LMAN_MSG_RFU_FATAL_ERROR: case LMAN_MSG_RFU_FATAL_ERROR:
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
gRfu.unk_cdb = TRUE; gRfu.parentFinished = TRUE;
break; break;
} }
} }
static void sub_80115EC(s32 a0) static void ParentResetChildRecvMetadata(s32 slot)
{ {
s32 i; s32 i;
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
if ((a0 >> i) & 1) if ((slot >> i) & 1)
{ {
gRfu.unk_cea[i] = 0; gRfu.numChildRecvErrors[i] = 0;
gRfu.unk_cee[i] = 0xFF; gRfu.childRecvIds[i] = 0xFF;
} }
} }
} }
@ -2372,11 +2382,11 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
if (newChildren != 0) if (newChildren != 0)
{ {
acceptSlot = 1 << Rfu_GetIndexOfNewestChild(newChildren); acceptSlot = 1 << Rfu_GetIndexOfNewestChild(newChildren);
if (gRfu.newChildQueue == 0 && !gRfu.unk_ce8) if (gRfu.newChildQueue == 0 && !gRfu.playerExchangeActive)
{ {
gRfu.nextChildBits = acceptSlot; gRfu.nextChildBits = acceptSlot;
gRfu.newChildQueue |= (acceptSlot ^ newChildren); gRfu.newChildQueue |= (acceptSlot ^ newChildren);
gRfu.unk_ce8 = TRUE; gRfu.playerExchangeActive = TRUE;
} }
else else
{ {
@ -2394,7 +2404,7 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
rfu_REQ_disconnect(lman.acceptSlot_flag); rfu_REQ_disconnect(lman.acceptSlot_flag);
rfu_waitREQComplete(); rfu_waitREQComplete();
} }
sub_80115EC(lman.param[0]); ParentResetChildRecvMetadata(lman.param[0]);
break; break;
case LMAN_MSG_NEW_CHILD_CONNECT_REJECTED: case LMAN_MSG_NEW_CHILD_CONNECT_REJECTED:
break; break;
@ -2407,7 +2417,7 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
rfu_REQ_disconnect(lman.acceptSlot_flag ^ acceptSlot); rfu_REQ_disconnect(lman.acceptSlot_flag ^ acceptSlot);
rfu_waitREQComplete(); rfu_waitREQComplete();
} }
if (gRfu.state == RFUSTATE_15) if (gRfu.state == RFUSTATE_UR_STOP_MANAGER_END)
gRfu.state = RFUSTATE_UR_FINALIZE; gRfu.state = RFUSTATE_UR_FINALIZE;
break; break;
break; break;
@ -2434,7 +2444,7 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
case LMAN_MSG_CHILD_NAME_SEND_COMPLETED: case LMAN_MSG_CHILD_NAME_SEND_COMPLETED:
gRfu.state = RFUSTATE_UR_PLAYER_EXCHANGE; gRfu.state = RFUSTATE_UR_PLAYER_EXCHANGE;
RfuSetStatus(RFU_STATUS_CHILD_SEND_COMPLETE, 0); RfuSetStatus(RFU_STATUS_CHILD_SEND_COMPLETE, 0);
rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.unk_c3f, sizeof(gRfu.unk_c3f)); rfu_setRecvBuffer(TYPE_UNI, gRfu.childSlot, gRfu.childRecvQueue, sizeof(gRfu.childRecvQueue));
break; break;
case LMAN_MSG_CHILD_NAME_SEND_FAILED_AND_DISCONNECTED: case LMAN_MSG_CHILD_NAME_SEND_FAILED_AND_DISCONNECTED:
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, msg);
@ -2457,21 +2467,21 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
{ {
if (gReceivedRemoteLinkPlayers == 1) if (gReceivedRemoteLinkPlayers == 1)
{ {
gRfu.unk_ce2 &= ~(lman.param[0]); gRfu.parentSlots &= ~(lman.param[0]);
if (gRfu.unk_ce2 == 0) if (gRfu.parentSlots == 0)
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
else else
StartDisconnectNewChild(); StartDisconnectNewChild();
} }
} }
else if (gRfu.disconnectMode != RFU_DISCONNECT_NORMAL && gReceivedRemoteLinkPlayers == 1) else if (gRfu.disconnectMode != RFU_DISCONNECT_NORMAL && gReceivedRemoteLinkPlayers == 1)
{ {
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
rfu_LMAN_stopManager(0); rfu_LMAN_stopManager(FALSE);
} }
if (gRfuLinkStatus->parentChild == MODE_NEUTRAL if (gRfuLinkStatus->parentChild == MODE_NEUTRAL
&& lman.pcswitch_flag == 0 && !lman.pcswitch_flag
&& FuncIsActiveTask(Task_UnionRoomListen) == TRUE) && FuncIsActiveTask(Task_UnionRoomListen) == TRUE)
gRfu.state = RFUSTATE_17; gRfu.state = RFUSTATE_17;
@ -2486,16 +2496,16 @@ static void LinkManagerCB_UnionRoom(u8 msg, u8 paramCount)
break; break;
case LMAN_MSG_LMAN_API_ERROR_RETURN: case LMAN_MSG_LMAN_API_ERROR_RETURN:
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
gRfu.isShuttingDown = TRUE; gRfu.isShuttingDown = TRUE;
break; break;
case LMAN_MSG_REQ_API_ERROR: case LMAN_MSG_REQ_API_ERROR:
case LMAN_MSG_WATCH_DOG_TIMER_ERROR: case LMAN_MSG_WATCH_DOG_TIMER_ERROR:
case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA: case LMAN_MSG_CLOCK_SLAVE_MS_CHANGE_ERROR_BY_DMA:
case LMAN_MSG_RFU_FATAL_ERROR: case LMAN_MSG_RFU_FATAL_ERROR:
GetLinkmanErrorParams(msg); RfuSetErrorParams(msg);
RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg); RfuSetStatus(RFU_STATUS_FATAL_ERROR, msg);
gRfu.unk_cdb = FALSE; gRfu.parentFinished = FALSE;
break; break;
} }
} }
@ -2505,10 +2515,10 @@ void RfuSetNormalDisconnectMode(void)
gRfu.disconnectMode = RFU_DISCONNECT_NORMAL; gRfu.disconnectMode = RFU_DISCONNECT_NORMAL;
} }
void RfuSetStatus(u8 status, u16 msg) void RfuSetStatus(u8 status, u16 errorInfo)
{ {
gRfu.status = status; gRfu.status = status;
gRfu.linkmanMsg = msg; gRfu.errorInfo = errorInfo;
} }
u8 RfuGetStatus(void) u8 RfuGetStatus(void)
@ -2526,9 +2536,9 @@ bool32 RfuHasErrored(void)
return FALSE; return FALSE;
} }
bool32 sub_8011A9C(void) bool32 Rfu_IsPlayerExchangeActive(void)
{ {
return gRfu.unk_ce8; return gRfu.playerExchangeActive;
} }
bool8 Rfu_IsMaster(void) bool8 Rfu_IsMaster(void)
@ -2621,7 +2631,7 @@ void InitializeRfuLinkManager_JoinGroup(void)
{ {
gRfu.parentChild = MODE_CHILD; gRfu.parentChild = MODE_CHILD;
SetHostRfuUsername(); SetHostRfuUsername();
rfu_LMAN_initializeManager(LinkManagerCB_Child, LinkManagerCB_MSC); rfu_LMAN_initializeManager(LinkManagerCB_Child, MSCCallback_Child);
CreateTask_ChildSearchForParent(); CreateTask_ChildSearchForParent();
} }
@ -2667,10 +2677,10 @@ static void RfuReqDisconnectSlot(u32 slot)
{ {
rfu_REQ_disconnect(slot); rfu_REQ_disconnect(slot);
rfu_waitREQComplete(); rfu_waitREQComplete();
gRfu.unk_ce2 &= ~slot; gRfu.parentSlots &= ~slot;
rfu_clearSlot(1, gRfu.unk_cda); rfu_clearSlot(1, gRfu.parentSendSlot);
rfu_UNI_setSendData(gRfu.unk_ce2, gRfu.recvCmds, 70); rfu_UNI_setSendData(gRfu.parentSlots, gRfu.recvCmds, sizeof(gRfu.recvCmds));
gRfu.unk_cda = Rfu_GetIndexOfNewestChild(gRfu.unk_ce2); gRfu.parentSendSlot = Rfu_GetIndexOfNewestChild(gRfu.parentSlots);
} }
void RequestDisconnectSlotByTrainerNameAndId(const u8 *name, u16 id) void RequestDisconnectSlotByTrainerNameAndId(const u8 *name, u16 id)
@ -2689,7 +2699,7 @@ void Rfu_DisconnectPlayerById(u32 playerIdx)
for (i = 0; i < RFU_CHILD_MAX; i++) for (i = 0; i < RFU_CHILD_MAX; i++)
{ {
if (gRfu.linkPlayerIdx[i] == playerIdx && (gRfu.unk_ce2 >> i) & 1) if (gRfu.linkPlayerIdx[i] == playerIdx && (gRfu.parentSlots >> i) & 1)
toDisconnect |= 1 << i; toDisconnect |= 1 << i;
} }
if (toDisconnect) if (toDisconnect)
@ -2702,7 +2712,7 @@ void Rfu_DisconnectPlayerById(u32 playerIdx)
static void Task_SendDisconnectCommand(u8 taskId) static void Task_SendDisconnectCommand(u8 taskId)
{ {
if (gSendCmd[0] == 0 && !gRfu.unk_ce8) if (gSendCmd[0] == 0 && !gRfu.playerExchangeActive)
{ {
RfuPrepareSendBuffer(RFUCMD_DISCONNECT); RfuPrepareSendBuffer(RFUCMD_DISCONNECT);
gSendCmd[1] = gTasks[taskId].tDisconnectPlayers; gSendCmd[1] = gTasks[taskId].tDisconnectPlayers;
@ -2745,7 +2755,7 @@ static void Task_RfuReconnectWithParent(u8 taskId)
{ {
if (gRfuLinkStatus->partner[id].slot != 0xFF) if (gRfuLinkStatus->partner[id].slot != 0xFF)
{ {
gRfu.unk_c3d = id; gRfu.reconnectParentId = id;
if (TryReconnectParent()) if (TryReconnectParent())
DestroyTask(taskId); DestroyTask(taskId);
} }
@ -2757,14 +2767,14 @@ static void Task_RfuReconnectWithParent(u8 taskId)
else else
{ {
// Error, unable to reconnect to parent // Error, unable to reconnect to parent
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x7000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
DestroyTask(taskId); DestroyTask(taskId);
} }
} }
else else
{ {
tTime++; tTime++;
gRfu.unk_c3d = id; gRfu.reconnectParentId = id;
} }
} }
else else
@ -2775,7 +2785,7 @@ static void Task_RfuReconnectWithParent(u8 taskId)
if (tTime > 240) if (tTime > 240)
{ {
// Timeout error // Timeout error
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x7000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
DestroyTask(taskId); DestroyTask(taskId);
} }
} }
@ -2841,7 +2851,7 @@ static void Task_TryConnectToUnionRoomParent(u8 taskId)
if (++gTasks[taskId].tTime > 300) if (++gTasks[taskId].tTime > 300)
{ {
// Timeout error // Timeout error
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x7000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
DestroyTask(taskId); DestroyTask(taskId);
} }
@ -2866,7 +2876,7 @@ static void Task_TryConnectToUnionRoomParent(u8 taskId)
else else
{ {
// Incompatible partner activity // Incompatible partner activity
RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, 0x7000); RfuSetStatus(RFU_STATUS_CONNECTION_ERROR, F_RFU_ERROR_5 | F_RFU_ERROR_6 | F_RFU_ERROR_7);
DestroyTask(taskId); DestroyTask(taskId);
} }
} }

View File

@ -2888,7 +2888,7 @@ static void Task_RunUnionRoom(u8 taskId)
break; break;
case UR_STATE_PLAYER_CONTACTED_YOU: case UR_STATE_PLAYER_CONTACTED_YOU:
PlaySE(SE_DING_DONG); PlaySE(SE_DING_DONG);
sub_800EF7C(); StopUnionRoomLinkManager();
uroom->state = UR_STATE_RECV_CONTACT_DATA; uroom->state = UR_STATE_RECV_CONTACT_DATA;
uroom->recvActivityRequest[0] = 0; uroom->recvActivityRequest[0] = 0;
break; break;

View File

@ -997,7 +997,7 @@ static void Chat_Join(void)
sChat->funcState++; sChat->funcState++;
// fall through // fall through
case 1: case 1:
if (IsLinkTaskFinished() && !sub_8011A9C()) if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{ {
if (SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer))) if (SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer)))
sChat->funcState++; sChat->funcState++;
@ -1206,7 +1206,7 @@ static void Chat_AskQuitChatting(void)
} }
break; break;
case 4: case 4:
if (IsLinkTaskFinished() && !sub_8011A9C() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer))) if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer)))
{ {
if (!sChat->multiplayerId) if (!sChat->multiplayerId)
sChat->funcState = 6; sChat->funcState = 6;
@ -1257,15 +1257,15 @@ static void Chat_Exit(void)
} }
break; break;
case 3: case 3:
if (IsLinkTaskFinished() && !sub_8011A9C() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer))) if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer)))
sChat->funcState++; sChat->funcState++;
break; break;
case 4: case 4:
if ((GetBlockReceivedStatus() & 1) && !sub_8011A9C()) if ((GetBlockReceivedStatus() & 1) && !Rfu_IsPlayerExchangeActive())
sChat->funcState++; sChat->funcState++;
break; break;
case 5: case 5:
if (IsLinkTaskFinished() && !sub_8011A9C()) if (IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{ {
SetCloseLinkCallback(); SetCloseLinkCallback();
sChat->exitDelayTimer = 0; sChat->exitDelayTimer = 0;
@ -1300,7 +1300,7 @@ static void Chat_Drop(void)
} }
break; break;
case 1: case 1:
if (!IsDisplaySubtaskActive(0) && IsLinkTaskFinished() && !sub_8011A9C()) if (!IsDisplaySubtaskActive(0) && IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{ {
SetCloseLinkCallback(); SetCloseLinkCallback();
sChat->exitDelayTimer = 0; sChat->exitDelayTimer = 0;
@ -1346,7 +1346,7 @@ static void Chat_Disbanded(void)
} }
break; break;
case 2: case 2:
if (IsDisplaySubtaskActive(0) != TRUE && IsLinkTaskFinished() && !sub_8011A9C()) if (IsDisplaySubtaskActive(0) != TRUE && IsLinkTaskFinished() && !Rfu_IsPlayerExchangeActive())
{ {
SetCloseLinkCallback(); SetCloseLinkCallback();
sChat->exitDelayTimer = 0; sChat->exitDelayTimer = 0;
@ -1384,7 +1384,7 @@ static void Chat_SendMessage(void)
sChat->funcState++; sChat->funcState++;
// fall through // fall through
case 1: case 1:
if (IsLinkTaskFinished() == TRUE && !sub_8011A9C() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer))) if (IsLinkTaskFinished() == TRUE && !Rfu_IsPlayerExchangeActive() && SendBlock(0, sChat->sendMessageBuffer, sizeof(sChat->sendMessageBuffer)))
sChat->funcState++; sChat->funcState++;
break; break;
case 2: case 2:
@ -2028,7 +2028,7 @@ static void Task_ReceiveChatMessage(u8 taskId)
} }
tBlockReceivedStatus = GetBlockReceivedStatus(); tBlockReceivedStatus = GetBlockReceivedStatus();
if (!tBlockReceivedStatus && sub_8011A9C()) if (!tBlockReceivedStatus && Rfu_IsPlayerExchangeActive())
return; return;
tI = 0; tI = 0;
@ -2100,7 +2100,7 @@ static void Task_ReceiveChatMessage(u8 taskId)
DestroyTask(taskId); DestroyTask(taskId);
break; break;
case 2: case 2:
if (!sub_8011A9C()) if (!Rfu_IsPlayerExchangeActive())
{ {
if (!sChat->multiplayerId) if (!sChat->multiplayerId)
SetUnionRoomChatPlayerData(sChat->linkPlayerCount); SetUnionRoomChatPlayerData(sChat->linkPlayerCount);