diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_2.c | 31 | ||||
-rw-r--r-- | src/battle_controller_player.c | 4 | ||||
-rw-r--r-- | src/battle_controllers.c | 609 | ||||
-rw-r--r-- | src/berry_blender.c | 22 | ||||
-rw-r--r-- | src/egg_hatch.c | 6 | ||||
-rw-r--r-- | src/evolution_scene.c | 9 | ||||
-rw-r--r-- | src/librfu_rfu.c | 32 | ||||
-rw-r--r-- | src/link.c | 2429 | ||||
-rw-r--r-- | src/link_rfu.c | 4612 | ||||
-rw-r--r-- | src/main.c | 94 | ||||
-rw-r--r-- | src/reshow_battle_screen.c | 4 | ||||
-rw-r--r-- | src/rom_8011DC0.c | 18 |
12 files changed, 7413 insertions, 457 deletions
diff --git a/src/battle_2.c b/src/battle_2.c index 61e39b39f..aa033c537 100644 --- a/src/battle_2.c +++ b/src/battle_2.c @@ -19,6 +19,7 @@ #include "constants/hold_effects.h" #include "constants/trainers.h" #include "link.h" +#include "link_rfu.h" #include "bg.h" #include "dma3.h" #include "string_util.h" @@ -710,7 +711,7 @@ static void CB2_HandleStartBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); break; case 1: @@ -734,8 +735,8 @@ static void CB2_HandleStartBattle(void) SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); gBattleCommunication[MULTIUSE_STATE] = 2; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -905,7 +906,7 @@ static void CB2_HandleStartMultiPartnerBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); // fall through case 1: @@ -936,8 +937,8 @@ static void CB2_HandleStartMultiPartnerBattle(void) gBattleCommunication[MULTIUSE_STATE] = 2; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -1213,14 +1214,14 @@ static void CB2_PreInitMultiBattle(void) if (sub_800A520() && !gPaletteFade.active) { gBattleCommunication[MULTIUSE_STATE]++; - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800ADF8(); else sub_800AC34(); } break; case 3: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { if (sub_8010500()) { @@ -1305,7 +1306,7 @@ static void CB2_HandleStartMultiBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); break; case 1: @@ -1323,8 +1324,8 @@ static void CB2_HandleStartMultiBattle(void) SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); gBattleCommunication[MULTIUSE_STATE]++; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -2108,12 +2109,12 @@ static void sub_8038F34(void) } break; case 8: - if (!gLinkVSyncDisabled) + if (!gWirelessCommType) sub_800AC34(); gBattleCommunication[MULTIUSE_STATE]++; break; case 9: - if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1) + if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { gMain.field_439_x4 = 0; SetMainCallback2(gMain.savedCallback); @@ -2292,13 +2293,13 @@ static void sub_803939C(void) case 8: if (--gBattleCommunication[1] == 0) { - if (gMain.field_439_x4 && !gLinkVSyncDisabled) + if (gMain.field_439_x4 && !gWirelessCommType) sub_800AC34(); gBattleCommunication[MULTIUSE_STATE]++; } break; case 9: - if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1) + if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { gMain.field_439_x4 = 0; if (!gPaletteFade.active) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index a9d5b70eb..2434eb177 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -897,7 +897,7 @@ static void HandleMoveSwitchting(void) static void sub_80586F8(void) { - if (gLinkVSyncDisabled == 0) + if (gWirelessCommType == 0) { if (gReceivedRemoteLinkPlayers == 0) { @@ -933,7 +933,7 @@ void sub_80587B0(void) { if (sub_800A520()) { - if (gLinkVSyncDisabled == 0) + if (gWirelessCommType == 0) sub_800AC34(); else sub_800ADF8(); diff --git a/src/battle_controllers.c b/src/battle_controllers.c index c6d47e71e..96660e8ae 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -12,7 +12,6 @@ #include "constants/abilities.h" #include "battle_message.h" -extern u32 gBattleTypeFlags; extern u32 gBattleExecBuffer; extern void (*gBattleMainFunc)(void); extern void (*gBattleBankFunc[BATTLE_BANKS_COUNT])(void); @@ -27,7 +26,6 @@ extern u8 gUnknown_0203C7B4; extern u16 gBattlePartyID[BATTLE_BANKS_COUNT]; extern u8 gBattleBufferA[BATTLE_BANKS_COUNT][0x200]; extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200]; -extern u8 gBattleBuffersTransferData[0x100]; extern u8 gUnknown_02022D08; extern u8 gUnknown_02022D09; extern u8 gUnknown_02022D0A; @@ -38,12 +36,15 @@ extern u8 gEffectBank; extern u16 gBattleWeather; extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT]; extern u16 gCurrentMove; +extern u16 gLastUsedMove; extern u16 gChosenMove; extern u16 gLastUsedItem; extern u8 gBattleOutcome; extern u8 gLastUsedAbility; extern u8 gStringBank; +static EWRAM_DATA u8 sBattleBuffersTransferData[0x100] = {}; + extern const struct BattleMove gBattleMoves[]; extern void task00_08081A90(u8 taskId); // cable_club @@ -61,10 +62,10 @@ void HandleLinkBattleSetup(void) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800B488(); if (!gReceivedRemoteLinkPlayers) - sub_8009734(); + OpenLink(); CreateTask(task00_08081A90, 0); CreateTasksForSendRecvLinkBuffers(); } @@ -782,7 +783,7 @@ static void Task_HandleSendLinkBuffersData(u8 taskId) gTasks[taskId].data[11]++; break; case 2: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { gTasks[taskId].data[11]++; } @@ -793,9 +794,9 @@ static void Task_HandleSendLinkBuffersData(u8 taskId) else var = (gBattleTypeFlags & BATTLE_TYPE_MULTI) ? 4 : 2; - if (sub_800ABAC() >= var) + if (GetLinkPlayerCount_2() >= var) { - if (sub_800ABBC()) + if (IsLinkMaster()) { sub_800A620(); gTasks[taskId].data[11]++; @@ -941,171 +942,171 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) void EmitGetMonData(u8 bufferId, u8 requestId, u8 monToCheck) { - gBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA; - gBattleBuffersTransferData[1] = requestId; - gBattleBuffersTransferData[2] = monToCheck; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA; + sBattleBuffersTransferData[1] = requestId; + sBattleBuffersTransferData[2] = monToCheck; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitGetRawMonData(u8 bufferId, u8 monId, u8 bytes) { - gBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA; - gBattleBuffersTransferData[1] = monId; - gBattleBuffersTransferData[2] = bytes; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA; + sBattleBuffersTransferData[1] = monId; + sBattleBuffersTransferData[2] = bytes; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitSetMonData(u8 bufferId, u8 requestId, u8 monToCheck, u8 bytes, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA; - gBattleBuffersTransferData[1] = requestId; - gBattleBuffersTransferData[2] = monToCheck; + sBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA; + sBattleBuffersTransferData[1] = requestId; + sBattleBuffersTransferData[2] = monToCheck; for (i = 0; i < bytes; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 3 + bytes); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 3 + bytes); } void EmitSetRawMonData(u8 bufferId, u8 monId, u8 bytes, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA; - gBattleBuffersTransferData[1] = monId; - gBattleBuffersTransferData[2] = bytes; + sBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA; + sBattleBuffersTransferData[1] = monId; + sBattleBuffersTransferData[2] = bytes; for (i = 0; i < bytes; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, bytes + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, bytes + 3); } void EmitLoadMonSprite(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitSwitchInAnim(u8 bufferId, u8 partyId, bool8 dontClearSubstituteBit) { - gBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM; - gBattleBuffersTransferData[1] = partyId; - gBattleBuffersTransferData[2] = dontClearSubstituteBit; - gBattleBuffersTransferData[3] = 5; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM; + sBattleBuffersTransferData[1] = partyId; + sBattleBuffersTransferData[2] = dontClearSubstituteBit; + sBattleBuffersTransferData[3] = 5; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitReturnMonToBall(u8 bufferId, u8 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL; - gBattleBuffersTransferData[1] = arg1; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL; + sBattleBuffersTransferData[1] = arg1; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitDrawTrainerPic(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitTrainerSlide(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitTrainerSlideBack(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitFaintAnimation(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitPaletteFade(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitSuccessBallThrowAnim(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitBallThrowAnim(u8 bufferId, u8 caseId) { - gBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM; - gBattleBuffersTransferData[1] = caseId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM; + sBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitPause(u8 bufferId, u8 toWait, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_PAUSE; - gBattleBuffersTransferData[1] = toWait; + sBattleBuffersTransferData[0] = CONTROLLER_PAUSE; + sBattleBuffersTransferData[1] = toWait; for (i = 0; i < toWait * 3; i++) - gBattleBuffersTransferData[2 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, toWait * 3 + 2); + sBattleBuffersTransferData[2 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, toWait * 3 + 2); } void EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit) { - gBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION; - gBattleBuffersTransferData[1] = move; - gBattleBuffersTransferData[2] = (move & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = turnOfMove; - gBattleBuffersTransferData[4] = movePower; - gBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8; - gBattleBuffersTransferData[6] = dmg; - gBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8; - gBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16; - gBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24; - gBattleBuffersTransferData[10] = friendship; - gBattleBuffersTransferData[11] = multihit; + sBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION; + sBattleBuffersTransferData[1] = move; + sBattleBuffersTransferData[2] = (move & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = turnOfMove; + sBattleBuffersTransferData[4] = movePower; + sBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8; + sBattleBuffersTransferData[6] = dmg; + sBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8; + sBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16; + sBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24; + sBattleBuffersTransferData[10] = friendship; + sBattleBuffersTransferData[11] = multihit; if (WEATHER_HAS_EFFECT2) { - gBattleBuffersTransferData[12] = gBattleWeather; - gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8; + sBattleBuffersTransferData[12] = gBattleWeather; + sBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8; } else { - gBattleBuffersTransferData[12] = 0; - gBattleBuffersTransferData[13] = 0; + sBattleBuffersTransferData[12] = 0; + sBattleBuffersTransferData[13] = 0; } - gBattleBuffersTransferData[14] = 0; - gBattleBuffersTransferData[15] = 0; - memcpy(&gBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 16 + sizeof(struct DisableStruct)); + sBattleBuffersTransferData[14] = 0; + sBattleBuffersTransferData[15] = 0; + memcpy(&sBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 16 + sizeof(struct DisableStruct)); } void EmitPrintString(u8 bufferId, u16 stringID) @@ -1113,12 +1114,12 @@ void EmitPrintString(u8 bufferId, u16 stringID) s32 i; struct StringInfoBattle* stringInfo; - gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING; - gBattleBuffersTransferData[1] = gBattleOutcome; - gBattleBuffersTransferData[2] = stringID; - gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING; + sBattleBuffersTransferData[1] = gBattleOutcome; + sBattleBuffersTransferData[2] = stringID; + sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; - stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]); stringInfo->currentMove = gCurrentMove; stringInfo->originallyUsedMove = gChosenMove; stringInfo->lastItem = gLastUsedItem; @@ -1137,7 +1138,7 @@ void EmitPrintString(u8 bufferId, u16 stringID) stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; } - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); } void EmitPrintSelectionString(u8 bufferId, u16 stringID) @@ -1145,12 +1146,12 @@ void EmitPrintSelectionString(u8 bufferId, u16 stringID) s32 i; struct StringInfoBattle *stringInfo; - gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY; - gBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY; - gBattleBuffersTransferData[2] = stringID; - gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY; + sBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY; + sBattleBuffersTransferData[2] = stringID; + sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; - stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]); stringInfo->currentMove = gCurrentMove; stringInfo->originallyUsedMove = gChosenMove; stringInfo->lastItem = gLastUsedItem; @@ -1166,386 +1167,386 @@ void EmitPrintSelectionString(u8 bufferId, u16 stringID) stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; } - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); } void EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2) { - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitUnknownYesNoBox(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE; - gBattleBuffersTransferData[1] = isDoubleBattle; - gBattleBuffersTransferData[2] = NoPpNumber; - gBattleBuffersTransferData[3] = 0; + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE; + sBattleBuffersTransferData[1] = isDoubleBattle; + sBattleBuffersTransferData[2] = NoPpNumber; + sBattleBuffersTransferData[3] = 0; for (i = 0; i < sizeof(*movePpData); i++) - gBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(*movePpData) + 4); + sBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(*movePpData) + 4); } void EmitChooseItem(u8 bufferId, u8 *arg1) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_OPENBAG; + sBattleBuffersTransferData[0] = CONTROLLER_OPENBAG; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[1 + i] = arg1[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[1 + i] = arg1[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8* arg4) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON; - gBattleBuffersTransferData[1] = caseId; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = abilityId; + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON; + sBattleBuffersTransferData[1] = caseId; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = abilityId; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[4 + i] = arg4[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 8); // but only 7 bytes were written + sBattleBuffersTransferData[4 + i] = arg4[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 8); // but only 7 bytes were written } void EmitCmd23(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_23; - gBattleBuffersTransferData[1] = CONTROLLER_23; - gBattleBuffersTransferData[2] = CONTROLLER_23; - gBattleBuffersTransferData[3] = CONTROLLER_23; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_23; + sBattleBuffersTransferData[1] = CONTROLLER_23; + sBattleBuffersTransferData[2] = CONTROLLER_23; + sBattleBuffersTransferData[3] = CONTROLLER_23; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } // why is the argument u16 if it's being cast to s16 anyway? void EmitHealthBarUpdate(u8 bufferId, u16 hpValue) { - gBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE; - gBattleBuffersTransferData[1] = 0; - gBattleBuffersTransferData[2] = (s16)hpValue; - gBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE; + sBattleBuffersTransferData[1] = 0; + sBattleBuffersTransferData[2] = (s16)hpValue; + sBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } // why is the argument u16 if it's being cast to s16 anyway? void EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints) { - gBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE; - gBattleBuffersTransferData[1] = partyId; - gBattleBuffersTransferData[2] = (s16)expPoints; - gBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE; + sBattleBuffersTransferData[1] = partyId; + sBattleBuffersTransferData[2] = (s16)expPoints; + sBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE; - gBattleBuffersTransferData[1] = status1; - gBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8; - gBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16; - gBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24; - gBattleBuffersTransferData[5] = status2; - gBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8; - gBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16; - gBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 9); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE; + sBattleBuffersTransferData[1] = status1; + sBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8; + sBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16; + sBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24; + sBattleBuffersTransferData[5] = status2; + sBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8; + sBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16; + sBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 9); } void EmitStatusAnimation(u8 bufferId, bool8 status2, u32 status) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION; - gBattleBuffersTransferData[1] = status2; - gBattleBuffersTransferData[2] = status; - gBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8; - gBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16; - gBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 6); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION; + sBattleBuffersTransferData[1] = status2; + sBattleBuffersTransferData[2] = status; + sBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8; + sBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16; + sBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 6); } void EmitStatusXor(u8 bufferId, u8 b) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR; - gBattleBuffersTransferData[1] = b; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR; + sBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitDataTransfer(u8 bufferId, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER; - gBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER; - gBattleBuffersTransferData[2] = size; - gBattleBuffersTransferData[3] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER; + sBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER; + sBattleBuffersTransferData[2] = size; + sBattleBuffersTransferData[3] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[4 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 4); + sBattleBuffersTransferData[4 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 4); } void EmitDMA3Transfer(u8 bufferId, void *dst, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER; - gBattleBuffersTransferData[1] = (u32)(dst); - gBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8; - gBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16; - gBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24; - gBattleBuffersTransferData[5] = size; - gBattleBuffersTransferData[6] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER; + sBattleBuffersTransferData[1] = (u32)(dst); + sBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8; + sBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16; + sBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24; + sBattleBuffersTransferData[5] = size; + sBattleBuffersTransferData[6] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[7 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 7); + sBattleBuffersTransferData[7 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 7); } void EmitPlayBGM(u8 bufferId, u16 songId, void *unusedDumbDataParameter) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_31; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_31; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; for (i = 0; i < songId; i++) // ???? - gBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, songId + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, songId + 3); } void EmitCmd32(u8 bufferId, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_32; - gBattleBuffersTransferData[1] = size; - gBattleBuffersTransferData[2] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_32; + sBattleBuffersTransferData[1] = size; + sBattleBuffersTransferData[2] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 3); } void EmitTwoReturnValues(u8 bufferId, u8 arg1, u16 arg2) { - gBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitChosenMonReturnValue(u8 bufferId, u8 b, u8 *c) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE; - gBattleBuffersTransferData[1] = b; + sBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE; + sBattleBuffersTransferData[1] = b; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[2 + i] = c[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 5); + sBattleBuffersTransferData[2 + i] = c[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 5); } void EmitOneReturnValue(u8 bufferId, u16 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitOneReturnValue_Duplicate(u8 bufferId, u16 b) { - gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE; - gBattleBuffersTransferData[1] = b; - gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE; + sBattleBuffersTransferData[1] = b; + sBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitCmd37(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_37; - gBattleBuffersTransferData[1] = CONTROLLER_37; - gBattleBuffersTransferData[2] = CONTROLLER_37; - gBattleBuffersTransferData[3] = CONTROLLER_37; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_37; + sBattleBuffersTransferData[1] = CONTROLLER_37; + sBattleBuffersTransferData[2] = CONTROLLER_37; + sBattleBuffersTransferData[3] = CONTROLLER_37; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitCmd38(u8 bufferId, u8 b) { - gBattleBuffersTransferData[0] = CONTROLLER_38; - gBattleBuffersTransferData[1] = b; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_38; + sBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitCmd39(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_39; - gBattleBuffersTransferData[1] = CONTROLLER_39; - gBattleBuffersTransferData[2] = CONTROLLER_39; - gBattleBuffersTransferData[3] = CONTROLLER_39; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_39; + sBattleBuffersTransferData[1] = CONTROLLER_39; + sBattleBuffersTransferData[2] = CONTROLLER_39; + sBattleBuffersTransferData[3] = CONTROLLER_39; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitCmd40(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_40; - gBattleBuffersTransferData[1] = CONTROLLER_40; - gBattleBuffersTransferData[2] = CONTROLLER_40; - gBattleBuffersTransferData[3] = CONTROLLER_40; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_40; + sBattleBuffersTransferData[1] = CONTROLLER_40; + sBattleBuffersTransferData[2] = CONTROLLER_40; + sBattleBuffersTransferData[3] = CONTROLLER_40; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitHitAnimation(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitCmd42(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_42; - gBattleBuffersTransferData[1] = CONTROLLER_42; - gBattleBuffersTransferData[2] = CONTROLLER_42; - gBattleBuffersTransferData[3] = CONTROLLER_42; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_42; + sBattleBuffersTransferData[1] = CONTROLLER_42; + sBattleBuffersTransferData[2] = CONTROLLER_42; + sBattleBuffersTransferData[3] = CONTROLLER_42; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitPlaySE(u8 bufferId, u16 songId) { - gBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitPlayFanfareOrBGM(u8 bufferId, u16 songId, bool8 playBGM) { - gBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = playBGM; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = playBGM; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitFaintingCry(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitIntroSlide(u8 bufferId, u8 terrainId) { - gBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE; - gBattleBuffersTransferData[1] = terrainId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE; + sBattleBuffersTransferData[1] = terrainId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitIntroTrainerBallThrow(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitDrawPartyStatusSummary(u8 bufferId, struct HpAndStatus* hpAndStatus, u8 arg2) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; - gBattleBuffersTransferData[1] = arg2 & 0x7F; - gBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7; - gBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; + sBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; + sBattleBuffersTransferData[1] = arg2 & 0x7F; + sBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7; + sBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; for (i = 0; i < (s32)(sizeof(struct HpAndStatus) * 6); i++) - gBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus)); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4); + sBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus)); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4); } void EmitCmd49(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_49; - gBattleBuffersTransferData[1] = CONTROLLER_49; - gBattleBuffersTransferData[2] = CONTROLLER_49; - gBattleBuffersTransferData[3] = CONTROLLER_49; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_49; + sBattleBuffersTransferData[1] = CONTROLLER_49; + sBattleBuffersTransferData[2] = CONTROLLER_49; + sBattleBuffersTransferData[3] = CONTROLLER_49; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitCmd50(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_50; - gBattleBuffersTransferData[1] = CONTROLLER_50; - gBattleBuffersTransferData[2] = CONTROLLER_50; - gBattleBuffersTransferData[3] = CONTROLLER_50; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_50; + sBattleBuffersTransferData[1] = CONTROLLER_50; + sBattleBuffersTransferData[2] = CONTROLLER_50; + sBattleBuffersTransferData[3] = CONTROLLER_50; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitSpriteInvisibility(u8 bufferId, bool8 isInvisible) { - gBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY; - gBattleBuffersTransferData[1] = isInvisible; - gBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY; - gBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY; + sBattleBuffersTransferData[1] = isInvisible; + sBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY; + sBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitBattleAnimation(u8 bufferId, u8 animationId, u16 argument) { - gBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION; - gBattleBuffersTransferData[1] = animationId; - gBattleBuffersTransferData[2] = argument; - gBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION; + sBattleBuffersTransferData[1] = animationId; + sBattleBuffersTransferData[2] = argument; + sBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void EmitLinkStandbyMsg(u8 bufferId, u8 arg1, bool32 arg2) { bool8 arg2_ = arg2; - gBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG; - gBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG; + sBattleBuffersTransferData[1] = arg1; if (arg2_) - gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = sub_81850DC(&gBattleBuffersTransferData[4]); + sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = sub_81850DC(&sBattleBuffersTransferData[4]); else - gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = 0; + sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[2] + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[2] + 4); } void EmitResetActionMoveSelection(u8 bufferId, u8 caseId) { - gBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION; - gBattleBuffersTransferData[1] = caseId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION; + sBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void EmitCmd55(u8 bufferId, u8 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_55; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b; - gBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b; - gBattleBuffersTransferData[5] = gBattleBuffersTransferData[4] = sub_81850DC(&gBattleBuffersTransferData[6]); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[4] + 6); + sBattleBuffersTransferData[0] = CONTROLLER_55; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b; + sBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b; + sBattleBuffersTransferData[5] = sBattleBuffersTransferData[4] = sub_81850DC(&sBattleBuffersTransferData[6]); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[4] + 6); } diff --git a/src/berry_blender.c b/src/berry_blender.c index 51580b50b..b61bb8e9b 100644 --- a/src/berry_blender.c +++ b/src/berry_blender.c @@ -161,7 +161,7 @@ extern void sub_809882C(u8, u16, u8); extern void copy_textbox_border_tile_patterns_to_vram(u8, u16, u8); extern void sub_81AABF0(void (*callback)(void)); extern void sub_800B4C0(void); -extern void sub_8009F8C(void); +extern void ClearLinkCallback(void); extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void); extern void sub_8153430(void); extern bool8 sub_8153474(void); @@ -953,10 +953,10 @@ static void sub_807FAC8(void) sBerryBlenderData->syncArrowSpriteIds[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[i]], i + 8); } - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } SetVBlankCallback(VBlankCB0_BerryBlender); sBerryBlenderData->mainState++; @@ -1159,10 +1159,10 @@ static void sub_8080018(void) sBerryBlenderData->syncArrowSprite2Ids[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSprite2Ids[i]], i + 8); } - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } sBerryBlenderData->mainState++; break; @@ -1875,7 +1875,7 @@ static void sub_8081370(u16 a0) static bool32 sub_80814B0(u16 arg0, u16 arg1, u16 arg2) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { if ((arg0 & 0xFF00) == arg2) return TRUE; @@ -2317,7 +2317,7 @@ static void sub_8081E20(void) static void sub_8081F94(u16 *a0) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) *a0 = 0x2F00; else *a0 = 0x2FFF; @@ -2346,7 +2346,7 @@ static void CB2_HandleBlenderEndGame(void) sBerryBlenderData->field_4C -= 32; if (sBerryBlenderData->field_4C <= 0) { - sub_8009F8C(); + ClearLinkCallback(); sBerryBlenderData->field_4C = 0; if (gReceivedRemoteLinkPlayers != 0) @@ -2366,7 +2366,7 @@ static void CB2_HandleBlenderEndGame(void) } else if (sub_800A520()) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sBerryBlenderData->gameBlock.timeRPM.time = sBerryBlenderData->gameFrameTime; sBerryBlenderData->gameBlock.timeRPM.max_RPM = sBerryBlenderData->max_RPM; @@ -2395,7 +2395,7 @@ static void CB2_HandleBlenderEndGame(void) ResetBlockReceivedFlags(); sBerryBlenderData->gameEndState++; - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { struct BlenderGameBlock *receivedBlock = (struct BlenderGameBlock*)(&gBlockRecvBuffer); @@ -2872,7 +2872,7 @@ static void sub_8082D28(void) if (gReceivedRemoteLinkPlayers != 0) playerId = GetMultiplayerId(); - if (gLinkVSyncDisabled && gReceivedRemoteLinkPlayers != 0) + if (gWirelessCommType && gReceivedRemoteLinkPlayers != 0) { if (playerId == 0) { diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 1aff894b9..ed1e7f4cc 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -58,20 +58,14 @@ extern const u8 gText_HatchedFromEgg[]; extern const u8 gText_NickHatchPrompt[]; extern u8 sav1_map_get_name(void); -extern s8 ProcessMenuInputNoWrap_(void); extern void TVShowConvertInternationalString(u8* str1, u8* str2, u8); extern void sub_806A068(u16, u8); extern void fade_screen(u8, u8); extern void overworld_free_bg_tilemaps(void); extern void sub_80AF168(void); -extern void AllocateMonSpritesGfx(void); -extern void FreeMonSpritesGfx(void); extern void remove_some_task(void); -extern void reset_temp_tile_data_buffers(void); extern void c2_exit_to_overworld_2_switch(void); extern void play_some_sound(void); -extern void copy_decompressed_tile_data_to_vram_autofree(u8 bg_id, const void* src, u16 size, u16 offset, u8 mode); -extern void CreateYesNoMenu(const struct WindowTemplate*, u16, u8, u8); extern void DoNamingScreen(u8, const u8*, u16, u8, u32, MainCallback); extern u16 sub_80D22D0(void); extern u8 CountPartyAliveNonEggMonsExcept(u8); diff --git a/src/evolution_scene.c b/src/evolution_scene.c index 4b59147ff..536eb6979 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -69,9 +69,6 @@ extern const u8 gText_PkmnStoppedEvolving[]; extern const u8 gText_EllipsisQuestionMark[]; extern const u8 gText_CommunicationStandby5[]; -extern void copy_decompressed_tile_data_to_vram_autofree(u8 arg0, const void *arg1, bool32 arg2, u16 arg3, u8 arg4); -extern u32 sub_80391E0(u8, u8); -extern void SpriteCallbackDummy_2(struct Sprite *sprite); extern void sub_80356D0(void); extern void sub_807B154(void); extern void sub_806A068(u16, u8); @@ -473,10 +470,10 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void) } break; case 6: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } BlendPalettes(-1,0x10, 0); gMain.state++; @@ -1256,7 +1253,7 @@ static void Task_TradeEvolutionScene(u8 taskID) case 5: if (!gPaletteFade.active) { - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E084(); Free(GetBgTilemapBuffer(3)); diff --git a/src/librfu_rfu.c b/src/librfu_rfu.c index cf3fe12ad..c5aa25c10 100644 --- a/src/librfu_rfu.c +++ b/src/librfu_rfu.c @@ -3,38 +3,6 @@ #include "librfu.h" -struct RfuUnk1 -{ - u8 unk_0[0x14]; - u32 unk_14; - u32 unk_18; - struct RfuIntrStruct unk_1c; -}; - -struct RfuUnk2 -{ - u8 unk_0[0x68]; - u32 unk_68; - u32 unk_6c; - u8 unk_70[0x70]; -}; - -struct RfuUnk3 -{ - u32 unk_0; - u32 unk_4; - u8 unk_8[0xD4]; - u32 unk_dc; -}; - -extern u32 *gUnknown_03007890; -extern u32 *gUnknown_03007894; -extern struct RfuUnk3* gUnknown_03007898; -extern struct RfuUnk2* gUnknown_03007880[4]; -extern struct RfuUnk1* gUnknown_03007870[4]; -extern void* sub_82E53F4; -extern void rfu_STC_clearAPIVariables(void); - // Nonmatching, only register differences /*u16 rfu_initializeAPI(u32 *unk0, u16 unk1, IntrFunc *interrupt, bool8 copyInterruptToRam) { diff --git a/src/link.c b/src/link.c index ae2cd1992..65c5d3982 100644 --- a/src/link.c +++ b/src/link.c @@ -1,6 +1,33 @@ // Includes #include "global.h" +#include "m4a.h" +#include "malloc.h" +#include "reset_save_heap.h" +#include "save.h" +#include "bg.h" +#include "window.h" +#include "librfu.h" +#include "random.h" +#include "decompress.h" +#include "string_util.h" +#include "event_data.h" +#include "item_menu.h" +#include "overworld.h" +#include "gpu_regs.h" +#include "palette.h" +#include "task.h" +#include "unknown_task.h" +#include "menu.h" +#include "new_menu_helpers.h" +#include "text.h" +#include "strings.h" +#include "constants/songs.h" +#include "sound.h" +#include "trade.h" +#include "battle.h" +#include "link.h" +#include "link_rfu.h" // Static type declarations @@ -8,7 +35,7 @@ struct BlockTransfer { u16 pos; u16 size; - void *src; + const u8 *src; bool8 active; u8 multiplayerId; }; @@ -23,34 +50,2392 @@ struct LinkTestBGInfo // Static RAM declarations -IWRAM_DATA struct BlockTransfer gUnknown_03000D10; +IWRAM_DATA struct BlockTransfer sBlockSend; IWRAM_DATA u32 link_c_unused_03000d1c; -IWRAM_DATA struct BlockTransfer gUnknown_03000D20[4]; -IWRAM_DATA u32 gUnknown_03000D50; +IWRAM_DATA struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS]; +IWRAM_DATA u32 sBlockSendDelayCounter; IWRAM_DATA u32 gUnknown_03000D54; IWRAM_DATA u8 gUnknown_03000D58; -IWRAM_DATA u32 gUnknown_03000D5C; +IWRAM_DATA u32 sPlayerDataExchangeStatus; IWRAM_DATA u32 gUnknown_03000D60; -IWRAM_DATA u8 gUnknown_03000D64[4]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D68[4]; -IWRAM_DATA u8 gUnknown_03000D6C; -IWRAM_DATA bool8 gUnknown_03000D6D; -IWRAM_DATA u16 gUnknown_03000D6E; -IWRAM_DATA u16 gUnknown_03000D70; -IWRAM_DATA u8 gUnknown_03000D72; -IWRAM_DATA u8 gUnknown_03000D73; -IWRAM_DATA u8 gUnknown_03000D74[4]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D78[8]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D80[16]; -IWRAM_DATA u16 gUnknown_03000D90[8]; -IWRAM_DATA u32 gUnknown_03000DA0; -IWRAM_DATA u32 gUnknown_03000DA4; -IWRAM_DATA void *gUnknown_03000DA8; -IWRAM_DATA void *gUnknown_03000DAC; -IWRAM_DATA bool32 gUnknown_03000DB0; +IWRAM_DATA u8 sLinkTestLastBlockSendPos; +ALIGNED() IWRAM_DATA u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS]; +IWRAM_DATA u8 sNumVBlanksWithoutSerialIntr; +IWRAM_DATA bool8 sSendBufferEmpty; +IWRAM_DATA u16 sSendNonzeroCheck; +IWRAM_DATA u16 sRecvNonzeroCheck; +IWRAM_DATA u8 sChecksumAvailable; +IWRAM_DATA u8 sHandshakePlayerCount; + +u16 gLinkPartnersHeldKeys[6]; +u32 gLinkDebugSeed; +struct LinkPlayerBlock gLocalLinkPlayerBlock; +bool8 gLinkErrorOccurred; +u32 gLinkDebugFlags; +u32 gFiller_03003074; +bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS]; +u8 gBlockReceivedStatus[MAX_LINK_PLAYERS]; +u32 gFiller_03003080; +u16 gLinkHeldKeys; +u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; +u32 gLinkStatus; +bool8 gUnknown_030030E4; +bool8 gUnknown_030030E8; +bool8 gUnknown_030030EC[MAX_LINK_PLAYERS]; +bool8 gUnknown_030030F0[MAX_LINK_PLAYERS]; +u16 gUnknown_030030F4; +u8 gSuppressLinkErrorMessage; +bool8 gWirelessCommType; +bool8 gSavedLinkPlayerCount; +u16 gSendCmd[CMD_LENGTH]; +u8 gSavedMultiplayerId; +bool8 gReceivedRemoteLinkPlayers; +struct LinkTestBGInfo gLinkTestBGInfo; +void (*gLinkCallback)(void); +u8 gShouldAdvanceLinkState; +u16 gLinkTestBlockChecksums[MAX_LINK_PLAYERS]; +u8 gBlockRequestType; +u32 gFiller_03003154; +u32 gFiller_03003158; +u32 gFiller_0300315c; +u8 gLastSendQueueCount; +struct Link gLink; +u8 gLastRecvQueueCount; +u16 gLinkSavedIme; +u32 gFiller_03004138; +u32 gFiller_0300413C; + +EWRAM_DATA u8 gLinkTestDebugValuesEnabled = 0; +EWRAM_DATA u8 gUnknown_020223BD = 0; +EWRAM_DATA u32 gUnknown_020223C0 = 0; +EWRAM_DATA u16 gBlockRecvBuffer[MAX_RFU_PLAYERS][BLOCK_BUFFER_SIZE / 2] = {}; +EWRAM_DATA u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE] = {}; +EWRAM_DATA bool8 gLinkOpen = FALSE; +EWRAM_DATA u16 gLinkType = 0; +EWRAM_DATA u16 gLinkTimeOutCounter = 0; +EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {}; +EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {}; +EWRAM_DATA struct LinkPlayer gSavedLinkPlayers[MAX_RFU_PLAYERS] = {}; +EWRAM_DATA struct { + u32 status; + u8 lastRecvQueueCount; + u8 lastSendQueueCount; + u8 unk_06; +} sLinkErrorBuffer = {}; +EWRAM_DATA u16 gUnknown_02022B08 = 0; +EWRAM_DATA void *gUnknown_02022B0C = NULL; // Static ROM declarations +static void InitLocalLinkPlayer(void); +static void sub_80096BC(void); +static void CB2_LinkTest(void); +static void ProcessRecvCmds(u8 unused); +static void sub_8009F70(void); +static void ResetBlockSend(void); +static bool32 InitBlockSend(const void *src, size_t size); +static void LinkCB_BlockSendBegin(void); +static void LinkCB_BlockSend(void); +static void LinkCB_BlockSendEnd(void); +static void SetBlockReceivedFlag(u8 who); +static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size); +static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2); +static void LinkCB_RequestPlayerDataExchange(void); +static void Task_PrintTestData(u8 taskId); + +static void sub_800AC80(void); +static void sub_800ACAC(void); +static void sub_800AD5C(void); +static void sub_800AD88(void); +static void sub_800AE30(void); +static void sub_800AE5C(void); + +static void CheckErrorStatus(void); +static void CB2_PrintErrorMessage(void); +static bool8 IsSioMultiMaster(void); +static void sub_800B4A4(void); +static void DisableSerial(void); +static void EnableSerial(void); +static void CheckMasterOrSlave(void); +static void InitTimer(void); +static void EnqueueSendCmd(u16 *sendCmd); +static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH]); + +static void StartTransfer(void); +static bool8 DoHandshake(void); +static void DoRecv(void); +static void DoSend(void); +static void StopTimer(void); +static void SendRecvDone(void); + // .rodata +ALIGNED(4) const u16 gWirelessLinkDisplayPal[] = INCBIN_U16("graphics/interface/wireless_link_display.gbapal"); +const u8 gWirelessLinkDisplayGfx[] = INCBIN_U8("graphics/interface/wireless_link_display.4bpp.lz"); +const u8 gWirelessLinkDisplayTilemap[] = INCBIN_U8("graphics/interface/wireless_link_display.bin.lz"); +const u16 gLinkTestDigitsPal[] = INCBIN_U16("graphics/interface/link_test_digits.gbapal"); +const u16 gLinkTestDigitsGfx[] = INCBIN_U16("graphics/interface/link_test_digits.4bpp"); +const u8 unkstring_82ed160[] = _("{HIGHLIGHT TRANSPARENT}{COLOR WHITE}"); +const u16 g2BlankTilesGfx[] = INCBIN_U16("graphics/interface/blank_1x2.4bpp"); +const struct BlockRequest gUnknown_082ED1A8[] = { + {gBlockSendBuffer, 200}, + {gBlockSendBuffer, 200}, + {gBlockSendBuffer, 100}, + {gBlockSendBuffer, 220}, + {gBlockSendBuffer, 40} +}; +const u8 gBGControlRegs[] = { + REG_OFFSET_BG0CNT, + REG_OFFSET_BG1CNT, + REG_OFFSET_BG2CNT, + REG_OFFSET_BG3CNT +}; +const char gASCIIGameFreakInc[] = "GameFreak inc."; +const char gASCIITestPrint[] = "TEST PRINT\nP0\nP1\nP2\nP3"; +const struct BgTemplate gUnknown_082ED1FC[] = { + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .priority = 0 + }, { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 8, + .priority = 1 + } +}; +const struct WindowTemplate gUnknown_082ED204[] = { + {0x00, 0x00, 0x00, 0x1E, 0x05, 0x0F, 0x0002}, + {0x00, 0x00, 0x06, 0x1E, 0x07, 0x0F, 0x0098}, + {0x00, 0x00, 0x0D, 0x1E, 0x07, 0x0F, 0x016A}, + DUMMY_WIN_TEMPLATE +}; +const u8 gUnknown_082ED224[] = { + 0x00, 0x01, 0x02, 0x00, + 0xff, 0xfe, 0xff, 0x00 +}; + // .text + +bool8 sub_80093CC(void) +{ + sub_800B488(); + sub_800E700(); + if (sub_800BEC0() == 0x8001) + { + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + return TRUE; + } + sub_800B4A4(); + CloseLink(); + RestoreSerialTimer3IntrHandlers(); + return FALSE; +} + +void Task_DestroySelf(u8 taskId) +{ + DestroyTask(taskId); +} + +static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock, u16 a4) +{ + LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20); + DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock) + (16 * a4), sizeof gLinkTestDigitsGfx); + gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; + gLinkTestBGInfo.paletteNum = paletteNum; + gLinkTestBGInfo.dummy_8 = a4; + switch (bgNum) + { + case 1: + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + case 2: + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + case 3: + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + } + SetGpuReg(REG_OFFSET_BG0HOFS + bgNum * 4, 0); + SetGpuReg(REG_OFFSET_BG0VOFS + bgNum * 4, 0); +} + +void sub_80094EC(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock) +{ + LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20); + DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock), sizeof gLinkTestDigitsGfx); + gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; + gLinkTestBGInfo.paletteNum = paletteNum; + gLinkTestBGInfo.dummy_8 = 0; + SetGpuReg(gBGControlRegs[bgNum], BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_CHARBASE(charBaseBlock)); +} + +void LinkTestScreen(void) +{ + int i; + + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetTasks(); + SetVBlankCallback(sub_80096BC); + ResetBlockSend(); + gLinkType = 0x1111; + OpenLink(); + SeedRng(gMain.vblankCounter2); + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gSaveBlock2Ptr->playerTrainerId[i] = Random() % 256; + } + InitLinkTestBG(0, 2, 4, 0, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON); + CreateTask(Task_DestroySelf, 0); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + gUnknown_03000D60 = 0; + InitLocalLinkPlayer(); + CreateTask(Task_PrintTestData, 0); + SetMainCallback2(CB2_LinkTest); +} + +void sub_8009628(u8 a0) +{ + gLocalLinkPlayer.lp_field_18 = a0; +} + +static void InitLocalLinkPlayer(void) +{ + gLocalLinkPlayer.trainerId = gSaveBlock2Ptr->playerTrainerId[0] | (gSaveBlock2Ptr->playerTrainerId[1] << 8) | (gSaveBlock2Ptr->playerTrainerId[2] << 16) | (gSaveBlock2Ptr->playerTrainerId[3] << 24); + StringCopy(gLocalLinkPlayer.name, gSaveBlock2Ptr->playerName); + gLocalLinkPlayer.gender = gSaveBlock2Ptr->playerGender; + gLocalLinkPlayer.linkType = gLinkType; + gLocalLinkPlayer.language = gGameLanguage; + gLocalLinkPlayer.version = gGameVersion + 0x4000; + gLocalLinkPlayer.lp_field_2 = 0x8000; + gLocalLinkPlayer.name[8] = IsNationalPokedexEnabled(); + if (FlagGet(FLAG_0x87F)) + { + gLocalLinkPlayer.name[8] |= 0x10; + } +} + +static void sub_80096BC(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void InitLink(void) +{ + int i; + + for (i = 0; i < 8; i++) + { + gSendCmd[i] = 0xefff; + } + gLinkOpen = TRUE; + EnableSerial(); +} + +static void Task_TriggerHandshake(u8 taskId) +{ + if (++gTasks[taskId].data[0] == 5) + { + gShouldAdvanceLinkState = 1; + DestroyTask(taskId); + } +} + +void OpenLink(void) +{ + int i; + + if (!gWirelessCommType) + { + ResetSerial(); + InitLink(); + gLinkCallback = LinkCB_RequestPlayerDataExchange; + gLinkVSyncDisabled = FALSE; + gLinkErrorOccurred = FALSE; + gSuppressLinkErrorMessage = FALSE; + ResetBlockReceivedFlags(); + ResetBlockSend(); + gUnknown_03000D54 = 0; + gUnknown_030030E8 = FALSE; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + CreateTask(Task_TriggerHandshake, 2); + } + else + { + sub_800E700(); + } + gReceivedRemoteLinkPlayers = 0; + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gRemoteLinkPlayersNotReceived[i] = TRUE; + gUnknown_030030F0[i] = FALSE; + gUnknown_030030EC[i] = FALSE; + } +} + +void CloseLink(void) +{ + gReceivedRemoteLinkPlayers = FALSE; + if (gWirelessCommType) + { + sub_800EDD4(); + } + gLinkOpen = FALSE; + DisableSerial(); +} + +static void TestBlockTransfer(u8 nothing, u8 is, u8 used) +{ + u8 i; + u8 status; + + if (sLinkTestLastBlockSendPos != sBlockSend.pos) + { + LinkTest_prnthex(sBlockSend.pos, 2, 3, 2); + sLinkTestLastBlockSendPos = sBlockSend.pos; + } + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if (sLinkTestLastBlockRecvPos[i] != sBlockRecv[i].pos) + { + LinkTest_prnthex(sBlockRecv[i].pos, 2, i + 4, 2); + sLinkTestLastBlockRecvPos[i] = sBlockRecv[i].pos; + } + } + status = GetBlockReceivedStatus(); + if (status == 0xF) // 0b1111 + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if ((status >> i) & 1) + { + gLinkTestBlockChecksums[i] = LinkTestCalcBlockChecksum(gBlockRecvBuffer[i], sBlockRecv[i].size); + ResetBlockReceivedFlag(i); + if (gLinkTestBlockChecksums[i] != 0x0342) + { + gLinkTestDebugValuesEnabled = FALSE; + gUnknown_020223BD = FALSE; + } + } + } + } +} + +static void LinkTestProcessKeyInput(void) +{ + if (gMain.newKeys & A_BUTTON) + { + gShouldAdvanceLinkState = 1; + } + if (gMain.heldKeys & B_BUTTON) + { + InitBlockSend(gHeap + 0x4000, 0x00002004); + } + if (gMain.newKeys & L_BUTTON) + { + BeginNormalPaletteFade(-1, 0, 16, 0, 2); + } + if (gMain.newKeys & START_BUTTON) + { + SetSuppressLinkErrorMessage(TRUE); + } + if (gMain.newKeys & R_BUTTON) + { + TrySavingData(1); + } + if (gMain.newKeys & SELECT_BUTTON) + { + sub_800AC34(); + } + if (gLinkTestDebugValuesEnabled) + { + SetLinkDebugValues(gMain.vblankCounter2, gLinkCallback ? gLinkVSyncDisabled : gLinkVSyncDisabled | 0x10); + } +} + +static void CB2_LinkTest(void) +{ + LinkTestProcessKeyInput(); + TestBlockTransfer(1, 1, 0); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +u16 LinkMain2(const u16 *heldKeys) +{ + u8 i; + + if (!gLinkOpen) + { + return 0; + } + for (i = 0; i < 8; i++) + { + gSendCmd[i] = 0; + } + gLinkHeldKeys = *heldKeys; + if (gLinkStatus & LINK_STAT_CONN_ESTABLISHED) + { + ProcessRecvCmds(SIO_MULTI_CNT->id); + if (gLinkCallback != NULL) + { + gLinkCallback(); + } + CheckErrorStatus(); + } + return gLinkStatus; +} + +static void HandleReceiveRemoteLinkPlayer(u8 who) +{ + int i; + int count; + + count = 0; + gRemoteLinkPlayersNotReceived[who] = FALSE; + for (i = 0; i < GetLinkPlayerCount_2(); i++) + { + count += gRemoteLinkPlayersNotReceived[i]; + } + if (count == 0 && gReceivedRemoteLinkPlayers == 0) + { + gReceivedRemoteLinkPlayers = 1; + } +} + +static void ProcessRecvCmds(u8 unused) +{ + u16 i; + + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gLinkPartnersHeldKeys[i] = 0; + if (gRecvCmds[i][0] == 0) + { + continue; + } + switch (gRecvCmds[i][0]) + { + case LINKCMD_SEND_LINK_TYPE: + { + struct LinkPlayerBlock *block; + + InitLocalLinkPlayer(); + block = &gLocalLinkPlayerBlock; + block->linkPlayer = gLocalLinkPlayer; + memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1); + memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1); + InitBlockSend(block, sizeof(*block)); + break; + } + case LINKCMD_SEND_HELD_KEYS: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + case LINKCMD_0x5555: + gUnknown_030030E8 = TRUE; + break; + case LINKCMD_0x5566: + gUnknown_030030E8 = TRUE; + break; + case LINKCMD_INIT_BLOCK: + { + struct BlockTransfer *blockRecv; + + blockRecv = &sBlockRecv[i]; + blockRecv->pos = 0; + blockRecv->size = gRecvCmds[i][1]; + blockRecv->multiplayerId = gRecvCmds[i][2]; + break; + } + case LINKCMD_CONT_BLOCK: + { + if (sBlockRecv[i].size > BLOCK_BUFFER_SIZE) + { + u16 *buffer; + u16 j; + + buffer = (u16 *)gDecompressionBuffer; + for (j = 0; j < CMD_LENGTH - 1; j++) + { + buffer[(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1]; + } + } + else + { + u16 j; + + for (j = 0; j < CMD_LENGTH - 1; j++) + { + gBlockRecvBuffer[i][(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1]; + } + } + + sBlockRecv[i].pos += (CMD_LENGTH - 1) * 2; + + if (sBlockRecv[i].pos >= sBlockRecv[i].size) + { + if (gRemoteLinkPlayersNotReceived[i] == TRUE) + { + struct LinkPlayerBlock *block; + struct LinkPlayer *linkPlayer; + + block = (struct LinkPlayerBlock *)&gBlockRecvBuffer[i]; + linkPlayer = &gLinkPlayers[i]; + *linkPlayer = block->linkPlayer; + if ((linkPlayer->version & 0xFF) == VERSION_RUBY || (linkPlayer->version & 0xFF) == VERSION_SAPPHIRE) + { + linkPlayer->name[10] = 0; + linkPlayer->name[9] = 0; + linkPlayer->name[8] = 0; + } + sub_800B524(linkPlayer); + if (strcmp(block->magic1, gASCIIGameFreakInc) != 0 + || strcmp(block->magic2, gASCIIGameFreakInc) != 0) + { + SetMainCallback2(CB2_LinkError); + } + else + { + HandleReceiveRemoteLinkPlayer(i); + } + } + else + { + SetBlockReceivedFlag(i); + } + } + } + break; + case LINKCMD_0x5FFF: + gUnknown_030030F0[i] = TRUE; + break; + case LINKCMD_0x2FFE: + gUnknown_030030EC[i] = TRUE; + break; + case LINKCMD_0xAAAA: + sub_800A418(); + break; + case LINKCMD_0xCCCC: + SendBlock(0, gUnknown_082ED1A8[gRecvCmds[i][1]].address, gUnknown_082ED1A8[gRecvCmds[i][1]].size); + break; + case LINKCMD_SEND_HELD_KEYS_2: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + } + } +} + +static void BuildSendCmd(u16 command) +{ + switch (command) + { + case LINKCMD_SEND_LINK_TYPE: + gSendCmd[0] = LINKCMD_SEND_LINK_TYPE; + gSendCmd[1] = gLinkType; + break; + case LINKCMD_0x2FFE: + gSendCmd[0] = LINKCMD_0x2FFE; + break; + case LINKCMD_SEND_HELD_KEYS: + gSendCmd[0] = LINKCMD_SEND_HELD_KEYS; + gSendCmd[1] = gMain.heldKeys; + break; + case LINKCMD_0x5555: + gSendCmd[0] = LINKCMD_0x5555; + break; + case LINKCMD_0x6666: + gSendCmd[0] = LINKCMD_0x6666; + gSendCmd[1] = 0; + break; + case LINKCMD_0x7777: + { + u8 i; + + gSendCmd[0] = LINKCMD_0x7777; + for (i = 0; i < 5; i++) + { + gSendCmd[i + 1] = 0xEE; + } + break; + } + case LINKCMD_INIT_BLOCK: + gSendCmd[0] = LINKCMD_INIT_BLOCK; + gSendCmd[1] = sBlockSend.size; + gSendCmd[2] = sBlockSend.multiplayerId + 0x80; + break; + case LINKCMD_0xAAAA: + gSendCmd[0] = LINKCMD_0xAAAA; + break; + case LINKCMD_0xAAAB: + gSendCmd[0] = LINKCMD_0xAAAB; + gSendCmd[1] = gSpecialVar_ItemId; + break; + case LINKCMD_0xCCCC: + gSendCmd[0] = LINKCMD_0xCCCC; + gSendCmd[1] = gBlockRequestType; + break; + case LINKCMD_0x5FFF: + gSendCmd[0] = LINKCMD_0x5FFF; + gSendCmd[1] = gUnknown_030030F4; + break; + case LINKCMD_0x5566: + gSendCmd[0] = LINKCMD_0x5566; + break; + case LINKCMD_SEND_HELD_KEYS_2: + if (gUnknown_03005DA8 == 0 || gLinkTransferringData) + { + break; + } + gSendCmd[0] = LINKCMD_SEND_HELD_KEYS_2; + gSendCmd[1] = gUnknown_03005DA8; + break; + } +} + +void sub_8009F18(void) +{ + if (gWirelessCommType) + { + sub_800F804(); + } + gLinkCallback = sub_8009F70; +} + +bool32 sub_8009F3C(void) +{ + if (gWirelessCommType) + { + return sub_800F7E4(); + } + if (gLinkCallback == sub_8009F70) + { + return TRUE; + } + return FALSE; +} + +static void sub_8009F70(void) +{ + if (gReceivedRemoteLinkPlayers == TRUE) + { + BuildSendCmd(LINKCMD_SEND_HELD_KEYS_2); + } +} + +void ClearLinkCallback(void) +{ + if (gWirelessCommType) + { + Rfu_set_zero(); + } + else + { + gLinkCallback = NULL; + } +} + +void ClearLinkCallback_2(void) +{ + if (gWirelessCommType) + { + Rfu_set_zero(); + } + else + { + gLinkCallback = NULL; + } +} + +u8 GetLinkPlayerCount(void) +{ + if (gWirelessCommType) + { + return sub_80104F4(); + } + return EXTRACT_PLAYER_COUNT(gLinkStatus); +} + +static int sub_8009FF8(u32 version1, u32 version2) +{ + int i; + u8 nPlayers; + + nPlayers = GetLinkPlayerCount(); + for (i = 0; i < nPlayers; i++) + { + if ((gLinkPlayers[i].version & 0xFF) == version1 || (gLinkPlayers[i].version & 0xFF) == version2) + { + return 1; + } + } + return -1; +} + +u32 sub_800A03C(void) +{ + return 2; +} + +bool32 sub_800A040(void) +{ + if (GetLinkPlayerCount() != 4 || sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) < 0) + { + return FALSE; + } + return TRUE; +} + +bool32 sub_800A064(void) +{ + if (sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) >= 0) + { + return TRUE; + } + return FALSE; +} + +bool32 sub_800A07C(void) +{ + int i; + + i = sub_8009FF8(VERSION_FIRE_RED, VERSION_LEAF_GREEN); + if (i >= 0 && gLinkPlayers[i].language == LANGUAGE_JAPANESE) + { + return TRUE; + } + return FALSE; +} + +void OpenLinkTimed(void) +{ + sPlayerDataExchangeStatus = EXCHANGE_NOT_STARTED; + gLinkTimeOutCounter = 0; + OpenLink(); +} + +u8 GetLinkPlayerDataExchangeStatusTimed(int lower, int upper) +{ + int i; + int count; + u32 index; + u8 cmpVal; + u32 linkType1; + u32 linkType2; + + count = 0; + if (gReceivedRemoteLinkPlayers == TRUE) + { + cmpVal = GetLinkPlayerCount_2(); + if (lower > cmpVal || cmpVal > upper) + { + sPlayerDataExchangeStatus = EXCHANGE_STAT_6; + return 6; + } + else + { + if (GetLinkPlayerCount() == 0) + { + gLinkErrorOccurred = TRUE; + CloseLink(); + } + for (i = 0, index = 0; i < GetLinkPlayerCount(); index++, i++) + { + if (gLinkPlayers[index].linkType == gLinkPlayers[0].linkType) + { + count++; + } + } + if (count == GetLinkPlayerCount()) + { + if (gLinkPlayers[0].linkType == 0x1133) + { + switch (sub_807A728()) + { + case 1: + sPlayerDataExchangeStatus = EXCHANGE_STAT_4; + break; + case 2: + sPlayerDataExchangeStatus = EXCHANGE_STAT_5; + break; + case 0: + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + break; + } + } + else + { + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + } + } + else + { + sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS; + linkType1 = gLinkPlayers[GetMultiplayerId()].linkType; + linkType2 = gLinkPlayers[GetMultiplayerId() ^ 1].linkType; + if ((linkType1 == 0x2266 && linkType2 == 0x2277) || (linkType1 == 0x2277 && linkType2 == 0x2266)) + { + gSpecialVar_0x8005 = 3; + } + } + } + } + else if (++gLinkTimeOutCounter > 600) + { + sPlayerDataExchangeStatus = EXCHANGE_TIMED_OUT; + } + return sPlayerDataExchangeStatus; +} + +bool8 IsLinkPlayerDataExchangeComplete(void) +{ + u8 i; + u8 count; + bool8 retval; + + count = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + if (gLinkPlayers[i].linkType == gLinkPlayers[0].linkType) + { + count++; + } + } + if (count == GetLinkPlayerCount()) + { + retval = TRUE; + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + } + else + { + retval = FALSE; + sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS; + } + return retval; +} + +u32 GetLinkPlayerTrainerId(u8 who) +{ + return gLinkPlayers[who].trainerId; +} + +void ResetLinkPlayers(void) +{ + int i; + + for (i = 0; i <= MAX_LINK_PLAYERS; i++) + { + gLinkPlayers[i] = (struct LinkPlayer){}; + } +} + +static void ResetBlockSend(void) +{ + sBlockSend.active = FALSE; + sBlockSend.pos = 0; + sBlockSend.size = 0; + sBlockSend.src = NULL; +} + +static bool32 InitBlockSend(const void *src, size_t size) +{ + if (sBlockSend.active) + { + return FALSE; + } + sBlockSend.multiplayerId = GetMultiplayerId(); + sBlockSend.active = TRUE; + sBlockSend.size = size; + sBlockSend.pos = 0; + if (size > 0x100) + { + sBlockSend.src = src; + } + else + { + if (src != gBlockSendBuffer) + { + memcpy(gBlockSendBuffer, src, size); + } + sBlockSend.src = gBlockSendBuffer; + } + BuildSendCmd(LINKCMD_INIT_BLOCK); + gLinkCallback = LinkCB_BlockSendBegin; + sBlockSendDelayCounter = 0; + return TRUE; +} + +static void LinkCB_BlockSendBegin(void) +{ + if (++sBlockSendDelayCounter > 2) + { + gLinkCallback = LinkCB_BlockSend; + } +} + +static void LinkCB_BlockSend(void) +{ + int i; + const u8 *src; + + src = sBlockSend.src; + gSendCmd[0] = LINKCMD_CONT_BLOCK; + for (i = 0; i < 7; i++) + { + gSendCmd[i + 1] = (src[sBlockSend.pos + i * 2 + 1] << 8) | src[sBlockSend.pos + i * 2]; + } + sBlockSend.pos += 14; + if (sBlockSend.size <= sBlockSend.pos) + { + sBlockSend.active = FALSE; + gLinkCallback = LinkCB_BlockSendEnd; + } +} + +static void LinkCB_BlockSendEnd(void) +{ + gLinkCallback = NULL; +} + +static void sub_800A3F8(void) +{ + GetMultiplayerId(); + BuildSendCmd(LINKCMD_SEND_HELD_KEYS); + gUnknown_020223C0++; +} + +void sub_800A418(void) +{ + gUnknown_020223C0 = 0; + if (gWirelessCommType) + { + sub_800F850(); + } + else + { + gLinkCallback = sub_800A3F8; + } +} + +u32 sub_800A44C(void) +{ + return gUnknown_020223C0; +} + +void sub_800A458(void) +{ + BuildSendCmd(LINKCMD_0xAAAA); +} + +u8 GetMultiplayerId(void) +{ + if (gWirelessCommType == TRUE) + { + return rfu_get_multiplayer_id(); + } + return SIO_MULTI_CNT->id; +} + +u8 bitmask_all_link_players_but_self(void) +{ + u8 mpId; + + mpId = GetMultiplayerId(); + return ((1 << MAX_LINK_PLAYERS) - 1) ^ (1 << mpId); +} + +bool8 SendBlock(u8 unused, const void *src, u16 size) +{ + if (gWirelessCommType == TRUE) + { + return sub_800FE84(src, size); + } + return InitBlockSend(src, size); +} + +bool8 sub_800A4D8(u8 a0) +{ + if (gWirelessCommType == TRUE) + { + return sub_8010100(a0); + } + if (gLinkCallback == NULL) + { + gBlockRequestType = a0; + BuildSendCmd(LINKCMD_0xCCCC); + return TRUE; + } + return FALSE; +} + +bool8 sub_800A520(void) +{ + if (gWirelessCommType == TRUE) + { + return sub_8010500(); + } + return gLinkCallback == NULL; +} + +u8 GetBlockReceivedStatus(void) +{ + if (gWirelessCommType == TRUE) + { + return sub_800FCD8(); + } + return (gBlockReceivedStatus[3] << 3) | (gBlockReceivedStatus[2] << 2) | (gBlockReceivedStatus[1] << 1) | (gBlockReceivedStatus[0] << 0); +} + +static void SetBlockReceivedFlag(u8 who) +{ + if (gWirelessCommType == TRUE) + { + sub_800F6FC(who); + } + else + { + gBlockReceivedStatus[who] = TRUE; + } +} + +void ResetBlockReceivedFlags(void) +{ + int i; + + if (gWirelessCommType == TRUE) + { + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + sub_800F728(i); + } + } + else + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gBlockReceivedStatus[i] = FALSE; + } + } +} + +void ResetBlockReceivedFlag(u8 who) +{ + if (gWirelessCommType == TRUE) + { + sub_800F728(who); + } + else if (gBlockReceivedStatus[who]) + { + gBlockReceivedStatus[who] = FALSE; + } +} + +void sub_800A620(void) +{ + if ((gLinkStatus & LINK_STAT_MASTER) && EXTRACT_PLAYER_COUNT(gLinkStatus) > 1) + { + gShouldAdvanceLinkState = 1; + } +} + +static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size) +{ + u16 chksum; + u16 i; + + chksum = 0; + for (i = 0; i < size / 2; i++) + { + chksum += src[i]; + } + return chksum; +} + +static void LinkTest_prnthexchar(char a0, u8 a1, u8 a2) +{ + u16 *vAddr; + + vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); + vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + 1 + gLinkTestBGInfo.dummy_8); +} + +static void LinkTest_prntchar(char a0, u8 a1, u8 a2) +{ + u16 *vAddr; + + vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); + vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + gLinkTestBGInfo.dummy_8); +} + +static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2) +{ + char sp[32 / 2]; + int i; + + for (i = 0; i < a2; i++) + { + sp[i] = pos & 0xf; + pos >>= 4; + } + for (i = a2 - 1; i >= 0; i--) + { + LinkTest_prnthexchar(sp[i], a0, a1); + a0++; + } +} + +static void LinkTest_prntint(int a0, u8 a1, u8 a2, u8 a3) +{ + char sp[32 / 2]; + int sp10; + int i; + + sp10 = -1; + if (a0 < 0) + { + sp10 = a1; + a0 = -a0; + } + for (i = 0; i < a3; i++) + { + sp[i] = a0 % 10; + a0 /= 10; + } + for (i = a3 - 1; i >= 0; i--) + { + LinkTest_prnthexchar(sp[i], a1, a2); + a1++; + } + if (sp10 != -1) + { + LinkTest_prnthexchar(*"\n", sp10, a2); + } +} + +static void LinkTest_prntstr(const char *a0, u8 a1, u8 a2) +{ + int r6; + int i; + int r5; + + r5 = 0; + r6 = 0; + for (i = 0; a0[i] != 0; a0++) + { + if (a0[i] == *"\n") + { + r5++; + r6 = 0; + } + else + { + LinkTest_prntchar(a0[i], a1 + r6, a2 + r5); + r6++; + } + } +} + +static void LinkCB_RequestPlayerDataExchange(void) +{ + if (gLinkStatus & LINK_STAT_MASTER) + { + BuildSendCmd(LINKCMD_SEND_LINK_TYPE); + } + gLinkCallback = NULL; +} + +static void Task_PrintTestData(u8 taskId) +{ + char sp[32]; + int i; + + strcpy(sp, gASCIITestPrint); + LinkTest_prntstr(sp, 5, 2); + LinkTest_prnthex(gShouldAdvanceLinkState, 2, 1, 2); + LinkTest_prnthex(gLinkStatus, 15, 1, 8); + LinkTest_prnthex(gLink.state, 2, 10, 2); + LinkTest_prnthex(EXTRACT_PLAYER_COUNT(gLinkStatus), 15, 10, 2); + LinkTest_prnthex(GetMultiplayerId(), 15, 12, 2); + LinkTest_prnthex(gLastSendQueueCount, 25, 1, 2); + LinkTest_prnthex(gLastRecvQueueCount, 25, 2, 2); + LinkTest_prnthex(GetBlockReceivedStatus(), 15, 5, 2); + LinkTest_prnthex(gLinkDebugSeed, 2, 12, 8); + LinkTest_prnthex(gLinkDebugFlags, 2, 13, 8); + LinkTest_prnthex(GetSioMultiSI(), 25, 5, 1); + LinkTest_prnthex(IsSioMultiMaster(), 25, 6, 1); + LinkTest_prnthex(IsLinkConnectionEstablished(), 25, 7, 1); + LinkTest_prnthex(HasLinkErrorOccurred(), 25, 8, 1); + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + LinkTest_prnthex(gLinkTestBlockChecksums[i], 10, 4 + i, 4); + } +} + +void SetLinkDebugValues(u32 seed, u32 flags) +{ + gLinkDebugSeed = seed; + gLinkDebugFlags = flags; +} + +u8 sub_800A9A8(void) +{ + int i; + u8 flags; + + flags = 0; + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + flags |= (1 << i); + } + return flags; +} + +u8 sub_800A9D8(void) +{ + int i; + u8 flags; + + flags = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + flags |= (1 << i); + } + return flags; +} + +void sub_800AA04(u8 a0) +{ + int i; + + gSavedLinkPlayerCount = a0; + gSavedMultiplayerId = GetMultiplayerId(); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + gSavedLinkPlayers[i] = gLinkPlayers[i]; + } +} + +u8 sub_800AA48(void) +{ + return gSavedLinkPlayerCount; +} + +u8 sub_800AA54(void) +{ + return gSavedMultiplayerId; +} + +bool8 sub_800AA60(void) +{ + int i; + unsigned count; + + count = 0; + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + if (gLinkPlayers[i].trainerId == gSavedLinkPlayers[i].trainerId) + { + if (gLinkType == 0x2288) + { + if (gLinkType == gLinkPlayers[i].linkType) + { + count++; + } + } + else + { + count++; + } + } + } + if (count == gSavedLinkPlayerCount) + { + if (GetLinkPlayerCount_2() == gSavedLinkPlayerCount) + { + return TRUE; + } + } + return FALSE; +} + +void sub_800AAF4(void) +{ + int i; + + // Clearly not what was meant to be written, but here it is anyway. + for (i = 0; i < 4; i++) + { + CpuSet(&gSavedLinkPlayers[i], NULL, sizeof(struct LinkPlayer)); + } +} + +void sub_800AB18(void) +{ + u8 i; + + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + if (gSavedLinkPlayers[i].trainerId != gLinkPlayers[i].trainerId || StringCompare(gSavedLinkPlayers[i].name, gLinkPlayers[i].name) != 0) + { + gLinkErrorOccurred = TRUE; + CloseLink(); + SetMainCallback2(CB2_LinkError); + } + } +} + +void sub_800AB98(void) +{ + gSavedLinkPlayerCount = 0; + gSavedMultiplayerId = 0; +} + +u8 GetLinkPlayerCount_2(void) +{ + return EXTRACT_PLAYER_COUNT(gLinkStatus); +} + +bool8 IsLinkMaster(void) +{ + if (gWirelessCommType) + { + return Rfu_IsMaster(); + } + return EXTRACT_MASTER(gLinkStatus); +} + +u8 sub_800ABE8(void) +{ + return gUnknown_03000D58; +} + +void sub_800ABF4(u16 a0) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback == NULL) + { + gLinkCallback = sub_800AC80; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = a0; + } + } +} + +void sub_800AC34(void) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback != NULL) + { + gUnknown_02022B08++; + } + else + { + gLinkCallback = sub_800AC80; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + } + } +} + +static void sub_800AC80(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x5FFF); + gLinkCallback = sub_800ACAC; + } +} + +static void sub_800ACAC(void) +{ + int i; + unsigned count; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + count = 0; + for (i = 0; i < linkPlayerCount; i++) + { + if (gUnknown_030030F0[i]) + { + count++; + } + } + if (count == linkPlayerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + gLinkVSyncDisabled = TRUE; + CloseLink(); + gLinkCallback = NULL; + gUnknown_030030E4 = TRUE; + } +} + +void sub_800AD10(void) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback != NULL) + { + gUnknown_02022B08++; + } + else + { + gLinkCallback = sub_800AD5C; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + } + } +} + +static void sub_800AD5C(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x5FFF); + gLinkCallback = sub_800AD88; + } +} + +static void sub_800AD88(void) +{ + int i; + unsigned count; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + count = 0; + for (i = 0; i < linkPlayerCount; i++) + { + if (gLinkPlayers[i].language == LANGUAGE_JAPANESE) + { + count++; + } + else if (gUnknown_030030F0[i]) + { + count++; + } + } + if (count == linkPlayerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + gLinkVSyncDisabled = TRUE; + CloseLink(); + gLinkCallback = NULL; + gUnknown_030030E4 = TRUE; + } +} + +void sub_800ADF8(void) +{ + if (gWirelessCommType == TRUE) + { + sub_8010434(); + } + else + { + if (gLinkCallback == NULL) + { + gLinkCallback = sub_800AE30; + } + gUnknown_030030E4 = FALSE; + } +} + +static void sub_800AE30(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x2FFE); + gLinkCallback = sub_800AE5C; + } +} + +static void sub_800AE5C(void) +{ + u8 i; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + for (i = 0; i < linkPlayerCount; i++) + { + if (!gUnknown_030030EC[i]) + { + break; + } + } + if (i == linkPlayerCount) + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gUnknown_030030EC[i] = FALSE; + } + gLinkCallback = NULL; + } +} + +static void CheckErrorStatus(void) +{ + if (gLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus)) + { + if (!gSuppressLinkErrorMessage) + { + sLinkErrorBuffer.status = gLinkStatus; + sLinkErrorBuffer.lastRecvQueueCount = gLastRecvQueueCount; + sLinkErrorBuffer.lastSendQueueCount = gLastSendQueueCount; + SetMainCallback2(CB2_LinkError); + } + gLinkErrorOccurred = TRUE; + CloseLink(); + } +} + +void sub_800AF18(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, u8 unk_06) +{ + sLinkErrorBuffer.status = status; + sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount; + sLinkErrorBuffer.lastRecvQueueCount = lastRecvQueueCount; + sLinkErrorBuffer.unk_06 = unk_06; +} + +void CB2_LinkError(void) +{ + u8 *tilemapBuffer; + + SetGpuReg(REG_OFFSET_DISPCNT, 0); + m4aMPlayStop(&gMPlayInfo_SE1); + m4aMPlayStop(&gMPlayInfo_SE2); + m4aMPlayStop(&gMPlayInfo_SE3); + InitHeap(gHeap, HEAP_SIZE); + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetPaletteFadeControl(); + FillPalette(0, 0, 2); + ResetTasks(); + remove_some_task(); + if (gWirelessCommType) + { + if (!sLinkErrorBuffer.unk_06) + { + gWirelessCommType = 3; + } + sub_800E604(); + } + SetVBlankCallback(sub_80096BC); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, gUnknown_082ED1FC, 2); + gUnknown_02022B0C = tilemapBuffer = malloc(0x800); + SetBgTilemapBuffer(1, tilemapBuffer); + if (InitWindows(gUnknown_082ED204)) + { + DeactivateAllTextPrinters(); + reset_temp_tile_data_buffers(); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON); + LoadPalette(gUnknown_0860F074, 0xf0, 0x20); + gSoftResetDisabled = FALSE; + CreateTask(Task_DestroySelf, 0); + StopMapMusic(); + gMain.callback1 = NULL; + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + SetMainCallback2(CB2_PrintErrorMessage); + } +} + +static void sub_800B080(void) +{ + LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0); + copy_decompressed_tile_data_to_vram_autofree(1, gWirelessLinkDisplayGfx, FALSE, 0, 0); + CopyToBgTilemapBuffer(1, gWirelessLinkDisplayTilemap, 0, 0); + CopyBgTilemapBufferToVram(1); + LoadPalette(gWirelessLinkDisplayPal, 0, 0x20); + FillWindowPixelBuffer(0, 0x00); + FillWindowPixelBuffer(2, 0x00); + box_print(0, 3, 2, 6, gUnknown_082ED224, 0, gText_CommErrorEllipsis); + box_print(2, 3, 2, 1, gUnknown_082ED224, 0, gText_MoveCloserToLinkPartner); + PutWindowTilemap(0); + PutWindowTilemap(2); + CopyWindowToVram(0, 0); + CopyWindowToVram(2, 3); +} + +static void sub_800B138(void) +{ + LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0); + FillWindowPixelBuffer(1, 0x00); + FillWindowPixelBuffer(2, 0x00); + box_print(1, 3, 2, 0, gUnknown_082ED224, 0, gText_CommErrorCheckConnections); + PutWindowTilemap(1); + PutWindowTilemap(2); + CopyWindowToVram(1, 0); + CopyWindowToVram(2, 3); +} + +static void CB2_PrintErrorMessage(void) +{ + switch (gMain.state) + { + case 00: + if (sLinkErrorBuffer.unk_06) + { + sub_800B080(); + } + else + { + sub_800B138(); + } + break; + case 02: + ShowBg(0); + if (sLinkErrorBuffer.unk_06) + { + ShowBg(1); + } + break; + case 30: + PlaySE(SE_BOO); + break; + case 60: + PlaySE(SE_BOO); + break; + case 90: + PlaySE(SE_BOO); + break; + case 130: + if (gWirelessCommType == 2) + { + box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnTitleScreen); + } + else if (gWirelessCommType == 1) + { + box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnRegistrationCounter); + } + break; + } + if (gMain.state == 160) + { + if (gWirelessCommType == 1) + { + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_PIN); + gWirelessCommType = 0; + sLinkErrorBuffer.unk_06 = 0; + sub_81700F8(); + } + } + else if (gWirelessCommType == 2) + { + if (gMain.newKeys & A_BUTTON) + { + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + DoSoftReset(); + } + } + } + if (gMain.state != 160) + { + gMain.state++; + } +} + +// TODO: there might be a file boundary here, let's name it + +bool8 GetSioMultiSI(void) +{ + return (REG_SIOCNT & 0x04) != 0; +} + +static bool8 IsSioMultiMaster(void) +{ + return (REG_SIOCNT & 0x8) && !(REG_SIOCNT & 0x04); +} + +bool8 IsLinkConnectionEstablished(void) +{ + return EXTRACT_CONN_ESTABLISHED(gLinkStatus); +} + +void SetSuppressLinkErrorMessage(bool8 flag) +{ + gSuppressLinkErrorMessage = flag; +} + +bool8 HasLinkErrorOccurred(void) +{ + return gLinkErrorOccurred; +} + +void sub_800B348(void) +{ + struct LinkPlayerBlock *block; + + InitLocalLinkPlayer(); + block = &gLocalLinkPlayerBlock; + block->linkPlayer = gLocalLinkPlayer; + memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1); + memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1); + memcpy(gBlockSendBuffer, block, sizeof(*block)); +} + +void sub_800B3A4(u32 who) +{ + u8 who_ = who; + struct LinkPlayerBlock *block; + struct LinkPlayer *player; + + block = (struct LinkPlayerBlock *)gBlockRecvBuffer[who_]; + player = &gLinkPlayers[who_]; + *player = block->linkPlayer; + sub_800B524(player); + if (strcmp(block->magic1, gASCIIGameFreakInc) != 0 || strcmp(block->magic2, gASCIIGameFreakInc) != 0) + { + SetMainCallback2(CB2_LinkError); + } +} + +bool8 HandleLinkConnection(void) +{ + bool32 r4; + bool32 r5; + + if (gWirelessCommType == 0) + { + gLinkStatus = LinkMain1(&gShouldAdvanceLinkState, gSendCmd, gRecvCmds); + LinkMain2(&gMain.heldKeys); + if ((gLinkStatus & LINK_STAT_RECEIVED_NOTHING) && sub_808766C() == TRUE) + { + return TRUE; + } + } + else + { + r4 = sub_8010EC0(); + r5 = sub_8010F1C(); + if (sub_808766C() == TRUE) + { + if (r4 == TRUE || sub_800F0B8() || r5) + { + return TRUE; + } + } + } + return FALSE; +} + +void sub_800B488(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 1; + } +} + +static void sub_800B4A4(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 0; + } +} + +void sub_800B4C0(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 0; + } +} + +u32 sub_800B4DC(void) +{ + if (gWirelessCommType != 0) + { + return sub_80124D4(); + } + return gLink.recvQueue.count; +} + +bool8 sub_800B504(void) +{ + if (sub_800B4DC() > 2) + { + return TRUE; + } + return FALSE; +} + +u8 sub_800B518(void) +{ + return gWirelessCommType; +} + +void sub_800B524(struct LinkPlayer *player) +{ + player->name[10] = player->name[8]; + ConvertInternationalString(player->name, player->language); +} + +static void DisableSerial(void) +{ + DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + REG_SIOCNT = SIO_MULTI_MODE; + REG_TMCNT_H(3) = 0; + REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL; + REG_SIOMLT_SEND = 0; + REG_SIOMLT_RECV = 0; + CpuFill32(0, &gLink, sizeof(gLink)); +} + +static void EnableSerial(void) +{ + DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + REG_RCNT = 0; + REG_SIOCNT = SIO_MULTI_MODE; + REG_SIOCNT |= SIO_115200_BPS | SIO_INTR_ENABLE; + EnableInterrupts(INTR_FLAG_SERIAL); + REG_SIOMLT_SEND = 0; + CpuFill32(0, &gLink, sizeof(gLink)); + sNumVBlanksWithoutSerialIntr = 0; + sSendNonzeroCheck = 0; + sRecvNonzeroCheck = 0; + sChecksumAvailable = 0; + sHandshakePlayerCount = 0; + gLastSendQueueCount = 0; + gLastRecvQueueCount = 0; +} + +void ResetSerial(void) +{ + EnableSerial(); + DisableSerial(); +} + +// link_main1.c + +u32 LinkMain1(u8 *shouldAdvanceLinkState, u16 *sendCmd, u16 (*recvCmds)[CMD_LENGTH]) +{ + u32 retVal; + u32 retVal2; + + switch (gLink.state) + { + case LINK_STATE_START0: + DisableSerial(); + gLink.state = 1; + break; + case LINK_STATE_START1: + if (*shouldAdvanceLinkState == 1) + { + EnableSerial(); + gLink.state = 2; + } + break; + case LINK_STATE_HANDSHAKE: + switch (*shouldAdvanceLinkState) + { + default: + CheckMasterOrSlave(); + break; + case 1: + if (gLink.isMaster == LINK_MASTER && gLink.playerCount > 1) + { + gLink.handshakeAsMaster = TRUE; + } + break; + case 2: + gLink.state = LINK_STATE_START0; + REG_SIOMLT_SEND = 0; + break; + } + break; + case LINK_STATE_INIT_TIMER: + InitTimer(); + gLink.state = LINK_STATE_CONN_ESTABLISHED; + // fallthrough + case LINK_STATE_CONN_ESTABLISHED: + EnqueueSendCmd(sendCmd); + DequeueRecvCmds(recvCmds); + break; + } + *shouldAdvanceLinkState = 0; + retVal = gLink.localId; + retVal |= (gLink.playerCount << LINK_STAT_PLAYER_COUNT_SHIFT); + if (gLink.isMaster == LINK_MASTER) + { + retVal |= LINK_STAT_MASTER; + } + { + u32 receivedNothing = gLink.receivedNothing << LINK_STAT_RECEIVED_NOTHING_SHIFT; + u32 link_field_F = gLink.link_field_F << LINK_STAT_UNK_FLAG_9_SHIFT; + u32 hardwareError = gLink.hardwareError << LINK_STAT_ERROR_HARDWARE_SHIFT; + u32 badChecksum = gLink.badChecksum << LINK_STAT_ERROR_CHECKSUM_SHIFT; + u32 queueFull = gLink.queueFull << LINK_STAT_ERROR_QUEUE_FULL_SHIFT; + u32 val; + + if (gLink.state == LINK_STATE_CONN_ESTABLISHED) + { + val = LINK_STAT_CONN_ESTABLISHED; + val |= receivedNothing; + val |= retVal; + val |= link_field_F; + val |= hardwareError; + val |= badChecksum; + val |= queueFull; + } + else + { + val = retVal; + val |= receivedNothing; + val |= link_field_F; + val |= hardwareError; + val |= badChecksum; + val |= queueFull; + } + + retVal = val; + } + + if (gLink.lag == LAG_MASTER) + { + retVal |= LINK_STAT_ERROR_LAG_MASTER; + } + + if (gLink.localId >= MAX_LINK_PLAYERS) + { + retVal |= LINK_STAT_ERROR_INVALID_ID; + } + + retVal2 = retVal; + if (gLink.lag == LAG_SLAVE) + { + retVal2 |= LINK_STAT_ERROR_LAG_SLAVE; + } + + return retVal2; +} + +static void CheckMasterOrSlave(void) +{ + u32 terminals; + + terminals = *(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SD | SIO_MULTI_SI); + if (terminals == SIO_MULTI_SD && gLink.localId == 0) + { + gLink.isMaster = LINK_MASTER; + } + else + { + gLink.isMaster = LINK_SLAVE; + } +} + +static void InitTimer(void) +{ + if (gLink.isMaster) + { + REG_TM3CNT_L = -197; + REG_TM3CNT_H = TIMER_64CLK | TIMER_INTR_ENABLE; + EnableInterrupts(INTR_FLAG_TIMER3); + } +} + +static void EnqueueSendCmd(u16 *sendCmd) +{ + u8 i; + u8 offset; + + gLinkSavedIme = REG_IME; + REG_IME = 0; + if (gLink.sendQueue.count < QUEUE_CAPACITY) + { + offset = gLink.sendQueue.pos + gLink.sendQueue.count; + if (offset >= QUEUE_CAPACITY) + { + offset -= QUEUE_CAPACITY; + } + for (i = 0; i < CMD_LENGTH; i++) + { + sSendNonzeroCheck |= *sendCmd; + gLink.sendQueue.data[i][offset] = *sendCmd; + *sendCmd = 0; + sendCmd++; + } + } + else + { + gLink.queueFull = QUEUE_FULL_SEND; + } + if (sSendNonzeroCheck) + { + gLink.sendQueue.count++; + sSendNonzeroCheck = 0; + } + REG_IME = gLinkSavedIme; + gLastSendQueueCount = gLink.sendQueue.count; +} + + +static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH]) +{ + u8 i; + u8 j; + + gLinkSavedIme = REG_IME; + REG_IME = 0; + if (gLink.recvQueue.count == 0) + { + for (i = 0; i < gLink.playerCount; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + recvCmds[i][j] = 0; + } + } + + gLink.receivedNothing = TRUE; + } + else + { + for (i = 0; i < gLink.playerCount; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + recvCmds[i][j] = gLink.recvQueue.data[i][j][gLink.recvQueue.pos]; + } + } + gLink.recvQueue.count--; + gLink.recvQueue.pos++; + if (gLink.recvQueue.pos >= QUEUE_CAPACITY) + { + gLink.recvQueue.pos = 0; + } + gLink.receivedNothing = FALSE; + } + REG_IME = gLinkSavedIme; +} + +// link_intr.c + +void LinkVSync(void) +{ + if (gLink.isMaster) + { + switch (gLink.state) + { + case LINK_STATE_CONN_ESTABLISHED: + if (gLink.serialIntrCounter < 9) + { + if (gLink.hardwareError != TRUE) + { + gLink.lag = LAG_MASTER; + } + else + { + StartTransfer(); + } + } + else if (gLink.lag != LAG_MASTER) + { + gLink.serialIntrCounter = 0; + StartTransfer(); + } + break; + case LINK_STATE_HANDSHAKE: + StartTransfer(); + break; + } + } + else if (gLink.state == LINK_STATE_CONN_ESTABLISHED || gLink.state == LINK_STATE_HANDSHAKE) + { + if (++sNumVBlanksWithoutSerialIntr > 10) + { + if (gLink.state == LINK_STATE_CONN_ESTABLISHED) + { + gLink.lag = LAG_SLAVE; + } + if (gLink.state == LINK_STATE_HANDSHAKE) + { + gLink.playerCount = 0; + gLink.link_field_F = FALSE; + } + } + } +} + +void Timer3Intr(void) +{ + StopTimer(); + StartTransfer(); +} + +void SerialCB(void) +{ + gLink.localId = SIO_MULTI_CNT->id; + switch (gLink.state) + { + case LINK_STATE_CONN_ESTABLISHED: + gLink.hardwareError = SIO_MULTI_CNT->error; + DoRecv(); + DoSend(); + SendRecvDone(); + break; + case LINK_STATE_HANDSHAKE: + if (DoHandshake()) + { + if (gLink.isMaster) + { + gLink.state = LINK_STATE_INIT_TIMER; + gLink.serialIntrCounter = 8; + } + else + { + gLink.state = LINK_STATE_CONN_ESTABLISHED; + } + } + break; + } + gLink.serialIntrCounter++; + sNumVBlanksWithoutSerialIntr = 0; + if (gLink.serialIntrCounter == 8) + { + gLastRecvQueueCount = gLink.recvQueue.count; + } +} + +static void StartTransfer(void) +{ + REG_SIOCNT |= SIO_START; +} + +static bool8 DoHandshake(void) +{ + u8 i; + u8 playerCount; + u16 minRecv; + + playerCount = 0; + minRecv = 0xFFFF; + if (gLink.handshakeAsMaster == TRUE) + { + REG_SIOMLT_SEND = MASTER_HANDSHAKE; + } + else + { + REG_SIOMLT_SEND = SLAVE_HANDSHAKE; + } + *(u64 *)gLink.tempRecvBuffer = REG_SIOMLT_RECV; + REG_SIOMLT_RECV = 0; + gLink.handshakeAsMaster = FALSE; + for (i = 0; i < 4; i++) + { + if ((gLink.tempRecvBuffer[i] & ~0x3) == SLAVE_HANDSHAKE || gLink.tempRecvBuffer[i] == MASTER_HANDSHAKE) + { + playerCount++; + if (minRecv > gLink.tempRecvBuffer[i] && gLink.tempRecvBuffer[i] != 0) + { + minRecv = gLink.tempRecvBuffer[i]; + } + } + else + { + if (gLink.tempRecvBuffer[i] != 0xFFFF) + { + playerCount = 0; + } + break; + } + } + gLink.playerCount = playerCount; + if (gLink.playerCount > 1 && gLink.playerCount == sHandshakePlayerCount && gLink.tempRecvBuffer[0] == MASTER_HANDSHAKE) + { + return TRUE; + } + if (gLink.playerCount > 1) + { + gLink.link_field_F = (minRecv & 3) + 1; + } + else + { + gLink.link_field_F = 0; + } + sHandshakePlayerCount = gLink.playerCount; + return FALSE; +} + +static void DoRecv(void) +{ + u16 recv[4]; + u8 i; + u8 index; + + *(u64 *)recv = REG_SIOMLT_RECV; + if (gLink.sendCmdIndex == 0) + { + for (i = 0; i < gLink.playerCount; i++) + { + if (gLink.checksum != recv[i] && sChecksumAvailable) + { + gLink.badChecksum = TRUE; + } + } + gLink.checksum = 0; + sChecksumAvailable = TRUE; + } + else + { + index = gLink.recvQueue.pos + gLink.recvQueue.count; + if (index >= QUEUE_CAPACITY) + { + index -= QUEUE_CAPACITY; + } + if (gLink.recvQueue.count < QUEUE_CAPACITY) + { + for (i = 0; i < gLink.playerCount; i++) + { + gLink.checksum += recv[i]; + sRecvNonzeroCheck |= recv[i]; + gLink.recvQueue.data[i][gLink.recvCmdIndex][index] = recv[i]; + } + } + else + { + gLink.queueFull = QUEUE_FULL_RECV; + } + gLink.recvCmdIndex++; + if (gLink.recvCmdIndex == CMD_LENGTH && sRecvNonzeroCheck) + { + gLink.recvQueue.count++; + sRecvNonzeroCheck = 0; + } + } +} + +static void DoSend(void) +{ + if (gLink.sendCmdIndex == CMD_LENGTH) + { + REG_SIOMLT_SEND = gLink.checksum; + if (!sSendBufferEmpty) + { + gLink.sendQueue.count--; + gLink.sendQueue.pos++; + if (gLink.sendQueue.pos >= QUEUE_CAPACITY) + { + gLink.sendQueue.pos = 0; + } + } + else + { + sSendBufferEmpty = FALSE; + } + } + else + { + if (!sSendBufferEmpty && gLink.sendQueue.count == 0) + { + sSendBufferEmpty = TRUE; + } + if (sSendBufferEmpty) + { + REG_SIOMLT_SEND = 0; + } + else + { + REG_SIOMLT_SEND = gLink.sendQueue.data[gLink.sendCmdIndex][gLink.sendQueue.pos]; + } + gLink.sendCmdIndex++; + } +} + +static void StopTimer(void) +{ + if (gLink.isMaster) + { + REG_TM3CNT_H &= ~TIMER_ENABLE; + REG_TM3CNT_L = -197; + } +} + +static void SendRecvDone(void) +{ + if (gLink.recvCmdIndex == CMD_LENGTH) + { + gLink.sendCmdIndex = 0; + gLink.recvCmdIndex = 0; + } + else if (gLink.isMaster) + { + REG_TM3CNT_H |= TIMER_ENABLE; + } +} + +void ResetSendBuffer(void) +{ + u8 i; + u8 j; + + gLink.sendQueue.count = 0; + gLink.sendQueue.pos = 0; + for (i = 0; i < CMD_LENGTH; i++) + { + for (j = 0; j < QUEUE_CAPACITY; j++) + { + gLink.sendQueue.data[i][j] = 0xEFFF; + } + } +} + +void ResetRecvBuffer(void) +{ + u8 i; + u8 j; + u8 k; + + gLink.recvQueue.count = 0; + gLink.recvQueue.pos = 0; + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + for (k = 0; k < QUEUE_CAPACITY; k++) + { + gLink.recvQueue.data[i][j][k] = 0xEFFF; + } + } + } +} diff --git a/src/link_rfu.c b/src/link_rfu.c new file mode 100644 index 000000000..ed7062d98 --- /dev/null +++ b/src/link_rfu.c @@ -0,0 +1,4612 @@ + +// Includes +#include "global.h" +#include "malloc.h" +#include "battle.h" +#include "berry_blender.h" +#include "task.h" +#include "random.h" +#include "decompress.h" +#include "text.h" +#include "string_util.h" +#include "event_data.h" +#include "overworld.h" +#include "link.h" +#include "librfu.h" +#include "rom_8011DC0.h" +#include "link_rfu.h" + +// Static type declarations + +// Static RAM declarations + +struct UnkRfuStruct_1 gUnknown_03004140; +struct UnkRfuStruct_2 gUnknown_03005000; + +IWRAM_DATA u8 gUnknown_03000D74; +ALIGNED(4) IWRAM_DATA u8 gUnknown_03000D78[8]; +IWRAM_DATA u8 gUnknown_03000D80[16]; +IWRAM_DATA u16 gUnknown_03000D90[8]; + +EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0; +EWRAM_DATA ALIGNED(4) struct UnkLinkRfuStruct_02022B14 gUnknown_02022B14 = {}; +EWRAM_DATA ALIGNED(2) u8 gUnknown_02022B22[8] = {}; +EWRAM_DATA struct UnkLinkRfuStruct_02022B2C gUnknown_02022B2C = {}; +EWRAM_DATA struct UnkLinkRfuStruct_02022B44 gUnknown_02022B44 = {}; + +// Static ROM declarations + +static void sub_800C000(void); +static void sub_800C7B4(u16 r8, u16 r6); +static void sub_800C744(u32 a0); +static void sub_800CEB0(u16 r6); +static void sub_800CF34(void); +static void sub_800D158(void); +static void sub_800D20C(void); +static void sub_800D268(void); +static u8 sub_800D294(void); +static void sub_800D30C(u8 a0, u8 a1); +static void sub_800D334(u8 a0); +static void sub_800D358(u8 a0); +static void sub_800D434(void); +static void sub_800D610(void); +void sub_800D630(void); +static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2); +static void sub_800EAB4(void); +static void sub_800EAFC(void); +void sub_800ED34(u16 unused); +static void sub_800EDBC(u16 unused); +static void sub_800F048(void); +static void sub_800F86C(u8 unused); +static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data); +void sub_800FD14(u16 command); +static void rfufunc_80F9F44(void); +static void sub_800FFB0(void); +static void rfufunc_80FA020(void); +bool32 sub_8010454(u32 a0); +static void sub_8010528(void); +void sub_8010750(void); +int sub_80107A0(void); +void sub_801084C(u8 taskId); +void sub_80109E8(u16 a0); +void sub_8010A70(void *a0); +void sub_8010AAC(u8 taskId); +void sub_8010D0C(u8 taskId); +u8 sub_8011CE4(const u8 *a0, u16 a1); +void sub_8011D6C(u8 a0); +void sub_8011E94(u8 a0, u8 a1); +u8 sub_8012224(void); +void sub_801227C(void); + +// .rodata + +const u16 gWirelessLinkIconPalette[] = INCBIN_U16("graphics/interface/wireless_link_icon.gbapal"); +const u8 gWirelessLinkIconPic[] = INCBIN_U8("graphics/interface/wireless_link_icon.4bpp.lz"); +const u8 sWireless_ASCIItoRSETable[] = { + 0xff, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x00, 0xab, 0xb5, 0xb6, 0xb1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb2, 0xf1, 0x00, 0xae, 0xad, 0xba, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0x00, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, + 0xd2, 0xd3, 0xd4, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0x00, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0x2d, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x50, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0xad, 0xb3, 0xb4, 0x00, 0xaf, 0x7d, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xa0, + 0xae, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7e, 0xb0, 0xac, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2e, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94 +}; +const u8 sWireless_RSEtoASCIITable[] = { + 0x20, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, + 0x9d, 0x9e, 0x9f, 0xa0, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0x7b, 0xf1, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x84, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xa6, 0xdd, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, + 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0xaf, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x21, 0xdf, 0xa1, 0xb0, 0xa5, + 0xde, 0x24, 0x2a, 0xa2, 0xa3, 0x22, 0x23, 0x20, + 0xa4, 0x20, 0x2f, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, + 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x20, + 0x20, 0x2b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00 +}; +const struct OamData sWirelessStatusIndicatorOamData = { + .size = 1 +}; +static const union AnimCmd sWirelessStatusIndicatorAnim0[] = { + // 3 bars + ANIMCMD_FRAME( 4, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_FRAME(16, 10), + ANIMCMD_FRAME(12, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim1[] = { + // 2 bars + ANIMCMD_FRAME( 4, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_FRAME(12, 10), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim2[] = { + // 1 bar + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim3[] = { + // searching + ANIMCMD_FRAME( 4, 10), + ANIMCMD_FRAME(20, 10), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim4[] = { + // error + ANIMCMD_FRAME(24, 10), + ANIMCMD_FRAME( 4, 10), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd *const sWirelessStatusIndicatorAnims[] = { + sWirelessStatusIndicatorAnim0, + sWirelessStatusIndicatorAnim1, + sWirelessStatusIndicatorAnim2, + sWirelessStatusIndicatorAnim3, + sWirelessStatusIndicatorAnim4 +}; +const struct CompressedSpriteSheet sWirelessStatusIndicatorSpriteSheet = { + gWirelessLinkIconPic, 0x0380, 0xD431 +}; +const struct SpritePalette sWirelessStatusIndicatorSpritePalette = { + gWirelessLinkIconPalette, 0xD432 +}; +static const struct SpriteTemplate sWirelessStatusIndicatorSpriteTemplate = { + 0xD431, + 0xD432, + &sWirelessStatusIndicatorOamData, + sWirelessStatusIndicatorAnims, + NULL, + gDummySpriteAffineAnimTable, + SpriteCallbackDummy +}; + +const struct UnkLinkRfuStruct_02022B2C gUnknown_082ED608 = { + 0x04, 0x20, 0x00, 0x00, 0x02, + &gUnknown_02022B14, + gUnknown_02022B22, + 0x01, 0x00, 0x258, 0x12c +}; +const u8 gUnknown_082ED620[] = { + 0, 3, 2, 1, 0 +}; +const u32 gUnknown_082ED628[] = { + 0x000000, + 0x000001, + 0x000003, + 0x000007, + 0x00000f, + 0x00001f, + 0x00003f, + 0x00007f, + 0x0000ff, + 0x0001ff, + 0x0003ff, + 0x0007ff, + 0x000fff, + 0x001fff, + 0x003fff, + 0x007fff, + 0x00ffff, + 0x01ffff, + 0x03ffff, + 0x07ffff, + 0x0fffff, + 0x1fffff, + 0x3fffff, + 0x7fffff, + 0xffffff +}; +const u8 gUnknown_082ED68C[] = { + 0, 0, 1, + 1, 2, 2, + 2, 2, 3 +}; +const u8 gUnknown_082ED695[] = { + 0, 1, 1, 2, + 1, 2, 2, 3, + 1, 2, 2, 3, + 2, 3, 3, 4 +}; +const u8 gUnknown_082ED6A5[] = { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; +const struct { + u8 *buffer; + u32 size; +} gUnknown_082ED6B8[] = { + { gBlockSendBuffer, 200 }, + { gBlockSendBuffer, 200 }, + { gBlockSendBuffer, 100 }, + { gBlockSendBuffer, 220 }, + { gBlockSendBuffer, 40 } +}; +const u16 gUnknown_082ED6E0[] = { + 0x0002, 0x7f7d, 0x0000, 0xffff +}; + +const char sUnref_082ED6E8[][15] = { + "RFU WAIT", + "RFU BOOT", + "RFU ERROR", + "RFU RESET", + "RFU CONFIG", + "RFU START", + "RFU SC POLL", + "RFU SP POLL", + "RFU START", + "RFU SEND ERR", + "RFU CP POLL" +}; +const char sUnref_082ED6E9[][16] = { + " ", + "RECOVER START ", + "DISSCONECT ", + "RECOVER SUUSES", + "RECOVER FAILED" +}; +const TaskFunc gUnknown_082ED7E0[] = { + sub_801084C, + sub_8010AAC, + sub_8010D0C +}; +const char gUnknown_082ED7EC[] = "PokemonSioInfo"; +const char gUnknown_082ED7FC[] = "LINK LOSS DISCONNECT!"; +const char gUnknown_082ED814[] = "LINK LOSS RECOVERY NOW"; + +// .text + +u32 sub_800BEC0(void) +{ + u32 r4; + + r4 = rfu_REQBN_softReset_and_checkID(); + if (r4 == 0x8001) + { + gUnknown_03004140.unk_08 = 1; + } + if (gUnknown_03004140.unk_04 != 0x17 && gUnknown_03004140.unk_04 != 0x01) + { + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + } + gUnknown_03004140.unk_07 = 0; + gUnknown_03004140.unk_0d = 0; + gUnknown_03004140.unk_01 = 0; + gUnknown_03004140.unk_00 = 0; + gUnknown_03004140.unk_06 = -1; + sub_800D610(); + return r4; +} + +void rfu_REQ_sendData_wrapper(u8 r2) +{ + u8 val; + if (!gUnknown_03007890->unk_00) + { + val = gUnknown_03004140.unk_02; + r2 = 0; + if (val == 1) + { + r2 = 1; + } + } + else + { + gUnknown_03004140.unk_03 = 0; + } + rfu_REQ_sendData(r2); +} + +int sub_800BF4C(void (*func1)(u8, u8), void (*func2)(u16)) +{ + if (func1 == NULL) + { + return 4; + } + CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, filler_48)); + gUnknown_03004140.unk_06 = -1; + gUnknown_03004140.unk_40 = func1; + gUnknown_03004140.unk_44 = func2; + rfu_setMSCCallback(sub_800CEB0); + rfu_setREQCallback(sub_800C7B4); + return 0; +} + +void sub_800BFA0(void) +{ + CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, unk_40)); + gUnknown_03004140.unk_06 = -1; +} + +void sub_800BFCC(const struct UnkLinkRfuStruct_02022B2C *unk0) +{ + sub_800C000(); + gUnknown_03004140.unk_04 = 1; + gUnknown_03004140.unk_05 = 2; + gUnknown_03004140.unk_3c = unk0; + gUnknown_03004140.unk_09 = unk0->unk_11; + gUnknown_03004140.unk_32 = unk0->unk_12; + gUnknown_03004140.unk_18 = unk0->unk_14; + if (unk0->unk_10) + { + gUnknown_03004140.unk_0b = 1; + } +} + +static void sub_800C000(void) +{ + u8 i; + + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + gUnknown_03004140.unk_06 = -1; + gUnknown_03004140.unk_07 = 0; + gUnknown_03004140.unk_10 = 0; + gUnknown_03004140.unk_0c = 0; + gUnknown_03004140.unk_24 = 0; + gUnknown_03004140.unk_30 = 0; + for (i = 0; i < 4; i++) + { + gUnknown_03004140.unk_28[i] = 0; + gUnknown_03004140.unk_34[i] = 0; + } +} + +void sub_800C048(void) +{ + gUnknown_03004140.unk_04 = 0x15; +} + +u8 sub_800C054(u8 r5, u16 r7, u16 r8, const u16 *r6) +{ + u8 i; + const u16 *buffer; + + if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 != 0x08 || r5 != 1)) + { + gUnknown_03004140.unk_14 = 1; + sub_800D30C(0xf3, 0x01); + return 1; + } + if (!rfu_getMasterSlave()) + { + gUnknown_03004140.unk_14 = 2; + sub_800D30C(0xf3, 0x01); + return 2; + } + for (i = 0, buffer = r6; i < 16; i++) + { + if (*buffer++ == 0xFFFF) + { + break; + } + } + if (i == 16) + { + gUnknown_03004140.unk_14 = 4; + sub_800D30C(0xf3, 0x01); + return 4; + } + if (r5 > 1) + { + gUnknown_03004140.unk_07 = 1; + r5 = 1; + r7 = 0; + } + else + { + gUnknown_03004140.unk_07 = 0; + } + if (r5 != 0) + { + gUnknown_03004140.unk_04 = 5; + } + else + { + gUnknown_03004140.unk_04 = 9; + if (gUnknown_03004140.unk_0b) + { + gUnknown_03004140.unk_0b = 2; + } + } + gUnknown_03004140.unk_06 = r5; + gUnknown_03004140.unk_1a = r7; + gUnknown_03004140.unk_26 = r8; + gUnknown_03004140.unk_20 = r6; + return 0; +} + +u8 sub_800C12C(u16 r6, u16 r8) +{ + u8 i; + struct RfuUnk5 *tmp; + + if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 < 9 || gUnknown_03004140.unk_04 > 11)) + { + gUnknown_03004140.unk_14 = 1; + sub_800D30C(0xF3, 0x01); + return 1; + } + if (!rfu_getMasterSlave()) + { + gUnknown_03004140.unk_14 = 2; + sub_800D30C(0xF3, 0x01); + return 2; + } + for (i = 0; i < gUnknown_03007890->unk_08; i++) + { + if (gUnknown_03007890->unk_14[i].unk_00 == r6) + { + break; + } + } + if (gUnknown_03007890->unk_08 == 0 || i == gUnknown_03007890->unk_08) + { + gUnknown_03004140.unk_14 = 3; + sub_800D30C(0xF3, 0x01); + return 3; + } + if (gUnknown_03004140.unk_04 == 0 || gUnknown_03004140.unk_04 == 9) + { + gUnknown_03004140.unk_04 = 12; + gUnknown_03004140.unk_05 = 13; + } + else + { + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 12; + } + gUnknown_03004140.unk_1e = r6; + gUnknown_03004140.unk_1a = r8; + if (gUnknown_03004140.unk_07 != 0) + { + gUnknown_03004140.unk_07 = 7; + } + return 0; +} + +void sub_800C210(u8 a0) +{ + u8 i; + + if (a0 & gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_30 &= ~a0; + for (i = 0; i < 4; i++) + { + if ((a0 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + i = gUnknown_03007890->unk_03 & a0; + if (i) + { + sub_800D334(i); + } + gUnknown_03004140.unk_14 = i; + sub_800D30C(0x33, i); + } +} + +void sub_800C27C(bool8 a0) +{ + u8 r2; + + r2 = 0; + gUnknown_03004140.unk_07 = 0; + if (a0) + { + sub_800C000(); + gUnknown_03004140.unk_04 = 23; + } + else + { + switch (gUnknown_03004140.unk_04) + { + case 5: + gUnknown_03004140.unk_04 = 8; + gUnknown_03004140.unk_05 = 0; + r2 = 0x13; + break; + case 6: + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + break; + case 7: + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + break; + case 8: + break; + case 9: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x21; + break; + case 10: + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + break; + case 11: + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + break; + case 12: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x23; + break; + case 13: + gUnknown_03004140.unk_04 = 14; + break; + case 14: + gUnknown_03004140.unk_04 = 14; + break; + case 15: + break; + case 16: + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11; + gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12; + sub_800D334(gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03; + sub_800D30C(0x33, 0x01); + return; + case 17: + gUnknown_03004140.unk_04 = 18; + break; + case 18: + gUnknown_03004140.unk_04 = 18; + break; + default: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x43; + break; + } + if (gUnknown_03004140.unk_04 == 0) + { + sub_800D30C(r2, 0); + } + } +} + +bool8 sub_800C36C(u16 a0) +{ + bool8 retVal; + u8 i; + u8 sp0; + u8 sp1; + u8 sp2; + u8 flags; + + retVal = FALSE; + rfu_REQBN_watchLink(a0, &sp0, &sp1, &sp2); + if (sp0) + { + gUnknown_03004140.unk_14 = sp0; + gUnknown_03004140.unk_16 = sp1; + if (gUnknown_03004140.unk_09) + { + gUnknown_03004140.unk_0a = 1; + if (gUnknown_03004140.unk_06 == 0 && sp1 == 0) + { + gUnknown_03004140.unk_0a = 4; + } + if (gUnknown_03004140.unk_0a == 1) + { + for (i = 0; i < 4; i++) + { + if ((sp0 >> i) & 1) + { + gUnknown_03004140.unk_30 |= (1 << i); + gUnknown_03004140.unk_34[i] = gUnknown_03004140.unk_32; + } + } + sub_800D30C(0x31, 0x01); + } + else + { + gUnknown_03004140.unk_0a = 0; + sub_800D334(sp0); + retVal = TRUE; + sub_800D30C(0x33, 0x01); + } + } + else + { + sub_800D334(sp0); + retVal = TRUE; + sub_800D30C(0x30, 0x02); + } + sub_800D610(); + } + if (gUnknown_03007890->unk_00 == 1) + { + if (sp2) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_30 >> i) & 1 && (sp2 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + gUnknown_03004140.unk_30 &= ~sp2; + gUnknown_03004140.unk_14 = sp2; + sub_800D30C(0x32, 0x01); + } + if (gUnknown_03004140.unk_30) + { + flags = 0; + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_30 >> i) & 1 && gUnknown_03004140.unk_34[i] && --gUnknown_03004140.unk_34[i] == 0) + { + gUnknown_03004140.unk_30 &= ~(1 << i); + flags |= (1 << i); + } + } + if (flags) + { + sub_800D334(flags); + retVal = TRUE; + gUnknown_03004140.unk_14 = flags; + sub_800D30C(0x33, 0x01); + } + } + if (!gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_0a = 0; + } + } + return retVal; +} + +void rfu_syncVBlank_(void) +{ + if (rfu_syncVBlank()) + { + sub_800D30C(0xF1, 0x00); + sub_800D610(); + } +} + +void sub_800C54C(u32 a0) +{ + u8 r2; + + if (gUnknown_03004140.unk_40 == NULL && gUnknown_03004140.unk_04 != 0) + { + gUnknown_03004140.unk_04 = 0; + } + else + { + if (gUnknown_03004140.unk_07 != 0) + { + sub_800C744(a0); + } + do + { + if (gUnknown_03004140.unk_04 != 0) + { + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = 1; + switch (gUnknown_03004140.unk_04) + { + case 23: + r2 = sub_800BEC0() == 0x8001 ? 0x44 : 0xFF; + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(r2, 0); + break; + case 1: + if (sub_800BEC0() == 0x8001) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 3; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0xFF, 0); + } + break; + case 2: + rfu_REQ_reset(); + break; + case 3: + rfu_REQ_configSystem(gUnknown_03004140.unk_3c->unk_02, gUnknown_03004140.unk_3c->unk_00, gUnknown_03004140.unk_3c->unk_01); + break; + case 4: + rfu_REQ_configGameData(gUnknown_03004140.unk_3c->unk_04, gUnknown_03004140.unk_3c->unk_06, gUnknown_03004140.unk_3c->unk_08, gUnknown_03004140.unk_3c->unk_0c); + break; + case 5: + rfu_REQ_startSearchChild(); + break; + case 6: + rfu_REQ_pollSearchChild(); + break; + case 7: + rfu_REQ_endSearchChild(); + break; + case 8: + break; + case 9: + rfu_REQ_startSearchParent(); + break; + case 10: + rfu_REQ_pollSearchParent(); + break; + case 11: + rfu_REQ_endSearchParent(); + break; + case 12: + rfu_REQ_startConnectParent(gUnknown_03004140.unk_1e); + break; + case 13: + rfu_REQ_pollConnectParent(); + break; + case 14: + rfu_REQ_endConnectParent(); + break; + case 15: + break; + case 16: + rfu_REQ_CHILD_startConnectRecovery(gUnknown_03007890->unk_03); + break; + case 17: + rfu_REQ_CHILD_pollConnectRecovery(); + break; + case 18: + rfu_REQ_CHILD_endConnectRecovery(); + break; + case 19: + rfu_REQ_changeMasterSlave(); + break; + case 20: + break; + case 21: + rfu_REQ_stopMode(); + break; + case 22: + break; + } + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = 0; + } + } while (gUnknown_03004140.unk_04 == 18 || gUnknown_03004140.unk_04 == 19); + if (gUnknown_03007890->unk_00 != 1 || !sub_800C36C(0)) + { + sub_800CF34(); + sub_800D158(); + sub_800D268(); + sub_800D434(); + } + } +} + +static void sub_800C744(u32 a0) +{ + if (gUnknown_03004140.unk_07 == 5) + { + gUnknown_03004140.unk_06 = 1; + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c; + if (gUnknown_03004140.unk_1a) + { + gUnknown_03004140.unk_07 = 6; + } + else + { + gUnknown_03004140.unk_07 = 1; + } + } + if (gUnknown_03004140.unk_07 == 1) + { + gUnknown_03004140.unk_06 = 1; + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_1a = a0 % 140; + gUnknown_03004140.unk_1c = 140 - gUnknown_03004140.unk_1a; + if (gUnknown_03004140.unk_1a) + { + gUnknown_03004140.unk_07 = 2; + } + else + { + gUnknown_03004140.unk_07 = 3; + } + } + if (gUnknown_03004140.unk_07 == 3) + { + gUnknown_03004140.unk_06 = 0; + gUnknown_03004140.unk_1a = 40; + gUnknown_03004140.unk_07 = 4; + gUnknown_03004140.unk_04 = 9; + } +} + +static void sub_800C7B4(u16 r8, u16 r6) +{ + u8 sp0; + register u8 *stwiRecvBuffer asm("r0"); + u8 *tmp; + u8 i; + + if (gUnknown_03004140.unk_0e != 0) + { + gUnknown_03004140.unk_0e = 0; + switch (r8) + { + case 16: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 4; + } + break; + case 23: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 0; + } + break; + case 22: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x00, 0x00); + } + break; + case 25: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 6; + } + break; + case 26: + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + } + break; + case 27: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 0; + if (gUnknown_03004140.unk_07 == 0) + { + sub_800D30C(0x13, 0x00); + } + } + break; + case 28: + if (r6 == 0) + { + if (gUnknown_03004140.unk_0b == 1 && gUnknown_03004140.unk_1a > 1) + { + gUnknown_03004140.unk_1a--; + } + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 10; + } + break; + case 29: + if (r6 == 0) + { + sp0 = sub_800D294(); + gUnknown_03004140.unk_14 = sp0; + if (sp0) + { + sub_800D30C(0x20, 0x01); + } + if (gUnknown_03004140.unk_0b && gUnknown_03004140.unk_1a != 1 && gUnknown_03007890->unk_08 == 4) + { + rfu_REQ_endSearchParent(); + rfu_waitREQComplete(); + gUnknown_03004140.unk_04 = 9; + gUnknown_03004140.unk_0b = 1; + } + } + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + } + break; + case 30: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + if (gUnknown_03004140.unk_07 == 0) + { + if (gUnknown_03004140.unk_04 == 0) + { + sub_800D30C(0x21, 0x00); + } + } + else if (gUnknown_03004140.unk_07 != 7) + { + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_07 = 5; + } + } + break; + case 31: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 13; + } + break; + case 32: + if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10) && !sp0) + { + gUnknown_03004140.unk_04 = 14; + } + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 14; + } + break; + case 33: + if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10)) + { + if (!sp0) + { + gUnknown_03004140.unk_04 = 19; + gUnknown_03004140.unk_05 = 15; + gUnknown_03004140.unk_1e = 0x22; + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_10; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_1e = 0x23; + gUnknown_03004140.unk_14 = sp0; + if (gUnknown_03004140.unk_07) + { + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + } + } + sub_800D30C(gUnknown_03004140.unk_1e, 0x01); + gUnknown_03004140.unk_1e = 0; + } + break; + case 50: + if (r6 == 0) + { + gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03; + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 17; + for (gUnknown_03004140.unk_10 = 0; gUnknown_03004140.unk_10 < 4; gUnknown_03004140.unk_10 ++) + { + if ((gUnknown_03007890->unk_03 >> gUnknown_03004140.unk_10) & 1) + { + break; + } + } + } + break; + case 51: + if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0) && sp0 < 2) + { + gUnknown_03004140.unk_04 = 18; + } + if (gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] && --gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] == 0) + { + gUnknown_03004140.unk_04 = 18; + } + break; + case 52: + if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0)) + { + if (!sp0) + { + gUnknown_03004140.unk_04 = 19; + gUnknown_03004140.unk_05 = 22; + gUnknown_03004140.unk_1e = 0x32; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D334(gUnknown_03007890->unk_03); + gUnknown_03004140.unk_1e = 0x33; + } + gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] = 0; + gUnknown_03004140.unk_30 = 0; + gUnknown_03004140.unk_0a = 0; + sub_800D30C(gUnknown_03004140.unk_1e, 0x01); + gUnknown_03004140.unk_1e = 0; + } + break; + case 39: + if (r6 == 0) + { + if (gUnknown_03004140.unk_05 == 22) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11; + gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12; + gUnknown_03004140.unk_02 = 1; + sub_800D30C(0x41, 0x00); + } + else if (gUnknown_03004140.unk_05 == 15) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_02 = 1; + sub_800D30C(0x41, 0x00); + gUnknown_03004140.unk_24 |= 1 << gUnknown_03004140.unk_10; + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = gUnknown_03004140.unk_26; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + tmp = &sp0; + *tmp = rfu_NI_CHILD_setSendGameName(gUnknown_03004140.unk_10, 0x0e); + if (*tmp) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D610(); + sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = sp0; + sub_800D30C(0x25, 0x01); + } + } + } + break; + case 61: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x42, 0x00); + } + break; + } + gUnknown_03004140.unk_0e = 1; + } + else if (r6 == 3 && gUnknown_03004140.unk_0f && (r8 == 0x24 || r8 == 0x26 || r8 == 0x27)) + { + rfu_REQ_RFUStatus(); + rfu_waitREQComplete(); + rfu_getRFUStatus(&sp0); + if (sp0 == 0 && gUnknown_03007890->unk_00 == 0) + { + stwiRecvBuffer = rfu_getSTWIRecvBuffer(); + stwiRecvBuffer[4] = gUnknown_03007890->unk_02; + stwiRecvBuffer[5] = 1; + sub_800C36C(0x29); + r6 = 0; + } + } + switch (r8) + { + case 48: + if (r6 == 0) + { + stwiRecvBuffer = rfu_getSTWIRecvBuffer(); + gUnknown_03004140.unk_14 = stwiRecvBuffer[8]; + sub_800D358(gUnknown_03004140.unk_14); + if (gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_30 &= ~gUnknown_03004140.unk_14; + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_14 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + if (gUnknown_03004140.unk_06 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + } + } + sp0 = gUnknown_03004140.unk_00 & gUnknown_03004140.unk_14; + for (i = 0; i < 4; i++) + { + if ((sp0 >> i) & 1 && gUnknown_03004140.unk_01) + { + gUnknown_03004140.unk_01--; + } + } + gUnknown_03004140.unk_00 &= ~gUnknown_03004140.unk_14; + if (gUnknown_03004140.unk_07) + { + if (gUnknown_03007890->unk_00 == 0xFF) + { + if (gUnknown_03004140.unk_07 == 8) + { + gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c; + gUnknown_03004140.unk_07 = 6; + gUnknown_03004140.unk_04 = 6; + } + else if (gUnknown_03004140.unk_04 != 6 && gUnknown_03004140.unk_04 != 7) + { + gUnknown_03004140.unk_07 = 1; + gUnknown_03004140.unk_04 = 5; + } + } + } + if (gUnknown_03007890->unk_00 == 0xFF) + { + if (gUnknown_03004140.unk_04 == 0) + { + gUnknown_03004140.unk_06 = -1; + } + } + if (gUnknown_03004140.unk_0e == 0) + { + sub_800D30C(0x40, 0x01); + } + } + break; + case 38: + sub_800D20C(); + if (gUnknown_03007890->unk_00 != 0xFF) + { + sub_800D30C(0x50, 0x00); + } + break; + case 16: + case 61: + if (r6 == 0) + { + gUnknown_03004140.unk_0d = 0; + gUnknown_03004140.unk_01 = 0; + gUnknown_03004140.unk_00 = 0;; + gUnknown_03004140.unk_06 = -1; + sub_800D610(); + if (r8 == 61) + { + sub_800BFA0(); + } + } + break; + } + if (r6 != 0) + { + if (r8 == 28 && r6 != 0 && gUnknown_03004140.unk_07 == 4) + { + gUnknown_03007890->unk_00 = 1; + gUnknown_03007890->unk_02 = 15; + sub_800D334(15); + rfu_waitREQComplete(); + return; + } + else + { + gUnknown_03004140.unk_14 = r8; + gUnknown_03004140.unk_16 = r6; + if (gUnknown_03004140.unk_0e) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + } + sub_800D30C(0xf0, 0x02); + sub_800D610(); + } + } + if (r8 == 0xFF) + { + sub_800D30C(0xf2, 0x00); + sub_800D610(); + } +} + +static void sub_800CEB0(u16 r6) +{ + u8 r7; + u8 sp0; + + r7 = gUnknown_03004140.unk_0e; + gUnknown_03004140.unk_0e = 0; + gUnknown_03004140.unk_0f = 1; + if (gUnknown_03007890->unk_00 == 0) + { + sub_800C36C(r6); + if (gUnknown_03004140.unk_02 != 1) + { + sub_800D610(); + gUnknown_03004140.unk_0f = 0; + gUnknown_03004140.unk_0e = r7; + return; + } + } + else + { + if (!rfu_UNI_PARENT_getDRAC_ACK(&sp0)) + { + gUnknown_03004140.unk_03 |= sp0; + } + } + if (gUnknown_03004140.unk_44 != NULL) + { + gUnknown_03004140.unk_44(r6); + rfu_waitREQComplete(); + if (gUnknown_03004140.unk_02 == 2) + { + sub_800D610(); + } + } + gUnknown_03004140.unk_0f = 0; + gUnknown_03004140.unk_0e = r7; +} + +static void sub_800CF34(void) +{ + u8 flags; + u8 sp0; + u8 i; + u8 r5; + u8 r4; + const u16 *ptr; + + if (gUnknown_03004140.unk_04 == 5 || gUnknown_03004140.unk_04 == 6 || gUnknown_03004140.unk_04 == 7 || gUnknown_03004140.unk_04 == 8) + { + flags = ((gUnknown_03007890->unk_02 ^ gUnknown_03004140.unk_0c) & gUnknown_03007890->unk_02) & ~gUnknown_03007890->unk_07; + gUnknown_03004140.unk_0c = gUnknown_03007890->unk_02; + if (flags) + { + gUnknown_03004140.unk_14 = flags; + sub_800D30C(0x10, 0x01); + } + sp0 = 0x00; + for (i = 0; i < 4; i++) + { + r4 = 1 << i; + r5 = 0x00; + if (flags & r4) + { + gUnknown_03004140.unk_28[i] = gUnknown_03004140.unk_26; + gUnknown_03004140.unk_24 |= r4; + } + else if (gUnknown_03004140.unk_24 & r4) + { + if (gUnknown_03007880[i]->unk_34 == 0x46) + { + if (gUnknown_03007880[i]->unk_61 == 1) + { + r5 = 0x02; + for (ptr = gUnknown_03004140.unk_20; *ptr != 0xFFFF; ptr++) + { + if (gUnknown_03007890->unk_14[i].unk_04 == *ptr) + { + gUnknown_03004140.unk_00 |= r4; + gUnknown_03004140.unk_01++; + sp0 |= r4; + r5 |= 0x01; + break; + } + } + if (!(r5 & 0x01)) + { + r5 |= 0x04; + } + } + } + else if (--gUnknown_03004140.unk_28[i] == 0) + { + r5 = 0x06; + } + if (r5 & 0x02) + { + gUnknown_03004140.unk_24 &= ~r4; + gUnknown_03004140.unk_28[i] = 0; + rfu_clearSlot(0x08, i); + } + if (r5 & 0x04) + { + gUnknown_03004140.unk_0d |= r4; + } + } + } + if (sp0) + { + gUnknown_03004140.unk_14 = sp0; + sub_800D30C(0x11, 0x01); + } + if (gUnknown_03004140.unk_0d) + { + r5 = 0x01; + if (gUnknown_03007890->unk_06 && ((gUnknown_03004140.unk_03 & gUnknown_03004140.unk_00) != gUnknown_03004140.unk_00)) + { + r5 = 0x00; + } + if (r5) + { + sub_800D334(gUnknown_03004140.unk_0d); + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_0d; + gUnknown_03004140.unk_0d = 0; + sub_800D30C(0x12, 0x01); + } + } + if (gUnknown_03004140.unk_24 == 0 && gUnknown_03004140.unk_04 == 8) + { + if (gUnknown_03004140.unk_07 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x14, 0x00); + } + else + { + if (gUnknown_03004140.unk_07 == 2) + { + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + } + else + { + gUnknown_03004140.unk_07 = 1; + gUnknown_03004140.unk_04 = 5; + } + if (gUnknown_03004140.unk_00) + { + gUnknown_03004140.unk_1a = 0; + gUnknown_03004140.unk_07 = 8; + gUnknown_03004140.unk_04 = 5; + } + } + } + } +} + +static void sub_800D158(void) +{ + u16 imeBak = REG_IME; + REG_IME = 0; + if (gUnknown_03004140.unk_04 == 15) + { + if (--gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] == 0 || gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x27) + { + sub_800D630(); + gUnknown_03004140.unk_04 = 24; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10); + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0; + } + } + REG_IME = imeBak; + if (gUnknown_03004140.unk_04 == 24) + { + if (gUnknown_03004140.unk_02 == 1) + { + sub_800D630(); + } + if (gUnknown_03004140.unk_02 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = 0; + sub_800D30C(0x25, 0x01); + } + } +} + +static void sub_800D20C(void) +{ + if (gUnknown_03004140.unk_04 == 15 && gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x26) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10); + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0; + sub_800D30C(0x24, 0x00); + } +} + +static void sub_800D268(void) +{ + if (gUnknown_03004140.unk_06 == 0 && gUnknown_03004140.unk_0a == 1) + { + gUnknown_03004140.unk_11 = gUnknown_03004140.unk_04; + gUnknown_03004140.unk_12 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_04 = 16; + gUnknown_03004140.unk_05 = 17; + gUnknown_03004140.unk_0a = 2; + } +} + +static u8 sub_800D294(void) +{ + u8 i; + const u16 *ptr; + u8 flags = 0x00; + + for (i = 0; i < gUnknown_03007890->unk_08; i++) + { + for (ptr = gUnknown_03004140.unk_20; *ptr != 0xffff; ptr++) + { + if (gUnknown_03007890->unk_14[i].unk_04 == *ptr) + { + flags |= (1 << i); + } + } + } + return flags; +} + +static void sub_800D30C(u8 a0, u8 a1) +{ + if (gUnknown_03004140.unk_40 != NULL) + { + gUnknown_03004140.unk_40(a0, a1); + } + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_16 = 0; +} + +static void sub_800D334(u8 a0) +{ + u8 unk_0e_bak = gUnknown_03004140.unk_0e; + gUnknown_03004140.unk_0e = 1; + rfu_REQ_disconnect(a0); + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = unk_0e_bak; +} + +static void sub_800D358(u8 a0) +{ + u8 i; + + if (gUnknown_03007890->unk_04) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_0 & 0x8000 && gUnknown_03007880[i]->unk_1a & a0) + { + rfu_changeSendTarget(0x20, i, gUnknown_03007880[i]->unk_1a & ~a0); + } + } + } + if (gUnknown_03007890->unk_05) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_4e & a0) + { + rfu_NI_stopReceivingData(i); + } + } + } + if (gUnknown_03007890->unk_06) + { + gUnknown_03007890->unk_06 &= ~a0; + for (i = 0; i < 4; i++) + { + if (gUnknown_03007870[i]->unk_0 == 0x8024 && a0 & gUnknown_03007870[i]->unk_3) + { + gUnknown_03007870[i]->unk_3 &= ~a0; + } + } + } +} + +static void sub_800D434(void) +{ + u8 i; + u8 j; + u8 flags; + + if (gUnknown_03004140.unk_18) + { + if (gUnknown_03007890->unk_04) + { + for (i = 0; i < 4; i ++) + { + if (gUnknown_03007880[i]->unk_0 & 0x8000) + { + flags = 0; + for (j = 0; j < 4; j++) + { + if ((gUnknown_03007880[i]->unk_1a >> j) & 1 && gUnknown_03007880[j]->unk_2 > gUnknown_03004140.unk_18) + { + flags |= (1 << j); + } + if (flags) + { + rfu_changeSendTarget(0x20, i, flags ^ gUnknown_03007880[i]->unk_1a); + } + } + } + } + } + if (gUnknown_03007890->unk_05) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_36 > gUnknown_03004140.unk_18) + { + rfu_NI_stopReceivingData(i); + } + } + } + } +} + +void sub_800D52C(void (*func)(u16)) +{ + gUnknown_03004140.unk_44 = func; + rfu_setMSCCallback(sub_800CEB0); +} + +void sub_800D544(void (*func)(u8, u8)) +{ + gUnknown_03004140.unk_40 = func; +} + +u8 sub_800D550(u8 a0, u16 a1) +{ + u16 imeBak; + if (gUnknown_03004140.unk_09 && a0 == 0 && gUnknown_03004140.unk_30) + { + return 5; + } + imeBak = REG_IME; + REG_IME = 0; + gUnknown_03004140.unk_09 = a0; + gUnknown_03004140.unk_32 = a1; + REG_IME = imeBak; + return 0; +} + +u8 sub_800D594(u16 a0) +{ + if (gUnknown_03007890->unk_04 | gUnknown_03007890->unk_05) + { + gUnknown_03004140.unk_14 = 6; + sub_800D30C(0xf3, 0x01); + return 6; + } + gUnknown_03004140.unk_18 = a0; + return 0; +} + +u8 sub_800D5D0(u8 a0) +{ + if (gUnknown_03004140.unk_04 == 9 || gUnknown_03004140.unk_04 == 10 || gUnknown_03004140.unk_04 == 11) + { + gUnknown_03004140.unk_14 = 7; + sub_800D30C(0xf3, 0x01); + return 7; + } + if (a0) + { + gUnknown_03004140.unk_0b = 1; + } + else + { + gUnknown_03004140.unk_0b = 0; + } + return 0; +} + +static void sub_800D610(void) +{ + if (gUnknown_03004140.unk_02) + { + gUnknown_03004140.unk_02 = 0; + sub_800D30C(0x45, 0x00); + } +} + +void sub_800D630(void) +{ + if (gUnknown_03004140.unk_02 == 0) + { + sub_800D30C(0x45, 0x00); + } + else if (gUnknown_03004140.unk_02 == 1) + { + gUnknown_03004140.unk_02 = 2; + } +} + +void sub_800D658(void) +{ + if (gUnknown_03004140.unk_07) + { + switch (gUnknown_03004140.unk_04) + { + case 5: + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + break; + case 6: + gUnknown_03004140.unk_07 = 2; + gUnknown_03004140.unk_1a = 1; + break; + case 7: + case 8: + gUnknown_03004140.unk_07 = 2; + break; + case 9: + case 10: + gUnknown_03004140.unk_1a = 40; + break; + case 11: + gUnknown_03004140.unk_1a = 40; + gUnknown_03004140.unk_04 = 10; + break; + } + } +} + +// TODO: Is there a file boundary here? + +void sub_800D6C8(struct UnkRfuStruct_2_Sub_124 *ptr) +{ + int i; + int j; + + for (i = 0; i < 32; i++) + { + for (j = 0; j < 70; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_8c1 = 0; + ptr->unk_8c0 = 0; + ptr->unk_8c2 = 0; + ptr->unk_8c3 = 0; +} + +void sub_800D724(struct UnkRfuStruct_2_Sub_9e8 *ptr) +{ + int i; + int j; + + for (i = 0; i < 40; i++) + { + for (j = 0; j < 14; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_231 = 0; + ptr->unk_230 = 0; + ptr->unk_232 = 0; + ptr->unk_233 = 0; +} + +void sub_800D780(struct UnkRfuStruct_Sub_Unused *ptr) +{ + int i; + int j; + + for (i = 0; i < 2; i++) + { + for (j = 0; j < 256; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_201 = 0; + ptr->unk_200 = 0; + ptr->unk_202 = 0; + ptr->unk_203 = 0; +} + +void sub_800D7D8(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2) +{ + int i; + u16 imeBak; + u8 count; + + if (q1->unk_8c2 < 32) + { + imeBak = REG_IME; + REG_IME = 0; + count = 0; + for (i = 0; i < 70; i += 14) + { + if (q2[i] == 0 && q2[i + 1] == 0) + { + count++; + } + } + if (count != 5) + { + for (i = 0; i < 70; i++) + { + q1->unk_00[q1->unk_8c0][i] = q2[i]; + } + q1->unk_8c0++; + q1->unk_8c0 %= 32; + q1->unk_8c2++; + for (i = 0; i < 70; i++) + { + q2[i] = 0; + } + } + REG_IME = imeBak; + } + else + { + q1->unk_8c3 = 1; + } +} + +void sub_800D888(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2) +{ + int i; + u16 imeBak; + + if (q1->unk_232 < 40) + { + imeBak = REG_IME; + REG_IME = 0; + for (i = 0; i < 14; i++) + { + if (q2[i] != 0) + { + break; + } + } + if (i != 14) + { + for (i = 0; i < 14; i++) + { + q1->unk_00[q1->unk_230][i] = q2[i]; + } + q1->unk_230++; + q1->unk_230 %= 40; + q1->unk_232++; + for (i = 0; i < 14; i++) + { + q2[i] = 0; + } + } + REG_IME = imeBak; + } + else + { + q1->unk_233 = 1; + } +} + +bool8 sub_800D934(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2) +{ + u16 imeBak; + int i; + + imeBak = REG_IME; + REG_IME = 0; + if (q1->unk_8c0 == q1->unk_8c1 || q1->unk_8c3 != 0) + { + for (i = 0; i < 70; i++) + { + q2[i] = 0; + } + REG_IME = imeBak; + return FALSE; + } + for (i = 0; i < 70; i++) + { + q2[i] = q1->unk_00[q1->unk_8c1][i]; + } + q1->unk_8c1++; + q1->unk_8c1 %= 32; + q1->unk_8c2--; + REG_IME = imeBak; + return TRUE; +} + +bool8 sub_800D9DC(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2) +{ + int i; + u16 imeBak; + + if (q1->unk_230 == q1->unk_231 || q1->unk_233 != 0) + { + return FALSE; + } + imeBak = REG_IME; + REG_IME = 0; + for (i = 0; i < 14; i++) + { + q2[i] = q1->unk_00[q1->unk_231][i]; + } + q1->unk_231++; + q1->unk_231 %= 40; + q1->unk_232--; + REG_IME = imeBak; + return TRUE; +} + +void sub_800DA68(struct UnkRfuStruct_2_Sub_c1c *q1, const u8 *q2) +{ + int i; + + if (q2[1] == 0) + { + sub_800DAC8(q1, NULL); + } + else + { + for (i = 0; i < 14; i++) + { + q1->unk_00[q1->unk_1c][i] = q2[i]; + } + q1->unk_1c++; + q1->unk_1c %= 2; + if (q1->unk_1e < 2) + { + q1->unk_1e++; + } + else + { + q1->unk_1d = q1->unk_1c; + } + } +} + +static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2) +{ + int i; + + if (q1->unk_1e == 0) + { + return FALSE; + } + if (q2 != NULL) + { + for (i = 0; i < 14; i++) + { + q2[i] = q1->unk_00[q1->unk_1d][i]; + } + } + q1->unk_1d++; + q1->unk_1d %= 2; + q1->unk_1e--; + return TRUE; +} + +void sub_800DB18(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2) +{ + int i; + + if (q1->unk_202 < 2) + { + for (i = 0; i < 256; i++) + { + q1->unk_00[q1->unk_200][i] = q2[i]; + } + q1->unk_200++; + q1->unk_200 %= 2; + q1->unk_202++; + } + else + { + q1->unk_203 = 1; + } +} + +bool8 sub_800DB84(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2) +{ + int i; + + if (q1->unk_200 == q1->unk_201 || q1->unk_203) + { + return FALSE; + } + for (i = 0; i < 256; i++) + { + q2[i] = q1->unk_00[q1->unk_201][i]; + } + q1->unk_201++; + q1->unk_201 %= 2; + q1->unk_202--; + return TRUE; +} + +void sub_800DBF8(u8 *q1, u8 mode) +{ + int i; + u8 rval; + u16 r5 = 0; + switch (mode) + { + case 0: + for (i = 0; i < 200; i++) + { + q1[i] = i + 1; + r5 += i + 1; + } + *((u16 *)(q1 + i)) = r5; + break; + case 1: + for (i = 0; i < 100; i++) + { + q1[i] = i + 1; + r5 += i + 1; + } + *((u16 *)(q1 + 200)) = r5; + break; + case 2: + for (i = 0; i < 200; i++) + { + rval = Random(); + q1[i] = rval; + r5 += rval; + } + *((u16 *)(q1 + i)) = r5; + break; + case 3: + for (i = 0; i < 200; i++) + { + q1[i] = i + 1 + gUnknown_03000D74; + r5 += (i + 1 + gUnknown_03000D74) & 0xFF; + } + *((u16 *)(q1 + i)) = r5; + gUnknown_03000D74++; + break; + } +} + +void PkmnStrToASCII(u8 *q1, const u8 *q2) +{ + int i; + + for (i = 0; q2[i] != EOS; i++) + { + q1[i] = sWireless_RSEtoASCIITable[q2[i]]; + } + q1[i] = 0; +} + +void ASCIIToPkmnStr(u8 *q1, const u8 *q2) +{ + int i; + + for (i = 0; q2[i] != 0; i++) + { + q1[i] = sWireless_ASCIItoRSETable[q2[i]]; + } + q1[i] = EOS; +} + +#ifdef NONMATCHING +u8 sub_800DD1C(u8 maxFlags) +{ + u8 flagCount = 0; + u8 flags = gUnknown_03007890->unk_02; + u8 i; + + if (gUnknown_03007890->unk_00 == 1) + { + i = 0; + for (i = 0; i < 4; flags >>= 1, i++) + { + if (flags & 1) + { + if (maxFlags == flagCount + 1) + { + return gUnknown_03007890->unk_0a[i]; + } + flagCount++; + } + } + } + else + { + for (i = 0; i < 4; flags >>= 1, i++) + { + if (flags & 1) + { + return gUnknown_03007890->unk_0a[i]; + } + } + } + return 0; +} +#else +__attribute__((naked)) u8 sub_800DD1C(u8 maxFlags) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tmovs r6, 0\n" + "\tldr r0, =gUnknown_03007890\n" + "\tldr r4, [r0]\n" + "\tldrb r2, [r4, 0x2]\n" + "\tldrb r1, [r4]\n" + "\tadds r7, r0, 0\n" + "\tcmp r1, 0x1\n" + "\tbne _0800DD72\n" + "\tmovs r3, 0\n" + "\tands r1, r2\n" + "\tcmp r1, 0\n" + "\tbeq _0800DD4E\n" + "\tcmp r5, 0x1\n" + "\tbne _0800DD48\n" + "\tldrb r0, [r4, 0xA]\n" + "\tb _0800DD8C\n" + "\t.pool\n" + "_0800DD48:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r6, r0, 24\n" + "_0800DD4E:\n" + "\tlsrs r2, 1\n" + "\tadds r0, r3, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r3, r0, 24\n" + "\tcmp r3, 0x3\n" + "\tbhi _0800DD8A\n" + "\tmovs r0, 0x1\n" + "\tands r0, r2\n" + "\tcmp r0, 0\n" + "\tbeq _0800DD4E\n" + "\tadds r0, r6, 0x1\n" + "\tcmp r5, r0\n" + "\tbne _0800DD48\n" + "_0800DD68:\n" + "\tldr r0, [r7]\n" + "\tadds r0, 0xA\n" + "\tadds r0, r3\n" + "\tldrb r0, [r0]\n" + "\tb _0800DD8C\n" + "_0800DD72:\n" + "\tmovs r3, 0\n" + "\tmovs r1, 0x1\n" + "_0800DD76:\n" + "\tadds r0, r2, 0\n" + "\tands r0, r1\n" + "\tcmp r0, 0\n" + "\tbne _0800DD68\n" + "\tlsrs r2, 1\n" + "\tadds r0, r3, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r3, r0, 24\n" + "\tcmp r3, 0x3\n" + "\tbls _0800DD76\n" + "_0800DD8A:\n" + "\tmovs r0, 0\n" + "_0800DD8C:\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1"); +} +#endif + +void sub_800DD94(struct UnkLinkRfuStruct_02022B14 *data, u8 r9, bool32 r2, int r3) +{ + int i; + + for (i = 0; i < 2; i++) + { + data->playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i]; + } + for (i = 0; i < 4; i++) + { + data->unk_04[i] = r3; + r3 >>= 8; + } + data->playerGender = gSaveBlock2Ptr->playerGender; + data->unk_0a_0 = r9; + data->unk_0a_7 = r2; + data->unk_00_0 = 2; + data->unk_01_2 = 3; + data->unk_00_4 = 0; + data->unk_00_5 = 0; + data->unk_00_6 = 0; + data->unk_00_7 = FlagGet(FLAG_0x87F); + data->unk_01_0 = IsNationalPokedexEnabled(); + data->unk_01_1 = FlagGet(FLAG_SYS_GAME_CLEAR); +} + +bool8 sub_800DE7C(void *buff1, void *buff2, u8 idx) +{ + bool8 retVal; + + if (gUnknown_03004140.unk_06 == 1) + { + retVal = TRUE; + if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04) && ((gUnknown_03007890->unk_07 >> idx) & 1)) + { + memcpy(buff1, gUnknown_03007890->unk_14[idx].unk_06, 13); + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, 8); + } + else + { + memset(buff1, 0, 13); + memset(buff2, 0, 8); + } + } + else + { + retVal = FALSE; + if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04)) + { + memcpy(buff1, gUnknown_03007890->unk_14[idx].unk_06, 13); + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, 8); + } + else + { + memset(buff1, 0, 13); + memset(buff2, 0, 8); + } + } + return retVal; +} + +bool8 sub_800DF34(void *buff1, void *buff2, u8 idx) +{ + bool8 retVal = FALSE; + if (gUnknown_03007890->unk_14[idx].unk_04 == 0x7F7D) + { + memcpy(buff1, gUnknown_03007890->unk_14[idx].unk_06, 13); + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, 8); + retVal = TRUE; + } + else + { + memset(buff1, 0, 13); + memset(buff2, 0, 8); + } + return retVal; +} + +void sub_800DF90(void *buff1, void *buff2) +{ + memcpy(buff1, &gUnknown_02022B14, 13); + memcpy(buff2, gUnknown_02022B22, 8); +} + +void CreateWirelessStatusIndicatorSprite(u8 x, u8 y) +{ + u8 sprId; + + if (x == 0 && y == 0) + { + x = 0xE7; + y = 0x08; + } + if (gUnknown_03007890->unk_00 == 1) + { + sprId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0); + gSprites[sprId].data[7] = 0x1234; + gSprites[sprId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag); + gSprites[sprId].invisible = TRUE; + gWirelessStatusIndicatorSpriteId = sprId; + } + else + { + gWirelessStatusIndicatorSpriteId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0); + gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0x1234; + gSprites[gWirelessStatusIndicatorSpriteId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag); + gSprites[gWirelessStatusIndicatorSpriteId].invisible = TRUE; + } +} + +void sub_800E084(void) +{ + if (gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234) + { + gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0; + DestroySprite(&gSprites[gWirelessStatusIndicatorSpriteId]); + gMain.oamBuffer[125] = gDummyOamData; + CpuCopy16(&gDummyOamData, (struct OamData *)OAM + 125, sizeof(struct OamData)); + } +} + +void sub_800E0E8(void) +{ + if (GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag) == 0xFFFF) + { + LoadCompressedObjectPic(&sWirelessStatusIndicatorSpriteSheet); + } + LoadSpritePalette(&sWirelessStatusIndicatorSpritePalette); + gWirelessStatusIndicatorSpriteId = 0xFF; +} + +u8 sub_800E124(void) +{ + u8 i; + u8 flags = gUnknown_03007890->unk_02; + for (i = 0; i < 4; i++) + { + if (flags & 1) + { + return gUnknown_03007890->unk_0a[i]; + } + flags >>= 1; + } + return 0; +} + +void sub_800E15C(struct Sprite *sprite, int signalStrengthAnimNum) +{ + if (sprite->data[2] != signalStrengthAnimNum) + { + sprite->data[2] = signalStrengthAnimNum; + sprite->data[3] = 0; + sprite->data[4] = 0; + } +} + +void sub_800E174(void) +{ + if (gWirelessStatusIndicatorSpriteId != 0xFF && gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234) + { + struct Sprite *sprite = &gSprites[gWirelessStatusIndicatorSpriteId]; + u8 signalStrength = 255; + u8 i = 0; + if (gUnknown_03007890->unk_00 == 1) + { + for (i = 0; i < GetLinkPlayerCount() - 1; i++) + { + if (signalStrength >= sub_800DD1C(i + 1)) + { + signalStrength = sub_800DD1C(i + 1); + } + } + } + else + { + signalStrength = sub_800E124(); + } + if (sub_8012224() == TRUE) + { + sprite->data[0] = 4; + } + else if (signalStrength < 25) + { + sprite->data[0] = 3; + } + else if (signalStrength >= 25 && signalStrength < 127) + { + sprite->data[0] = 2; + } + else if (signalStrength >= 127 && signalStrength < 229) + { + sprite->data[0] = 1; + } + else if (signalStrength >= 229) + { + sprite->data[0] = 0; + } + if (sprite->data[0] != sprite->data[1]) + { + sub_800E15C(sprite, sprite->data[0]); + sprite->data[1] = sprite->data[0]; + } + if (sprite->anims[sprite->data[2]][sprite->data[4]].frame.duration < sprite->data[3]) + { + sprite->data[4]++; + sprite->data[3] = 0; + if (sprite->anims[sprite->data[2]][sprite->data[4]].type == -2) + { + sprite->data[4] = 0; + } + } + else + { + sprite->data[3]++; + } + gMain.oamBuffer[125] = sWirelessStatusIndicatorOamData; + gMain.oamBuffer[125].x = sprite->pos1.x + sprite->centerToCornerVecX; + gMain.oamBuffer[125].y = sprite->pos1.y + sprite->centerToCornerVecY; + gMain.oamBuffer[125].paletteNum = sprite->oam.paletteNum; + gMain.oamBuffer[125].tileNum = sprite->data[6] + sprite->anims[sprite->data[2]][sprite->data[4]].frame.imageValue; + CpuCopy16(gMain.oamBuffer + 125, (struct OamData *)OAM + 125, sizeof(struct OamData)); + if (sub_8011A74() == 1) + { + sub_800E084(); + } + } +} + +void sub_800E378(struct UnkSaveSubstruct_3b98 *dest, u32 trainerId, const u8 *name) +{ + dest->trainerId = trainerId; + StringCopy(dest->trainerName, name); +} + +bool32 sub_800E388(const u8 *name) +{ + int i; + + for (i = 0; i < 8; i++) + { + if (name[i] != 0) + { + return TRUE; + } + } + return FALSE; +} + +void sub_800E3A8(void) +{ + if (gWirelessCommType != 0) + { + int i; + int j; + int cnt; + int sp0[5]; + struct UnkSaveSubstruct_3b98 *sp14 = calloc(20, sizeof(struct UnkSaveSubstruct_3b98)); + for (i = 0; i < GetLinkPlayerCount(); i++) + { + sp0[i] = -1; + for (j = 0; j < 20; j++) + { + if ((u16)gLinkPlayers[i].trainerId == gSaveBlock1Ptr->unk_3B98[j].trainerId && StringCompare(gLinkPlayers[i].name, gSaveBlock1Ptr->unk_3B98[j].trainerName) == 0) + { + sp0[i] = j; + } + } + } + cnt = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + if (i != GetMultiplayerId() && gLinkPlayers[i].language != LANGUAGE_JAPANESE) + { + sub_800E378(&sp14[cnt], (u16)gLinkPlayers[i].trainerId, gLinkPlayers[i].name); + if (sp0[i] >= 0) + { + memset(gSaveBlock1Ptr->unk_3B98[sp0[i]].trainerName, 0, 8); + } + cnt++; + } + } + for (i = 0; i < 20; i++) + { + if (sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName)) + { + sub_800E378(&sp14[cnt], gSaveBlock1Ptr->unk_3B98[i].trainerId, gSaveBlock1Ptr->unk_3B98[i].trainerName); + if (++cnt >= 20) + { + break; + } + } + } + memcpy(gSaveBlock1Ptr->unk_3B98, sp14, 20 * sizeof(struct UnkSaveSubstruct_3b98)); + free(sp14); + } +} + +bool32 sub_800E540(u16 id, u8 *name) +{ + int i; + + for (i = 0; i < 20; i++) + { + if (StringCompare(gSaveBlock1Ptr->unk_3B98[i].trainerName, name) == 0 && gSaveBlock1Ptr->unk_3B98[i].trainerId == id) + { + return TRUE; + } + if (!sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName)) + { + return FALSE; + } + } + return FALSE; +} + +void sub_800E5AC(void) +{ + int i; + + for (i = 0; i < 20; i++) + { + gSaveBlock1Ptr->unk_3B98[i].trainerId = 0; + CpuFill16(0, gSaveBlock1Ptr->unk_3B98[i].trainerName, 8); + } +} + +void nullsub_5(void *unused_0, u8 unused_1, u8 unused_2) +{ + // debug? +} + +void nullsub_13(u8 unused_0, u8 unused_1, u8 unused_2, u8 unused_3) +{ + +} + +void sub_800E604(void) +{ + int i; + u8 unk_ee_bak = gUnknown_03005000.unk_ee; + CpuFill16(0, &gUnknown_03005000, sizeof gUnknown_03005000); + gUnknown_03005000.unk_ee = unk_ee_bak; + gUnknown_03005000.unk_0c = 0xFF; + if (gUnknown_03005000.unk_ee != 4) + { + gUnknown_03005000.unk_ee = 0; + } + for (i = 0; i < 5; i++) + { + sub_800FCC4(gUnknown_03005000.unk_80 + i); + } + sub_800FCC4(&gUnknown_03005000.unk_6c); + sub_800D6C8(&gUnknown_03005000.unk_124); + sub_800D724(&gUnknown_03005000.unk_9e8); + CpuFill16(0, gSendCmd, sizeof gSendCmd); + CpuFill16(0, gRecvCmds, sizeof gRecvCmds); + CpuFill16(0, gLinkPlayers, sizeof gLinkPlayers) +} + +void sub_800E6D0(void) +{ + IntrFunc serialIntr = gIntrTable[1]; + IntrFunc timerIntr = gIntrTable[2]; + sub_800E700(); + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + REG_IME = 0; + gIntrTable[1] = serialIntr; + gIntrTable[2] = timerIntr; + REG_IME = INTR_FLAG_VBLANK; +} + +void sub_800E700(void) +{ + if (!rfu_initializeAPI(gUnknown_03004140.unk_50, sizeof gUnknown_03004140.unk_50, gIntrTable + 1, TRUE)) + { + gLinkType = 0; + sub_800AAF4(); + sub_80111B0(0); + sub_800E604(); + rfu_setTimerInterrupt(3, gIntrTable + 2); + } +} + +void sub_800E748(u8 taskId) +{ + sub_8010750(); + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_02022B2C); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 2: + sub_800C054(gUnknown_03005000.unk_0c, 0, 240, gUnknown_082ED6E0); + gUnknown_03005000.unk_04 = 3; + gTasks[taskId].data[1] = 6; + break; + case 3: + break; + case 4: + sub_800C27C(FALSE); + gUnknown_03005000.unk_04 = 5; + break; + case 5: + break; + case 18: + gUnknown_03005000.unk_cdb = 0; + sub_800D52C(sub_800EDBC); + sub_800EAB4(); + sub_800EAFC(); + gUnknown_03005000.unk_04 = 20; + gTasks[taskId].data[1] = 8; + CreateTask(sub_801084C, 5); + DestroyTask(taskId); + break; + } +} + +u8 sub_800E87C(u8 idx) +{ + return gUnknown_082ED6A5[idx]; +} + +void sub_800E88C(int r2, int r5) +{ + u8 i; + u8 r4 = 1; + int r1 = r2; + int r6 = 0; + if (r5 == -1) + { + for (i = 0; i < 4; r2 >>= 1, i++) + { + if (r2 & 1) + { + gUnknown_03005000.unk_cde[i] = r4; + r4++; + } + } + } + else + { + for (i = 0; i < 4; r1 >>= 1, i++) + { + if (!(r1 & 1)) + { + gUnknown_03005000.unk_cde[i] = 0; + } + } + for (r4 = 4; r4 != 0; r4--) + { + for (i = 0; i < 4 && gUnknown_03005000.unk_cde[i] != r4; i++); + if (i == 4) + { + r6 = r4; + } + } + for (r5 &= ~r2, i = 0; i < 4; r5 >>= 1, i++) + { + if (r5 & 1) + { + gUnknown_03005000.unk_cde[i] = r6++; + } + } + } +} + +void sub_800E94C(u8 taskId) +{ + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_082ED608); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 6: + sub_800C054(gUnknown_03005000.unk_0c, 0, 0xf0, gUnknown_082ED6E0); + gUnknown_03005000.unk_04 = 7; + gTasks[taskId].data[1] = 7; + break; + case 7: + break; + case 9: + gTasks[taskId].data[1] = 10; + break; + case 11: + switch (sub_80107A0()) + { + case 5: + gUnknown_03005000.unk_04 = 12; + break; + case 6: + case 9: + sub_800D630(); + gUnknown_03005000.unk_ce4 = 2; + DestroyTask(taskId); + break; + } + break; + case 12: + { + u8 r5 = 1 << gUnknown_03005000.unk_c3e; + rfu_clearSlot(12, gUnknown_03005000.unk_c3e); + rfu_setRecvBuffer(16, gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_c3f, 70); + rfu_UNI_setSendData(r5, gUnknown_03005000.unk_4c, 14); + gTasks[taskId].data[1] = 8; + DestroyTask(taskId); + if (gUnknown_02022B44.unk_0f == 0) + { + sub_801227C(); + gUnknown_02022B44.unk_0f++; + } + CreateTask(sub_801084C, 5); + break; + } + } +} + +static void sub_800EAB4(void) +{ + u8 i; + u8 r5 = gUnknown_03004140.unk_00; + for (i = 0; i < 4; i++) + { + if (r5 & 1) + { + rfu_setRecvBuffer(16, i, gUnknown_03005000.unk_14[i], 14); + rfu_clearSlot(3, i); + } + r5 >>= 1; + } +} + +static void sub_800EAFC(void) +{ + u8 r5 = gUnknown_03004140.unk_00; + rfu_UNI_setSendData(r5, gUnknown_03005000.unk_c87, 70); + gUnknown_03005000.unk_cda = sub_800E87C(r5); + gUnknown_03005000.unk_ce2 = r5; + sub_800E88C(r5, -1); + gUnknown_03005000.unk_0c = 1; +} + +void sub_800EB44(u8 taskId) +{ + if (sub_800F7DC()->unk_0a_0 == 0x54 && sub_8011A74() == 4) + { + rfu_REQ_disconnect(gUnknown_03004140.unk_00); + rfu_waitREQComplete(); + sub_8011A64(0, 0); + } + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_02022B2C); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 17: + sub_800C054(2, 0, 240, gUnknown_082ED6E0); + sub_800D52C(sub_800ED34); + gUnknown_03005000.unk_04 = 18; + break; + case 18: + break; + case 13: + if (rfu_UNI_setSendData(1 << gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_4c, 14) == 0) + { + gUnknown_03005000.unk_0c = 0; + DestroyTask(taskId); + if (gTasks[taskId].data[7]) + { + CreateTask(sub_8010D0C, 1); + } + else + { + CreateTask(sub_801084C, 5); + } + } + break; + case 14: + sub_800C27C(0); + gUnknown_03005000.unk_04 = 15; + break; + case 15: + break; + case 16: + gUnknown_03005000.unk_cdb = 0; + sub_800D52C(sub_800EDBC); + sub_8011068(1); + sub_800EAB4(); + sub_800EAFC(); + gUnknown_03005000.unk_04 = 20; + gTasks[taskId].data[1] = 8; + gUnknown_03005000.unk_0c = 1; + CreateTask(sub_801084C, 5); + gUnknown_03005000.unk_ce8 = 1; + DestroyTask(taskId); + break; + } +} + +void sub_800ED10(void) +{ + sub_800C054(1, 0, 240, gUnknown_082ED6E0); +} + +void sub_800ED28(void) +{ + sub_800C27C(FALSE); +} + +void sub_800ED34(u16 unused) +{ + int i; + + for (i = 0; i < 14; i++) + { + gUnknown_03005000.unk_4c[i] = 0; + } + rfu_REQ_recvData(); + rfu_waitREQComplete(); + if (gUnknown_03007870[gUnknown_03005000.unk_c3e]->unk_12) + { + gUnknown_03005000.unk_cd0++; + sub_800D7D8(&gUnknown_03005000.unk_124, gUnknown_03005000.unk_c3f); + gUnknown_02022B44.unk_06++; + sub_800F048(); + rfu_UNI_readySendData(gUnknown_03005000.unk_c3e); + rfu_UNI_clearRecvNewDataFlag(gUnknown_03005000.unk_c3e); + } + rfu_REQ_sendData_wrapper(1); +} + +static void sub_800EDBC(u16 unused) +{ + gUnknown_03005000.unk_cdb = 1; +} + +void sub_800EDD4(void) +{ + u8 i; + + sub_800C048(); + if (gUnknown_03005000.unk_0c == 1) + { + if (FuncIsActiveTask(sub_800E748) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + else if (gUnknown_03005000.unk_0c == 0) + { + if (FuncIsActiveTask(sub_800E94C) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + else if (gUnknown_03005000.unk_0c == 2) + { + if (FuncIsActiveTask(sub_800EB44) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + for (i = 0; i < 3; i++) + { + if (FuncIsActiveTask(gUnknown_082ED7E0[i]) == TRUE) + { + DestroyTask(FindTaskIdByFunc(gUnknown_082ED7E0[i])); + } + } +} + +void sub_800EE78(void) +{ + gUnknown_03005000.unk_67 = CreateTask(sub_800E748, 1); +} + +bool8 sub_800EE94(void) +{ + if (gUnknown_03005000.unk_04 == 7 && gUnknown_03005000.unk_ccd) + { + return TRUE; + } + return FALSE; +} + +bool8 sub_800EEBC(void) +{ + if (gUnknown_03005000.unk_04 == 7 && !sub_800C12C(gUnknown_03007890->unk_14[gUnknown_03005000.unk_c3d].unk_00, 240)) + { + gUnknown_03005000.unk_04 = 9; + return TRUE; + } + return FALSE; +} + +void sub_800EF00(void) +{ + gUnknown_03005000.unk_67 = CreateTask(sub_800E94C, 1); +} + +bool8 sub_800EF1C(void) +{ + if (gUnknown_03004140.unk_00) + { + return TRUE; + } + return FALSE; +} + +void sub_800EF38(void) +{ + gUnknown_03005000.unk_04 = 4; + gUnknown_03005000.unk_ce7 = gUnknown_03004140.unk_00; +} + +bool8 sub_800EF58(bool32 a0) +{ + if (gUnknown_03005000.unk_04 == 17 || a0) + { + gUnknown_03005000.unk_04 = 18; + return TRUE; + } + return FALSE; +} + +void sub_800EF7C(void) +{ + gUnknown_03005000.unk_04 = 14; +} + +void sub_800EF88(u8 a0) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + if (a0 & 1) + { + rfu_UNI_readySendData(i); + break; + } + a0 >>= 1; + } +} + +#ifdef NONMATCHING +// FIXME: gUnknown_03005000.unk_c87 should be in r5 +// FIXME: gRecvCmds should be in r6 and r7 +void sub_800EFB0(void) +{ + int i, j; + for (i = 0; i < 5; i++) + { + for (j = 0; j < 7; j++) + { + gUnknown_03005000.unk_c87[i][j][1] = gRecvCmds[i][j] >> 8; + gUnknown_03005000.unk_c87[i][j][0] = gRecvCmds[i][j]; + } + } + CpuFill16(0, gRecvCmds, sizeof gRecvCmds); +} +#else +__attribute__((naked)) void sub_800EFB0(void) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tsub sp, 0x4\n" + "\tmovs r2, 0\n" + "\tldr r7, =gRecvCmds\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r6, r7, 0\n" + "\tldr r1, =0x00000c87\n" + "\tadds r5, r0, r1\n" + "_0800EFC0:\n" + "\tmovs r3, 0\n" + "\tlsls r0, r2, 3\n" + "\tlsls r1, r2, 4\n" + "\tadds r4, r2, 0x1\n" + "\tsubs r0, r2\n" + "\tlsls r0, 1\n" + "\tadds r2, r0, r5\n" + "\tadds r1, r6\n" + "_0800EFD0:\n" + "\tldrh r0, [r1]\n" + "\tlsrs r0, 8\n" + "\tstrb r0, [r2, 0x1]\n" + "\tldrh r0, [r1]\n" + "\tstrb r0, [r2]\n" + "\tadds r2, 0x2\n" + "\tadds r1, 0x2\n" + "\tadds r3, 0x1\n" + "\tcmp r3, 0x6\n" + "\tble _0800EFD0\n" + "\tadds r2, r4, 0\n" + "\tcmp r2, 0x4\n" + "\tble _0800EFC0\n" + "\tmovs r0, 0\n" + "\tmov r1, sp\n" + "\tstrh r0, [r1]\n" + "\tldr r2, =0x01000028\n" + "\tmov r0, sp\n" + "\tadds r1, r7, 0\n" + "\tbl CpuSet\n" + "\tadd sp, 0x4\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800F014(void) +{ + int i; + for (i = 0; i < 7; i++) + { + gRecvCmds[0][i] = gSendCmd[i]; + } + for (i = 0; i < 7; i++) + { + gSendCmd[i] = 0; + } +} + +static void sub_800F048(void) +{ + if (gUnknown_03005000.unk_c3c) + { + u8 r2 = sub_800DAC8(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c); + if (gUnknown_03005000.unk_c1c.unk_1e == 0) + { + gUnknown_03005000.unk_c3c = 0; + } + if (r2) + { + return; + } + } + if (gUnknown_03005000.unk_c3c == 0) + { + sub_800D9DC(&gUnknown_03005000.unk_9e8, gUnknown_03005000.unk_4c); + sub_800DA68(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c); + } +} + +bool32 sub_800F0B8(void) +{ + int i; + int j; + + if (gUnknown_03007890->unk_06 == 0) + { + return FALSE; + } + for (i = 0; i < 5; i++) + { + for (j = 0; j < 7; j++) + { + if (gRecvCmds[i][j] != 0) + { + return FALSE; + } + } + } + return TRUE; +} + +bool32 sub_800F0F8(void) +{ + if (gUnknown_03005000.unk_04 < 20) + { + rfu_REQ_recvData(); + rfu_waitREQComplete(); + rfu_REQ_sendData_wrapper(0); + } + else + { + gUnknown_03005000.unk_cdb = 0; + if ((gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02) == gUnknown_03005000.unk_ce2 && (gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02)) + { + if (!gUnknown_03005000.unk_cdc) + { + if (gUnknown_03005000.unk_ce3) + { + sub_8011D6C(gUnknown_03005000.unk_ce3); + gUnknown_03005000.unk_ce3 = 0; + if (gUnknown_03005000.unk_ce4 == 1) + { + sub_8011A64(2, 0x8000); + sub_8011170(0x8000); + return FALSE; + } + if (!gUnknown_03004140.unk_00) + { + sub_800EDD4(); + gReceivedRemoteLinkPlayers = 0; + return FALSE; + } + } + sub_800EFB0(); + rfu_UNI_readySendData(gUnknown_03005000.unk_cda); + rfu_REQ_sendData_wrapper(1); + } + else + { + rfu_REQ_PARENT_resumeRetransmitAndChange(); + } + gUnknown_03005000.unk_0e = 1; + } + } + return FALSE; +} + +bool32 sub_800F1E0(void) +{ + u16 i; + u16 flags; + u8 r0; + u16 j; + u8 retval; + + if (gUnknown_03005000.unk_04 >= 20 && gUnknown_03005000.unk_0e == 1) + { + rfu_waitREQComplete(); + while (gUnknown_03005000.unk_cdb == 0) + { + if (gUnknown_03005000.unk_ee != 0) + { + return FALSE; + } + } + rfu_REQ_recvData(); + rfu_waitREQComplete(); + if ((gUnknown_03004140.unk_03 & gUnknown_03005000.unk_ce2) == gUnknown_03005000.unk_ce2) + { + gUnknown_03005000.unk_cdc = 0; + gUnknown_02022B44.unk_06++; + flags = gUnknown_03004140.unk_00; + for (i = 0; i < 4; i++) + { + if (flags & 1) + { + if (gUnknown_03005000.unk_14[i][1]) + { + if (gUnknown_03005000.unk_cee[i] != 0xff && (gUnknown_03005000.unk_14[i][0] >> 5) != ((gUnknown_03005000.unk_cee[i] + 1) & 7)) + { + if (++gUnknown_03005000.unk_cea[i] > 4) + sub_8011170(0x8100); + } + else + { + gUnknown_03005000.unk_cee[i] = gUnknown_03005000.unk_14[i][0] / 32; + gUnknown_03005000.unk_cea[i] = 0; + gUnknown_03005000.unk_14[i][0] &= 0x1f; + r0 = gUnknown_03005000.unk_cde[i]; + for (j = 0; j < 7; j++) + { + gRecvCmds[r0][j] = (gUnknown_03005000.unk_14[i][(j << 1) + 1] << 8) | gUnknown_03005000.unk_14[i][(j << 1) + 0]; + gUnknown_03005000.unk_14[i][(j << 1) + 1] = 0; + gUnknown_03005000.unk_14[i][(j << 1) + 0] = 0; + } + } + } + rfu_UNI_clearRecvNewDataFlag(i); + } + flags >>= 1; + } + sub_800F014(); + sub_800F86C(0); + sub_8010528(); + if (gUnknown_03005000.unk_ce5 && !gUnknown_03005000.unk_cd9) + { + gUnknown_02022B44.unk_0e = 0; + rfu_clearSlot(3, gUnknown_03005000.unk_cda); + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce5 >> i) & 1) + { + rfu_setRecvBuffer(0x10, i, gUnknown_03005000.unk_14[i], 14); + } + } + sub_800E88C(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_ce2 | gUnknown_03005000.unk_ce5); + gUnknown_03005000.unk_ce9 = gUnknown_03005000.unk_ce5; + gUnknown_03005000.unk_ce2 |= gUnknown_03005000.unk_ce5; + gUnknown_03005000.unk_ce5 = 0; + rfu_UNI_setSendData(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_c87, 70); + gUnknown_03005000.unk_cda = sub_800E87C(gUnknown_03005000.unk_ce2); + CreateTask(sub_8010AAC, 0); + } + } + else + { + gUnknown_03005000.unk_cdc = 1; + gUnknown_03005000.unk_0e = 0; + } + gUnknown_03005000.unk_0e = 0; + } + retval = gUnknown_03005000.unk_cdc; + return gUnknown_03007890->unk_06 ? retval & 1 : FALSE; +} + +void sub_800F498(u16 *a0, u8 *a1) +{ + int i; + + if (a0[0]) + { + a0[0] |= (gUnknown_03005000.unk_102 << 5); + gUnknown_03005000.unk_102 = (gUnknown_03005000.unk_102 + 1) & 7; + for (i = 0; i < 7; i++) + { + a1[2 * i + 1] = a0[i] >> 8; + a1[2 * i + 0] = a0[i]; + } + } + else + { + for (i = 0; i < 14; i++) + a1[i] = 0; + } +} + +bool32 sub_800F4F0(void) +{ + u8 i; + u8 j; + u8 sp00[MAX_RFU_PLAYERS * (2 * (CMD_LENGTH - 1))]; + u8 sp48[2 * (CMD_LENGTH - 1)]; + u8 switchval; + + sub_800D934(&gUnknown_03005000.unk_124, sp00); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + for (j = 0; j < CMD_LENGTH - 1; j++) + { + gRecvCmds[i][j] = (sp00[i * 14 + (j << 1) + 1] << 8) | sp00[i * 14 + (j << 1) + 0]; + } + } + sub_800F86C(0); + if (gUnknown_03004140.unk_02 == 0 && gUnknown_03005000.unk_ce4) + { + rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + rfu_waitREQComplete(); + switchval = sub_8011A74(); + if (switchval != 1 && switchval != 6 && switchval != 9) + sub_8011A64(2, 0x9000); + rfu_clearAllSlot(); + gReceivedRemoteLinkPlayers = FALSE; + gUnknown_03005000.unk_00 = 0; + if (gUnknown_03005000.unk_ce4 == 1) + { + sub_8011A64(2, 0x9000); + sub_8011170(0x9000); + } + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + gUnknown_03005000.unk_ce4 = 0; + } + if (gUnknown_03005000.unk_cd0) + { + gUnknown_03005000.unk_cd0--; + sub_8010528(); + sub_800F498(gSendCmd, sp48); + sub_800D888(&gUnknown_03005000.unk_9e8, sp48); + for (i = 0; i < CMD_LENGTH - 1; i++) + gSendCmd[i] = 0; + } + return sub_800F0B8(); +} + +#ifdef NONMATCHING +void sub_800F638(u8 unused, u32 flags) +{ + int i; + int j; + + u8 *r10 = gUnknown_03005000.unk_6c.unk_04; + for (i = 0; i < gUnknown_03005000.unk_6c.unk_02; i++) + { + if (!(flags & 1)) + { + gUnknown_03000D90[0] = (~0x76ff) | i; + for (j = 0; j < 7; j++) + { + gUnknown_03000D90[j + 1] = (r10[12 * i + (j << 1) + 1] << 8) | r10[12 * i + (j << 1) + 0]; + } + for (j = 0; j < 7; j++) + // This should be an ascending loop. + // GCC compiles this as descending. + { + gUnknown_03000D80[2 * j + 1] = gUnknown_03000D90[j] >> 8; + gUnknown_03000D80[2 * j + 0] = gUnknown_03000D90[j]; + } + sub_800D888(&gUnknown_03005000.unk_9e8, gUnknown_03000D80); + gUnknown_03005000.unk_6c.unk_0c |= (1 << i); + } + flags >>= 1; + } +} +#else +__attribute__((naked)) void sub_800F638(u8 unused, u32 flags) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tldr r0, =gUnknown_03005000\n" + "\tldr r2, [r0, 0x70]\n" + "\tmov r10, r2\n" + "\tmovs r5, 0\n" + "\tadds r2, r0, 0\n" + "\tadds r2, 0x6E\n" + "\tldrh r3, [r2]\n" + "\tcmp r5, r3\n" + "\tbge _0800F6D4\n" + "\tmov r9, r0\n" + "\tldr r0, =gUnknown_03000D90\n" + "\tmov r8, r0\n" + "_0800F65A:\n" + "\tmovs r0, 0x1\n" + "\tands r0, r1\n" + "\tlsrs r7, r1, 1\n" + "\tadds r6, r5, 0x1\n" + "\tcmp r0, 0\n" + "\tbne _0800F6C8\n" + "\tldr r1, =0xffff8900\n" + "\tadds r0, r1, 0\n" + "\tadds r1, r5, 0\n" + "\torrs r1, r0\n" + "\tmov r2, r8\n" + "\tstrh r1, [r2]\n" + "\tmovs r4, 0\n" + "\tlsls r0, r5, 1\n" + "\tldr r3, =gUnknown_03000D80\n" + "\tmov r12, r3\n" + "\tadds r0, r5\n" + "\tlsls r0, 2\n" + "\tmov r1, r10\n" + "\tadds r2, r0, r1\n" + "\tmov r3, r8\n" + "\tadds r3, 0x2\n" + "_0800F686:\n" + "\tldrb r1, [r2, 0x1]\n" + "\tlsls r1, 8\n" + "\tldrb r0, [r2]\n" + "\torrs r0, r1\n" + "\tstrh r0, [r3]\n" + "\tadds r2, 0x2\n" + "\tadds r3, 0x2\n" + "\tadds r4, 0x1\n" + "\tcmp r4, 0x6\n" + "\tble _0800F686\n" + "\tmovs r4, 0\n" + "\tldr r2, =gUnknown_03000D90\n" + "\tldr r1, =gUnknown_03000D80\n" + "_0800F6A0:\n" + "\tldrh r0, [r2]\n" + "\tlsrs r0, 8\n" + "\tstrb r0, [r1, 0x1]\n" + "\tldrh r0, [r2]\n" + "\tstrb r0, [r1]\n" + "\tadds r2, 0x2\n" + "\tadds r1, 0x2\n" + "\tadds r4, 0x1\n" + "\tcmp r4, 0x6\n" + "\tble _0800F6A0\n" + "\tldr r0, =gUnknown_03005000+0x9E8\n" + "\tmov r1, r12\n" + "\tbl sub_800D888\n" + "\tmovs r1, 0x1\n" + "\tlsls r1, r5\n" + "\tmov r2, r9\n" + "\tldr r0, [r2, 0x78]\n" + "\torrs r0, r1\n" + "\tstr r0, [r2, 0x78]\n" + "_0800F6C8:\n" + "\tadds r1, r7, 0\n" + "\tadds r5, r6, 0\n" + "\tldr r3, =gUnknown_03005000+0x6E\n" + "\tldrh r3, [r3]\n" + "\tcmp r5, r3\n" + "\tblt _0800F65A\n" + "_0800F6D4:\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800F6FC(u8 a0) +{ + if (gUnknown_03005000.unk_0c == 1 && a0) + gUnknown_03005000.unk_61[a0] = 1; + else + gUnknown_03005000.unk_5c[a0] = 1; +} + +void sub_800F728(u8 a0) +{ + gUnknown_03005000.unk_5c[a0] = 0; + gUnknown_03005000.unk_80[a0].unk_12 = 0; +} + +u8 sub_800F74C(const u8 *a0) +{ + u8 i; + + if (gUnknown_03005000.unk_0c == 1) + return FALSE; + for (i = 0; i < 4; i++) + { + gUnknown_03005000.unk_cde[i] = a0[i]; + } + return a0[gUnknown_03005000.unk_c3e]; +} + +void rfu_func_080F97B8(void) +{ + if (gReceivedRemoteLinkPlayers && gUnknown_03005DA8 && gLinkTransferringData != 1) + { + gUnknown_03000D78[0]++; + gUnknown_03005DA8 |= (gUnknown_03000D78[0] << 8); + sub_800FD14(0xbe00); + } +} + +struct UnkLinkRfuStruct_02022B14 *sub_800F7DC(void) +{ + return &gUnknown_02022B14; +} + +bool32 sub_800F7E4(void) +{ + return gUnknown_03005000.unk_00 == rfu_func_080F97B8; +} + +void sub_800F804(void) +{ + gUnknown_03005000.unk_00 = rfu_func_080F97B8; +} + +void Rfu_set_zero(void) +{ + gUnknown_03005000.unk_00 = NULL; +} + +void sub_800F820(void) +{ + sub_800FD14(0x4400); + if (GetMultiplayerId() == 0) + gSendCmd[6] = GetBlenderArrowPosition(); + gUnknown_020223C0++; +} + +void sub_800F850(void) +{ + if (gUnknown_03005000.unk_00 == NULL) + gUnknown_03005000.unk_00 = sub_800F820; +} + +static void sub_800F86C(u8 unused) +{ + u16 i; + u16 j; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + switch (gRecvCmds[i][0] & 0xff00) + { + case 0x7800: + if (gUnknown_03005000.unk_0c == 0 && gReceivedRemoteLinkPlayers != 0) + return; + // fallthrough + case 0x7700: + if (gUnknown_03007890->unk_00 == 0) + { + gUnknown_03005000.playerCount = gRecvCmds[i][1]; + gUnknown_03005000.unk_cce = sub_800F74C((u8 *)(gRecvCmds[i] + 2)); + } + break; + case 0x8800: + if (gUnknown_03005000.unk_80[i].unk_12 == 0) + { + gUnknown_03005000.unk_80[i].unk_00 = 0; + gUnknown_03005000.unk_80[i].unk_02 = gRecvCmds[i][1]; + gUnknown_03005000.unk_80[i].unk_11 = gRecvCmds[i][2]; + gUnknown_03005000.unk_80[i].unk_08 = 0; + gUnknown_03005000.unk_80[i].unk_12 = 1; + gUnknown_03005000.unk_5c[i] = 0; + } + break; + case 0x8900: + if (gUnknown_03005000.unk_80[i].unk_12 == 1) + { + gUnknown_03005000.unk_80[i].unk_00 = gRecvCmds[i][0] & 0xff; + gUnknown_03005000.unk_80[i].unk_08 |= (1 << gUnknown_03005000.unk_80[i].unk_00); + for (j = 0; j < 6; j++) + gBlockRecvBuffer[i][gUnknown_03005000.unk_80[i].unk_00 * 6 + j] = gRecvCmds[i][j + 1]; + if (gUnknown_03005000.unk_80[i].unk_08 == gUnknown_082ED628[gUnknown_03005000.unk_80[i].unk_02]) + { + gUnknown_03005000.unk_80[i].unk_12 = 2; + sub_800F6FC(i); + if (sub_800F7DC()->unk_0a_0 == 0x45 && gReceivedRemoteLinkPlayers != 0 && gUnknown_03005000.unk_0c == 0) + sub_8010A70(gBlockRecvBuffer); + } + } + break; + case 0xa100: + sub_800FE84(gUnknown_082ED6B8[gRecvCmds[i][1]].buffer, (u16)gUnknown_082ED6B8[gRecvCmds[i][1]].size); + break; + case 0x5f00: + gUnknown_03005000.unk_e4[i] = 1; + break; + case 0x6600: + if (gUnknown_03005000.unk_100 == gRecvCmds[i][1]) + gUnknown_03005000.unk_e9[i] = 1; + break; + case 0xed00: + if (gUnknown_03005000.unk_0c == 0) + { + if (gReceivedRemoteLinkPlayers != 0) + { + if (gRecvCmds[i][1] & gUnknown_03007890->unk_02) + { + gReceivedRemoteLinkPlayers = 0; + sub_800D630(); + gUnknown_03005000.unk_ce4 = gRecvCmds[i][2]; + } + gUnknown_03005000.playerCount = gRecvCmds[i][3]; + sub_80109E8(gRecvCmds[i][1]); + } + } + else + { + sub_800FD14(0xee00); + gSendCmd[1] = gRecvCmds[i][1]; + gSendCmd[2] = gRecvCmds[i][2]; + gSendCmd[3] = gRecvCmds[i][3]; + } + break; + case 0xee00: + if (gUnknown_03005000.unk_0c == 1) + { + gUnknown_03005000.unk_ce3 |= gRecvCmds[i][1]; + gUnknown_03005000.unk_ce4 = gRecvCmds[i][2]; + sub_80109E8(gRecvCmds[i][1]); + } + break; + case 0x4400: + case 0xbe00: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + } + if (gUnknown_03005000.unk_0c == 1 && gUnknown_03005000.unk_61[i]) + { + if (gUnknown_03005000.unk_61[i] == 4) + { + gUnknown_03005000.unk_5c[i] = 1; + gUnknown_03005000.unk_61[i] = 0; + } + else + gUnknown_03005000.unk_61[i]++; + } + } +} + +bool8 sub_800FC60(void) +{ + int i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12) + return FALSE; + } + return TRUE; +} + +bool8 sub_800FC88(void) +{ + int i; + + for (i = 0; i < gUnknown_03005000.playerCount; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12 != 2 || gUnknown_03005000.unk_5c[i] != 1) + return FALSE; + } + return TRUE; +} + +static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data) +{ + data->unk_00 = 0; + data->unk_02 = 0; + data->unk_04 = NULL; + data->unk_08 = 0; + data->unk_10 = 0; + data->unk_11 = 0; + data->unk_12 = 0; +} + +u8 sub_800FCD8(void) +{ + u8 flags = 0; + int i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12 == 2 && gUnknown_03005000.unk_5c[i] == 1) + { + flags |= (1 << i); + } + } + return flags; +} + +#ifdef NONMATCHING +// The switch tree is incorrect +void sub_800FD14(u16 command) +{ + u8 i; + u8 *buff; + u8 tmp; + + gSendCmd[0] = command; + switch (command) + { + case 0x8800: + gSendCmd[1] = gUnknown_03005000.unk_6c.unk_02; + gSendCmd[2] = gUnknown_03005000.unk_6c.unk_11 + 0x80; + break; + case 0xa100: + if (sub_800FC60()) + gSendCmd[1] = gUnknown_03005000.unk_5a; + break; + case 0x7800: + case 0x7700: + tmp = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3; + gUnknown_03005000.playerCount = gUnknown_082ED695[tmp] + 1; + gSendCmd[1] = gUnknown_03005000.playerCount; + buff = (u8 *)(gSendCmd + 2); + for (i = 0; i < 4; i++) + buff[i] = gUnknown_03005000.unk_cde[i]; + break; + case 0x6600: + case 0x5f00: + gSendCmd[1] = gUnknown_03005000.unk_100; + break; + case 0x4400: + gSendCmd[0] = 0x4400; + gSendCmd[1] = gMain.heldKeys; + break; + case 0x2f00: + for (i = 0; i < 6; i++) + gSendCmd[1 + i] = gUnknown_03005000.unk_f2[i]; + break; + case 0xbe00: + gSendCmd[1] = gUnknown_03005DA8; + break; + } +} +#else +__attribute__((naked)) void sub_800FD14(u16 command) +{ + asm_unified("\tpush {r4,r5,lr}\n" + "\tlsls r0, 16\n" + "\tlsrs r1, r0, 16\n" + "\tldr r5, =gSendCmd\n" + "\tstrh r1, [r5]\n" + "\tmovs r0, 0xF0\n" + "\tlsls r0, 7\n" + "\tadds r4, r5, 0\n" + "\tcmp r1, r0\n" + "\tbeq _0800FDB0_case_7700_case_7800\n" + "\tcmp r1, r0\n" + "\tbgt _0800FD62\n" + "\tmovs r0, 0xBE\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE00_case_5f00_case_6600\n" + "\tcmp r1, r0\n" + "\tbgt _0800FD50\n" + "\tmovs r0, 0xBC\n" + "\tlsls r0, 6\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE20_case_2f00\n" + "\tmovs r0, 0x88\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE14_case_4400\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FD50:\n" + "\tmovs r0, 0xCC\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE00_case_5f00_case_6600\n" + "\tmovs r0, 0xEE\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FDB0_case_7700_case_7800\n" + "\tb _0800FE46_break\n" + "_0800FD62:\n" + "\tmovs r0, 0xBE\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE40_case_be00\n" + "\tcmp r1, r0\n" + "\tbgt _0800FE46_break\n" + "\tmovs r0, 0x88\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FD80_case_8800\n" + "\tmovs r0, 0xA1\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FD98_case_a100\n" + "\tb _0800FE46_break\n" + "_0800FD80_case_8800:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r1, r0, 0\n" + "\tadds r1, 0x6E\n" + "\tldrh r1, [r1]\n" + "\tstrh r1, [r5, 0x2]\n" + "\tadds r0, 0x7D\n" + "\tldrb r0, [r0]\n" + "\tadds r0, 0x80\n" + "\tstrh r0, [r5, 0x4]\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FD98_case_a100:\n" + "\tbl sub_800FC60\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _0800FE46_break\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r0, 0x5A\n" + "\tldrb r0, [r0]\n" + "\tb _0800FE44_str_break\n" + "\t.pool\n" + "_0800FDB0_case_7700_case_7800:\n" + "\tldr r3, =gUnknown_03005000\n" + "\tldr r1, =0x00000ce2\n" + "\tadds r0, r3, r1\n" + "\tldr r2, =0x00000ce3\n" + "\tadds r1, r3, r2\n" + "\tldrb r2, [r0]\n" + "\tldrb r0, [r1]\n" + "\teors r0, r2\n" + "\tldr r1, =gUnknown_082ED695\n" + "\tadds r0, r1\n" + "\tldrb r0, [r0]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r3, 0xD]\n" + "\tldrb r0, [r3, 0xD]\n" + "\tstrh r0, [r4, 0x2]\n" + "\tadds r2, r4, 0x4\n" + "\tmovs r4, 0\n" + "\tldr r0, =0x00000cde\n" + "\tadds r3, r0\n" + "_0800FDD6:\n" + "\tadds r1, r2, r4\n" + "\tadds r0, r4, r3\n" + "\tldrb r0, [r0]\n" + "\tstrb r0, [r1]\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tcmp r4, 0x3\n" + "\tbls _0800FDD6\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE00_case_5f00_case_6600:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tmovs r1, 0x80\n" + "\tlsls r1, 1\n" + "\tadds r0, r1\n" + "\tldrh r0, [r0]\n" + "\tstrh r0, [r4, 0x2]\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE14_case_4400:\n" + "\tstrh r1, [r5]\n" + "\tldr r0, =gMain\n" + "\tldrh r0, [r0, 0x2C]\n" + "\tb _0800FE44_str_break\n" + "\t.pool\n" + "_0800FE20_case_2f00:\n" + "\tmovs r4, 0\n" + "\tldr r3, =gUnknown_03005000+0xF2\n" + "_0800FE24:\n" + "\tadds r2, r4, 0x1\n" + "\tlsls r1, r2, 1\n" + "\tadds r1, r5\n" + "\tlsls r0, r4, 1\n" + "\tadds r0, r3\n" + "\tldrh r0, [r0]\n" + "\tstrh r0, [r1]\n" + "\tlsls r2, 24\n" + "\tlsrs r4, r2, 24\n" + "\tcmp r4, 0x5\n" + "\tbls _0800FE24\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE40_case_be00:\n" + "\tldr r0, =gUnknown_03005DA8\n" + "\tldrh r0, [r0]\n" + "_0800FE44_str_break:\n" + "\tstrh r0, [r5, 0x2]\n" + "_0800FE46_break:\n" + "\tpop {r4,r5}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800FE50(u16 *a0) +{ + if (gSendCmd[0] == 0 && sub_8011A80() == 0) + { + memcpy(gUnknown_03005000.unk_f2, a0, sizeof(gUnknown_03005000.unk_f2)); + sub_800FD14(0x2f00); + } +} + +bool32 sub_800FE84(const u8 *src, size_t size) +{ + bool8 r4; + if (gUnknown_03005000.unk_00 != NULL) + return FALSE; + if (gSendCmd[0] != 0) + return FALSE; + if (gUnknown_03005000.unk_6c.unk_10 != 0) + { + gUnknown_02022B44.unk_83++; + return FALSE; + } + r4 = (size % 12) != 0; + gUnknown_03005000.unk_6c.unk_11 = GetMultiplayerId(); + gUnknown_03005000.unk_6c.unk_10 = 1; + gUnknown_03005000.unk_6c.unk_02 = (size / 12) + r4; + gUnknown_03005000.unk_6c.unk_00 = 0; + if (size > 0x100) + gUnknown_03005000.unk_6c.unk_04 = src; + else + { + if (src != gBlockSendBuffer) + memcpy(gBlockSendBuffer, src, size); + gUnknown_03005000.unk_6c.unk_04 = gBlockSendBuffer; + } + sub_800FD14(0x8800); + gUnknown_03005000.unk_00 = rfufunc_80F9F44; + gUnknown_03005000.unk_5b = 0; + return TRUE; +} + +static void rfufunc_80F9F44(void) +{ + if (gSendCmd[0] == 0) + { + sub_800FD14(0x8800); + if (gUnknown_03005000.unk_0c == 1) + { + if (++gUnknown_03005000.unk_5b > 2) + gUnknown_03005000.unk_00 = sub_800FFB0; + } + else + { + if ((gRecvCmds[GetMultiplayerId()][0] & 0xff00) == 0x8800) + gUnknown_03005000.unk_00 = sub_800FFB0; + } + } +} + +static void sub_800FFB0(void) +{ + int i; + const u8 *src = gUnknown_03005000.unk_6c.unk_04; + gSendCmd[0] = 0x8900 | gUnknown_03005000.unk_6c.unk_00; + for (i = 0; i < 7; i++) + gSendCmd[i + 1] = (src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 1] << 8) | src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 0]; + gUnknown_03005000.unk_6c.unk_00++; + if (gUnknown_03005000.unk_6c.unk_02 <= gUnknown_03005000.unk_6c.unk_00) + { + gUnknown_03005000.unk_6c.unk_10 = 0; + gUnknown_03005000.unk_00 = rfufunc_80FA020; + } +} + +static void rfufunc_80FA020(void) +{ + const u8 *src = gUnknown_03005000.unk_6c.unk_04; + u8 mpId = GetMultiplayerId(); + int i; + if (gUnknown_03005000.unk_0c == 0) + { + gSendCmd[0] = (~0x76ff) | (gUnknown_03005000.unk_6c.unk_02 - 1); + for (i = 0; i < 7; i++) + gSendCmd[i + 1] = (src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 1] << 8) | src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 0]; + if ((u8)gRecvCmds[mpId][0] == gUnknown_03005000.unk_6c.unk_02 - 1) + { + if (gUnknown_03005000.unk_80[mpId].unk_08 != gUnknown_082ED628[gUnknown_03005000.unk_80[mpId].unk_02]) + { + sub_800F638(mpId, gUnknown_03005000.unk_80[mpId].unk_08); + gUnknown_02022B44.unk_64++; + } + else + gUnknown_03005000.unk_00 = NULL; + } + } + else + gUnknown_03005000.unk_00 = NULL; +} + +bool8 sub_8010100(u8 a0) +{ + gUnknown_03005000.unk_5a = a0; + sub_800FD14(0xa100); + return TRUE; +} + +void sub_801011C(void) +{ + rfu_clearAllSlot(); + sub_800C048(); + gReceivedRemoteLinkPlayers = 0; + gUnknown_03005000.unk_ef = 1; + gUnknown_03005000.unk_00 = NULL; +} + +void sub_8010148(void) +{ + rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + rfu_waitREQComplete(); + sub_801011C(); +} + +void sub_8010168(void) +{ + if (gUnknown_03005000.unk_0c == 0) + { + sub_800D630(); + gUnknown_03005000.unk_ce4 = 2; + } + else + gUnknown_03005000.unk_00 = sub_8010148; +} + +void sub_8010198(void) +{ + sub_800D630(); + gUnknown_03005000.unk_ce4 = 1; + gUnknown_03005000.unk_ce3 = gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03; +} + +void sub_80101CC(void) +{ + int i; + u8 playerCount = gUnknown_03005000.playerCount; + int count = 0; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + if (gUnknown_03005000.unk_e4[i]) + count++; + } + if (count == playerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + if (gUnknown_03005000.unk_0c == 0) + { + gUnknown_03005000.unk_ee = 3; + sub_8010168(); + } + else + gUnknown_03005000.unk_00 = sub_8010168; + } +} + +void sub_801022C(void) +{ + if (gSendCmd[0] == 0 && gUnknown_03005000.unk_ce8 == 0) + { + sub_800FD14(0x5f00); + gUnknown_03005000.unk_00 = sub_80101CC; + } +} + +void sub_8010264(u8 taskId) +{ + if (gUnknown_03005000.unk_00 == NULL) + { + gUnknown_03005000.unk_cd9 = 1; + gUnknown_03005000.unk_00 = sub_801022C; + DestroyTask(taskId); + } +} + +void task_add_05_task_del_08FA224_when_no_RfuFunc(void) +{ + if (!FuncIsActiveTask(sub_8010264)) + CreateTask(sub_8010264, 5); +} + +void sub_80102B8(void) +{ + u8 playerCount; + u8 i; + + if (GetMultiplayerId() != 0) + { + u8 r4 = gUnknown_03005000.unk_124.unk_8c2; + if (r4 == 0 && gUnknown_03005000.unk_fe > 0x3c) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_fe = r4; + } + } + playerCount = GetLinkPlayerCount(); + for (i = 0; i < playerCount; i++) + { + if (gUnknown_03005000.unk_e9[i] == 0) + break; + } + if (i == playerCount) + { + for (i = 0; i < MAX_RFU_PLAYERS; i++) + gUnknown_03005000.unk_e9[i] = 0; + gUnknown_03005000.unk_100++; + gUnknown_03005000.unk_00 = NULL; + } + gUnknown_03005000.unk_fe++; +} + +void sub_8010358(void) +{ + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_80102B8; + } +} + +void sub_8010390(void) +{ + u8 i; + u8 playerCount; + + if (GetMultiplayerId() != 0) + { + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_80102B8; + } + } + else + { + playerCount = GetLinkPlayerCount(); + for (i = 1; i < playerCount; i++) + { + if (gUnknown_03005000.unk_e9[i] == 0) + break; + } + if (i == playerCount) + { + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_8010358; + } + } + } +} + +void sub_8010434(void) +{ + if (gUnknown_03005000.unk_00 == NULL) + { + gUnknown_03005000.unk_00 = sub_8010390; + gUnknown_03005000.unk_fe = 0; + } +} + +bool32 sub_8010454(u32 a0) +{ + int i; + for (i = 0; gUnknown_082ED6E0[i] != a0; i++) + { + if (gUnknown_082ED6E0[i] == 0xffff) + return FALSE; + } + return TRUE; +} + +u8 sub_801048C(bool32 a0) +{ + if (a0 == 0) + return sub_800D550(0, 0); + sub_800D550(1, 0x258); + return FALSE; +} + +void sub_80104B0(void) +{ + gUnknown_03005000.unk_cd9 = 1; + sub_800C27C(FALSE); +} + +u8 rfu_get_multiplayer_id(void) +{ + if (gUnknown_03005000.unk_0c == 1) + return 0; + return gUnknown_03005000.unk_cce; +} + +u8 sub_80104F4(void) +{ + return gUnknown_03005000.playerCount; +} + +bool8 sub_8010500(void) +{ + if (gUnknown_03005000.unk_f1 == 2) + return FALSE; + return gUnknown_03005000.unk_00 ? FALSE : TRUE; +} + +static void sub_8010528(void) +{ + if (gUnknown_03005000.unk_00) + gUnknown_03005000.unk_00(); +} + +bool8 sub_8010540(void) +{ + int i; + bool8 retval = FALSE; + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd1[i] < 5 || gUnknown_03005000.unk_cd1[i] > 6) + { + if (gUnknown_03007880[i]->unk_34 == 0x46 || gUnknown_03007880[i]->unk_34 == 0x48) + { + if (gUnknown_03005000.unk_cd5[i] == 8) + { + gUnknown_03005000.unk_cd1[i] = 9; + gUnknown_03005000.unk_cd5[i] = 10; + rfu_clearSlot(8, i); + rfu_NI_setSendData(1 << i, 8, gUnknown_03005000.unk_cd1 + i, 1); + retval = TRUE; + } + + } + else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47) + rfu_clearSlot(8, i); + { + + } + } + } + return retval; +} + +bool8 sub_80105EC(void) +{ + u8 flags = 0; + int i; + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd5[i] == 11) + { + flags |= (1 << i); + gUnknown_03005000.unk_cd5[i] = 0; + } + } + if (flags) + { + rfu_REQ_disconnect(flags); + rfu_waitREQComplete(); + } + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd5[i] == 10 || gUnknown_03005000.unk_cd5[i] == 11) + return TRUE; + } + return FALSE; +} + +bool8 sub_801064C(u16 a0, const u8 *a1) +{ + u8 r1 = sub_8011CE4(a1, a0); + if (r1 == 0xFF) + return TRUE; + if (gUnknown_03005000.unk_cd1[r1] == 9) + return TRUE; + return FALSE; +} + +void sub_8010688(u8 a0, u16 a1, const u8 *a2) +{ + u8 r4 = sub_8011CE4(a2, a1); + gUnknown_03005000.unk_cd1[r4] = a0; + rfu_clearSlot(4, r4); + rfu_NI_setSendData(1 << r4, 8, gUnknown_03005000.unk_cd1 + r4, 1); +} + +void sub_80106D4(void) +{ + gUnknown_03005000.unk_c85 = 8; + rfu_clearSlot(4, gUnknown_03005000.unk_c3e); + rfu_NI_setSendData(1 << gUnknown_03005000.unk_c3e, 8, &gUnknown_03005000.unk_c85, 1); +} + +u8 sub_8010714(u16 a0, const u8 *a1) +{ + u8 r0 = sub_8011CE4(a1, a0); + if (r0 == 0xff) + return 2; + if (gUnknown_03007880[r0]->unk_0 == 0) + return TRUE; + return FALSE; +} + +void sub_8010750(void) +{ + int i; + + sub_8010540(); + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_0 == 0x26 || gUnknown_03007880[i]->unk_0 == 0x27) + { + if (gUnknown_03005000.unk_cd5[i] == 10) + gUnknown_03005000.unk_cd5[i] = 11; + rfu_clearSlot(4, i); + } + } +} + +int sub_80107A0(void) +{ + int retval = 0; + if (gUnknown_03005000.unk_c85 == 8) + { + if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x26 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x27) + rfu_clearSlot(4, gUnknown_03005000.unk_c3e); + } + if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x46 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x48) + { + rfu_clearSlot(8, gUnknown_03005000.unk_c3e); + sub_8011A64(gUnknown_03005000.unk_c86, 0); + retval = gUnknown_03005000.unk_c86; + } + else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47) + { + rfu_clearSlot(8, gUnknown_03005000.unk_c3e); + retval = 6; + } + return retval; +} + +void sub_801084C(u8 taskId) +{ + int i; + + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + { + gUnknown_03005000.unk_ce8 = 0; + DestroyTask(taskId); + } + switch (gTasks[taskId].data[0]) + { + case 0: + if (sub_800FC60()) + { + ResetBlockReceivedFlags(); + sub_800B348(); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (gUnknown_03005000.unk_0c == 1) + { + if (gReceivedRemoteLinkPlayers) + sub_800FD14(0x7800); + else + sub_800FD14(0x7700); + gTasks[taskId].data[0] = 101; + } + else + gTasks[taskId].data[0] = 2; + break; + case 101: + if (gSendCmd[0] == 0) + gTasks[taskId].data[0] = 2; + break; + case 2: + if (gUnknown_03005000.playerCount) + gTasks[taskId].data[0]++; + break; + case 3: + if (gUnknown_03005000.unk_0c == 1) + { + if (sub_800FC60()) + { + gUnknown_03005000.unk_5a = 0; + sub_800FD14(0xa100); + gTasks[taskId].data[0]++; + } + } + else + gTasks[taskId].data[0]++; + break; + case 4: + if (sub_800FC88()) + gTasks[taskId].data[0]++; + break; + case 5: + for (i = 0; i < gUnknown_03005000.playerCount; i++) + { + sub_800B3A4(i); + sub_800F728(i); + } + gTasks[taskId].data[0]++; + break; + case 6: + DestroyTask(taskId); + gReceivedRemoteLinkPlayers = 1; + gUnknown_03005000.unk_ce8 = 0; + sub_800D550(1, 0x258); + if (gUnknown_03005000.unk_ce6) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce6 >> i) & 1) + { + gUnknown_03005000.unk_ce5 = 1 << i; + gUnknown_03005000.unk_ce6 ^= (1 << i); + } + } + } + break; + } +} + +void sub_80109E8(u16 a0) +{ + int i; + + for (i = 0; i < 4; i++) + { + if ((a0 >> i) & 1) + gUnknown_03005000.unk_cde[i] = 0; + } +} + +void sub_8010A14(const struct UnkRfuStruct_8010A14 *a0) +{ + int i; + gUnknown_03005000.playerCount = a0->unk_0f; + for (i = 0; i < 4; i++) + gUnknown_03005000.unk_cde[i] = a0->unk_10[i]; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + gLinkPlayers[i] = a0->unk_14[i]; + sub_800B524(gLinkPlayers + i); + } +} + +void sub_8010A70(void *a0) +{ + if (strcmp(gUnknown_082ED7EC, a0) == 0) + { + sub_8010A14(a0); + CpuFill16(0, a0, sizeof(struct UnkRfuStruct_8010A14)); + ResetBlockReceivedFlag(0); + } +} + +void sub_8010AAC(u8 taskId) +{ + int i; + struct LinkPlayerBlock *r2; + struct UnkRfuStruct_8010A14 *r5; + u8 r4 = gUnknown_03005000.unk_cde[gUnknown_082ED68C[gUnknown_03005000.unk_ce9]]; + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + { + gUnknown_03005000.unk_ce8 = 0; + DestroyTask(taskId); + } + switch (gTasks[taskId].data[0]) + { + case 0: + if (gSendCmd[0] == 0) + { + ResetBlockReceivedFlag(r4); + sub_800FD14(0x7800); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (gSendCmd[0] == 0) + gTasks[taskId].data[0]++; + break; + case 2: + if ((GetBlockReceivedStatus() >> r4) & 1) + { + ResetBlockReceivedFlag(r4); + r2 = (struct LinkPlayerBlock *)gBlockRecvBuffer[r4]; + gLinkPlayers[r4] = r2->linkPlayer; + sub_800B524(gLinkPlayers + r4); + gTasks[taskId].data[0]++; + } + break; + case 3: + r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer; + memcpy(r5->unk_00, gUnknown_082ED7EC, sizeof gUnknown_082ED7EC); + r5->unk_0f = gUnknown_03005000.playerCount; + for (i = 0; i < 4; i++) + r5->unk_10[i] = gUnknown_03005000.unk_cde[i]; + memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers); + gTasks[taskId].data[0]++; + // fallthrough + case 4: + r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer; + r5->unk_0f = gUnknown_03005000.playerCount; + for (i = 0; i < 4; i++) + r5->unk_10[i] = gUnknown_03005000.unk_cde[i]; + memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers); + if (SendBlock(0, gBlockSendBuffer, 0xa0)) + gTasks[taskId].data[0]++; + break; + case 5: + if (sub_800A520() && GetBlockReceivedStatus() & 1) + { + CpuFill16(0, gBlockRecvBuffer, sizeof(struct UnkRfuStruct_8010A14)); + ResetBlockReceivedFlag(0); + gUnknown_03005000.unk_ce8 = 0; + if (gUnknown_03005000.unk_ce6) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce6 >> i) & 1) + { + gUnknown_03005000.unk_ce5 = 1 << i; + gUnknown_03005000.unk_ce6 ^= (1 << i); + gUnknown_03005000.unk_ce8 = 1; + break; + } + } + } + DestroyTask(taskId); + } + break; + } +} + +void sub_8010D0C(u8 taskId) +{ + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + DestroyTask(taskId); + switch (gTasks[taskId].data[0]) + { + case 0: + if (gUnknown_03005000.playerCount) + { + sub_800B348(); + SendBlock(0, gBlockSendBuffer, sizeof(struct LinkPlayerBlock)); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (sub_800A520()) + gTasks[taskId].data[0]++; + break; + case 2: + if (GetBlockReceivedStatus() & 1) + { + sub_8010A14((const struct UnkRfuStruct_8010A14 *)gBlockRecvBuffer); + ResetBlockReceivedFlag(0); + gReceivedRemoteLinkPlayers = 1; + DestroyTask(taskId); + } + break; + } +} + +void sub_8010DB4(void) +{ + if (gUnknown_03005000.unk_ee == 1 && gUnknown_03004140.unk_02 == 0) + { + if (gMain.callback2 == sub_8018438 || gUnknown_03004140.unk_3c->unk_04) + gWirelessCommType = 2; + SetMainCallback2(CB2_LinkError); + gMain.savedCallback = CB2_LinkError; + sub_800AF18((gUnknown_03005000.unk_0a << 16) | (gUnknown_03005000.unk_10 << 8) | gUnknown_03005000.unk_12, gUnknown_03005000.unk_124.unk_8c2, gUnknown_03005000.unk_9e8.unk_232, sub_8011A74() == 2); + gUnknown_03005000.unk_ee = 2; + CloseLink(); + } + else if (gUnknown_03005000.unk_9e8.unk_233 == 1 || gUnknown_03005000.unk_124.unk_8c3 == 1) + { + if (gUnknown_03004140.unk_02) + sub_800D630(); + sub_8011A64(1, 0x7000); + sub_8011170(0x7000); + } +} + +void rfu_REQ_recvData_then_sendData(void) +{ + if (gUnknown_03004140.unk_06 == 1) + { + rfu_REQ_recvData(); + rfu_waitREQComplete(); + rfu_REQ_sendData_wrapper(0); + } +} + +bool32 sub_8010EC0(void) +{ + bool32 retval = FALSE; + gUnknown_03005000.unk_ccd = 0; + sub_800C54C(Random2()); + if (gUnknown_03005000.unk_ef == 0) + { + switch (gUnknown_03005000.unk_0c) + { + case 1: + sub_800F0F8(); + break; + case 0: + retval = sub_800F4F0(); + break; + case 2: + rfu_REQ_recvData_then_sendData(); + break; + } + } + return retval; +} + +bool32 sub_8010F1C(void) +{ + bool32 retval = FALSE; + if (gUnknown_03005000.unk_ef == 0) + { + if (gUnknown_03005000.unk_0c == 1) + retval = sub_800F1E0(); + sub_8010DB4(); + } + return retval; +} + +void sub_8010F48(void) +{ + StringCopy(gUnknown_02022B22, gSaveBlock2Ptr->playerName); +} + +void sub_8010F60(void) +{ + gUnknown_02022B14 = (struct UnkLinkRfuStruct_02022B14){}; + sub_800DD94(&gUnknown_02022B14, 0, 0, 0); +} + +void sub_8010F84(u8 a0, u32 a1, u32 a2) +{ + sub_800DD94(&gUnknown_02022B14, a0, a2, a1); +} + +void sub_8010FA0(bool32 a0, bool32 a1) +{ + gUnknown_02022B14.unk_00_4 = a0; + gUnknown_02022B14.unk_00_5 = a1; +} + +void sub_8010FCC(u32 a0, u32 a1, u32 a2) +{ + gUnknown_02022B14.unk_09_2 = a0; + gUnknown_02022B14.unk_08_0 = a1; + gUnknown_02022B14.unk_0b_1 = a2; +} + +u8 sub_801100C(int a0) +{ + u8 retval = 0x80; + retval |= (gLinkPlayers[a0].gender << 3); + retval |= (gLinkPlayers[a0].trainerId & 7); + return retval; +} + +void sub_801103C(void) +{ + struct UnkLinkRfuStruct_02022B14 *r5 = &gUnknown_02022B14; + int i; + + for (i = 1; i < GetLinkPlayerCount(); i++) + r5->unk_04[i - 1] = sub_801100C(i); +} + +void sub_8011068(u8 a0) +{ + gUnknown_02022B14.unk_0a_7 = a0; + rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22); +} + +void sub_8011090(u8 a0, u32 a1, u32 a2) +{ + if (a0) + sub_8010F84(a0, a1, a2); + rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22); +} + +void sub_80110B8(u32 a0) +{ + int i; + u32 r5; + u32 r7; + int r8; + + if (sub_800F7DC()->unk_0a_0 == 0x45) + { + r5 = 0; + r7 = 0; + r8 = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3; + for (i = 0; i < 4; i++) + { + if ((r8 >> i) & 1) + { + r7 |= ((0x80 | ((gLinkPlayers[gUnknown_03005000.unk_cde[i]].gender & 1) << 3) | (gLinkPlayers[gUnknown_03005000.unk_cde[i]].trainerId & 7)) << (r5 << 3)); + r5++; + if (r5 == a0 - 1) + break; + } + } + sub_8011090(0x45, r7, 0); + } +} + +void sub_8011170(u32 a0) +{ + if (gUnknown_03005000.unk_ee == 0) + { + gUnknown_03005000.unk_10 = gUnknown_03004140.unk_14; + gUnknown_03005000.unk_12 = gUnknown_03004140.unk_16; + gUnknown_03005000.unk_0a = a0; + gUnknown_03005000.unk_ee = 1; + } +} + +void sub_80111A0(void) +{ + gUnknown_03005000.unk_ee = 0; +} + +void sub_80111B0(bool32 a0) +{ + if (!a0) + gUnknown_03005000.unk_ee = 0; + else + gUnknown_03005000.unk_ee = 4; +} + +void sub_80111DC(void) +{ + sub_8011E94(gUnknown_03004140.unk_00, 1); + gUnknown_03005000.unk_00 = NULL; +} + +void sub_80111FC(void) +{ + gUnknown_03005000.unk_00 = sub_80111DC; +} diff --git a/src/main.c b/src/main.c index 07b7d9147..822aeda21 100644 --- a/src/main.c +++ b/src/main.c @@ -1,50 +1,30 @@ #include "global.h" -#include "main.h" +#include "crt0.h" +#include "malloc.h" +#include "link.h" +#include "link_rfu.h" +#include "librfu.h" #include "m4a.h" +#include "bg.h" #include "rtc.h" +#include "unknown_task.h" +#include "overworld.h" +#include "play_time.h" #include "random.h" #include "dma3.h" #include "gba/flash_internal.h" +#include "load_save.h" +#include "gpu_regs.h" +#include "agb_flash.h" +#include "sound.h" #include "battle.h" +#include "battle_controllers.h" +#include "text.h" +#include "intro.h" +#include "main.h" -extern u16 GetGpuReg(u8); -extern void SetGpuReg(u8, u16); -extern void LinkVSync(void); -extern void sub_800E174(void); -extern void sub_800B9B8(void); -extern void InitGpuRegManager(void); -extern void sub_800E6D0(void); -extern void CheckForFlashMemory(void); -extern void InitMapMusic(void); -extern void ResetBgs(void); -extern void SetDefaultFontsPointer(void); -extern void InitHeap(void *heapStart, u32 heapSize); // malloc.h -extern void rfu_REQ_stopMode(void); -extern void rfu_waitREQComplete(void); -extern bool32 sub_8087634(void); -extern bool32 sub_80875C8(void); -extern void ClearSpriteCopyRequests(void); -extern void PlayTimeCounter_Update(void); -extern void MapMusicMain(void); -extern void EnableInterrupts(u16); -extern void sub_8033648(void); -extern u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void)); -extern void remove_some_task(void); - -extern struct SoundInfo gSoundInfo; -extern u32 gFlashMemoryPresent; -extern u32 IntrMain[]; -extern u8 gHeap[]; -extern struct SaveBlock2 gSaveblock2; -extern struct PokemonStorage gPokemonStorage; -extern u32 gBattleTypeFlags; -extern u8 gUnknown_03002748; extern u32 *gUnknown_0203CF5C; -void Timer3Intr(void); -bool8 HandleLinkConnection(void); -void c2_copyright_1(void); - static void VBlankIntr(void); static void HBlankIntr(void); static void VCountIntr(void); @@ -79,19 +59,19 @@ const IntrFunc gIntrTableTemplate[] = static u16 gUnknown_03000000; -extern u16 gKeyRepeatStartDelay; -extern u8 gUnknown_030022B4; -extern struct Main gMain; -extern u16 gKeyRepeatContinueDelay; -extern u8 gSoftResetDisabled; -extern IntrFunc gIntrTable[INTR_COUNT]; -extern bool8 gLinkVSyncDisabled; -extern u32 IntrMain_Buffer[0x200]; -extern u8 gPcmDmaCounter; +u16 gKeyRepeatStartDelay; +bool8 gLinkTransferringData; +struct Main gMain; +u16 gKeyRepeatContinueDelay; +bool8 gSoftResetDisabled; +IntrFunc gIntrTable[INTR_COUNT]; +u8 gLinkVSyncDisabled; +u32 IntrMain_Buffer[0x200]; +u8 gPcmDmaCounter; -extern u16 gTrainerId; +static EWRAM_DATA u16 gTrainerId = 0; -EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL; +//EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL; static void UpdateLinkAndCallCallbacks(void); static void InitMainCallbacks(void); @@ -129,7 +109,7 @@ void AgbMain() if (gFlashMemoryPresent != TRUE) SetMainCallback2(NULL); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; gUnknown_03000000 = 0xFC0; for (;;) @@ -147,22 +127,22 @@ void AgbMain() if (sub_8087634() == 1) { - gUnknown_030022B4 = 1; + gLinkTransferringData = TRUE; UpdateLinkAndCallCallbacks(); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; } else { - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; UpdateLinkAndCallCallbacks(); if (sub_80875C8() == 1) { gMain.newKeys = 0; ClearSpriteCopyRequests(); - gUnknown_030022B4 = 1; + gLinkTransferringData = TRUE; UpdateLinkAndCallCallbacks(); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; } } @@ -335,10 +315,10 @@ extern void CopyBufferedValuesToGpuRegs(void); static void VBlankIntr(void) { - if (gLinkVSyncDisabled != FALSE) + if (gWirelessCommType != 0) + RfuVSync(); + else if (gLinkVSyncDisabled == FALSE) LinkVSync(); - else if (gUnknown_03002748 == FALSE) - sub_800B9B8(); gMain.vblankCounter1++; diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c index 3df2ff151..32c85a5ee 100644 --- a/src/reshow_battle_screen.c +++ b/src/reshow_battle_screen.c @@ -177,10 +177,10 @@ static void CB2_ReshowBattleScreenAfterMenu(void) ActionSelectionCreateCursorAt(gActionSelectionCursor[gBankInMenu], 0); - if (gLinkVSyncDisabled != 0 && gReceivedRemoteLinkPlayers != 0) + if (gWirelessCommType != 0 && gReceivedRemoteLinkPlayers != 0) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } } break; diff --git a/src/rom_8011DC0.c b/src/rom_8011DC0.c new file mode 100644 index 000000000..9076b611a --- /dev/null +++ b/src/rom_8011DC0.c @@ -0,0 +1,18 @@ + +// Includes +#include "global.h" + +// Static type declarations + +// Static RAM declarations +IWRAM_DATA u32 gUnknown_03000DA0; +IWRAM_DATA u32 gUnknown_03000DA4; +IWRAM_DATA void *gUnknown_03000DA8; +IWRAM_DATA void *gUnknown_03000DAC; +IWRAM_DATA bool32 gUnknown_03000DB0; + +// Static ROM declarations + +// .rodata + +// .text |