diff options
Diffstat (limited to 'src')
52 files changed, 9076 insertions, 4950 deletions
diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index 8dc939919..9fdd4d0c3 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -2089,12 +2089,7 @@ static void Cmd_get_used_held_item(void) else battlerId = gBattlerTarget; - // This is likely a leftover from Ruby's code and its ugly ewram access. - #ifdef NONMATCHING - AI_THINKING_STRUCT->funcResult = gBattleStruct->usedHeldItems[battlerId]; - #else - AI_THINKING_STRUCT->funcResult = *(u8*)((u8*)(gBattleStruct) + offsetof(struct BattleStruct, usedHeldItems) + (battlerId * 2)); - #endif // NONMATCHING + AI_THINKING_STRUCT->funcResult = *(u8 *)&gBattleStruct->usedHeldItems[battlerId]; gAIScriptPtr += 2; } diff --git a/src/battle_anim_fight.c b/src/battle_anim_fight.c index 05138111b..328f178ae 100644 --- a/src/battle_anim_fight.c +++ b/src/battle_anim_fight.c @@ -51,51 +51,43 @@ const struct SpriteTemplate gUnusedSpriteTemplate_08595E14 = .callback = AnimUnused_080B08A0, }; -static const union AnimCmd sAnim_HandOrFoot[] = +static const union AnimCmd sAnim_Fist[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END, }; -static const union AnimCmd sAnim_SlidingKick_0[] = +static const union AnimCmd sAnim_FootWide[] = { ANIMCMD_FRAME(16, 1), ANIMCMD_END, }; -static const union AnimCmd sAnim_SlidingKick_1[] = +static const union AnimCmd sAnim_FootTall[] = { ANIMCMD_FRAME(32, 1), ANIMCMD_END, }; -static const union AnimCmd sAnim_CrossChopHand_0[] = +static const union AnimCmd sAnim_HandLeft[] = { ANIMCMD_FRAME(48, 1), ANIMCMD_END, }; -static const union AnimCmd sAnim_CrossChopHand_1[] = +static const union AnimCmd sAnim_HandRight[] = { ANIMCMD_FRAME(48, 1, .hFlip = TRUE), ANIMCMD_END, }; -static const union AnimCmd *const sAnims_HandOrFoot[] = +static const union AnimCmd *const sAnims_HandsAndFeet[] = { - sAnim_HandOrFoot, -}; - -static const union AnimCmd *const sAnims_SlidingKick[] = -{ - sAnim_SlidingKick_0, - sAnim_SlidingKick_1, -}; - -static const union AnimCmd *const sAnims_CrossChopHand[] = -{ - sAnim_CrossChopHand_0, - sAnim_CrossChopHand_1, + sAnim_Fist, + sAnim_FootWide, + sAnim_FootTall, + sAnim_HandLeft, + sAnim_HandRight, }; const struct SpriteTemplate gKarateChopSpriteTemplate = @@ -103,7 +95,7 @@ const struct SpriteTemplate gKarateChopSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSlideHandOrFootToTarget, @@ -114,7 +106,7 @@ const struct SpriteTemplate gJumpKickSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimJumpKick, @@ -125,7 +117,7 @@ const struct SpriteTemplate gFistFootSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimBasicFistOrFoot, @@ -136,7 +128,7 @@ const struct SpriteTemplate gFistFootRandomPosSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimFistOrFootRandomPos, @@ -147,7 +139,7 @@ const struct SpriteTemplate gCrossChopHandSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_CrossChopHand, + .anims = &sAnims_HandsAndFeet[3], .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimCrossChopHand, @@ -158,7 +150,7 @@ const struct SpriteTemplate gSlidingKickSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_SlidingKick, + .anims = &sAnims_HandsAndFeet[1], .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimSlidingKick, @@ -182,7 +174,7 @@ const struct SpriteTemplate gSpinningHandOrFootSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = sAffineAnims_SpinningHandOrFoot, .callback = AnimSpinningKickOrPunch, @@ -205,7 +197,7 @@ const struct SpriteTemplate gMegaPunchKickSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = sAffineAnims_MegaPunchKick, .callback = AnimSpinningKickOrPunch, @@ -216,7 +208,7 @@ const struct SpriteTemplate gStompFootSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_SlidingKick, + .anims = &sAnims_HandsAndFeet[1], .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimStompFoot, @@ -307,7 +299,7 @@ const struct SpriteTemplate gArmThrustHandSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = AnimArmThrustHit, @@ -411,7 +403,7 @@ const struct SpriteTemplate gFocusPunchFistSpriteTemplate = .tileTag = ANIM_TAG_HANDS_AND_FEET, .paletteTag = ANIM_TAG_HANDS_AND_FEET, .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = sAnims_HandOrFoot, + .anims = sAnims_HandsAndFeet, .images = NULL, .affineAnims = sAffineAnims_FocusPunchFist, .callback = AnimFocusPunchFist, diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 3f8ccad52..6fd8cd621 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -1815,7 +1815,7 @@ void SetBattlerSpriteYOffsetFromYScale(u8 spriteId) { int var = 64 - GetBattlerYDeltaFromSpriteId(spriteId) * 2; u16 matrix = gSprites[spriteId].oam.matrixNum; - int var2 = (var << 8) / gOamMatrices[matrix].d; + int var2 = SAFE_DIV(var << 8, gOamMatrices[matrix].d); if (var2 > 128) var2 = 128; @@ -1828,7 +1828,7 @@ void SetBattlerSpriteYOffsetFromOtherYScale(u8 spriteId, u8 otherSpriteId) { int var = 64 - GetBattlerYDeltaFromSpriteId(otherSpriteId) * 2; u16 matrix = gSprites[spriteId].oam.matrixNum; - int var2 = (var << 8) / gOamMatrices[matrix].d; + int var2 = SAFE_DIV(var << 8, gOamMatrices[matrix].d); if (var2 > 128) var2 = 128; diff --git a/src/battle_arena.c b/src/battle_arena.c index 0ffba4910..11c918225 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -774,7 +774,8 @@ void BattleArena_DeductMindPoints(u8 battler, u16 stringId) } } -void sub_81A586C(u8 battler) // Unused. +// Unused +static void UpdateHPAtStart(u8 battler) { u16 *hpAtStart = gBattleStruct->arenaStartHp; diff --git a/src/battle_factory_screen.c b/src/battle_factory_screen.c index 8c056da1b..7b0af774a 100644 --- a/src/battle_factory_screen.c +++ b/src/battle_factory_screen.c @@ -529,7 +529,7 @@ static const union AnimCmd * const sAnims_Select_Pokeball[] = sAnim_Select_Pokeball_Moving, }; -static const union AffineAnimCmd gUnknown_0861050C[] = +static const union AffineAnimCmd sAffineAnim_Select_MonPicBg_Opening[] = { AFFINEANIMCMD_FRAME(5, 5, 0, 0), AFFINEANIMCMD_FRAME(0, 0, 0, 1), @@ -545,7 +545,7 @@ static const union AffineAnimCmd gUnknown_0861050C[] = AFFINEANIMCMD_END, }; -static const union AffineAnimCmd gUnknown_0861056C[] = +static const union AffineAnimCmd sAffineAnim_Select_MonPicBg_Closing[] = { AFFINEANIMCMD_FRAME(128, 5, 0, 0), AFFINEANIMCMD_FRAME(0, 0, 0, 1), @@ -559,7 +559,7 @@ static const union AffineAnimCmd gUnknown_0861056C[] = AFFINEANIMCMD_END, }; -static const union AffineAnimCmd gUnknown_086105BC[] = +static const union AffineAnimCmd sAffineAnim_Select_MonPicBg_Open[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_END, @@ -567,9 +567,9 @@ static const union AffineAnimCmd gUnknown_086105BC[] = static const union AffineAnimCmd * const sAffineAnims_Select_MonPicBgAnim[] = { - gUnknown_0861050C, - gUnknown_0861056C, - gUnknown_086105BC, + sAffineAnim_Select_MonPicBg_Opening, + sAffineAnim_Select_MonPicBg_Closing, + sAffineAnim_Select_MonPicBg_Open, }; static const struct SpriteTemplate sSpriteTemplate_Select_Pokeball = @@ -780,7 +780,7 @@ static const union AnimCmd * const sAnims_Swap_Pokeball[] = sAnim_Swap_Pokeball_Moving, }; -static const union AffineAnimCmd gUnknown_08610768[] = +static const union AffineAnimCmd sAffineAnim_Swap_MonPicBg_Opening[] = { AFFINEANIMCMD_FRAME(5, 5, 0, 0), AFFINEANIMCMD_FRAME(0, 0, 0, 1), @@ -796,7 +796,7 @@ static const union AffineAnimCmd gUnknown_08610768[] = AFFINEANIMCMD_END, }; -static const union AffineAnimCmd gUnknown_086107C8[] = +static const union AffineAnimCmd sAffineAnim_Swap_MonPicBg_Closing[] = { AFFINEANIMCMD_FRAME(128, 5, 0, 0), AFFINEANIMCMD_FRAME(0, 0, 0, 1), @@ -810,7 +810,7 @@ static const union AffineAnimCmd gUnknown_086107C8[] = AFFINEANIMCMD_END, }; -static const union AffineAnimCmd gUnknown_08610818[] = +static const union AffineAnimCmd sAffineAnim_Swap_MonPicBg_Open[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_END, @@ -818,9 +818,9 @@ static const union AffineAnimCmd gUnknown_08610818[] = static const union AffineAnimCmd * const sAffineAnims_Swap_MonPicBgAnim[] = { - gUnknown_08610768, - gUnknown_086107C8, - gUnknown_08610818, + sAffineAnim_Swap_MonPicBg_Opening, + sAffineAnim_Swap_MonPicBg_Closing, + sAffineAnim_Swap_MonPicBg_Open, }; static const struct SpriteTemplate sSpriteTemplate_Swap_Pokeball = diff --git a/src/battle_main.c b/src/battle_main.c index a1bc6ae7b..3507ff765 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -68,9 +68,6 @@ extern const struct BgTemplate gBattleBgTemplates[]; extern const struct WindowTemplate *const gBattleWindowTemplates[]; // this file's functions -#if !defined(NONMATCHING) && MODERN -#define static -#endif static void CB2_InitBattleInternal(void); static void CB2_PreInitMultiBattle(void); static void CB2_PreInitIngamePlayerPartnerBattle(void); @@ -579,7 +576,7 @@ void CB2_InitBattle(void) AllocateBattleResources(); AllocateBattleSpritesData(); AllocateMonSpritesGfx(); - sub_8185F84(); + RecordedBattle_ClearFrontierPassFlag(); if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { @@ -736,16 +733,16 @@ static void BufferPartyVsScreenHealth_AtStart(void) s32 i; BUFFER_PARTY_VS_SCREEN_STATUS(gPlayerParty, flags, i); - gBattleStruct->vsScreenHealthFlagsLo = flags; - *(&gBattleStruct->vsScreenHealthFlagsHi) = flags >> 8; - gBattleStruct->vsScreenHealthFlagsHi |= FlagGet(FLAG_SYS_FRONTIER_PASS) << 7; + gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsLo = flags; + *(&gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi) = flags >> 8; + gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi |= FlagGet(FLAG_SYS_FRONTIER_PASS) << 7; } static void SetPlayerBerryDataInBattleStruct(void) { s32 i; struct BattleStruct *battleStruct = gBattleStruct; - struct BattleEnigmaBerry *battleBerry = &battleStruct->battleEnigmaBerry; + struct BattleEnigmaBerry *battleBerry = &battleStruct->multiBuffer.linkBattlerHeader.battleEnigmaBerry; if (IsEnigmaBerryValid() == TRUE) { @@ -885,52 +882,56 @@ static void SetAllPlayersBerryData(void) } } -static void sub_8036EB8(u8 arg0, u8 arg1) +// This was inlined in Ruby/Sapphire +static void FindLinkBattleMaster(u8 numPlayers, u8 multiPlayerId) { - u8 var = 0; + u8 found = 0; - if (gBlockRecvBuffer[0][0] == 256) + // If player 1 is playing the minimum version, player 1 is master. + if (gBlockRecvBuffer[0][0] == 0x100) { - if (arg1 == 0) + if (multiPlayerId == 0) gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; else gBattleTypeFlags |= BATTLE_TYPE_TRAINER; - var++; + found++; } - if (var == 0) + if (found == 0) { + // If multiple different versions are being used, player 1 is master. s32 i; - for (i = 0; i < arg0; i++) + for (i = 0; i < numPlayers; i++) { if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0]) break; } - if (i == arg0) + if (i == numPlayers) { - if (arg1 == 0) + if (multiPlayerId == 0) gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; else gBattleTypeFlags |= BATTLE_TYPE_TRAINER; - var++; + found++; } - if (var == 0) + if (found == 0) { - for (i = 0; i < arg0; i++) + // Lowest index player with the highest game version is master. + for (i = 0; i < numPlayers; i++) { - if (gBlockRecvBuffer[i][0] == 0x300) + if (gBlockRecvBuffer[i][0] == 0x300 && i != multiPlayerId) { - if (i != arg1 && i < arg1) + if (i < multiPlayerId) break; } - if (gBlockRecvBuffer[i][0] > 0x300 && i != arg1) + if (gBlockRecvBuffer[i][0] > 0x300 && i != multiPlayerId) break; } - if (i == arg0) + if (i == numPlayers) gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER; else gBattleTypeFlags |= BATTLE_TYPE_TRAINER; @@ -973,8 +974,9 @@ static void CB2_HandleStartBattle(void) { if (IsLinkTaskFinished()) { - *(&gBattleStruct->field_180) = 0; - *(&gBattleStruct->field_181) = 3; + // 0x300 + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0; + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3; BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); @@ -984,7 +986,7 @@ static void CB2_HandleStartBattle(void) gLinkPlayers[1].id = 1; } - SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); + SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader)); gBattleCommunication[MULTIUSE_STATE] = 2; } if (gWirelessCommType) @@ -1005,16 +1007,16 @@ static void CB2_HandleStartBattle(void) u8 taskId; ResetBlockReceivedFlags(); - sub_8036EB8(2, playerMultiplayerId); + FindLinkBattleMaster(2, playerMultiplayerId); SetAllPlayersBerryData(); taskId = CreateTask(InitLinkBattleVsScreen, 0); gTasks[taskId].data[1] = 0x10E; gTasks[taskId].data[2] = 0x5A; gTasks[taskId].data[5] = 0; - gTasks[taskId].data[3] = gBattleStruct->vsScreenHealthFlagsLo | (gBattleStruct->vsScreenHealthFlagsHi << 8); + gTasks[taskId].data[3] = gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsLo | (gBattleStruct->multiBuffer.linkBattlerHeader.vsScreenHealthFlagsHi << 8); gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1]; - sub_8185F90(gBlockRecvBuffer[playerMultiplayerId][1]); - sub_8185F90(gBlockRecvBuffer[enemyMultiplayerId][1]); + RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[playerMultiplayerId][1]); + RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[enemyMultiplayerId][1]); SetDeoxysStats(); gBattleCommunication[MULTIUSE_STATE]++; } @@ -1181,11 +1183,12 @@ static void CB2_HandleStartMultiPartnerBattle(void) if (IsLinkTaskFinished()) { - *(&gBattleStruct->field_180) = 0; - *(&gBattleStruct->field_181) = 3; + // 0x300 + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0; + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3; BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); - SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); + SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader)); gBattleCommunication[MULTIUSE_STATE] = 2; } @@ -1207,7 +1210,7 @@ static void CB2_HandleStartMultiPartnerBattle(void) u8 taskId; ResetBlockReceivedFlags(); - sub_8036EB8(2, playerMultiplayerId); + FindLinkBattleMaster(2, playerMultiplayerId); SetAllPlayersBerryData(); taskId = CreateTask(InitLinkBattleVsScreen, 0); gTasks[taskId].data[1] = 0x10E; @@ -1568,12 +1571,13 @@ static void CB2_HandleStartMultiBattle(void) { if (IsLinkTaskFinished()) { - *(&gBattleStruct->field_180) = 0; - *(&gBattleStruct->field_181) = 3; + // 0x300 + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureLo) = 0; + *(&gBattleStruct->multiBuffer.linkBattlerHeader.versionSignatureHi) = 3; BufferPartyVsScreenHealth_AtStart(); SetPlayerBerryDataInBattleStruct(); - SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); + SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->multiBuffer.linkBattlerHeader, sizeof(gBattleStruct->multiBuffer.linkBattlerHeader)); gBattleCommunication[MULTIUSE_STATE]++; } if (gWirelessCommType) @@ -1592,7 +1596,7 @@ static void CB2_HandleStartMultiBattle(void) if ((GetBlockReceivedStatus() & 0xF) == 0xF) { ResetBlockReceivedFlags(); - sub_8036EB8(4, playerMultiplayerId); + FindLinkBattleMaster(4, playerMultiplayerId); SetAllPlayersBerryData(); SetDeoxysStats(); var = CreateTask(InitLinkBattleVsScreen, 0); @@ -1604,7 +1608,7 @@ static void CB2_HandleStartMultiBattle(void) for (id = 0; id < MAX_LINK_PLAYERS; id++) { - sub_8185F90(gBlockRecvBuffer[id][1]); + RecordedBattle_SetFrontierPassFlagFromHword(gBlockRecvBuffer[id][1]); switch (gLinkPlayers[id].id) { case 0: @@ -1789,10 +1793,10 @@ static void CB2_HandleStartMultiBattle(void) case 8: if (IsLinkTaskFinished()) { - u32* ptr = (u32*)(&gBattleStruct->field_180); + u32* ptr = gBattleStruct->multiBuffer.battleVideo; ptr[0] = gBattleTypeFlags; ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data - SendBlock(bitmask_all_link_players_but_self(), ptr, 8); + SendBlock(bitmask_all_link_players_but_self(), ptr, sizeof(gBattleStruct->multiBuffer.battleVideo)); gBattleCommunication[MULTIUSE_STATE]++; } break; @@ -2251,7 +2255,7 @@ static void EndLinkBattleInSteps(void) { u8 monsCount; - gMain.field_439_x4 = sub_8185FAC(); + gMain.anyLinkBattlerHasFrontierPass = RecordedBattle_GetFrontierPassFlag(); if (gBattleTypeFlags & BATTLE_TYPE_MULTI) monsCount = 4; @@ -2267,7 +2271,7 @@ static void EndLinkBattleInSteps(void) FreeAllWindowBuffers(); SetMainCallback2(sub_80392A8); } - else if (!gMain.field_439_x4) + else if (!gMain.anyLinkBattlerHasFrontierPass) { SetMainCallback2(gMain.savedCallback); FreeBattleResources(); @@ -2331,9 +2335,9 @@ static void EndLinkBattleInSteps(void) gBattleCommunication[MULTIUSE_STATE]++; break; case 9: - if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) + if (!gMain.anyLinkBattlerHasFrontierPass || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { - gMain.field_439_x4 = 0; + gMain.anyLinkBattlerHasFrontierPass = 0; SetMainCallback2(gMain.savedCallback); FreeBattleResources(); FreeBattleSpritesData(); @@ -2429,7 +2433,7 @@ static void sub_803939C(void) gBattleCommunication[MULTIUSE_STATE]++; break; case 1: - if (gMain.field_439_x4 && gReceivedRemoteLinkPlayers == 0) + if (gMain.anyLinkBattlerHasFrontierPass && gReceivedRemoteLinkPlayers == 0) CreateTask(Task_ReconnectWithLinkPlayers, 5); gBattleCommunication[MULTIUSE_STATE]++; break; @@ -2499,7 +2503,7 @@ static void sub_803939C(void) if (IsLinkTaskFinished() == TRUE) { HandleBattleWindow(0x18, 8, 0x1D, 0xD, WINDOW_CLEAR); - if (gMain.field_439_x4) + if (gMain.anyLinkBattlerHasFrontierPass) { SetLinkStandbyCallback(); BattlePutTextOnWindow(gText_LinkStandby3, 0); @@ -2510,15 +2514,15 @@ static void sub_803939C(void) case 8: if (--gBattleCommunication[1] == 0) { - if (gMain.field_439_x4 && !gWirelessCommType) + if (gMain.anyLinkBattlerHasFrontierPass && !gWirelessCommType) SetCloseLinkCallback(); gBattleCommunication[MULTIUSE_STATE]++; } break; case 9: - if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) + if (!gMain.anyLinkBattlerHasFrontierPass || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { - gMain.field_439_x4 = 0; + gMain.anyLinkBattlerHasFrontierPass = 0; if (!gPaletteFade.active) { SetMainCallback2(gMain.savedCallback); @@ -2548,7 +2552,7 @@ static void sub_803939C(void) case 11: if (IsLinkTaskFinished() == TRUE && !IsTextPrinterActive(0) && --gBattleCommunication[1] == 0) { - if (gMain.field_439_x4) + if (gMain.anyLinkBattlerHasFrontierPass) { SetLinkStandbyCallback(); BattlePutTextOnWindow(gText_LinkStandby3, 0); @@ -2560,7 +2564,7 @@ static void sub_803939C(void) case 7: if (!IsTextPrinterActive(0)) { - if (gMain.field_439_x4) + if (gMain.anyLinkBattlerHasFrontierPass) { if (IsLinkTaskFinished() == TRUE) { diff --git a/src/battle_pike.c b/src/battle_pike.c index ccb52fda2..ed89f5ed9 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -57,8 +57,8 @@ static void GetRoomType(void); static void SetInWildMonRoom(void); static void ClearInWildMonRoom(void); static void SavePikeChallenge(void); -static void nullsub_76(void); -static void nullsub_124(void); +static void PikeDummy1(void); +static void PikeDummy2(void); static void GetRoomInflictedStatus(void); static void GetRoomInflictedStatusMon(void); static void HealOneOrTwoMons(void); @@ -488,8 +488,8 @@ static void (* const sBattlePikeFunctions[])(void) = [BATTLE_PIKE_FUNC_SET_IN_WILD_MON_ROOM] = SetInWildMonRoom, [BATTLE_PIKE_FUNC_CLEAR_IN_WILD_MON_ROOM] = ClearInWildMonRoom, [BATTLE_PIKE_FUNC_SAVE] = SavePikeChallenge, - [BATTLE_PIKE_FUNC_NULL_9] = nullsub_76, - [BATTLE_PIKE_FUNC_NULL_10] = nullsub_124, + [BATTLE_PIKE_FUNC_DUMMY_1] = PikeDummy1, + [BATTLE_PIKE_FUNC_DUMMY_2] = PikeDummy2, [BATTLE_PIKE_FUNC_GET_ROOM_STATUS] = GetRoomInflictedStatus, [BATTLE_PIKE_FUNC_GET_ROOM_STATUS_MON] = GetRoomInflictedStatusMon, [BATTLE_PIKE_FUNC_HEAL_ONE_TWO_MONS] = HealOneOrTwoMons, @@ -715,12 +715,12 @@ static void SavePikeChallenge(void) TrySavingData(SAVE_LINK); } -static void nullsub_76(void) +static void PikeDummy1(void) { } -static void nullsub_124(void) +static void PikeDummy2(void) { } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 43c554e88..96c849cbc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -258,7 +258,7 @@ static void Cmd_trysetperishsong(void); static void Cmd_rolloutdamagecalculation(void); static void Cmd_jumpifconfusedandstatmaxed(void); static void Cmd_furycuttercalc(void); -static void Cmd_happinesstodamagecalculation(void); +static void Cmd_friendshiptodamagecalculation(void); static void Cmd_presentdamagecalculation(void); static void Cmd_setsafeguard(void); static void Cmd_magnitudedamagecalculation(void); @@ -510,7 +510,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_rolloutdamagecalculation, //0xB3 Cmd_jumpifconfusedandstatmaxed, //0xB4 Cmd_furycuttercalc, //0xB5 - Cmd_happinesstodamagecalculation, //0xB6 + Cmd_friendshiptodamagecalculation, //0xB6 Cmd_presentdamagecalculation, //0xB7 Cmd_setsafeguard, //0xB8 Cmd_magnitudedamagecalculation, //0xB9 @@ -8471,7 +8471,7 @@ static void Cmd_furycuttercalc(void) } } -static void Cmd_happinesstodamagecalculation(void) +static void Cmd_friendshiptodamagecalculation(void) { if (gBattleMoves[gCurrentMove].effect == EFFECT_RETURN) gDynamicBasePower = 10 * (gBattleMons[gBattlerAttacker].friendship) / 25; diff --git a/src/battle_tower.c b/src/battle_tower.c index 1bf4b737c..b1e5d7817 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -878,12 +878,8 @@ static const u16 sFrontierTrainerIdRangesHard[][2] = {FRONTIER_TRAINER_JAXON, FRONTIER_TRAINER_GRETEL}, // 200 - 299 }; -// Trainer IDs? Don't make sense as part of previous array, min/max relationship reversed and never accessed -static const u16 sUnused_085DFA1A[][2] = -{ - {179, 141}, // FRONTIER_TRAINER_ALISON - FRONTIER_TRAINER_KAYDEN - {200, 183}, // FRONTIER_TRAINER_JAXON - FRONTIER_TRAINER_HUNTER -}; +// Unknown, unused data +static const u16 sUnused[] = { 179, 141, 200, 183 }; static const u8 sBattleTowerPartySizes[FRONTIER_MODE_COUNT] = { diff --git a/src/battle_util.c b/src/battle_util.c index 2bf06f331..6e1202bd1 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3949,7 +3949,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget) return targetBattler; } -static bool32 IsNotEventLegalMewOrDeoxys(u8 battlerId) +static bool32 IsMonEventLegal(u8 battlerId) { if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT) return TRUE; @@ -3970,7 +3970,7 @@ u8 IsMonDisobedient(void) if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) return 0; - if (IsNotEventLegalMewOrDeoxys(gBattlerAttacker)) // only if species is Mew or Deoxys + if (IsMonEventLegal(gBattlerAttacker)) // only false if illegal Mew or Deoxys { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == 2) return 0; diff --git a/src/berry.c b/src/berry.c index ea62deabf..d56ec801c 100644 --- a/src/berry.c +++ b/src/berry.c @@ -889,50 +889,50 @@ const struct Berry gBerries[] = }, }; -const struct UnkStruct_0858AB24 gUnknown_0858AB24[] = { - { 50, 20}, - { 50, 20}, - { 50, 20}, - { 50, 20}, - { 50, 20}, - { 50, 30}, - { 50, 30}, - { 50, 30}, - { 50, 30}, - { 50, 30}, - { 60, 50}, - { 60, 50}, - { 60, 50}, - { 60, 50}, - { 60, 50}, - { 80, 70}, - { 80, 70}, - { 80, 70}, - { 80, 70}, - { 80, 70}, - {100, 100}, - {100, 100}, - {100, 100}, - {100, 100}, - {100, 100}, - {130, 150}, - {130, 150}, - {130, 150}, - {130, 150}, - {130, 150}, - {160, 250}, - {160, 250}, - {160, 250}, - {160, 250}, - {160, 250}, - {180, 500}, - {180, 500}, - {180, 500}, - {180, 500}, - {180, 500}, - {200, 750}, - {200, 750}, - {150, 200} +const struct BerryCrushBerryData gBerryCrush_BerryData[] = { + [ITEM_CHERI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_CHESTO_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_PECHA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_RAWST_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_ASPEAR_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_LEPPA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_ORAN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_PERSIM_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_LUM_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_SITRUS_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_FIGY_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_WIKI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_MAGO_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_AGUAV_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_IAPAPA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_RAZZ_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_BLUK_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_NANAB_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_WEPEAR_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_PINAP_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_POMEG_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_KELPSY_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_QUALOT_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_HONDEW_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_GREPA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_TAMATO_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 150}, + [ITEM_CORNN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 150}, + [ITEM_MAGOST_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 150}, + [ITEM_RABUTA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 150}, + [ITEM_NOMEL_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 150}, + [ITEM_SPELON_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_PAMTRE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_WATMEL_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_DURIN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_BELUE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_LIECHI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, + [ITEM_GANLON_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, + [ITEM_SALAC_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, + [ITEM_PETAYA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, + [ITEM_APICOT_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, + [ITEM_LANSAT_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 200, .powder = 750}, + [ITEM_STARF_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 200, .powder = 750}, + [ITEM_ENIGMA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 150, .powder = 200} }; const struct BerryTree gBlankBerryTree = {}; diff --git a/src/berry_crush.c b/src/berry_crush.c index 89a0ad282..e63eb9f82 100755 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -38,200 +38,352 @@ #include "constants/rgb.h" #include "constants/songs.h" -struct BerryCrushGame_Player -{ - u8 unk0[PLAYER_NAME_LENGTH + 1 + 4]; - u16 unkC; - u16 unkE; - u16 unk10; - u16 unk12; - u16 unk14; - u16 unk16; - u16 unk18; - u16 unk1A; - u8 unk1B; - u8 unk1C; +#define MAX_TIME (10 * 60 * 60) // Timer can go up to 9:59:59 + +#define TAG_CRUSHER_BASE 1 +#define PALTAG_EFFECT 2 // The next two gfx tags share this pal tag +#define GFXTAG_IMPACT 2 +#define GFXTAG_SPARKLE 3 +#define TAG_TIMER_DIGITS 4 +#define TAG_PLAYER1_BERRY 5 +#define TAG_PLAYER2_BERRY 6 +#define TAG_PLAYER3_BERRY 7 +#define TAG_PLAYER4_BERRY 8 +#define TAG_PLAYER5_BERRY 9 + +#define TAG_COUNTDOWN 0x1000 + +#define CRUSHER_START_Y (-104) + +enum { + RUN_CMD, + SCHEDULE_CMD, }; -struct BerryCrushGame_4E -{ - u16 unk0; - u16 unk2; - u8 unk4_0:1; - u8 unk4_1:1; - u8 unk4_2:1; - u8 unk4_3:5; - s8 unk5; - u16 unk6; - u16 unk8; - u16 unkA; - u16 unkC; +// IDs for the main berry crush game functions +enum { + CMD_NONE, + CMD_FADE, + CMD_WAIT_FADE, + CMD_PRINT_MSG, + CMD_SHOW_GAME, + CMD_HIDE_GAME, + CMD_READY_BEGIN, + CMD_ASK_PICK_BERRY, + CMD_PICK_BERRY, + CMD_WAIT_BERRIES, + CMD_DROP_BERRIES, + CMD_DROP_LID, + CMD_COUNTDOWN, + CMD_PLAY_GAME_LEADER, + CMD_PLAY_GAME_MEMBER, + CMD_FINISH_GAME, + CMD_TIMES_UP, + CMD_CALC_RESULTS, + CMD_SHOW_RESULTS, + CMD_SAVE, + CMD_ASK_PLAY_AGAIN, + CMD_COMM_PLAY_AGAIN, + CMD_PLAY_AGAIN_YES, + CMD_PLAY_AGAIN_NO, + CMD_CLOSE_LINK, + CMD_QUIT, }; -struct BerryCrushGame_40 -{ - s16 unk0; - s16 unk2; - s16 unk4; - s16 unk6; - s16 unk8; - s16 unkA; - s16 unkC; - s16 unkE; +enum { + MSG_PICK_BERRY, + MSG_WAIT_PICK, + MSG_POWDER, + MSG_SAVING, + MSG_PLAY_AGAIN, + MSG_NO_BERRIES, + MSG_DROPPED, + MSG_TIMES_UP, + MSG_COMM_STANDBY, +}; + +#define F_MSG_CLEAR (1 << 0) +#define F_MSG_EXPAND (1 << 1) + +// Main states for the game. Many are assigned but never checked +enum { + STATE_INIT = 1, + STATE_RESET, + STATE_PICK_BERRY, + STATE_DROP_BERRIES, + STATE_DROP_LID, + STATE_COUNTDOWN, + STATE_PLAYING, + STATE_FINISHED, + STATE_TIMES_UP, + STATE_10, // Unused + STATE_RESULTS_PRESSES, + STATE_RESULTS_RANDOM, + STATE_RESULTS_CRUSHING, + STATE_14, // Unused + STATE_PLAY_AGAIN, +}; + +#define RESULTS_STATE_START STATE_RESULTS_PRESSES +#define RESULTS_STATE_END STATE_RESULTS_CRUSHING + +// IDs for each results page that shows in succession at the game's end. +// Only 3 pages are shown for a given game. Presses and Crushing are always shown 1st and 3rd. +// The 2nd page is random, and can be rankings for either Neatness, Cooperative, or Power. +enum { + RESULTS_PAGE_PRESSES, + RESULTS_PAGE_RANDOM, + RESULTS_PAGE_CRUSHING, + NUM_RESULTS_PAGES, +}; +// Random pages, see above +// "Neatness" is how many of the player's inputs were at a regular interval +// "Cooperative" is how often the player pressed A at the same time as others +// "Power" is how much of the time the player spent pressing A +enum { + RESULTS_PAGE_NEATNESS, + RESULTS_PAGE_COOPERATIVE, + RESULTS_PAGE_POWER, + NUM_RANDOM_RESULTS_PAGES +}; + +#define PLAY_AGAIN_YES 0 +#define PLAY_AGAIN_NO 1 +#define PLAY_AGAIN_NO_BERRIES 3 + +enum { + COLORID_GREY, + COLORID_BLACK, + COLORID_LIGHT_GREY, + COLORID_BLUE, + COLORID_GREEN, + COLORID_RED, }; -struct BerryCrushGame_5C -{ - u16 unk00; - u8 unk02_0:1; - u8 unk02_1:1; - u8 unk02_2:1; - u8 unk02_3:5; - s8 unk03; - u16 unk04; - u16 unk06; - u16 unk08; - u16 unk0A; +// Flags for the inputFlags field +// Field is 16 bits; 3 bits for each player, last bit is unused +// The first two bits are interchangeable +// Needlessly complicated system, the inputState field is sufficient by itself +#define F_INPUT_HIT_A (1 << 0) +#define F_INPUT_HIT_B (1 << 1) +#define F_INPUT_HIT_SYNC (1 << 2) // Input at same time as another player +#define INPUT_FLAGS_PER_PLAYER 3 +#define INPUT_FLAG_MASK ((1 << INPUT_FLAGS_PER_PLAYER) - 1) + +// Values for the inputState field +enum { + INPUT_STATE_NONE, + INPUT_STATE_HIT, // Hit the crusher + INPUT_STATE_HIT_SYNC, // Hit the crusher at same time as another player }; -struct BerryCrushGame_68 +// No reason for this to be 2 +// Simply a flag for whether a given player has sent their data this round +// Data is only sent if the player is the leader or if they pressed A +#define SEND_GAME_STATE 2 + +struct BerryCrushGame_Player { - u32 unk00; - u16 unk04; - u16 unk06; - u16 unk08; - u16 unk0A; - u16 unk0C[2][5]; - u8 unk20[2][8]; + u8 name[PLAYER_NAME_LENGTH + 1 + 4]; + u16 berryId; + u16 inputTime; + u16 neatInputStreak; + u16 timeSincePrevInput; + u16 maxNeatInputStreak; + u16 numAPresses; + u16 numSyncedAPresses; + u16 timePressingA; + u8 inputFlags; + u8 inputState; +}; + +// This data is set locally and sent to the other players +struct BerryCrushGame_LocalState +{ + u16 sendFlag; + bool8 endGame:1; + bool8 bigSparkle:1; + bool8 pushedAButton:1; + u8 playerPressedAFlags:5; // 1 bit for each player + s8 vibration; + u16 depth; + u16 timer; + u16 inputFlags; + u16 sparkleAmount; }; -struct BerryCrushGame_138_C +// This data is read from another player's local state above by casting the recvCmd buffer +// It is identical with exception to the addition of rfuCmd +struct BerryCrushGame_LinkState +{ + u16 rfuCmd; + u16 sendFlag; + bool8 endGame:1; + bool8 bigSparkle:1; + bool8 pushedAButton:1; + u8 playerPressedAFlags:5; + s8 vibration; + u16 depth; + u16 timer; + u16 inputFlags; + u16 sparkleAmount; +}; + +struct BerryCrushGame_Results { - u8 unk0; - u8 unk1; - u8 unk2; - s16 unk4; - s16 unk6; - s16 unk8; - s16 unkA; + u32 powder; + u16 time; + u16 targetPressesPerSec; // Never read + u16 silkiness; + u16 totalAPresses; + u16 stats[2][MAX_RFU_PLAYERS]; + u8 playerIdsRanked[2][MAX_RFU_PLAYERS + 3]; +}; + +// playerIdsRanked above has 3 additional elements after the players. +// Only 1 of these 2*3 is ever used, and it stores the id for which +// random results page to show. Its define below is for readability. +#define randomPageId playerIdsRanked[0][7] + +// Holds position data for various player-associated graphics +struct BerryCrushPlayerCoords +{ + u8 playerId; + u8 windowGfxX; + u8 windowGfxY; + s16 impactXOffset; + s16 impactYOffset; + s16 berryXOffset; + s16 berryXDest; }; -struct BerryCrushGame_138 -{ - u8 unk0; - u8 unk1; - u8 unk2; - u8 unk3; - s16 unk4; - s16 unk6; - s16 unk8; - const struct BerryCrushGame_138_C *unkC[5]; - struct Sprite *unk20; - struct Sprite *unk24[5]; - struct Sprite *unk38[5]; - struct Sprite *unk4C[11]; - struct Sprite *unk78[2]; - u8 unk80; - u8 filler81; - u8 unk82; - u8 unk83[5]; - u16 unk88[4][0x800]; +struct BerryCrushGame_Gfx +{ + u8 counter; + u8 vibrationIdx; + u8 numVibrations; + bool8 vibrating; + s16 minutes; + s16 secondsInt; + s16 secondsFrac; + const struct BerryCrushPlayerCoords *playerCoords[MAX_RFU_PLAYERS]; + struct Sprite *coreSprite; + struct Sprite *impactSprites[MAX_RFU_PLAYERS]; + struct Sprite *berrySprites[MAX_RFU_PLAYERS]; + struct Sprite *sparkleSprites[11]; + struct Sprite *timerSprites[2]; + u8 resultsState; + u8 unused; + u8 resultsWindowId; + u8 nameWindowIds[MAX_RFU_PLAYERS]; + u16 bgBuffers[4][0x800]; }; struct BerryCrushGame { - MainCallback unk0; - u32 (*unk4)(struct BerryCrushGame *, u8 *); - u8 unk8; - u8 unk9; - u8 mainTask; - u8 unkB; - u8 unkC; - u8 unkD; - u8 unkE; - u8 unkF; - u16 unk10; - u16 unk12; - u16 unk14; - u16 unk16; - s16 unk18; - s16 unk1A; - s32 unk1C; - s32 unk20; - u8 unk24; - u8 unk25_0:1; - u8 unk25_1:1; - u8 unk25_2:1; - u8 unk25_3:1; - u8 unk25_4:1; - u8 unk25_5:3; - u16 unk26; - u16 unk28; - s16 unk2A; - s16 unk2C; - s16 unk2E; - s16 unk30; - s16 unk32; - s16 unk34; - u8 unk36[0xC]; - u16 unk42[6]; - u16 unk4E[7]; - struct BerryCrushGame_5C unk5C; - struct BerryCrushGame_68 unk68; - struct BerryCrushGame_Player unk98[5]; - struct BerryCrushGame_138 unk138; + MainCallback exitCallback; + u32 (*cmdCallback)(struct BerryCrushGame *, u8 *); + u8 localId; + u8 playerCount; + u8 taskId; + u8 textSpeed; + u8 cmdState; + u8 unused; // Never read + u8 nextCmd; + u8 afterPalFadeCmd; + u16 cmdTimer; + u16 gameState; + u16 playAgainState; + u16 pressingSpeed; + s16 targetAPresses; + s16 totalAPresses; + s32 powder; + s32 targetDepth; + u8 newDepth; + bool8 noRoomForPowder:1; // Never read + bool8 newRecord:1; + bool8 playedSound:1; + bool8 endGame:1; + bool8 bigSparkle:1; + u8 sparkleAmount:3; + u16 leaderTimer; + u16 timer; + s16 depth; + s16 vibration; + s16 bigSparkleCounter; + s16 numBigSparkles; + s16 numBigSparkleChecks; + s16 sparkleCounter; + u8 commandArgs[12]; + u16 sendCmd[6]; + u16 recvCmd[7]; + struct BerryCrushGame_LocalState localState; + struct BerryCrushGame_Results results; + struct BerryCrushGame_Player players[MAX_RFU_PLAYERS]; + struct BerryCrushGame_Gfx gfx; }; static void VBlankCB(void); static void MainCB(void); static void MainTask(u8); -static void ParseName_Options(struct BerryCrushGame *); -static void BerryCrush_RunOrScheduleCommand(u16, u8, u8 *); -static void BerryCrush_SetPaletteFadeParams(u8 *, bool8, u32, s8, u8, u8, u16); -static s32 sub_8021450(struct BerryCrushGame *); -static void sub_8022588(struct BerryCrushGame *); -static void sub_8022600(struct BerryCrushGame *); -static void sub_80226D0(struct BerryCrushGame *); -static void sub_8022730(struct BerryCrushGame *); -static void sub_8022960(struct BerryCrushGame *); -static void BerryCrush_PrintTimeOnSprites(struct BerryCrushGame_138 *, u16); -static void sub_8022B28(struct Sprite *); -static void BerryCrush_HideTimerSprites(struct BerryCrushGame_138 *r0); -static void sub_8024578(struct BerryCrushGame *); -static void BerryCrush_SetShowMessageParams(u8 *, u32, u32, u32, u32); -static void SpriteCB_BerryCrushImpact(struct Sprite *sprite); -static u32 BerryCrushCommand_BeginNormalPaletteFade(struct BerryCrushGame *r6, u8 *r1); -static u32 BerryCrushCommand_WaitPaletteFade(struct BerryCrushGame *r4, u8 *r5); -static u32 BerryCrushCommand_PrintMessage(struct BerryCrushGame *r7, u8 *r5); -static u32 BerryCrushCommand_InitGfx(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_TeardownGfx(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_SignalReadyToBegin(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_AskPickBerry(struct BerryCrushGame *r4, u8 *r5); -static u32 BerryCrushCommand_GoToBerryPouch(struct BerryCrushGame *r0, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_WaitForOthersToPickBerries(struct BerryCrushGame *r5, u8 *r2); -static u32 BerryCrushCommand_DropBerriesIntoCrusher(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_DropLid(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_Countdown(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_PlayGame_Master(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_PlayGame_Slave(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_FinishGame(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_HandleTimeUp(struct BerryCrushGame *r5, u8 *r6); -static u32 BerryCrushCommand_TabulateResults(struct BerryCrushGame *r7, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_ShowResults(struct BerryCrushGame *r5, u8 *r6); -static u32 BerryCrushCommand_SaveGame(struct BerryCrushGame *r5, u8 *r4); -static u32 BerryCrushCommand_AskPlayAgain(struct BerryCrushGame *r5, u8 *r6); -static u32 BerryCrushCommand_CommunicatePlayAgainResponses(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_FadeOutToPlayAgain(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_PlayAgainFailureMessage(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_GracefulExit(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1); -static u32 BerryCrushCommand_Quit(__attribute__((unused)) struct BerryCrushGame *r0, __attribute__((unused)) u8 *r1); - -static EWRAM_DATA struct BerryCrushGame *sBerryCrushGamePtr = NULL; - -static const u8 gUnknown_082F325C[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; -static const u8 gUnknown_082F3264[] = { 0, 1, 2, 3, 5, 0, 0, 0 }; - -static const s8 gUnknown_082F326C[][7] = +static void SetNamesAndTextSpeed(struct BerryCrushGame *); +static void RunOrScheduleCommand(u16, u8, u8 *); +static void SetPaletteFadeArgs(u8 *, bool8, u32, s8, u8, u8, u16); +static s32 UpdateGame(struct BerryCrushGame *); +static void CreatePlayerNameWindows(struct BerryCrushGame *); +static void DrawPlayerNameWindows(struct BerryCrushGame *); +static void CopyPlayerNameWindowGfxToBg(struct BerryCrushGame *); +static void CreateGameSprites(struct BerryCrushGame *); +static void DestroyGameSprites(struct BerryCrushGame *); +static void PrintTimer(struct BerryCrushGame_Gfx *, u16); +static void SpriteCB_Sparkle_Init(struct Sprite *); +static void HideTimer(struct BerryCrushGame_Gfx *); +static void ResetGame(struct BerryCrushGame *); +static void SetPrintMessageArgs(u8 *, u8, u8, u16, u8); +static void SpriteCB_Impact(struct Sprite *); +static u32 Cmd_BeginNormalPaletteFade(struct BerryCrushGame *, u8 *); +static u32 Cmd_WaitPaletteFade(struct BerryCrushGame *, u8 *); +static u32 Cmd_PrintMessage(struct BerryCrushGame *, u8 *); +static u32 Cmd_ShowGameDisplay(struct BerryCrushGame *, u8 *); +static u32 Cmd_HideGameDisplay(struct BerryCrushGame *, u8 *); +static u32 Cmd_SignalReadyToBegin(struct BerryCrushGame *, u8 *); +static u32 Cmd_AskPickBerry(struct BerryCrushGame *, u8 *); +static u32 Cmd_GoToBerryPouch(struct BerryCrushGame *, u8 *); +static u32 Cmd_WaitForOthersToPickBerries(struct BerryCrushGame *, u8 *); +static u32 Cmd_DropBerriesIntoCrusher(struct BerryCrushGame *, u8 *); +static u32 Cmd_DropLid(struct BerryCrushGame *, u8 *); +static u32 Cmd_Countdown(struct BerryCrushGame *, u8 *); +static u32 Cmd_PlayGame_Leader(struct BerryCrushGame *, u8 *); +static u32 Cmd_PlayGame_Member(struct BerryCrushGame *, u8 *); +static u32 Cmd_FinishGame(struct BerryCrushGame *, u8 *); +static u32 Cmd_HandleTimeUp(struct BerryCrushGame *, u8 *); +static u32 Cmd_TabulateResults(struct BerryCrushGame *, u8 *); +static u32 Cmd_ShowResults(struct BerryCrushGame *, u8 *); +static u32 Cmd_SaveGame(struct BerryCrushGame *, u8 *); +static u32 Cmd_AskPlayAgain(struct BerryCrushGame *, u8 *); +static u32 Cmd_CommunicatePlayAgainResponses(struct BerryCrushGame *, u8 *); +static u32 Cmd_PlayAgain(struct BerryCrushGame *, u8 *); +static u32 Cmd_StopGame(struct BerryCrushGame *, u8 *); +static u32 Cmd_CloseLink(struct BerryCrushGame *, u8 *); +static u32 Cmd_Quit(struct BerryCrushGame *, u8 *); + +static EWRAM_DATA struct BerryCrushGame *sGame = NULL; + +static const u8 sBitTable[] = { + 1 << 0, + 1 << 1, + 1 << 2, + 1 << 3, + 1 << 4, + 1 << 5, + 1 << 6, + 1 << 7 +}; +// Additional A presses are counted depending on the number of players +// The bonus of 5 is unobtainable +static const u8 sSyncPressBonus[MAX_RFU_PLAYERS] = { 0, 1, 2, 3, 5 }; +ALIGNED(4) +static const s8 sIntroOutroVibrationData[][7] = { { 4, 1, 0, -1, 0, 0, 0}, { 4, 2, 0, -1, 0, 0, 0}, @@ -240,9 +392,8 @@ static const s8 gUnknown_082F326C[][7] = { 6, 4, 1, -2, -4, -2, 0}, }; -static const u8 sUnusedZero = 0; - -static const u8 gUnknown_082F3290[][4] = +ALIGNED(4) +static const u8 sVibrationData[MAX_RFU_PLAYERS][4] = { {3, 2, 1, 0}, {3, 3, 1, 0}, @@ -251,20 +402,20 @@ static const u8 gUnknown_082F3290[][4] = {3, 5, 3, 0}, }; -static const u8 *const gUnknown_082F32A4[] = -{ - gText_ReadyToBerryCrush, - gText_WaitForAllChooseBerry, - gText_EndedWithXUnitsPowder, - gText_RecordingGameResults, - gText_PlayBerryCrushAgain, - gText_YouHaveNoBerries, - gText_MemberDroppedOut, - gText_TimesUpNoGoodPowder, - gText_CommunicationStandby2, +static const u8 *const sMessages[] = +{ + [MSG_PICK_BERRY] = gText_ReadyPickBerry, + [MSG_WAIT_PICK] = gText_WaitForAllChooseBerry, + [MSG_POWDER] = gText_EndedWithXUnitsPowder, + [MSG_SAVING] = gText_RecordingGameResults, + [MSG_PLAY_AGAIN] = gText_PlayBerryCrushAgain, + [MSG_NO_BERRIES] = gText_YouHaveNoBerries, + [MSG_DROPPED] = gText_MemberDroppedOut, + [MSG_TIMES_UP] = gText_TimesUpNoGoodPowder, + [MSG_COMM_STANDBY] = gText_CommunicationStandby2, }; -static const struct BgTemplate gUnknown_082F32C8[4] = +static const struct BgTemplate sBgTemplates[4] = { { .bg = 0, @@ -304,19 +455,18 @@ static const struct BgTemplate gUnknown_082F32C8[4] = }, }; - -static const u8 sBerryCrushTextColorTable[][3] = +static const u8 sTextColorTable[][3] = { - {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, - {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY}, - {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_LIGHT_GREY, TEXT_COLOR_RED}, - {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, - {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, - {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, + [COLORID_GREY] = {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, + [COLORID_BLACK] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY}, + [COLORID_LIGHT_GREY] = {TEXT_COLOR_TRANSPARENT, TEXT_COLOR_LIGHT_GREY, TEXT_COLOR_RED}, + [COLORID_BLUE] = {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, + [COLORID_GREEN] = {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, + [COLORID_RED] = {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, }; -static const struct WindowTemplate sWindowTemplate_BerryCrushRankings = +static const struct WindowTemplate sWindowTemplate_Rankings = { .bg = 0, .tilemapLeft = 3, @@ -327,7 +477,7 @@ static const struct WindowTemplate sWindowTemplate_BerryCrushRankings = .baseBlock = 1 }; -static const struct WindowTemplate gUnknown_082F32F4[] = +static const struct WindowTemplate sWindowTemplates_PlayerNames[MAX_RFU_PLAYERS + 1] = { { .bg = 0, @@ -377,9 +527,9 @@ static const struct WindowTemplate gUnknown_082F32F4[] = DUMMY_WIN_TEMPLATE, }; -static const struct WindowTemplate gUnknown_082F3324[] = +static const struct WindowTemplate sWindowTemplates_Results[] = { - { + [STATE_RESULTS_PRESSES - RESULTS_STATE_START] = { .bg = 0, .tilemapLeft = 5, .tilemapTop = 2, @@ -388,7 +538,7 @@ static const struct WindowTemplate gUnknown_082F3324[] = .paletteNum = 15, .baseBlock = 1 }, - { + [STATE_RESULTS_RANDOM - RESULTS_STATE_START] = { .bg = 0, .tilemapLeft = 5, .tilemapTop = 2, @@ -397,7 +547,7 @@ static const struct WindowTemplate gUnknown_082F3324[] = .paletteNum = 15, .baseBlock = 1 }, - { + [STATE_RESULTS_CRUSHING - RESULTS_STATE_START] = { .bg = 0, .tilemapLeft = 4, .tilemapTop = 2, @@ -409,101 +559,105 @@ static const struct WindowTemplate gUnknown_082F3324[] = DUMMY_WIN_TEMPLATE, }; -static const u8 gUnknown_082F3344[][4] = +// The height of the results window depending on the number of players +// 2 players, 3 players, 4 players, or 5 players +static const u8 sResultsWindowHeights[][MAX_RFU_PLAYERS - 1] = { - {6, 8, 9, 11}, - {12, 14, 15, 16}, + {6, 8, 9, 11}, // "Presses" and "Neatness/Cooperative/Power" pages + {12, 14, 15, 16}, // "Crushing" page }; static const u32 sPressingSpeedConversionTable[] = { - 50000000 / (1 << 0), - 50000000 / (1 << 1), - 50000000 / (1 << 2), - 50000000 / (1 << 3), - 50000000 / (1 << 4), - 50000000 / (1 << 5), - 50000000 / (1 << 6), - 50000000 / (1 << 7), + 50000000, // 50 + 25000000, // 25 + 12500000, // 12.5 + 6250000, // 6.25 + 3125000, // 3.125 + 1562500, // 1.5625 + 781250, // 0.78125 + 390625 // 0.390625 }; -static const u16 gBerryCrushGrinderBasePal[] = INCBIN_U16("graphics/link_games/berrycrush_grinder_base.gbapal"); -static const u16 gBerryCrushMiscSpritesPal[] = INCBIN_U16("graphics/link_games/berrycrush_misc.gbapal"); -static const u16 gBerryCrushTimerDigitsPal[] = INCBIN_U16("graphics/link_games/berrycrush_timerdigits.gbapal"); -static const u32 gBerryCrushGrinderBaseGfx[] = INCBIN_U32("graphics/link_games/berrycrush_grinder_base.4bpp.lz"); -static const u32 gBerryCrushBtnPressGfx[] = INCBIN_U32("graphics/link_games/berrycrush_btnpress.4bpp.lz"); -static const u32 gBerryCrushSparkleGfx[] = INCBIN_U32("graphics/link_games/berrycrush_sparkle.4bpp.lz"); -static const u8 gBerryCrushTimerDigitsGfx[] = INCBIN_U8("graphics/link_games/berrycrush_timerdigits.4bpp.lz"); -static const u8 gBerryCrushGrinderTopTilemap[] = INCBIN_U8("graphics/link_games/berrycrush_grinder_top.bin.lz"); -static const u8 gBerryCrushContainerCapTilemap[] = INCBIN_U8("graphics/link_games/berrycrush_container_cap.bin.lz"); -static const u8 gBerryCrushBackgroundTilemap[] = INCBIN_U8("graphics/link_games/berrycrush_background.bin.lz"); - -static const u8 gUnknown_082F417C[][5] = -{ - {1, 3, 0, 0, 0}, - {0, 1, 3, 0, 0}, - {1, 3, 2, 4, 0}, +static const u16 sCrusherBase_Pal[] = INCBIN_U16("graphics/berry_crush/crusher_base.gbapal"); +static const u16 sEffects_Pal[] = INCBIN_U16("graphics/berry_crush/effects.gbapal"); +static const u16 sTimerDigits_Pal[] = INCBIN_U16("graphics/berry_crush/timer_digits.gbapal"); +static const u32 sCrusherBase_Gfx[] = INCBIN_U32("graphics/berry_crush/crusher_base.4bpp.lz"); +static const u32 sImpact_Gfx[] = INCBIN_U32("graphics/berry_crush/impact.4bpp.lz"); +static const u32 sSparkle_Gfx[] = INCBIN_U32("graphics/berry_crush/sparkle.4bpp.lz"); +static const u32 sTimerDigits_Gfx[] = INCBIN_U32("graphics/berry_crush/timer_digits.4bpp.lz"); +static const u8 sCrusherTop_Tilemap[] = INCBIN_U8("graphics/berry_crush/crusher_top.bin.lz"); +static const u8 sContainerCap_Tilemap[] = INCBIN_U8("graphics/berry_crush/container_cap.bin.lz"); +static const u8 sBg_Tilemap[] = INCBIN_U8("graphics/berry_crush/bg.bin.lz"); + +// Takes the number of players - 2 and a player id and returns the +// index into sPlayerCoords where that player should be seated +static const u8 sPlayerIdToPosId[MAX_RFU_PLAYERS - 1][MAX_RFU_PLAYERS] = +{ + {1, 3}, + {0, 1, 3}, + {1, 3, 2, 4}, {0, 1, 3, 2, 4}, }; -static const struct BerryCrushGame_138_C gUnknown_082F4190[] = +static const struct BerryCrushPlayerCoords sPlayerCoords[MAX_RFU_PLAYERS] = { { - .unk0 = 0, - .unk1 = 0, - .unk2 = 0, - .unk4 = 0, - .unk6 = -16, - .unk8 = 0, - .unkA = 0, + .playerId = 0, + .windowGfxX = 0, + .windowGfxY = 0, + .impactXOffset = 0, + .impactYOffset = -16, + .berryXOffset = 0, + .berryXDest = 0, }, { - .unk0 = 1, - .unk1 = 0, - .unk2 = 3, - .unk4 = -28, - .unk6 = -4, - .unk8 = -24, - .unkA = 16, + .playerId = 1, + .windowGfxX = 0, + .windowGfxY = 3, + .impactXOffset = -28, + .impactYOffset = -4, + .berryXOffset = -24, + .berryXDest = 16, }, { - .unk0 = 2, - .unk1 = 0, - .unk2 = 6, - .unk4 = -16, - .unk6 = 20, - .unk8 = -8, - .unkA = 16, + .playerId = 2, + .windowGfxX = 0, + .windowGfxY = 6, + .impactXOffset = -16, + .impactYOffset = 20, + .berryXOffset = -8, + .berryXDest = 16, }, { - .unk0 = 3, - .unk1 = 20, - .unk2 = 3, - .unk4 = 28, - .unk6 = -4, - .unk8 = 32, - .unkA = -8, + .playerId = 3, + .windowGfxX = 20, + .windowGfxY = 3, + .impactXOffset = 28, + .impactYOffset = -4, + .berryXOffset = 32, + .berryXDest = -8, }, { - .unk0 = 4, - .unk1 = 20, - .unk2 = 6, - .unk4 = 16, - .unk6 = 20, - .unk8 = 16, - .unkA = -8, + .playerId = 4, + .windowGfxX = 20, + .windowGfxY = 6, + .impactXOffset = 16, + .impactYOffset = 20, + .berryXOffset = 16, + .berryXDest = -8, } }; -static const s8 gUnknown_082F41CC[][2] = +static const s8 sImpactCoords[][2] = { { 0, 0}, {-1, 0}, { 1, 1}, }; -static const s8 gUnknown_082F41D2[][2] = +static const s8 sSparkleCoords[][2] = { { 0, 0}, {-16, -4}, @@ -518,41 +672,42 @@ static const s8 gUnknown_082F41D2[][2] = { 40, -16}, }; -static const u16 sPlayerBerrySpriteTags[] = {5, 6, 7, 8, 9, 0}; - -static const struct CompressedSpriteSheet gUnknown_082F41F4[] = +static const u16 sPlayerBerrySpriteTags[MAX_RFU_PLAYERS] = { - { .data = gBerryCrushGrinderBaseGfx, .size = 0x800, .tag = 1 }, - { .data = gBerryCrushBtnPressGfx, .size = 0xE00, .tag = 2 }, - { .data = gBerryCrushSparkleGfx, .size = 0x700, .tag = 3 }, + TAG_PLAYER1_BERRY, + TAG_PLAYER2_BERRY, + TAG_PLAYER3_BERRY, + TAG_PLAYER4_BERRY, + TAG_PLAYER5_BERRY }; -static const struct SpriteSheet gUnknown_082F420C[] = +// sTimerDigits_Gfx is part of this array but is (apparently) uncompressed +// It gets cast to raw uncompressed data when used in sDigitObjTemplates +static const struct CompressedSpriteSheet sSpriteSheets[] = { - { .data = gBerryCrushTimerDigitsGfx, .size = 0x2C0, .tag = 4 }, + { .data = sCrusherBase_Gfx, .size = 0x800, .tag = TAG_CRUSHER_BASE }, + { .data = sImpact_Gfx, .size = 0xE00, .tag = GFXTAG_IMPACT }, + { .data = sSparkle_Gfx, .size = 0x700, .tag = GFXTAG_SPARKLE }, + { .data = sTimerDigits_Gfx, .size = 0x2C0, .tag = TAG_TIMER_DIGITS }, {} }; -static const struct SpritePalette gUnknown_082F421C[] = -{ - { .data = gBerryCrushGrinderBasePal, .tag = 1 }, - { .data = gBerryCrushMiscSpritesPal, .tag = 2 }, -}; - -static const struct SpritePalette gUnknown_082F422C[] = +static const struct SpritePalette sSpritePals[] = { - { .data = gBerryCrushTimerDigitsPal, .tag = 4 }, + { .data = sCrusherBase_Pal, .tag = TAG_CRUSHER_BASE }, + { .data = sEffects_Pal, .tag = PALTAG_EFFECT }, // For the impact and sparkle effects + { .data = sTimerDigits_Pal, .tag = TAG_TIMER_DIGITS }, {} }; -static const union AnimCmd gUnknown_082F423C[] = +static const union AnimCmd sAnim_CrusherBase[] = { ANIMCMD_FRAME(0, 0), ANIMCMD_END }; -static const union AnimCmd gUnknown_082F4244[] = +static const union AnimCmd sAnim_Impact_Small[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_FRAME(16, 4), @@ -560,7 +715,7 @@ static const union AnimCmd gUnknown_082F4244[] = ANIMCMD_END }; -static const union AnimCmd gUnknown_082F4254[] = +static const union AnimCmd sAnim_Impact_Big[] = { ANIMCMD_FRAME(48, 2), ANIMCMD_FRAME(64, 2), @@ -569,7 +724,7 @@ static const union AnimCmd gUnknown_082F4254[] = ANIMCMD_END }; -static const union AnimCmd gUnknown_082F4268[] = +static const union AnimCmd sAnim_Sparkle_Small[] = { ANIMCMD_FRAME(0, 2), ANIMCMD_FRAME(4, 2), @@ -580,7 +735,7 @@ static const union AnimCmd gUnknown_082F4268[] = ANIMCMD_JUMP(0) }; -static const union AnimCmd gUnknown_082F4284[] = +static const union AnimCmd sAnim_Sparkle_Big[] = { ANIMCMD_FRAME(24, 4), ANIMCMD_FRAME(28, 4), @@ -593,105 +748,105 @@ static const union AnimCmd gUnknown_082F4284[] = ANIMCMD_JUMP(0) }; -static const union AnimCmd gUnknown_082F42A8[] = +static const union AnimCmd sAnim_Timer[] = { ANIMCMD_FRAME(20, 0), ANIMCMD_END }; -static const union AnimCmd gUnknown_082F42B0[] = +static const union AnimCmd sAnim_PlayerBerry[] = { ANIMCMD_FRAME(0, 0), ANIMCMD_END }; -static const union AffineAnimCmd gUnknown_082F42B8[] = +static const union AffineAnimCmd sAffineAnim_PlayerBerry_0[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_FRAME(0, 0, 2, 1), AFFINEANIMCMD_JUMP(1) }; -static const union AffineAnimCmd gUnknown_082F42D0[] = +static const union AffineAnimCmd sAffineAnim_PlayerBerry_1[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_FRAME(0, 0, -2, 1), AFFINEANIMCMD_JUMP(1) }; -static const union AnimCmd *const gUnknown_082F42E8[] = +static const union AnimCmd *const sAnims_CrusherBase[] = { - gUnknown_082F423C + sAnim_CrusherBase }; -static const union AnimCmd *const gUnknown_082F42EC[] = +static const union AnimCmd *const sAnims_Impact[] = { - gUnknown_082F4244, - gUnknown_082F4254, + sAnim_Impact_Small, + sAnim_Impact_Big, }; -static const union AnimCmd *const gUnknown_082F42F4[] = +static const union AnimCmd *const sAnims_Sparkle[] = { - gUnknown_082F4268, - gUnknown_082F4284, + sAnim_Sparkle_Small, + sAnim_Sparkle_Big, }; -static const union AnimCmd *const gUnknown_082F42FC[] = +static const union AnimCmd *const sAnims_Timer[] = { - gUnknown_082F42A8 + sAnim_Timer }; -static const union AnimCmd *const gUnknown_082F4300[] = +static const union AnimCmd *const sAnims_PlayerBerry[] = { - gUnknown_082F42B0 + sAnim_PlayerBerry }; -static const union AffineAnimCmd *const gUnknown_082F4304[] = +static const union AffineAnimCmd *const sAffineAnims_PlayerBerry[] = { - gUnknown_082F42B8, - gUnknown_082F42D0, + sAffineAnim_PlayerBerry_0, + sAffineAnim_PlayerBerry_1, }; -static const struct SpriteTemplate gUnknown_082F430C = +static const struct SpriteTemplate sSpriteTemplate_CrusherBase = { - .tileTag = 1, - .paletteTag = 1, + .tileTag = TAG_CRUSHER_BASE, + .paletteTag = TAG_CRUSHER_BASE, .oam = &gOamData_AffineOff_ObjNormal_64x64, - .anims = gUnknown_082F42E8, + .anims = sAnims_CrusherBase, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_082F4324 = +static const struct SpriteTemplate sSpriteTemplate_Impact = { - .tileTag = 2, - .paletteTag = 2, + .tileTag = GFXTAG_IMPACT, + .paletteTag = PALTAG_EFFECT, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = gUnknown_082F42EC, + .anims = sAnims_Impact, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCB_BerryCrushImpact + .callback = SpriteCB_Impact }; -static const struct SpriteTemplate gUnknown_082F433C = +static const struct SpriteTemplate sSpriteTemplate_Sparkle = { - .tileTag = 3, - .paletteTag = 2, + .tileTag = GFXTAG_SPARKLE, + .paletteTag = PALTAG_EFFECT, .oam = &gOamData_AffineOff_ObjNormal_16x16, - .anims = gUnknown_082F42F4, + .anims = sAnims_Sparkle, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_082F4354 = +static const struct SpriteTemplate sSpriteTemplate_Timer = { - .tileTag = 4, - .paletteTag = 4, + .tileTag = TAG_TIMER_DIGITS, + .paletteTag = TAG_TIMER_DIGITS, .oam = &gOamData_AffineOff_ObjNormal_8x16, - .anims = gUnknown_082F42FC, + .anims = sAnims_Timer, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy @@ -699,18 +854,18 @@ static const struct SpriteTemplate gUnknown_082F4354 = static const struct SpriteTemplate sSpriteTemplate_PlayerBerry = { - .tileTag = 5, - .paletteTag = 5, + .tileTag = TAG_PLAYER1_BERRY, + .paletteTag = TAG_PLAYER1_BERRY, .oam = &gOamData_AffineDouble_ObjNormal_32x32, - .anims = gUnknown_082F4300, + .anims = sAnims_PlayerBerry, .images = NULL, - .affineAnims = gUnknown_082F4304, + .affineAnims = sAffineAnims_PlayerBerry, .callback = SpriteCallbackDummy }; -static const struct DigitObjUtilTemplate gUnknown_082F4384[] = +static const struct DigitObjUtilTemplate sDigitObjTemplates[] = { - { + { // Minutes .strConvMode = 1, .shape = 2, .size = 0, @@ -719,10 +874,10 @@ static const struct DigitObjUtilTemplate gUnknown_082F4384[] = .xDelta = 8, .x = 156, .y = 0, - .spriteSheet = gUnknown_082F420C, - .spritePal = gUnknown_082F422C, + .spriteSheet = (void*) &sSpriteSheets[3], + .spritePal = &sSpritePals[2], }, - { + { // Seconds .strConvMode = 0, .shape = 2, .size = 0, @@ -731,10 +886,10 @@ static const struct DigitObjUtilTemplate gUnknown_082F4384[] = .xDelta = 8, .x = 180, .y = 0, - .spriteSheet = gUnknown_082F420C, - .spritePal = gUnknown_082F422C, + .spriteSheet = (void*) &sSpriteSheets[3], + .spritePal = &sSpritePals[2], }, - { + { // 1/60ths of a second .strConvMode = 0, .shape = 2, .size = 0, @@ -743,79 +898,83 @@ static const struct DigitObjUtilTemplate gUnknown_082F4384[] = .xDelta = 8, .x = 204, .y = 0, - .spriteSheet = gUnknown_082F420C, - .spritePal = gUnknown_082F422C, + .spriteSheet = (void*) &sSpriteSheets[3], + .spritePal = &sSpritePals[2], } }; -static const u8 *const gUnknown_082F43B4[] = +static const u8 *const sResultsTexts[] = { - gText_SpaceTimes2, - gText_XDotY, - gText_Var1Berry, - gText_NeatnessRankings, - gText_CoopRankings, - gText_PressingPowerRankings, + [RESULTS_PAGE_PRESSES] = gText_SpaceTimes2, // " times" + [RESULTS_PAGE_RANDOM] = gText_XDotY, // "##.##", for Neatness, Cooperation, or Power value + [RESULTS_PAGE_CRUSHING] = gText_Var1Berry, + + [RESULTS_PAGE_NEATNESS + NUM_RESULTS_PAGES] = gText_NeatnessRankings, + [RESULTS_PAGE_COOPERATIVE + NUM_RESULTS_PAGES] = gText_CoopRankings, + [RESULTS_PAGE_POWER + NUM_RESULTS_PAGES] = gText_PressingPowerRankings, }; -static u32 (*const sBerryCrushCommands[])(struct BerryCrushGame *, u8 *) = -{ - NULL, - BerryCrushCommand_BeginNormalPaletteFade, - BerryCrushCommand_WaitPaletteFade, - BerryCrushCommand_PrintMessage, - BerryCrushCommand_InitGfx, - BerryCrushCommand_TeardownGfx, - BerryCrushCommand_SignalReadyToBegin, - BerryCrushCommand_AskPickBerry, - BerryCrushCommand_GoToBerryPouch, - BerryCrushCommand_WaitForOthersToPickBerries, - BerryCrushCommand_DropBerriesIntoCrusher, - BerryCrushCommand_DropLid, - BerryCrushCommand_Countdown, - BerryCrushCommand_PlayGame_Master, - BerryCrushCommand_PlayGame_Slave, - BerryCrushCommand_FinishGame, - BerryCrushCommand_HandleTimeUp, - BerryCrushCommand_TabulateResults, - BerryCrushCommand_ShowResults, - BerryCrushCommand_SaveGame, - BerryCrushCommand_AskPlayAgain, - BerryCrushCommand_CommunicatePlayAgainResponses, - BerryCrushCommand_FadeOutToPlayAgain, - BerryCrushCommand_PlayAgainFailureMessage, - BerryCrushCommand_GracefulExit, - BerryCrushCommand_Quit, +static u32 (*const sBerryCrushCommands[])(struct BerryCrushGame * game, u8 * data) = +{ + [CMD_NONE] = NULL, + [CMD_FADE] = Cmd_BeginNormalPaletteFade, + [CMD_WAIT_FADE] = Cmd_WaitPaletteFade, + [CMD_PRINT_MSG] = Cmd_PrintMessage, + [CMD_SHOW_GAME] = Cmd_ShowGameDisplay, + [CMD_HIDE_GAME] = Cmd_HideGameDisplay, + [CMD_READY_BEGIN] = Cmd_SignalReadyToBegin, + [CMD_ASK_PICK_BERRY] = Cmd_AskPickBerry, + [CMD_PICK_BERRY] = Cmd_GoToBerryPouch, + [CMD_WAIT_BERRIES] = Cmd_WaitForOthersToPickBerries, + [CMD_DROP_BERRIES] = Cmd_DropBerriesIntoCrusher, + [CMD_DROP_LID] = Cmd_DropLid, + [CMD_COUNTDOWN] = Cmd_Countdown, + [CMD_PLAY_GAME_LEADER] = Cmd_PlayGame_Leader, + [CMD_PLAY_GAME_MEMBER] = Cmd_PlayGame_Member, + [CMD_FINISH_GAME] = Cmd_FinishGame, + [CMD_TIMES_UP] = Cmd_HandleTimeUp, + [CMD_CALC_RESULTS] = Cmd_TabulateResults, + [CMD_SHOW_RESULTS] = Cmd_ShowResults, + [CMD_SAVE] = Cmd_SaveGame, + [CMD_ASK_PLAY_AGAIN] = Cmd_AskPlayAgain, + [CMD_COMM_PLAY_AGAIN] = Cmd_CommunicatePlayAgainResponses, + [CMD_PLAY_AGAIN_YES] = Cmd_PlayAgain, + [CMD_PLAY_AGAIN_NO] = Cmd_StopGame, + [CMD_CLOSE_LINK] = Cmd_CloseLink, + [CMD_QUIT] = Cmd_Quit, }; -static const u8 gUnknown_082F4434[][4] = +// Per group size, the number of A presses required to increase the number of sparkles. +static const u8 sSparkleThresholds[MAX_RFU_PLAYERS - 1][4] = { - {2, 4, 6, 7}, - {3, 5, 8, 11}, - {3, 7, 11, 15}, - {4, 8, 12, 17}, + {2, 4, 6, 7}, // 2 players + {3, 5, 8, 11}, // 3 players + {3, 7, 11, 15}, // 4 players + {4, 8, 12, 17}, // 5 players }; -static const u8 gUnknown_082F4444[] = {5, 7, 9, 12}; -static const u8 gUnknown_082F4448[] = {3, 7, 15, 31}; +// Per group size, the number of A presses required to get big sparkles +static const u8 sBigSparkleThresholds[MAX_RFU_PLAYERS - 1] = {5, 7, 9, 12}; + +static const u8 sReceivedPlayerBitmasks[] = {0x03, 0x07, 0x0F, 0x1F}; -struct BerryCrushGame * GetBerryCrushGame(void) +static struct BerryCrushGame * GetBerryCrushGame(void) { - return sBerryCrushGamePtr; + return sGame; } -u32 QuitBerryCrush(MainCallback callback) +static u32 QuitBerryCrush(MainCallback exitCallback) { - if (!sBerryCrushGamePtr) + if (!sGame) return 2; - if (!callback) - callback = sBerryCrushGamePtr->unk0; + if (!exitCallback) + exitCallback = sGame->exitCallback; - DestroyTask(sBerryCrushGamePtr->mainTask); - FREE_AND_SET_NULL(sBerryCrushGamePtr); - SetMainCallback2(callback); - if (callback == CB2_ReturnToField) + DestroyTask(sGame->taskId); + FREE_AND_SET_NULL(sGame); + SetMainCallback2(exitCallback); + if (exitCallback == CB2_ReturnToField) { gTextFlags.autoScroll = TRUE; PlayNewMapMusic(MUS_POKE_CENTER); @@ -825,17 +984,23 @@ u32 QuitBerryCrush(MainCallback callback) return 0; } -void StartBerryCrush(MainCallback callback) +#define ERROR_EXIT(exitCallback) \ + { \ + SetMainCallback2(exitCallback); \ + Rfu.unk_10 = 0; \ + Rfu.unk_12 = 0; \ + Rfu.errorState = 1; \ + } + +void StartBerryCrush(MainCallback exitCallback) { u8 playerCount = 0; u8 multiplayerId; if (!gReceivedRemoteLinkPlayers || gWirelessCommType == 0) { - SetMainCallback2(callback); - Rfu.unk_10 = 0; - Rfu.unk_12 = 0; - Rfu.errorState = 1; + // Link disconnected + ERROR_EXIT(exitCallback); return; } @@ -843,35 +1008,31 @@ void StartBerryCrush(MainCallback callback) multiplayerId = GetMultiplayerId(); if (playerCount < 2 || multiplayerId >= playerCount) { - SetMainCallback2(callback); - Rfu.unk_10 = 0; - Rfu.unk_12 = 0; - Rfu.errorState = 1; + // Too few players, or invalid id + ERROR_EXIT(exitCallback); return; } - sBerryCrushGamePtr = AllocZeroed(sizeof(struct BerryCrushGame)); - if (!sBerryCrushGamePtr) + sGame = AllocZeroed(sizeof(*sGame)); + if (!sGame) { - SetMainCallback2(callback); - Rfu.unk_10 = 0; - Rfu.unk_12 = 0; - Rfu.errorState = 1; + // Alloc failed + ERROR_EXIT(exitCallback); return; } - sBerryCrushGamePtr->unk0 = callback; - sBerryCrushGamePtr->unk8 = multiplayerId; - sBerryCrushGamePtr->unk9 = playerCount; - ParseName_Options(sBerryCrushGamePtr); - sBerryCrushGamePtr->unk12 = 1; - sBerryCrushGamePtr->unkE = 1; - sBerryCrushGamePtr->unkF = 6; - BerryCrush_SetPaletteFadeParams(sBerryCrushGamePtr->unk36, 1, -1, 0, 16, 0, 0); - BerryCrush_RunOrScheduleCommand(4, 1, sBerryCrushGamePtr->unk36); + sGame->exitCallback = exitCallback; + sGame->localId = multiplayerId; + sGame->playerCount = playerCount; + SetNamesAndTextSpeed(sGame); + sGame->gameState = STATE_INIT; + sGame->nextCmd = CMD_FADE; + sGame->afterPalFadeCmd = CMD_READY_BEGIN; + SetPaletteFadeArgs(sGame->commandArgs, TRUE, PALETTES_ALL, 0, 16, 0, RGB_BLACK); + RunOrScheduleCommand(CMD_SHOW_GAME, 1, sGame->commandArgs); SetMainCallback2(MainCB); - sBerryCrushGamePtr->mainTask = CreateTask(MainTask, 8); - gTextFlags.autoScroll = 0; + sGame->taskId = CreateTask(MainTask, 8); + gTextFlags.autoScroll = FALSE; } static void GetBerryFromBag(void) @@ -881,18 +1042,18 @@ static void GetBerryFromBag(void) else RemoveBagItem(gSpecialVar_ItemId, 1); - sBerryCrushGamePtr->unk98[sBerryCrushGamePtr->unk8].unkC = gSpecialVar_ItemId - FIRST_BERRY_INDEX; - sBerryCrushGamePtr->unkE = 1; - sBerryCrushGamePtr->unkF = 9; - BerryCrush_SetPaletteFadeParams(sBerryCrushGamePtr->unk36, 0, -1, 0, 16, 0, 0); - BerryCrush_RunOrScheduleCommand(4, 1, sBerryCrushGamePtr->unk36); - sBerryCrushGamePtr->mainTask = CreateTask(MainTask, 8); + sGame->players[sGame->localId].berryId = gSpecialVar_ItemId - FIRST_BERRY_INDEX; + sGame->nextCmd = CMD_FADE; + sGame->afterPalFadeCmd = CMD_WAIT_BERRIES; + SetPaletteFadeArgs(sGame->commandArgs, FALSE, PALETTES_ALL, 0, 16, 0, RGB_BLACK); + RunOrScheduleCommand(CMD_SHOW_GAME, 1, sGame->commandArgs); + sGame->taskId = CreateTask(MainTask, 8); SetMainCallback2(MainCB); } -static void BerryCrush_SetupMainTask(void) +static void ChooseBerry(void) { - DestroyTask(sBerryCrushGamePtr->mainTask); + DestroyTask(sGame->taskId); ChooseBerryForMachine(GetBerryFromBag); } @@ -906,54 +1067,60 @@ static void BerryCrush_InitVBlankCB(void) SetVBlankCallback(NULL); } -static void BerryCrush_SaveResults(void) +static void SaveResults(void) { - u32 var0, var1; + u32 time, presses; - var0 = sBerryCrushGamePtr->unk68.unk04; - var0 = Q_24_8(var0); - var0 = MathUtil_Div32(var0, Q_24_8(60)); - var1 = sBerryCrushGamePtr->unk68.unk0A; - var1 = Q_24_8(var1); - var1 = MathUtil_Div32(var1, var0) & 0xFFFF; - sBerryCrushGamePtr->unk16 = var1; - switch (sBerryCrushGamePtr->unk9) + // Calculate pressing speed ((time / 60) / presses) + time = sGame->results.time; + time = Q_24_8(time); + time = MathUtil_Div32(time, Q_24_8(60)); + presses = sGame->results.totalAPresses; + presses = Q_24_8(presses); + presses = MathUtil_Div32(presses, time) & 0xFFFF; + sGame->pressingSpeed = presses; + + switch (sGame->playerCount) { case 2: - if (sBerryCrushGamePtr->unk16 > gSaveBlock2Ptr->berryCrush.berryCrushResults[0]) + if (sGame->pressingSpeed > gSaveBlock2Ptr->berryCrush.pressingSpeeds[0]) { - sBerryCrushGamePtr->unk25_1 = 1; - gSaveBlock2Ptr->berryCrush.berryCrushResults[0] = sBerryCrushGamePtr->unk16; + // New 2-player record + sGame->newRecord = TRUE; + gSaveBlock2Ptr->berryCrush.pressingSpeeds[0] = sGame->pressingSpeed; } break; case 3: - if (sBerryCrushGamePtr->unk16 > gSaveBlock2Ptr->berryCrush.berryCrushResults[1]) + if (sGame->pressingSpeed > gSaveBlock2Ptr->berryCrush.pressingSpeeds[1]) { - sBerryCrushGamePtr->unk25_1 = 1; - gSaveBlock2Ptr->berryCrush.berryCrushResults[1] = sBerryCrushGamePtr->unk16; + // New 3-player record + sGame->newRecord = TRUE; + gSaveBlock2Ptr->berryCrush.pressingSpeeds[1] = sGame->pressingSpeed; } break; case 4: - if (sBerryCrushGamePtr->unk16 > gSaveBlock2Ptr->berryCrush.berryCrushResults[2]) + if (sGame->pressingSpeed > gSaveBlock2Ptr->berryCrush.pressingSpeeds[2]) { - sBerryCrushGamePtr->unk25_1 = 1; - gSaveBlock2Ptr->berryCrush.berryCrushResults[2] = sBerryCrushGamePtr->unk16; + // New 4-player record + sGame->newRecord = TRUE; + gSaveBlock2Ptr->berryCrush.pressingSpeeds[2] = sGame->pressingSpeed; } break; case 5: - if (sBerryCrushGamePtr->unk16 > gSaveBlock2Ptr->berryCrush.berryCrushResults[3]) + if (sGame->pressingSpeed > gSaveBlock2Ptr->berryCrush.pressingSpeeds[3]) { - sBerryCrushGamePtr->unk25_1 = 1; - gSaveBlock2Ptr->berryCrush.berryCrushResults[3] = sBerryCrushGamePtr->unk16; + // New 5-player record + sGame->newRecord = TRUE; + gSaveBlock2Ptr->berryCrush.pressingSpeeds[3] = sGame->pressingSpeed; } break; } - sBerryCrushGamePtr->unk1C = sBerryCrushGamePtr->unk68.unk00; - if (GiveBerryPowder(sBerryCrushGamePtr->unk1C)) + sGame->powder = sGame->results.powder; + if (GiveBerryPowder(sGame->powder)) return; - sBerryCrushGamePtr->unk25_0 = 1; + sGame->noRoomForPowder = TRUE; } static void VBlankCB(void) @@ -973,46 +1140,44 @@ static void MainCB(void) static void MainTask(u8 taskId) { - if (sBerryCrushGamePtr->unk4) - sBerryCrushGamePtr->unk4(sBerryCrushGamePtr, sBerryCrushGamePtr->unk36); + if (sGame->cmdCallback) + sGame->cmdCallback(sGame, sGame->commandArgs); - sub_8021450(sBerryCrushGamePtr); + UpdateGame(sGame); } -static void ParseName_Options(struct BerryCrushGame *arg0) +static void SetNamesAndTextSpeed(struct BerryCrushGame *game) { - u8 i = 0; - - for (; i < arg0->unk9; i++) - StringCopy(arg0->unk98[i].unk0, gLinkPlayers[i].name); - for (; i < 5; i++) + u8 i; + for (i = 0; i < game->playerCount; i++) + StringCopy(game->players[i].name, gLinkPlayers[i].name); + for (; i < MAX_RFU_PLAYERS; i++) { - memset(arg0->unk98[i].unk0, 1, PLAYER_NAME_LENGTH); - arg0->unk98[i].unk0[PLAYER_NAME_LENGTH] = EOS; + memset(game->players[i].name, 1, PLAYER_NAME_LENGTH); + game->players[i].name[PLAYER_NAME_LENGTH] = EOS; } switch (gSaveBlock2Ptr->optionsTextSpeed) { case OPTIONS_TEXT_SPEED_SLOW: - arg0->unkB = 8; + game->textSpeed = 8; break; case OPTIONS_TEXT_SPEED_MID: - arg0->unkB = 4; + game->textSpeed = 4; break; case OPTIONS_TEXT_SPEED_FAST: - arg0->unkB = 1; + game->textSpeed = 1; break; } } -// TODO: Everything from here on is likely in separate files. -s32 InitBerryCrushDisplay(void) +static s32 ShowGameDisplay(void) { struct BerryCrushGame *game = GetBerryCrushGame(); if (!game) return -1; - switch (game->unkC) + switch (game->cmdState) { case 0: SetVBlankCallback(NULL); @@ -1033,10 +1198,10 @@ s32 InitBerryCrushDisplay(void) break; case 3: ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, gUnknown_082F32C8, ARRAY_COUNT(gUnknown_082F32C8)); - SetBgTilemapBuffer(1, game->unk138.unk88[0]); - SetBgTilemapBuffer(2, game->unk138.unk88[2]); - SetBgTilemapBuffer(3, game->unk138.unk88[3]); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + SetBgTilemapBuffer(1, game->gfx.bgBuffers[0]); + SetBgTilemapBuffer(2, game->gfx.bgBuffers[2]); + SetBgTilemapBuffer(3, game->gfx.bgBuffers[3]); ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(2, 0, 0); @@ -1057,7 +1222,7 @@ s32 InitBerryCrushDisplay(void) CopyBgTilemapBufferToVram(1); CopyBgTilemapBufferToVram(2); CopyBgTilemapBufferToVram(3); - DecompressAndCopyTileDataToVram(1, gUnknown_08DE34B8, 0, 0, 0); + DecompressAndCopyTileDataToVram(1, gBerryCrush_Crusher_Gfx, 0, 0, 0); break; case 6: if (FreeTempTileDataBuffersIfPossible()) @@ -1065,16 +1230,16 @@ s32 InitBerryCrushDisplay(void) InitStandardTextBoxWindows(); InitTextBoxGfxAndPrinters(); - sub_8022588(game); - sub_8022600(game); + CreatePlayerNameWindows(game); + DrawPlayerNameWindows(game); gPaletteFade.bufferTransferDisabled = TRUE; break; case 7: - LoadPalette(gUnknown_08DE3398, 0, 0x180); - CopyToBgTilemapBuffer(1, gBerryCrushGrinderTopTilemap, 0, 0); - CopyToBgTilemapBuffer(2, gBerryCrushContainerCapTilemap, 0, 0); - CopyToBgTilemapBuffer(3, gBerryCrushBackgroundTilemap, 0, 0); - sub_80226D0(game); + LoadPalette(gBerryCrush_Crusher_Pal, 0, 0x180); + CopyToBgTilemapBuffer(1, sCrusherTop_Tilemap, 0, 0); + CopyToBgTilemapBuffer(2, sContainerCap_Tilemap, 0, 0); + CopyToBgTilemapBuffer(3, sBg_Tilemap, 0, 0); + CopyPlayerNameWindowGfxToBg(game); CopyBgTilemapBufferToVram(1); CopyBgTilemapBufferToVram(2); CopyBgTilemapBufferToVram(3); @@ -1082,7 +1247,7 @@ s32 InitBerryCrushDisplay(void) case 8: LoadWirelessStatusIndicatorSpriteGfx(); CreateWirelessStatusIndicatorSprite(0, 0); - sub_8022730(game); + CreateGameSprites(game); SetGpuReg(REG_OFFSET_BG1VOFS, -gSpriteCoordOffsetY); ChangeBgX(1, 0, 0); ChangeBgY(1, 0, 0); @@ -1096,21 +1261,21 @@ s32 InitBerryCrushDisplay(void) ShowBg(3); SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); BerryCrush_SetVBlankCB(); - game->unkC = 0; + game->cmdState = 0; return 1; } - game->unkC++; + game->cmdState++; return 0; } -static s32 BerryCrush_TeardownBgs(void) +static s32 HideGameDisplay(void) { - struct BerryCrushGame *var0 = GetBerryCrushGame(); - if (!var0) + struct BerryCrushGame *game = GetBerryCrushGame(); + if (!game) return -1; - switch (var0->unkC) + switch (game->cmdState) { case 0: Rfu_SetLinkStandbyCallback(); @@ -1118,8 +1283,11 @@ static s32 BerryCrush_TeardownBgs(void) case 1: if (!IsLinkTaskFinished()) return 0; - // fall through. The original author forgot to use "break" here - // because this will call BeginNormalPaletteFade() twice. + // fall through + // This will call BeginNormalPaletteFade() twice. +#ifdef BUGFIX + break; +#endif case 2: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); UpdatePaletteFade(); @@ -1152,83 +1320,98 @@ static s32 BerryCrush_TeardownBgs(void) break; case 6: DestroyWirelessStatusIndicatorSprite(); - sub_8022960(var0); + DestroyGameSprites(game); DigitObjUtil_Free(); break; case 7: - var0->unkC = 0; + game->cmdState = 0; return 1; } - var0->unkC++; + game->cmdState++; return 0; } -static s32 sub_8021450(struct BerryCrushGame *arg0) +// Handles the crusher vibration and the timer +static s32 UpdateGame(struct BerryCrushGame *game) { - gSpriteCoordOffsetY = arg0->unk2A + arg0->unk2C; + gSpriteCoordOffsetY = game->depth + game->vibration; SetGpuReg(REG_OFFSET_BG1VOFS, -gSpriteCoordOffsetY); - if (arg0->unk12 == 7) - { - BerryCrush_PrintTimeOnSprites(&arg0->unk138, arg0->unk28); - } + + if (game->gameState == STATE_PLAYING) + PrintTimer(&game->gfx, game->timer); return 0; } -void sub_8021488(struct BerryCrushGame *arg0) +static void ResetCrusherPos(struct BerryCrushGame *game) { - arg0->unk2A = -104; - arg0->unk2C = 0; + game->depth = CRUSHER_START_Y; + game->vibration = 0; gSpriteCoordOffsetX = 0; - gSpriteCoordOffsetY = -104; -} - -static void BerryCrush_CreateBerrySprites(struct BerryCrushGame *arg0, struct BerryCrushGame_138 *arg1) + gSpriteCoordOffsetY = CRUSHER_START_Y; +} + +// Sprite data for berry sprites. Identical to fields for sparkle sprites +#define sX data[0] +#define sYSpeed data[1] +#define sYAccel data[2] +#define sXSpeed data[3] +#define sSinIdx data[4] +#define sSinSpeed data[5] +#define sAmplitude data[6] +// The last element (data[7]) is a bitfield. +// The first 15 bits are the y coord to stop at. +// The last bit is a flag for whether or not to move horizontally too +#define sBitfield data[7] +#define MASK_TARGET_Y 0x7FFF +#define F_MOVE_HORIZ 0x8000 + +static void CreateBerrySprites(struct BerryCrushGame *game, struct BerryCrushGame_Gfx *gfx) { u8 i; u8 spriteId; - s16 var0, var1; + s16 distance, var1; s16 *data; - s32 var3; - s16 var5; - u32 var6; + s32 amplitude; + s16 speed; + u32 var2; - for (i = 0; i < arg0->unk9; i++) + for (i = 0; i < game->playerCount; i++) { spriteId = AddCustomItemIconSprite( &sSpriteTemplate_PlayerBerry, sPlayerBerrySpriteTags[i], sPlayerBerrySpriteTags[i], - arg0->unk98[i].unkC + FIRST_BERRY_INDEX); - arg1->unk38[i] = &gSprites[spriteId]; - arg1->unk38[i]->oam.priority = 3; - arg1->unk38[i]->affineAnimPaused = TRUE; - arg1->unk38[i]->pos1.x = arg1->unkC[i]->unk8 + 120; - arg1->unk38[i]->pos1.y = -16; - data = arg1->unk38[i]->data; - var5 = 512; - data[1] = var5; - data[2] = 32; - data[7] = 112; - var0 = arg1->unkC[i]->unkA - arg1->unkC[i]->unk8; - var3 = var0; - if (var0 < 0) - var3 += 3; - - data[6] = var3 >> 2; - var0 *= 128; - var6 = var5 + 32; - var6 = var6 / 2; - var1 = MathUtil_Div16Shift(7, Q_8_8(63.5), var6); - data[0] = (u16)arg1->unk38[i]->pos1.x * 128; - data[3] = MathUtil_Div16Shift(7, var0, var1); + game->players[i].berryId + FIRST_BERRY_INDEX); + gfx->berrySprites[i] = &gSprites[spriteId]; + gfx->berrySprites[i]->oam.priority = 3; + gfx->berrySprites[i]->affineAnimPaused = TRUE; + gfx->berrySprites[i]->pos1.x = gfx->playerCoords[i]->berryXOffset + 120; + gfx->berrySprites[i]->pos1.y = -16; + data = gfx->berrySprites[i]->data; + speed = 512; + sYSpeed = speed; + sYAccel = 32; + sBitfield = 112; // Setting bits in MASK_TARGET_Y + distance = gfx->playerCoords[i]->berryXDest - gfx->playerCoords[i]->berryXOffset; + amplitude = distance; + if (distance < 0) + amplitude += 3; + + sAmplitude = amplitude >> 2; + distance *= 128; + var2 = speed + 32; + var2 = var2 / 2; + var1 = MathUtil_Div16Shift(7, Q_8_8(63.5), var2); + sX = (u16)gfx->berrySprites[i]->pos1.x * 128; + sXSpeed = MathUtil_Div16Shift(7, distance, var1); var1 = MathUtil_Mul16Shift(7, var1, 85); - data[4] = 0; - data[5] = MathUtil_Div16Shift(7, Q_8_8(63.5), var1); - data[7] |= 0x8000; - if (arg1->unkC[i]->unk8 < 0) - StartSpriteAffineAnim(arg1->unk38[i], 1); + sSinIdx = 0; + sSinSpeed = MathUtil_Div16Shift(7, Q_8_8(63.5), var1); + sBitfield |= F_MOVE_HORIZ; + if (gfx->playerCoords[i]->berryXOffset < 0) + StartSpriteAffineAnim(gfx->berrySprites[i], 1); } } @@ -1236,22 +1419,22 @@ static void SpriteCB_DropBerryIntoCrusher(struct Sprite *sprite) { s16 *data = sprite->data; - data[1] += data[2]; - sprite->pos2.y += data[1] >> 8; - if (data[7] & 0x8000) + sYSpeed += sYAccel; + sprite->pos2.y += sYSpeed >> 8; + if (sBitfield & F_MOVE_HORIZ) { - sprite->data[0] += data[3]; - data[4] += data[5]; - sprite->pos2.x = Sin(data[4] >> 7, data[6]); - if ((data[7] & 0x8000) && (data[4] >> 7) > 126) + sprite->sX += sXSpeed; + sSinIdx += sSinSpeed; + sprite->pos2.x = Sin(sSinIdx >> 7, sAmplitude); + if ((sBitfield & F_MOVE_HORIZ) && (sSinIdx >> 7) > 126) { sprite->pos2.x = 0; - data[7] &= 0x7FFF; + sBitfield &= MASK_TARGET_Y; } } - sprite->pos1.x = data[0] >> 7; - if (sprite->pos1.y + sprite->pos2.y >= (data[7] & 0x7FFF)) + sprite->pos1.x = sX >> 7; + if (sprite->pos1.y + sprite->pos2.y >= (sBitfield & MASK_TARGET_Y)) { sprite->callback = SpriteCallbackDummy; FreeSpriteOamMatrix(sprite); @@ -1259,119 +1442,143 @@ static void SpriteCB_DropBerryIntoCrusher(struct Sprite *sprite) } } -void BerryCrushFreeBerrySpriteGfx(struct BerryCrushGame *arg0, __attribute__((unused)) struct BerryCrushGame_138 *arg1) +#undef sX +#undef sYSpeed +#undef sYAccel +#undef sXSpeed +#undef sSinIdx +#undef sSinSpeed +#undef sAmplitude +#undef sBitfield +#undef MASK_TARGET_Y +#undef F_MOVE_HORIZ + +static void BerryCrushFreeBerrySpriteGfx(struct BerryCrushGame *game, struct BerryCrushGame_Gfx *gfx) { u8 i; - for (i = 0; i < arg0->unk9; i++) + for (i = 0; i < game->playerCount; i++) { FreeSpritePaletteByTag(sPlayerBerrySpriteTags[i]); FreeSpriteTilesByTag(sPlayerBerrySpriteTags[i]); } } -void sub_80216E0(struct BerryCrushGame *arg0, struct BerryCrushGame_138 *arg1) +static void UpdateInputEffects(struct BerryCrushGame *game, struct BerryCrushGame_Gfx *gfx) { - u8 sp4; - struct BerryCrushGame_4E *var4E; + u8 numPlayersPressed; + struct BerryCrushGame_LinkState *linkState; u8 i; - u16 var, var2; + u16 temp1, xModifier; - sp4 = 0; - var4E = (struct BerryCrushGame_4E *)arg0->unk4E; - for (i = 0; i < arg0->unk9; i++) + numPlayersPressed = 0; + linkState = (struct BerryCrushGame_LinkState *)game->recvCmd; + + // Read inputs and update impact effects + for (i = 0; i < game->playerCount; i++) { - var = var4E->unkA >> (i * 3); - var &= 7; - if (var) + #define flags temp1 + + flags = linkState->inputFlags >> (i * INPUT_FLAGS_PER_PLAYER); + flags &= INPUT_FLAG_MASK; + if (flags) { - sp4++; - if (var & 0x4) - StartSpriteAnim(arg1->unk24[i], 1); + numPlayersPressed++; + if (flags & F_INPUT_HIT_SYNC) + StartSpriteAnim(gfx->impactSprites[i], 1); // Big impact sprite else - StartSpriteAnim(arg1->unk24[i], 0); + StartSpriteAnim(gfx->impactSprites[i], 0); // Small impact sprite - arg1->unk24[i]->invisible = FALSE; - arg1->unk24[i]->animPaused = FALSE; - arg1->unk24[i]->pos2.x = gUnknown_082F41CC[(var % 4) - 1][0]; - arg1->unk24[i]->pos2.y = gUnknown_082F41CC[(var % 4) - 1][1]; + gfx->impactSprites[i]->invisible = FALSE; + gfx->impactSprites[i]->animPaused = FALSE; + gfx->impactSprites[i]->pos2.x = sImpactCoords[(flags % (ARRAY_COUNT(sImpactCoords) + 1)) - 1][0]; + gfx->impactSprites[i]->pos2.y = sImpactCoords[(flags % (ARRAY_COUNT(sImpactCoords) + 1)) - 1][1]; } + + #undef flags } - if (sp4 == 0) + if (numPlayersPressed == 0) { - arg0->unk25_2 = 0; + game->playedSound = FALSE; } else { - var = (u8)(arg0->unk28 % 3); - var2 = var; - for (i = 0; i < var4E->unkC * 2 + 3; i++) + // Update sparkle effect + #define yModifier temp1 + + yModifier = (u8)(game->timer % 3); + xModifier = yModifier; + for (i = 0; i < linkState->sparkleAmount * 2 + 3; i++) { - if (arg1->unk4C[i]->invisible) + if (gfx->sparkleSprites[i]->invisible) { - arg1->unk4C[i]->callback = sub_8022B28; - arg1->unk4C[i]->pos1.x = gUnknown_082F41D2[i][0] + 120; - arg1->unk4C[i]->pos1.y = gUnknown_082F41D2[i][1] + 136 - (var * 4); - arg1->unk4C[i]->pos2.x = gUnknown_082F41D2[i][0] + (gUnknown_082F41D2[i][0] / (var2 * 4)); - arg1->unk4C[i]->pos2.y = gUnknown_082F41D2[i][1]; - if (var4E->unk4_1) - StartSpriteAnim(arg1->unk4C[i], 1); + gfx->sparkleSprites[i]->callback = SpriteCB_Sparkle_Init; + gfx->sparkleSprites[i]->pos1.x = sSparkleCoords[i][0] + 120; + gfx->sparkleSprites[i]->pos1.y = sSparkleCoords[i][1] + 136 - (yModifier * 4); + gfx->sparkleSprites[i]->pos2.x = sSparkleCoords[i][0] + (sSparkleCoords[i][0] / (xModifier * 4)); + gfx->sparkleSprites[i]->pos2.y = sSparkleCoords[i][1]; + if (linkState->bigSparkle) + StartSpriteAnim(gfx->sparkleSprites[i], 1); else - StartSpriteAnim(arg1->unk4C[i], 0); + StartSpriteAnim(gfx->sparkleSprites[i], 0); - var++; - if (var > 3) - var = 0; + yModifier++; + if (yModifier > 3) + yModifier = 0; } } - if (arg0->unk25_2) + #undef yModifier + + if (game->playedSound) { - arg0->unk25_2 = 0; + game->playedSound = FALSE; } else { - if (sp4 == 1) + if (numPlayersPressed == 1) PlaySE(SE_MUD_BALL); else PlaySE(SE_BREAKABLE_DOOR); - arg0->unk25_2 = 1; + game->playedSound = TRUE; } } } -bool32 sub_80218D4(struct BerryCrushGame *arg0, struct BerryCrushGame_138 *arg1) +static bool32 AreEffectsFinished(struct BerryCrushGame *game, struct BerryCrushGame_Gfx *gfx) { u8 i; - for (i = 0; i < arg0->unk9; i++) + // Are any impact sprites active + for (i = 0; i < game->playerCount; i++) { - if (!arg1->unk24[i]->invisible) + if (!gfx->impactSprites[i]->invisible) return FALSE; } - for (i = 0; i < 11; i++) + // Are any sparkle sprites active + for (i = 0; i < ARRAY_COUNT(gfx->sparkleSprites); i++) { - if (!arg1->unk4C[i]->invisible) + if (!gfx->sparkleSprites[i]->invisible) return FALSE; } - if (arg0->unk2C != 0) - arg0->unk2C = 0; + if (game->vibration != 0) + game->vibration = 0; return TRUE; } -static void FramesToMinSec(struct BerryCrushGame_138 *arg0, u16 arg1) +static void FramesToMinSec(struct BerryCrushGame_Gfx *gfx, u16 frames) { u8 i = 0; u32 fractionalFrames = 0; s16 r3 = 0; - arg0->unk4 = arg1 / 3600; - arg0->unk6 = (arg1 % 3600) / 60; - r3 = MathUtil_Mul16(Q_8_8(arg1 % 60), 4); + gfx->minutes = frames / (60 * 60); + gfx->secondsInt = (frames % (60 * 60)) / 60; + r3 = MathUtil_Mul16(Q_8_8(frames % 60), 4); for (i = 0; i < 8; i++) { @@ -1379,277 +1586,262 @@ static void FramesToMinSec(struct BerryCrushGame_138 *arg0, u16 arg1) fractionalFrames += sPressingSpeedConversionTable[i]; } - arg0->unk8 = fractionalFrames / 1000000; + gfx->secondsFrac = fractionalFrames / 1000000; } static void PrintTextCentered(u8 windowId, u8 left, u8 colorId, const u8 *string) { left = (left * 4) - (GetStringWidth(2, string, -1) / 2u); - AddTextPrinterParameterized3(windowId, 2, left, 0, sBerryCrushTextColorTable[colorId], 0, string); + AddTextPrinterParameterized3(windowId, 2, left, 0, sTextColorTable[colorId], 0, string); } -static void PrintBerryCrushResultWindow(struct BerryCrushGame * sp0C, u8 sp10, u8 sp14, u8 sp18) +static void PrintResultsText(struct BerryCrushGame * game, u8 page, u8 sp14, u8 baseY) { - u8 r8; - u8 sp1C = 0; - u8 sp20 = 0; - u8 r2; - s32 r3; - u8 r7; - struct BerryCrushGame_68 * sp24 = &sp0C->unk68; + u8 i, j; + u8 playerId = 0; + u8 ranking = 0; + s32 x; + u8 stat; + struct BerryCrushGame_Results * results = &game->results; u32 xOffset; - s32 r6; - - sp18 -= 16; - if (sp10 == 2) - sp18 -= 42; - r6 = sp18 - 14 * sp0C->unk9; - if (r6 > 0) - r6 = r6 / 2 + 16; + s32 y; + + baseY -= 16; + if (page == RESULTS_PAGE_CRUSHING) + baseY -= 42; + + y = baseY - 14 * game->playerCount; + if (y > 0) + y = y / 2 + 16; else - r6 = 16; + y = 16; - for (r8 = 0; r8 < sp0C->unk9; r6 += 14, ++r8) + for (i = 0; i < game->playerCount; y += 14, i++) { DynamicPlaceholderTextUtil_Reset(); - switch (sp10) + switch (page) { - case 0: - sp1C = sp24->unk20[sp10][r8]; - if (r8 != 0 && sp24->unk0C[sp10][r8] != sp24->unk0C[sp10][r8 - 1]) - sp20 = r8; - ConvertIntToDecimalStringN(gStringVar4, sp24->unk0C[sp10][r8], STR_CONV_MODE_RIGHT_ALIGN, 4); - StringAppend(gStringVar4, gUnknown_082F43B4[sp10]); + case RESULTS_PAGE_PRESSES: + playerId = results->playerIdsRanked[page][i]; + if (i != 0 && results->stats[page][i] != results->stats[page][i - 1]) + ranking = i; + ConvertIntToDecimalStringN(gStringVar4, results->stats[page][i], STR_CONV_MODE_RIGHT_ALIGN, 4); + StringAppend(gStringVar4, sResultsTexts[page]); break; - case 1: - sp1C = sp24->unk20[sp10][r8]; - if (r8 != 0 && sp24->unk0C[sp10][r8] != sp24->unk0C[sp10][r8 - 1]) - sp20 = r8; - ConvertIntToDecimalStringN(gStringVar1, sp24->unk0C[sp10][r8] >> 4, STR_CONV_MODE_RIGHT_ALIGN, 3); + case RESULTS_PAGE_RANDOM: + playerId = results->playerIdsRanked[page][i]; + if (i != 0 && results->stats[page][i] != results->stats[page][i - 1]) + ranking = i; + ConvertIntToDecimalStringN(gStringVar1, results->stats[page][i] >> 4, STR_CONV_MODE_RIGHT_ALIGN, 3); xOffset = 0; - r7 = sp24->unk0C[sp10][r8] & 15; - for (r2 = 0; r2 < 4; ++r2) - if ((r7 >> (3 - r2)) & 1) - xOffset += sPressingSpeedConversionTable[r2]; - r7 = xOffset / 1000000u; - ConvertIntToDecimalStringN(gStringVar2, r7, STR_CONV_MODE_LEADING_ZEROS, 2); - StringExpandPlaceholders(gStringVar4, gUnknown_082F43B4[sp10]); + stat = results->stats[page][i] & 15; + for (j = 0; j < 4; j++) + if ((stat >> (3 - j)) & 1) + xOffset += sPressingSpeedConversionTable[j]; + stat = xOffset / 1000000u; + ConvertIntToDecimalStringN(gStringVar2, stat, STR_CONV_MODE_LEADING_ZEROS, 2); + StringExpandPlaceholders(gStringVar4, sResultsTexts[page]); break; - case 2: - sp1C = r8; - sp20 = r8; - r2 = sp0C->unk98[r8].unkC; - if (r2 >= LAST_BERRY_INDEX - FIRST_BERRY_INDEX + 2) - r2 = 0; - StringCopy(gStringVar1, gBerries[r2].name); - StringExpandPlaceholders(gStringVar4, gUnknown_082F43B4[sp10]); + case RESULTS_PAGE_CRUSHING: + playerId = i; + ranking = i; + j = game->players[i].berryId; + if (j >= LAST_BERRY_INDEX - FIRST_BERRY_INDEX + 2) + j = 0; + StringCopy(gStringVar1, gBerries[j].name); + StringExpandPlaceholders(gStringVar4, sResultsTexts[page]); break; } - r3 = GetStringRightAlignXOffset(2, gStringVar4, sp14 - 4); - AddTextPrinterParameterized3(sp0C->unk138.unk82, 2, r3, r6, sBerryCrushTextColorTable[0], 0, gStringVar4); - if (sp1C == sp0C->unk8) + x = GetStringRightAlignXOffset(2, gStringVar4, sp14 - 4); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); + if (playerId == game->localId) StringCopy(gStringVar3, gText_1DotBlueF700); else StringCopy(gStringVar3, gText_1DotF700); - gStringVar3[0] = sp20 + CHAR_1; - DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, sp0C->unk98[sp1C].unk0); + gStringVar3[0] = ranking + CHAR_1; + DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, game->players[playerId].name); DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gStringVar3); - AddTextPrinterParameterized3(sp0C->unk138.unk82, 2, 4, r6, sBerryCrushTextColorTable[0], 0, gStringVar4); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, 4, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); } } -static void sub_8021D34(struct BerryCrushGame *r8) +static void PrintCrushingResults(struct BerryCrushGame *game) { - u8 r10 = 0; - u8 r6 = 0; - u32 sp0C = 0; - struct BerryCrushGame_68 *sp10 = &r8->unk68; - u8 r7 = GetWindowAttribute(r8->unk138.unk82, WINDOW_HEIGHT) * 8 - 42; + u8 i = 0; + u8 x = 0; + u32 pressingSpeedFrac = 0; + struct BerryCrushGame_Results *results = &game->results; + u8 y = GetWindowAttribute(game->gfx.resultsWindowId, WINDOW_HEIGHT) * 8 - 42; + + FramesToMinSec(&game->gfx, results->time); + + // Print time text + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gText_TimeColon); - FramesToMinSec(&r8->unk138, sp10->unk04); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gText_TimeColon); - r6 = 176 - (u8)GetStringWidth(2, gText_SpaceSec, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gText_SpaceSec); - ConvertIntToDecimalStringN(gStringVar1, r8->unk138.unk6, STR_CONV_MODE_LEADING_ZEROS, 2); - ConvertIntToDecimalStringN(gStringVar2, r8->unk138.unk8, STR_CONV_MODE_LEADING_ZEROS, 2); + // Print seconds text + x = 176 - (u8)GetStringWidth(2, gText_SpaceSec, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gText_SpaceSec); + + // Print seconds value + ConvertIntToDecimalStringN(gStringVar1, game->gfx.secondsInt, STR_CONV_MODE_LEADING_ZEROS, 2); + ConvertIntToDecimalStringN(gStringVar2, game->gfx.secondsFrac, STR_CONV_MODE_LEADING_ZEROS, 2); StringExpandPlaceholders(gStringVar4, gText_XDotY2); - r6 -= GetStringWidth(2, gStringVar4, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gStringVar4); - r6 -= GetStringWidth(2, gText_SpaceMin, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gText_SpaceMin); - ConvertIntToDecimalStringN(gStringVar1, r8->unk138.unk4, STR_CONV_MODE_LEADING_ZEROS, 1); + x -= GetStringWidth(2, gStringVar4, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); + + // Print minutes text + x -= GetStringWidth(2, gText_SpaceMin, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gText_SpaceMin); + + // Print minutes value + ConvertIntToDecimalStringN(gStringVar1, game->gfx.minutes, STR_CONV_MODE_LEADING_ZEROS, 1); StringExpandPlaceholders(gStringVar4, gText_StrVar1); - r6 -= GetStringWidth(2, gStringVar4, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gStringVar4); - r7 += 14; - AddTextPrinterParameterized3(r8->unk138.unk82, 2, 0, r7, sBerryCrushTextColorTable[0], 0, gText_PressingSpeed); - r6 = 176 - (u8)GetStringWidth(2, gText_TimesPerSec, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gText_TimesPerSec); - for (; r10 < 8; ++r10) - if (((u8)r8->unk16 >> (7 - r10)) & 1) - sp0C += *(r10 + sPressingSpeedConversionTable); // It's accessed in a different way here for unknown reason - ConvertIntToDecimalStringN(gStringVar1, r8->unk16 >> 8, STR_CONV_MODE_RIGHT_ALIGN, 3); - ConvertIntToDecimalStringN(gStringVar2, sp0C / 1000000, STR_CONV_MODE_LEADING_ZEROS, 2); + x -= GetStringWidth(2, gStringVar4, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); + + // Print pressing speed text + y += 14; + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, 0, y, sTextColorTable[COLORID_GREY], 0, gText_PressingSpeed); + x = 176 - (u8)GetStringWidth(2, gText_TimesPerSec, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gText_TimesPerSec); + + // Print pressing speed value + for (i = 0; i < 8; i++) + if (((u8)game->pressingSpeed >> (7 - i)) & 1) + pressingSpeedFrac += *(i + sPressingSpeedConversionTable); // It's accessed in a different way here for unknown reason + ConvertIntToDecimalStringN(gStringVar1, game->pressingSpeed >> 8, STR_CONV_MODE_RIGHT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar2, pressingSpeedFrac / 1000000, STR_CONV_MODE_LEADING_ZEROS, 2); StringExpandPlaceholders(gStringVar4, gText_XDotY3); - r6 -= GetStringWidth(2, gStringVar4, -1); - if (r8->unk25_1) - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[5], 0, gStringVar4); + x -= GetStringWidth(2, gStringVar4, -1); + if (game->newRecord) + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_RED], 0, gStringVar4); else - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gStringVar4); - r7 += 14; - AddTextPrinterParameterized3(r8->unk138.unk82, 2, 0, r7, sBerryCrushTextColorTable[0], 0, gText_Silkiness); - ConvertIntToDecimalStringN(gStringVar1, sp10->unk08, STR_CONV_MODE_RIGHT_ALIGN, 3); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); + + // Print silkiness text + y += 14; + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, 0, y, sTextColorTable[COLORID_GREY], 0, gText_Silkiness); + + // Print silkiness value + ConvertIntToDecimalStringN(gStringVar1, results->silkiness, STR_CONV_MODE_RIGHT_ALIGN, 3); StringExpandPlaceholders(gStringVar4, gText_Var1Percent); - r6 = 176 - (u8)GetStringWidth(2, gStringVar4, -1); - AddTextPrinterParameterized3(r8->unk138.unk82, 2, r6, r7, sBerryCrushTextColorTable[0], 0, gStringVar4); + x = 176 - (u8)GetStringWidth(2, gStringVar4, -1); + AddTextPrinterParameterized3(game->gfx.resultsWindowId, 2, x, y, sTextColorTable[COLORID_GREY], 0, gStringVar4); } -static bool32 sub_8022070(struct BerryCrushGame *r4, struct BerryCrushGame_138 *r6) +static bool32 OpenResultsWindow(struct BerryCrushGame *game, struct BerryCrushGame_Gfx *gfx) { - u8 r5; + u8 playerCountIdx; struct WindowTemplate template; - switch (r6->unk80) + switch (gfx->resultsState) { case 0: - r5 = r4->unk9 - 2; - BerryCrush_HideTimerSprites(r6); - memcpy(&template, &gUnknown_082F3324[r4->unk12 - 11], sizeof(struct WindowTemplate)); - if (r4->unk12 == 13) - template.height = gUnknown_082F3344[1][r5]; + playerCountIdx = game->playerCount - 2; + HideTimer(gfx); + memcpy(&template, &sWindowTemplates_Results[game->gameState - RESULTS_STATE_START], sizeof(struct WindowTemplate)); + if (game->gameState == STATE_RESULTS_CRUSHING) + template.height = sResultsWindowHeights[1][playerCountIdx]; else - template.height = gUnknown_082F3344[0][r5]; - r6->unk82 = AddWindow(&template); + template.height = sResultsWindowHeights[0][playerCountIdx]; + gfx->resultsWindowId = AddWindow(&template); break; case 1: - PutWindowTilemap(r6->unk82); - FillWindowPixelBuffer(r6->unk82, PIXEL_FILL(0)); + PutWindowTilemap(gfx->resultsWindowId); + FillWindowPixelBuffer(gfx->resultsWindowId, PIXEL_FILL(0)); break; case 2: - LoadUserWindowBorderGfx_(r6->unk82, 541, 208); - DrawStdFrameWithCustomTileAndPalette(r6->unk82, 0, 541, 13); + LoadUserWindowBorderGfx_(gfx->resultsWindowId, 541, 208); + DrawStdFrameWithCustomTileAndPalette(gfx->resultsWindowId, 0, 541, 13); break; case 3: - r5 = r4->unk9 - 2; - switch (r4->unk12) + playerCountIdx = game->playerCount - 2; + switch (game->gameState) { - case 11: - PrintTextCentered(r6->unk82, 20, 3, gText_PressesRankings); - PrintBerryCrushResultWindow(r4, 0, 0xA0, 8 * gUnknown_082F3344[0][r5]); - r6->unk80 = 5; + case STATE_RESULTS_PRESSES: + PrintTextCentered(gfx->resultsWindowId, 20, COLORID_BLUE, gText_PressesRankings); + PrintResultsText(game, RESULTS_PAGE_PRESSES, 0xA0, 8 * sResultsWindowHeights[0][playerCountIdx]); + gfx->resultsState = 5; // Skip past Crushing Results text return FALSE; - case 12: - PrintTextCentered(r6->unk82, 20, 4, gUnknown_082F43B4[r4->unk68.unk20[0][7] + 3]); - PrintBerryCrushResultWindow(r4, 1, 0xA0, 8 * gUnknown_082F3344[0][r5]); - r6->unk80 = 5; + case STATE_RESULTS_RANDOM: + PrintTextCentered(gfx->resultsWindowId, 20, COLORID_GREEN, sResultsTexts[game->results.randomPageId + NUM_RESULTS_PAGES]); + PrintResultsText(game, RESULTS_PAGE_RANDOM, 0xA0, 8 * sResultsWindowHeights[0][playerCountIdx]); + gfx->resultsState = 5; // Skip past Crushing Results text return FALSE; - case 13: - PrintTextCentered(r6->unk82, 22, 3, gText_CrushingResults); - PrintBerryCrushResultWindow(r4, 2, 0xB0, 8 * gUnknown_082F3344[1][r5]); + case STATE_RESULTS_CRUSHING: + PrintTextCentered(gfx->resultsWindowId, 22, COLORID_BLUE, gText_CrushingResults); + PrintResultsText(game, RESULTS_PAGE_CRUSHING, 0xB0, 8 * sResultsWindowHeights[1][playerCountIdx]); break; } break; case 4: - sub_8021D34(r4); + PrintCrushingResults(game); break; case 5: - CopyWindowToVram(r6->unk82, 3); - r6->unk80 = 0; + CopyWindowToVram(gfx->resultsWindowId, 3); + gfx->resultsState = 0; return TRUE; } - ++r6->unk80; + gfx->resultsState++; return FALSE; } -static void sub_802222C(struct BerryCrushGame *r4) +static void CloseResultsWindow(struct BerryCrushGame *game) { - ClearStdWindowAndFrameToTransparent(r4->unk138.unk82, 1); - RemoveWindow(r4->unk138.unk82); - sub_8022600(r4); + ClearStdWindowAndFrameToTransparent(game->gfx.resultsWindowId, 1); + RemoveWindow(game->gfx.resultsWindowId); + DrawPlayerNameWindows(game); } -static void Task_ShowBerryCrushRankings(u8 taskId) +#define tState data[0] +#define tWindowId data[1] +#define tPressingSpeeds(i) data[2 + (i)] // data[2]-[5], for different group sizes + +static void Task_ShowRankings(u8 taskId) { u8 i = 0, j, xPos, yPos; u32 score = 0; s16 *data = gTasks[taskId].data; - switch (data[0]) + switch (tState) { case 0: - data[1] = AddWindow(&sWindowTemplate_BerryCrushRankings); - PutWindowTilemap(data[1]); - FillWindowPixelBuffer(data[1], PIXEL_FILL(0)); - LoadUserWindowBorderGfx_(data[1], 541, 208); - DrawStdFrameWithCustomTileAndPalette(data[1], 0, 541, 13); + tWindowId = AddWindow(&sWindowTemplate_Rankings); + PutWindowTilemap(tWindowId); + FillWindowPixelBuffer(tWindowId, PIXEL_FILL(0)); + LoadUserWindowBorderGfx_(tWindowId, 541, 208); + DrawStdFrameWithCustomTileAndPalette(tWindowId, 0, 541, 13); break; case 1: + // Print header text xPos = 96 - GetStringWidth(1, gText_BerryCrush2, -1) / 2u; - AddTextPrinterParameterized3( - data[1], - 1, - xPos, - 1, - sBerryCrushTextColorTable[3], - 0, - gText_BerryCrush2 - ); + AddTextPrinterParameterized3(tWindowId, 1, xPos, 1, sTextColorTable[COLORID_BLUE], 0, gText_BerryCrush2); xPos = 96 - GetStringWidth(1, gText_PressingSpeedRankings, -1) / 2u; - AddTextPrinterParameterized3( - data[1], - 1, - xPos, - 17, - sBerryCrushTextColorTable[3], - 0, - gText_PressingSpeedRankings - ); + AddTextPrinterParameterized3(tWindowId, 1, xPos, 17, sTextColorTable[COLORID_BLUE], 0, gText_PressingSpeedRankings); + + // Print pressing speed record for each group size, ranked yPos = 41; - for (i = 0; i < 4; ++i) + for (i = 0; i < MAX_RFU_PLAYERS - 1; i++) { ConvertIntToDecimalStringN(gStringVar1, i + 2, STR_CONV_MODE_LEFT_ALIGN, 1); StringExpandPlaceholders(gStringVar4, gText_Var1Players); - AddTextPrinterParameterized3( - data[1], - 1, - 0, - yPos, - sBerryCrushTextColorTable[0], - 0, - gStringVar4 - ); + AddTextPrinterParameterized3(tWindowId, 1, 0, yPos, sTextColorTable[COLORID_GREY], 0, gStringVar4); xPos = 192 - (u8)GetStringWidth(1, gText_TimesPerSec, -1); - AddTextPrinterParameterized3( - data[1], - 1, - xPos, - yPos, - sBerryCrushTextColorTable[0], - 0, - gText_TimesPerSec - ); - for (j = 0; j < 8; ++j) + AddTextPrinterParameterized3(tWindowId, 1, xPos, yPos, sTextColorTable[COLORID_GREY], 0, gText_TimesPerSec); + for (j = 0; j < 8; j++) { - if (((data[i + 2] & 0xFF) >> (7 - j)) & 1) + if (((tPressingSpeeds(i) & 0xFF) >> (7 - j)) & 1) score += sPressingSpeedConversionTable[j]; } - ConvertIntToDecimalStringN(gStringVar1, (u16)data[i + 2] >> 8, STR_CONV_MODE_RIGHT_ALIGN, 3); + ConvertIntToDecimalStringN(gStringVar1, (u16)tPressingSpeeds(i) >> 8, STR_CONV_MODE_RIGHT_ALIGN, 3); ConvertIntToDecimalStringN(gStringVar2, score / 1000000, STR_CONV_MODE_LEADING_ZEROS, 2); StringExpandPlaceholders(gStringVar4, gText_XDotY3); xPos -= GetStringWidth(1, gStringVar4, -1); - AddTextPrinterParameterized3( - data[1], - 1, - xPos, - yPos, - sBerryCrushTextColorTable[0], - 0, - gStringVar4 - ); + AddTextPrinterParameterized3(tWindowId, 1, xPos, yPos, sTextColorTable[COLORID_GREY], 0, gStringVar4); yPos += 16; score = 0; } - CopyWindowToVram(data[1], 3); + CopyWindowToVram(tWindowId, 3); break; case 2: if (JOY_NEW(A_BUTTON | B_BUTTON)) @@ -1657,16 +1849,16 @@ static void Task_ShowBerryCrushRankings(u8 taskId) else return; case 3: - ClearStdWindowAndFrameToTransparent(data[1], 1); - ClearWindowTilemap(data[1]); - RemoveWindow(data[1]); + ClearStdWindowAndFrameToTransparent(tWindowId, 1); + ClearWindowTilemap(tWindowId); + RemoveWindow(tWindowId); DestroyTask(taskId); EnableBothScriptContexts(); ScriptContext2_Disable(); - data[0] = 0; + tState = 0; return; } - ++data[0]; + tState++; } void ShowBerryCrushRankings(void) @@ -1674,97 +1866,98 @@ void ShowBerryCrushRankings(void) u8 taskId; ScriptContext2_Enable(); - taskId = CreateTask(Task_ShowBerryCrushRankings, 0); - gTasks[taskId].data[2] = gSaveBlock2Ptr->berryCrush.berryCrushResults[0]; - gTasks[taskId].data[3] = gSaveBlock2Ptr->berryCrush.berryCrushResults[1]; - gTasks[taskId].data[4] = gSaveBlock2Ptr->berryCrush.berryCrushResults[2]; - gTasks[taskId].data[5] = gSaveBlock2Ptr->berryCrush.berryCrushResults[3]; + taskId = CreateTask(Task_ShowRankings, 0); + gTasks[taskId].tPressingSpeeds(0) = gSaveBlock2Ptr->berryCrush.pressingSpeeds[0]; + gTasks[taskId].tPressingSpeeds(1) = gSaveBlock2Ptr->berryCrush.pressingSpeeds[1]; + gTasks[taskId].tPressingSpeeds(2) = gSaveBlock2Ptr->berryCrush.pressingSpeeds[2]; + gTasks[taskId].tPressingSpeeds(3) = gSaveBlock2Ptr->berryCrush.pressingSpeeds[3]; } -static void BerryCrush_PrintTimeOnSprites(struct BerryCrushGame_138 *r4, u16 r1) +static void PrintTimer(struct BerryCrushGame_Gfx *gfx, u16 timer) { - FramesToMinSec(r4, r1); - DigitObjUtil_PrintNumOn(0, r4->unk4); - DigitObjUtil_PrintNumOn(1, r4->unk6); - DigitObjUtil_PrintNumOn(2, r4->unk8); + FramesToMinSec(gfx, timer); + DigitObjUtil_PrintNumOn(0, gfx->minutes); + DigitObjUtil_PrintNumOn(1, gfx->secondsInt); + DigitObjUtil_PrintNumOn(2, gfx->secondsFrac); } -static void BerryCrush_HideTimerSprites(struct BerryCrushGame_138 *r0) +static void HideTimer(struct BerryCrushGame_Gfx *gfx) { - r0->unk78[0]->invisible = TRUE; - r0->unk78[1]->invisible = TRUE; + gfx->timerSprites[0]->invisible = TRUE; + gfx->timerSprites[1]->invisible = TRUE; DigitObjUtil_HideOrShow(2, 1); DigitObjUtil_HideOrShow(1, 1); DigitObjUtil_HideOrShow(0, 1); } -static void sub_8022588(struct BerryCrushGame *r5) +static void CreatePlayerNameWindows(struct BerryCrushGame *game) { - u8 r6; - - for (r6 = 0; r6 < r5->unk9; ++r6) + u8 i; + for (i = 0; i < game->playerCount; i++) { - r5->unk138.unkC[r6] = &gUnknown_082F4190[gUnknown_082F417C[r5->unk9 - 2][r6]]; - r5->unk138.unk83[r6] = AddWindow(&gUnknown_082F32F4[r5->unk138.unkC[r6]->unk0]); - PutWindowTilemap(r5->unk138.unk83[r6]); - FillWindowPixelBuffer(r5->unk138.unk83[r6], 0); + game->gfx.playerCoords[i] = &sPlayerCoords[sPlayerIdToPosId[game->playerCount - 2][i]]; + game->gfx.nameWindowIds[i] = AddWindow(&sWindowTemplates_PlayerNames[game->gfx.playerCoords[i]->playerId]); + PutWindowTilemap(game->gfx.nameWindowIds[i]); + FillWindowPixelBuffer(game->gfx.nameWindowIds[i], 0); } } -static void sub_8022600(struct BerryCrushGame *r6) +static void DrawPlayerNameWindows(struct BerryCrushGame *game) { - u8 r7; - - for (r7 = 0; r7 < r6->unk9; ++r7) + u8 i; + for (i = 0; i < game->playerCount; i++) { - PutWindowTilemap(r6->unk138.unk83[r7]); - if (r7 == r6->unk8) + PutWindowTilemap(game->gfx.nameWindowIds[i]); + if (i == game->localId) { + // Print the player's name AddTextPrinterParameterized4( - r6->unk138.unk83[r7], + game->gfx.nameWindowIds[i], 2, - 36 - GetStringWidth(2, r6->unk98[r7].unk0, 0) / 2u, + 36 - GetStringWidth(2, game->players[i].name, 0) / 2u, 1, 0, 0, - sBerryCrushTextColorTable[1], + sTextColorTable[COLORID_BLACK], 0, - r6->unk98[r7].unk0 + game->players[i].name ); } else { + // Print a partner's name AddTextPrinterParameterized4( - r6->unk138.unk83[r7], + game->gfx.nameWindowIds[i], 2, - 36 - GetStringWidth(2, r6->unk98[r7].unk0, 0) / 2u, + 36 - GetStringWidth(2, game->players[i].name, 0) / 2u, 1, 0, 0, - sBerryCrushTextColorTable[2], + sTextColorTable[COLORID_LIGHT_GREY], 0, - r6->unk98[r7].unk0 + game->players[i].name ); } - CopyWindowToVram(r6->unk138.unk83[r7], 3); + CopyWindowToVram(game->gfx.nameWindowIds[i], 3); } CopyBgTilemapBufferToVram(0); } -static void sub_80226D0(struct BerryCrushGame *r6) +// Each player name window border uses a color that corresponds to a slot of the crusher lid +static void CopyPlayerNameWindowGfxToBg(struct BerryCrushGame *game) { - u8 r5 = 0; - u8 * r4; + u8 i = 0; + u8 * crusherGfx; - LZ77UnCompWram(gUnknown_08DE3FD4, gDecompressionBuffer); + LZ77UnCompWram(gBerryCrush_Crusher_Tilemap, gDecompressionBuffer); - for (r4 = gDecompressionBuffer; r5 < r6->unk9; ++r5) + for (crusherGfx = gDecompressionBuffer; i < game->playerCount; i++) { CopyToBgTilemapBufferRect( 3, - &r4[r6->unk138.unkC[r5]->unk0 * 40], - r6->unk138.unkC[r5]->unk1, - r6->unk138.unkC[r5]->unk2, + &crusherGfx[game->gfx.playerCoords[i]->playerId * 40], + game->gfx.playerCoords[i]->windowGfxX, + game->gfx.playerCoords[i]->windowGfxY, 10, 2 ); @@ -1772,96 +1965,99 @@ static void sub_80226D0(struct BerryCrushGame *r6) CopyBgTilemapBufferToVram(3); } -static void sub_8022730(struct BerryCrushGame *r6) +static void CreateGameSprites(struct BerryCrushGame *game) { - u8 r5 = 0; - u8 r2; + u8 i = 0; + u8 spriteId; - r6->unk2A = -104; - r6->unk2C = 0; + game->depth = CRUSHER_START_Y; + game->vibration = 0; gSpriteCoordOffsetX = 0; - gSpriteCoordOffsetY = -104; - for (; r5 < 4; ++r5) - LoadCompressedSpriteSheet(&gUnknown_082F41F4[r5]); - LoadSpritePalettes(gUnknown_082F421C); - r2 = CreateSprite(&gUnknown_082F430C, 120, 88, 5); - r6->unk138.unk20 = &gSprites[r2]; - r6->unk138.unk20->oam.priority = 3; - r6->unk138.unk20->coordOffsetEnabled = TRUE; - r6->unk138.unk20->animPaused = TRUE; - for (r5 = 0; r5 < r6->unk9; ++r5) - { - r2 = CreateSprite( - &gUnknown_082F4324, - r6->unk138.unkC[r5]->unk4 + 120, - r6->unk138.unkC[r5]->unk6 + 32, + gSpriteCoordOffsetY = CRUSHER_START_Y; + for (i = 0; i < ARRAY_COUNT(sSpriteSheets) - 1; i++) + LoadCompressedSpriteSheet(&sSpriteSheets[i]); + LoadSpritePalettes(sSpritePals); + + // Create sprite for crusher base + spriteId = CreateSprite(&sSpriteTemplate_CrusherBase, 120, 88, 5); + game->gfx.coreSprite = &gSprites[spriteId]; + game->gfx.coreSprite->oam.priority = 3; + game->gfx.coreSprite->coordOffsetEnabled = TRUE; + game->gfx.coreSprite->animPaused = TRUE; + + // Create sprites for the impact effect + for (i = 0; i < game->playerCount; i++) + { + spriteId = CreateSprite( + &sSpriteTemplate_Impact, + game->gfx.playerCoords[i]->impactXOffset + 120, + game->gfx.playerCoords[i]->impactYOffset + 32, 0 ); - r6->unk138.unk24[r5] = &gSprites[r2]; - r6->unk138.unk24[r5]->oam.priority = 1; - r6->unk138.unk24[r5]->invisible = TRUE; - r6->unk138.unk24[r5]->coordOffsetEnabled = TRUE; - r6->unk138.unk24[r5]->animPaused = TRUE; - } - for (r5 = 0; r5 < ARRAY_COUNT(r6->unk138.unk4C); ++r5) - { - r2 = CreateSprite( - &gUnknown_082F433C, - gUnknown_082F41D2[r5][0] + 120, - gUnknown_082F41D2[r5][1] + 136, + game->gfx.impactSprites[i] = &gSprites[spriteId]; + game->gfx.impactSprites[i]->oam.priority = 1; + game->gfx.impactSprites[i]->invisible = TRUE; + game->gfx.impactSprites[i]->coordOffsetEnabled = TRUE; + game->gfx.impactSprites[i]->animPaused = TRUE; + } + + // Create sprites for sparkle effect + for (i = 0; i < ARRAY_COUNT(game->gfx.sparkleSprites); i++) + { + spriteId = CreateSprite( + &sSpriteTemplate_Sparkle, + sSparkleCoords[i][0] + 120, + sSparkleCoords[i][1] + 136, 6 ); - r6->unk138.unk4C[r5] = &gSprites[r2]; - r6->unk138.unk4C[r5]->oam.priority = 3; - r6->unk138.unk4C[r5]->invisible = TRUE; - r6->unk138.unk4C[r5]->animPaused = TRUE; - r6->unk138.unk4C[r5]->data[0] = r5; - } - for (r5 = 0; r5 < ARRAY_COUNT(r6->unk138.unk78); ++r5) - { - r2 = CreateSprite( - &gUnknown_082F4354, - 24 * r5 + 176, - 8, - 0 - ); - r6->unk138.unk78[r5] = &gSprites[r2]; - r6->unk138.unk78[r5]->oam.priority = 0; - r6->unk138.unk78[r5]->invisible = FALSE; - r6->unk138.unk78[r5]->animPaused = FALSE; - } - DigitObjUtil_CreatePrinter(0, 0, &gUnknown_082F4384[0]); - DigitObjUtil_CreatePrinter(1, 0, &gUnknown_082F4384[1]); - DigitObjUtil_CreatePrinter(2, 0, &gUnknown_082F4384[2]); - if (r6->unk12 == 1) - BerryCrush_HideTimerSprites(&r6->unk138); -} - -static void sub_8022960(struct BerryCrushGame *r5) -{ - u8 r4 = 0; - - FreeSpriteTilesByTag(4); - FreeSpriteTilesByTag(3); - FreeSpriteTilesByTag(2); - FreeSpriteTilesByTag(1); - FreeSpritePaletteByTag(4); - FreeSpritePaletteByTag(2); - FreeSpritePaletteByTag(1); - for (; r4 < ARRAY_COUNT(r5->unk138.unk78); ++r4) - DestroySprite(r5->unk138.unk78[r4]); + game->gfx.sparkleSprites[i] = &gSprites[spriteId]; + game->gfx.sparkleSprites[i]->oam.priority = 3; + game->gfx.sparkleSprites[i]->invisible = TRUE; + game->gfx.sparkleSprites[i]->animPaused = TRUE; + game->gfx.sparkleSprites[i]->data[0] = i; + } + + // Create sprites for timer + for (i = 0; i < ARRAY_COUNT(game->gfx.timerSprites); i++) + { + spriteId = CreateSprite(&sSpriteTemplate_Timer, 24 * i + 176, 8, 0); + game->gfx.timerSprites[i] = &gSprites[spriteId]; + game->gfx.timerSprites[i]->oam.priority = 0; + game->gfx.timerSprites[i]->invisible = FALSE; + game->gfx.timerSprites[i]->animPaused = FALSE; + } + DigitObjUtil_CreatePrinter(0, 0, &sDigitObjTemplates[0]); + DigitObjUtil_CreatePrinter(1, 0, &sDigitObjTemplates[1]); + DigitObjUtil_CreatePrinter(2, 0, &sDigitObjTemplates[2]); + + if (game->gameState == STATE_INIT) + HideTimer(&game->gfx); +} + +static void DestroyGameSprites(struct BerryCrushGame *game) +{ + u8 i = 0; + FreeSpriteTilesByTag(TAG_TIMER_DIGITS); + FreeSpriteTilesByTag(GFXTAG_SPARKLE); + FreeSpriteTilesByTag(GFXTAG_IMPACT); + FreeSpriteTilesByTag(TAG_CRUSHER_BASE); + FreeSpritePaletteByTag(TAG_TIMER_DIGITS); + FreeSpritePaletteByTag(PALTAG_EFFECT); + FreeSpritePaletteByTag(TAG_CRUSHER_BASE); + for (i = 0; i < ARRAY_COUNT(game->gfx.timerSprites); i++) + DestroySprite(game->gfx.timerSprites[i]); DigitObjUtil_DeletePrinter(2); DigitObjUtil_DeletePrinter(1); DigitObjUtil_DeletePrinter(0); - for (r4 = 0; r4 < ARRAY_COUNT(r5->unk138.unk4C); ++r4) - DestroySprite(r5->unk138.unk4C[r4]); - for (r4 = 0; r4 < r5->unk9; ++r4) - DestroySprite(r5->unk138.unk24[r4]); - if (r5->unk138.unk20->inUse) - DestroySprite(r5->unk138.unk20); + for (i = 0; i < ARRAY_COUNT(game->gfx.sparkleSprites); i++) + DestroySprite(game->gfx.sparkleSprites[i]); + for (i = 0; i < game->playerCount; i++) + DestroySprite(game->gfx.impactSprites[i]); + if (game->gfx.coreSprite->inUse) + DestroySprite(game->gfx.coreSprite); } -static void SpriteCB_BerryCrushImpact(struct Sprite *sprite) +static void SpriteCB_Impact(struct Sprite *sprite) { if (sprite->animEnded) { @@ -1870,93 +2066,116 @@ static void SpriteCB_BerryCrushImpact(struct Sprite *sprite) } } -static void sub_8022A4C(struct Sprite *sprite) +static void SpriteCB_Sparkle_End(struct Sprite *sprite) { - u8 r1 = 0; - SpriteCallback r5 = SpriteCallbackDummy; - - for (; r1 < ARRAY_COUNT(sprite->data); ++r1) - sprite->data[r1] = 0; + u8 i; + for (i = 0; i < ARRAY_COUNT(sprite->data); i++) + sprite->data[i] = 0; sprite->pos2.x = 0; sprite->pos2.y = 0; sprite->invisible = TRUE; sprite->animPaused = TRUE; - sprite->callback = r5; + sprite->callback = SpriteCallbackDummy; } -static void sub_8022A94(struct Sprite *sprite) +#define sX data[0] +#define sYSpeed data[1] +#define sYAccel data[2] +#define sXSpeed data[3] +#define sSinIdx data[4] +#define sSinSpeed data[5] +#define sAmplitude data[6] +// The last element (data[7]) is a bitfield. +// The first 15 bits are the y coord to stop at. +// The last bit is a flag for whether or not to move on the x too +#define sBitfield data[7] +#define MASK_TARGET_Y 0x7FFF +#define F_MOVE_HORIZ 0x8000 + +static void SpriteCB_Sparkle(struct Sprite *sprite) { - s16 *r4 = sprite->data; + s16 *data = sprite->data; - r4[1] += r4[2]; - sprite->pos2.y += r4[1] >> 8; - if (r4[7] & 0x8000) + sYSpeed += sYAccel; + sprite->pos2.y += sYSpeed >> 8; + if (sBitfield & F_MOVE_HORIZ) { - sprite->data[0] += r4[3]; - r4[4] += r4[5]; - sprite->pos2.x = Sin(r4[4] >> 7, r4[6]); - if (r4[7] & 0x8000 && r4[4] >> 7 > 126) + sprite->sX += sXSpeed; + sSinIdx += sSinSpeed; + sprite->pos2.x = Sin(sSinIdx >> 7, sAmplitude); + if (sBitfield & F_MOVE_HORIZ && sSinIdx >> 7 > 126) { sprite->pos2.x = 0; - r4[7] &= 0x7FFF; + sBitfield &= MASK_TARGET_Y; } } - sprite->pos1.x = r4[0] >> 7; - if (sprite->pos1.y + sprite->pos2.y > (r4[7] & 0x7FFF)) - sprite->callback = sub_8022A4C; -} - -static void sub_8022B28(struct Sprite *sprite) -{ - s16 *r7 = sprite->data; - s16 r4, r5; - s32 r2; - u32 r8 = 0; - - r2 = 640; - r7[1] = r2; - r7[2] = 32; - r7[7] = 168; - r4 = sprite->pos2.x * 128; - r5 = MathUtil_Div16Shift(7, (168 - sprite->pos1.y) << 7, (r2 + 32) >> 1); - sprite->data[0] = sprite->pos1.x << 7; - r7[3] = MathUtil_Div16Shift(7, r4, r5); - r2 = MathUtil_Mul16Shift(7, r5, 85); - r7[4] = r8; - r7[5] = MathUtil_Div16Shift(7, Q_8_8(63.5), r2); - r7[6] = sprite->pos2.x / 4; - r7[7] |= 0x8000; - sprite->pos2.y = r8; - sprite->pos2.x = r8; - sprite->callback = sub_8022A94; + sprite->pos1.x = sX >> 7; + if (sprite->pos1.y + sprite->pos2.y > (sBitfield & MASK_TARGET_Y)) + sprite->callback = SpriteCB_Sparkle_End; +} + +static void SpriteCB_Sparkle_Init(struct Sprite *sprite) +{ + s16 *data = sprite->data; + s16 xMult, xDiv; + s32 var; + u32 zero = 0; + + var = 640; + sYSpeed = var; + sYAccel = 32; + sBitfield = 168; // Setting bits in MASK_TARGET_Y + xMult = sprite->pos2.x * 128; + xDiv = MathUtil_Div16Shift(7, (168 - sprite->pos1.y) << 7, (var + 32) >> 1); + sprite->sX = sprite->pos1.x << 7; + sXSpeed = MathUtil_Div16Shift(7, xMult, xDiv); + var = MathUtil_Mul16Shift(7, xDiv, 85); + sSinIdx = zero; + sSinSpeed = MathUtil_Div16Shift(7, Q_8_8(63.5), var); + sAmplitude = sprite->pos2.x / 4; + sBitfield |= F_MOVE_HORIZ; + sprite->pos2.y = zero; + sprite->pos2.x = zero; + sprite->callback = SpriteCB_Sparkle; sprite->animPaused = FALSE; sprite->invisible = FALSE; } -static void BerryCrush_RunOrScheduleCommand(u16 r5, u8 r4, u8 *r7) +#undef sX +#undef sYSpeed +#undef sYAccel +#undef sXSpeed +#undef sSinIdx +#undef sSinSpeed +#undef sAmplitude +#undef sBitfield +#undef MASK_TARGET_Y +#undef F_MOVE_HORIZ + +static void RunOrScheduleCommand(u16 cmdId, u8 mode, u8 *args) { - struct BerryCrushGame *r6 = GetBerryCrushGame(); + struct BerryCrushGame *game = GetBerryCrushGame(); - if (r5 >= ARRAY_COUNT(sBerryCrushCommands)) - r5 = 0; - switch (r4) + if (cmdId >= ARRAY_COUNT(sBerryCrushCommands)) + cmdId = CMD_NONE; + switch (mode) { - case 0: - if (r5 != 0) - sBerryCrushCommands[r5](r6, r7); - if (r6->unkE >= ARRAY_COUNT(sBerryCrushCommands)) - r6->unkE = r4; - r6->unk4 = sBerryCrushCommands[r6->unkE]; + case RUN_CMD: + if (cmdId != CMD_NONE) + sBerryCrushCommands[cmdId](game, args); + if (game->nextCmd >= ARRAY_COUNT(sBerryCrushCommands)) + game->nextCmd = CMD_NONE; + game->cmdCallback = sBerryCrushCommands[game->nextCmd]; break; - case 1: - r6->unk4 = sBerryCrushCommands[r5]; + case SCHEDULE_CMD: + game->cmdCallback = sBerryCrushCommands[cmdId]; break; } } -static u32 BerryCrushCommand_BeginNormalPaletteFade(struct BerryCrushGame *game, u8 *params) +static u32 Cmd_BeginNormalPaletteFade(struct BerryCrushGame *game, u8 *args) { - // params points to packed values: + // args points to packed values: // bytes 0-3: selectedPals (bitfield) // byte 4: delay // byte 5: startY @@ -1967,126 +2186,128 @@ static u32 BerryCrushCommand_BeginNormalPaletteFade(struct BerryCrushGame *game, u16 color; u32 selectedPals[2]; - selectedPals[0] = (u32)params[0]; - selectedPals[1] = (u32)params[1]; + selectedPals[0] = (u32)args[0]; + selectedPals[1] = (u32)args[1]; selectedPals[1] <<= 8; selectedPals[0] |= selectedPals[1]; - selectedPals[1] = (u32)params[2]; + selectedPals[1] = (u32)args[2]; selectedPals[1] <<= 16; selectedPals[0] |= selectedPals[1]; - selectedPals[1] = (u32)params[3]; + selectedPals[1] = (u32)args[3]; selectedPals[1] <<= 24; selectedPals[0] |= selectedPals[1]; - params[0] = params[9]; + args[0] = args[9]; - color = params[8]; + color = args[8]; color <<= 8; - color |= params[7]; + color |= args[7]; gPaletteFade.bufferTransferDisabled = FALSE; - BeginNormalPaletteFade(selectedPals[0], params[4], params[5], params[6], color); + BeginNormalPaletteFade(selectedPals[0], args[4], args[5], args[6], color); UpdatePaletteFade(); - game->unkE = 2; + game->nextCmd = CMD_WAIT_FADE; return 0; } -static u32 BerryCrushCommand_WaitPaletteFade(struct BerryCrushGame *r4, u8 *r5) +static u32 Cmd_WaitPaletteFade(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { case 0: if (UpdatePaletteFade()) return 0; - if(r5[0] != 0) - ++r4->unkC; + if(args[0] != 0) + game->cmdState++; else - r4->unkC = 3; + game->cmdState = 3; return 0; case 1: Rfu_SetLinkStandbyCallback(); - ++r4->unkC; + game->cmdState++; return 0; case 2: if (IsLinkTaskFinished()) { - ++r4->unkC; + game->cmdState++; return 0; } return 0; case 3: - BerryCrush_RunOrScheduleCommand(r4->unkF, 1, NULL); - r4->unkC = 0; + RunOrScheduleCommand(game->afterPalFadeCmd, SCHEDULE_CMD, NULL); + game->cmdState = 0; return 0; default: - ++r4->unkC; + game->cmdState++; return 0; } } -static u32 BerryCrushCommand_PrintMessage(struct BerryCrushGame *r7, u8 *r5) +static u32 Cmd_PrintMessage(struct BerryCrushGame *game, u8 *args) { - u16 r4 = r5[3]; + u16 keys = args[3]; + keys <<= 8; + keys |= args[2]; - r4 <<= 8; - r4 |= r5[2]; - switch (r7->unkC) + switch (game->cmdState) { case 0: DrawDialogueFrame(0, 0); - if (r5[1] & 2) + if (args[1] & F_MSG_EXPAND) { - StringExpandPlaceholders(gStringVar4, gUnknown_082F32A4[r5[0]]); - AddTextPrinterParameterized2(0, 1, gStringVar4, r7->unkB, 0, 2, 1, 3); + StringExpandPlaceholders(gStringVar4, sMessages[args[0]]); + AddTextPrinterParameterized2(0, 1, gStringVar4, game->textSpeed, 0, 2, 1, 3); } else { - AddTextPrinterParameterized2(0, 1, gUnknown_082F32A4[r5[0]], r7->unkB, 0, 2, 1, 3); + AddTextPrinterParameterized2(0, 1, sMessages[args[0]], game->textSpeed, 0, 2, 1, 3); } CopyWindowToVram(0, 3); break; case 1: if (!IsTextPrinterActive(0)) { - if (r4 == 0) - ++r7->unkC; + // If no wait keys are given, skip + // waiting state below + if (keys == 0) + game->cmdState++; break; } return 0; case 2: - if (!(r4 & gMain.newKeys)) + if (!JOY_NEW(keys)) return 0; break; case 3: - if (r5[1] & 1) + if (args[1] & F_MSG_CLEAR) ClearDialogWindowAndFrame(0, 1); - BerryCrush_RunOrScheduleCommand(r7->unkE, 1, NULL); - r7->unkC = r5[4]; + RunOrScheduleCommand(game->nextCmd, SCHEDULE_CMD, NULL); + game->cmdState = args[4]; return 0; } - ++r7->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_InitGfx(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_ShowGameDisplay(struct BerryCrushGame *game, u8 *args) { - if (InitBerryCrushDisplay() != 0) - BerryCrush_RunOrScheduleCommand(r4->unkE, 0, r4->unk36); + if (ShowGameDisplay()) + RunOrScheduleCommand(game->nextCmd, RUN_CMD, game->commandArgs); return 0; } -static u32 BerryCrushCommand_TeardownGfx(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_HideGameDisplay(struct BerryCrushGame *game, u8 *args) { - if (BerryCrush_TeardownBgs() != 0) - BerryCrush_RunOrScheduleCommand(r4->unkE, 0, r4->unk36); + if (HideGameDisplay()) + RunOrScheduleCommand(game->nextCmd, RUN_CMD, game->commandArgs); return 0; } -static u32 BerryCrushCommand_SignalReadyToBegin(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_SignalReadyToBegin(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { case 0: Rfu_SetLinkStandbyCallback(); @@ -2095,55 +2316,55 @@ static u32 BerryCrushCommand_SignalReadyToBegin(struct BerryCrushGame *r4, __att if (IsLinkTaskFinished()) { PlayNewMapMusic(MUS_RG_GAME_CORNER); - BerryCrush_RunOrScheduleCommand(7, 1, NULL); - r4->unk12 = 3; - r4->unkC = 0; + RunOrScheduleCommand(CMD_ASK_PICK_BERRY, SCHEDULE_CMD, NULL); + game->gameState = STATE_PICK_BERRY; + game->cmdState = 0; } return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_AskPickBerry(struct BerryCrushGame *r4, u8 *r5) +static u32 Cmd_AskPickBerry(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { default: - ++r4->unkC; + game->cmdState++; break; case 0: - sub_8024578(r4); - BerryCrush_SetShowMessageParams(r5, 0, 1, 0, 1); - r4->unkE = 7; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); + ResetGame(game); + SetPrintMessageArgs(args, MSG_PICK_BERRY, F_MSG_CLEAR, 0, 1); + game->nextCmd = CMD_ASK_PICK_BERRY; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); break; case 1: - r4->unkE = 8; - BerryCrush_RunOrScheduleCommand(5, 1, NULL); - r4->unkC = 2; + game->nextCmd = CMD_PICK_BERRY; + RunOrScheduleCommand(CMD_HIDE_GAME, SCHEDULE_CMD, NULL); + game->cmdState = 2; break; } return 0; } -static u32 BerryCrushCommand_GoToBerryPouch(struct BerryCrushGame *r0, __attribute__((unused)) u8 *r1) +static u32 Cmd_GoToBerryPouch(struct BerryCrushGame *game, u8 *args) { - r0->unk4 = NULL; - SetMainCallback2(BerryCrush_SetupMainTask); + game->cmdCallback = NULL; + SetMainCallback2(ChooseBerry); return 0; } -static u32 BerryCrushCommand_WaitForOthersToPickBerries(struct BerryCrushGame *r5, u8 *r2) +static u32 Cmd_WaitForOthersToPickBerries(struct BerryCrushGame *game, u8 *args) { - u8 r3; + u8 i; - switch (r5->unkC) + switch (game->cmdState) { case 0: - BerryCrush_SetShowMessageParams(r2, 1, 0, 0, 1); - r5->unkE = 9; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); + SetPrintMessageArgs(args, MSG_WAIT_PICK, 0, 0, 1); + game->nextCmd = CMD_WAIT_BERRIES; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); return 0; case 1: Rfu_SetLinkStandbyCallback(); @@ -2151,126 +2372,131 @@ static u32 BerryCrushCommand_WaitForOthersToPickBerries(struct BerryCrushGame *r case 2: if (!IsLinkTaskFinished()) return 0; - memset(r5->unk42, 0, sizeof(r5->unk42)); - r5->unk42[0] = r5->unk98[r5->unk8].unkC; - SendBlock(0, r5->unk42, 2); + + // Send player's chosen berry to partners + memset(game->sendCmd, 0, sizeof(game->sendCmd)); + game->sendCmd[0] = game->players[game->localId].berryId; + SendBlock(0, game->sendCmd, 2); break; case 3: if (!IsLinkTaskFinished()) return 0; - r5->unk10 = 0; + game->cmdTimer = 0; break; case 4: - if (GetBlockReceivedStatus() != gUnknown_082F4448[r5->unk9 - 2]) + // Wait for partners responses + if (GetBlockReceivedStatus() != sReceivedPlayerBitmasks[game->playerCount - 2]) return 0; - for (r3 = 0; r3 < r5->unk9; ++r3) + + // Read partners chosen berries + for (i = 0; i < game->playerCount; i++) { - r5->unk98[r3].unkC = gBlockRecvBuffer[r3][0]; - if (r5->unk98[r3].unkC > 0xB0) - r5->unk98[r3].unkC = 0; - r5->unk18 += gUnknown_0858AB24[r5->unk98[r3].unkC].unk0; - r5->unk1C += gUnknown_0858AB24[r5->unk98[r3].unkC].unk1; + game->players[i].berryId = gBlockRecvBuffer[i][0]; + if (game->players[i].berryId > LAST_BERRY_INDEX + 1) + game->players[i].berryId = 0; + game->targetAPresses += gBerryCrush_BerryData[game->players[i].berryId].difficulty; + game->powder += gBerryCrush_BerryData[game->players[i].berryId].powder; } - r5->unk10 = 0; + game->cmdTimer = 0; ResetBlockReceivedFlags(); - r5->unk20 = MathUtil_Div32(Q_24_8(r5->unk18), Q_24_8(32)); + game->targetDepth = MathUtil_Div32(Q_24_8(game->targetAPresses), Q_24_8(32)); break; case 5: ClearDialogWindowAndFrame(0, 1); - BerryCrush_RunOrScheduleCommand(10, 1, NULL); - r5->unk12 = 4; - r5->unkC = 0; + RunOrScheduleCommand(CMD_DROP_BERRIES, SCHEDULE_CMD, NULL); + game->gameState = STATE_DROP_BERRIES; + game->cmdState = 0; return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_DropBerriesIntoCrusher(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_DropBerriesIntoCrusher(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { case 0: - BerryCrush_CreateBerrySprites(r4, &r4->unk138); + CreateBerrySprites(game, &game->gfx); Rfu_SetLinkStandbyCallback(); break; case 1: if (!IsLinkTaskFinished()) return 0; - r4->unk138.unk0 = 0; - r4->unk138.unk1 = 0; - r4->unk138.unk2 = 0; - r4->unk138.unk3 = 0; + game->gfx.counter = 0; + game->gfx.vibrationIdx = 0; + game->gfx.numVibrations = 0; + game->gfx.vibrating = FALSE; break; case 2: - r4->unk138.unk38[r4->unk138.unk0]->callback = SpriteCB_DropBerryIntoCrusher; - r4->unk138.unk38[r4->unk138.unk0]->affineAnimPaused = FALSE; + game->gfx.berrySprites[game->gfx.counter]->callback = SpriteCB_DropBerryIntoCrusher; + game->gfx.berrySprites[game->gfx.counter]->affineAnimPaused = FALSE; PlaySE(SE_BALL_THROW); break; case 3: - if (r4->unk138.unk38[r4->unk138.unk0]->callback == SpriteCB_DropBerryIntoCrusher) + if (game->gfx.berrySprites[game->gfx.counter]->callback == SpriteCB_DropBerryIntoCrusher) return 0; - r4->unk138.unk38[r4->unk138.unk0] = NULL; - ++r4->unk138.unk0; + game->gfx.berrySprites[game->gfx.counter] = NULL; + game->gfx.counter++; Rfu_SetLinkStandbyCallback(); break; case 4: if (!IsLinkTaskFinished()) return 0; - if (r4->unk138.unk0 < r4->unk9) + if (game->gfx.counter < game->playerCount) { - r4->unkC = 2; + game->cmdState = 2; return 0; } - r4->unk138.unk0 = 0; + game->gfx.counter = 0; break; case 5: - BerryCrushFreeBerrySpriteGfx(r4, &r4->unk138); + BerryCrushFreeBerrySpriteGfx(game, &game->gfx); Rfu_SetLinkStandbyCallback(); break; case 6: if (!IsLinkTaskFinished()) return 0; PlaySE(SE_FALL); - BerryCrush_RunOrScheduleCommand(11, 1, NULL); - r4->unk12 = 5; - r4->unkC = 0; + RunOrScheduleCommand(CMD_DROP_LID, SCHEDULE_CMD, NULL); + game->gameState = STATE_DROP_LID; + game->cmdState = 0; return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_DropLid(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_DropLid(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { case 0: - r4->unk2A += 4; - if (r4->unk2A < 0) + game->depth += 4; + if (game->depth < 0) return 0; - r4->unk2A = 0; - r4->unk138.unk1 = 4; - r4->unk138.unk0 = 0; - r4->unk138.unk2 = gUnknown_082F326C[r4->unk138.unk1][0]; + game->depth = 0; + game->gfx.vibrationIdx = 4; + game->gfx.counter = 0; + game->gfx.numVibrations = sIntroOutroVibrationData[game->gfx.vibrationIdx][0]; PlaySE(SE_M_STRENGTH); break; case 1: - r4->unk2C = gUnknown_082F326C[r4->unk138.unk1][r4->unk138.unk0]; - SetGpuReg(REG_OFFSET_BG0VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG2VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG3VOFS, -r4->unk2C); - ++r4->unk138.unk0; - if (r4->unk138.unk0 < r4->unk138.unk2) + game->vibration = sIntroOutroVibrationData[game->gfx.vibrationIdx][game->gfx.counter]; + SetGpuReg(REG_OFFSET_BG0VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG2VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG3VOFS, -game->vibration); + game->gfx.counter++; + if (game->gfx.counter < game->gfx.numVibrations) return 0; - if (r4->unk138.unk1 == 0) + if (game->gfx.vibrationIdx == 0) break; - --r4->unk138.unk1; - r4->unk138.unk2 = gUnknown_082F326C[r4->unk138.unk1][0]; - r4->unk138.unk0 = 0; + game->gfx.vibrationIdx--; + game->gfx.numVibrations = sIntroOutroVibrationData[game->gfx.vibrationIdx][0]; + game->gfx.counter = 0; return 0; case 2: - r4->unk2C = 0; + game->vibration = 0; SetGpuReg(REG_OFFSET_BG0VOFS, 0); SetGpuReg(REG_OFFSET_BG2VOFS, 0); SetGpuReg(REG_OFFSET_BG3VOFS, 0); @@ -2279,23 +2505,23 @@ static u32 BerryCrushCommand_DropLid(struct BerryCrushGame *r4, __attribute__(( case 3: if (!IsLinkTaskFinished()) return 0; - BerryCrush_RunOrScheduleCommand(12, 1, NULL); - r4->unk12 = 6; - r4->unkC = 0; + RunOrScheduleCommand(CMD_COUNTDOWN, SCHEDULE_CMD, NULL); + game->gameState = STATE_COUNTDOWN; + game->cmdState = 0; return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_Countdown(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_Countdown(struct BerryCrushGame *game, u8 *args) { - switch (r4-> unkC) + switch (game->cmdState) { case 1: if (!IsLinkTaskFinished()) return 0; - StartMinigameCountdown(0x1000, 0x1000, 120, 80, 0); + StartMinigameCountdown(TAG_COUNTDOWN, TAG_COUNTDOWN, 120, 80, 0); break; case 2: if (IsMinigameCountdownRunning()) @@ -2307,405 +2533,442 @@ static u32 BerryCrushCommand_Countdown(struct BerryCrushGame *r4, __attribute__ case 3: if (!IsLinkTaskFinished()) return 0; - r4->unk138.unk0 = 0; - r4->unk138.unk1 = 0; - r4->unk138.unk2 = 0; - r4->unk138.unk3 = 0; - r4->unk10 = 0; - if (r4->unk8 == 0) - BerryCrush_RunOrScheduleCommand(13, 1, NULL); + game->gfx.counter = 0; + game->gfx.vibrationIdx = 0; + game->gfx.numVibrations = 0; + game->gfx.vibrating = FALSE; + game->cmdTimer = 0; + if (game->localId == 0) + RunOrScheduleCommand(CMD_PLAY_GAME_LEADER, SCHEDULE_CMD, NULL); else - BerryCrush_RunOrScheduleCommand(14, 1, NULL); - r4->unk12 = 7; - r4->unkC = 0; + RunOrScheduleCommand(CMD_PLAY_GAME_MEMBER, SCHEDULE_CMD, NULL); + game->gameState = STATE_PLAYING; + game->cmdState = 0; return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -void sub_802339C(struct BerryCrushGame *r4) +// Receive and process data from all players +// Only used by the link leader +static void HandlePartnerInput(struct BerryCrushGame *game) { - u8 r8 = 0; - u8 r7 = 0; - u16 r3; - s32 r2_ = 0; - struct BerryCrushGame_4E *r2; + u8 numPlayersPressed = 0; + u8 i = 0; + u16 timeDiff; + s32 temp = 0; + struct BerryCrushGame_LinkState *linkState; - for (r7 = 0; r7 < r4->unk9; r7++) + for (i = 0; i < game->playerCount; i++) { - r2 = (struct BerryCrushGame_4E *)gRecvCmds[r7]; - if ((r2->unk0 & 0xFF00) != RFUCMD_SEND_PACKET) + linkState = (struct BerryCrushGame_LinkState *)gRecvCmds[i]; + + // Skip player if we have not received a packet from them + if ((linkState->rfuCmd & 0xFF00) != RFUCMD_SEND_PACKET) continue; - if (r2->unk2 != 2) + if (linkState->sendFlag != SEND_GAME_STATE) continue; - if (r2->unk4_2) + if (linkState->pushedAButton) { - r4->unk5C.unk02_3 |= gUnknown_082F325C[r7]; - r4->unk98[r7].unk1C = 1; - ++r4->unk98[r7].unk16; - ++r8; - r3 = r4->unk28 - r4->unk98[r7].unkE; - if (r3 >= r4->unk98[r7].unk12 - 1 && r3 <= r4->unk98[r7].unk12 + 1) + game->localState.playerPressedAFlags |= sBitTable[i]; + game->players[i].inputState = INPUT_STATE_HIT; + game->players[i].numAPresses++; + numPlayersPressed++; + timeDiff = game->timer - game->players[i].inputTime; + + // If the interval between inputs is regular, the input is considered "neat" + // This counts toward the player's neatness score + if (timeDiff >= game->players[i].timeSincePrevInput - 1 + && timeDiff <= game->players[i].timeSincePrevInput + 1) { - ++r4->unk98[r7].unk10; - r4->unk98[r7].unk12 = r3; - if (r4->unk98[r7].unk10 > r4->unk98[r7].unk14) - r4->unk98[r7].unk14 = r4->unk98[r7].unk10; + // On neat input streak + game->players[i].neatInputStreak++; + game->players[i].timeSincePrevInput = timeDiff; + if (game->players[i].neatInputStreak > game->players[i].maxNeatInputStreak) + game->players[i].maxNeatInputStreak = game->players[i].neatInputStreak; } else { - r4->unk98[r7].unk10 = 0; - r4->unk98[r7].unk12 = r3; + // End neat input streak + game->players[i].neatInputStreak = 0; + game->players[i].timeSincePrevInput = timeDiff; } - r4->unk98[r7].unkE = r4->unk28; - ++r4->unk98[r7].unk1B; - if (r4->unk98[r7].unk1B > 2) - r4->unk98[r7].unk1B = 0; + + game->players[i].inputTime = game->timer; + game->players[i].inputFlags++; + if (game->players[i].inputFlags > F_INPUT_HIT_B) + game->players[i].inputFlags = 0; } else { - r4->unk98[r7].unk1C = 0; + game->players[i].inputState = INPUT_STATE_NONE; } } - if (r8 > 1) + if (numPlayersPressed > 1) { - for (r7 = 0; r7 < r4->unk9; ++r7) + // For each player that pressed A, flag their input as synchronous + // This is used to change their impact sprite to a big impact + for (i = 0; i < game->playerCount; i++) { - if (!r4->unk98[r7].unk1C) + if (game->players[i].inputState == INPUT_STATE_NONE) continue; - r4->unk98[r7].unk1C |= 2; - ++r4->unk98[r7].unk18; + game->players[i].inputState |= INPUT_STATE_HIT_SYNC; + game->players[i].numSyncedAPresses++; } } - if (r8 == 0) + if (numPlayersPressed == 0) return; - r4->unk2E += r8; - r8 += gUnknown_082F3264[r8 - 1]; - r4->unk34 += r8; - r4->unk1A += r8; - if (r4->unk18 - r4->unk1A > 0) - { - r2_ = (s32)r4->unk1A; - r2_ <<= 8; - r2_ = MathUtil_Div32(r2_, r4->unk20); - r2_ >>= 8; - r4->unk24 = (u8)r2_; + game->bigSparkleCounter += numPlayersPressed; + numPlayersPressed += sSyncPressBonus[numPlayersPressed - 1]; + game->sparkleCounter += numPlayersPressed; + game->totalAPresses += numPlayersPressed; + if (game->targetAPresses - game->totalAPresses > 0) + { + temp = (s32)game->totalAPresses; + temp = Q_24_8(temp); + temp = MathUtil_Div32(temp, game->targetDepth); + temp = Q_24_8_TO_INT(temp); + game->newDepth = (u8)temp; return; } - r4->unk24 = 32; - r4->unk5C.unk02_0 = 1; + // Target number of A presses has been reached, game is complete + game->newDepth = 32; + game->localState.endGame = TRUE; } -void sub_8023558(struct BerryCrushGame *r3) +// Updates the crusher, input flags, and timer to send to group members +// Only used by the link leader +static void UpdateLeaderGameState(struct BerryCrushGame *game) { - u8 r6 = 0; - u16 r1 = 0; - u16 r2 = 0; - u8 r4 = 0; + u8 numPlayersPressed = 0; + u16 flags = 0; + u16 temp = 0; + u8 i = 0; - for (r4 = 0; r4 < r3->unk9; ++r4) + for (i = 0; i < game->playerCount; i++) { - if (r3->unk98[r4].unk1C != 0) + if (game->players[i].inputState != INPUT_STATE_NONE) { - ++r6; - r1 = r3->unk98[r4].unk1B + 1; - if (r3->unk98[r4].unk1C & 2) - r1 |= 4; - r1 <<= 3 * r4; - r3->unk5C.unk08 |= r1; + numPlayersPressed++; + flags = game->players[i].inputFlags + F_INPUT_HIT_A; + if (game->players[i].inputState & INPUT_STATE_HIT_SYNC) + flags |= F_INPUT_HIT_SYNC; + flags <<= INPUT_FLAGS_PER_PLAYER * i; + game->localState.inputFlags |= flags; } } - r2 = (u16)r3->unk24; - r3->unk5C.unk04 = r2; - if (r6 == 0) + temp = (u16)game->newDepth; + game->localState.depth = temp; + if (numPlayersPressed == 0) { - if (r3->unk138.unk3 != 0) - ++r3->unk138.unk0; + if (game->gfx.vibrating) + game->gfx.counter++; } - else if (r3->unk138.unk3 != 0) + else if (game->gfx.vibrating) { - if (r6 != r3->unk138.unk1) + if (numPlayersPressed != game->gfx.vibrationIdx) { - r3->unk138.unk1 = r6 - 1; - r3->unk138.unk2 = gUnknown_082F3290[r6 - 1][0]; + game->gfx.vibrationIdx = numPlayersPressed - 1; + game->gfx.numVibrations = sVibrationData[numPlayersPressed - 1][0]; } else { - ++r3->unk138.unk0; + game->gfx.counter++; } } else { - r3->unk138.unk0 = 0; - r3->unk138.unk1 = r6 - 1; - r3->unk138.unk2 = gUnknown_082F3290[r6 - 1][0]; - r3->unk138.unk3 = 1; + game->gfx.counter = 0; + game->gfx.vibrationIdx = numPlayersPressed - 1; + game->gfx.numVibrations = sVibrationData[numPlayersPressed - 1][0]; + game->gfx.vibrating = TRUE; } - if (r3->unk138.unk3 != 0) + if (game->gfx.vibrating) { - if (r3->unk138.unk0 >= r3->unk138.unk2) + if (game->gfx.counter >= game->gfx.numVibrations) { - r3->unk138.unk0 = 0; - r3->unk138.unk1 = 0; - r3->unk138.unk2 = 0; - r3->unk138.unk3 = 0; - r1 = 0; + game->gfx.counter = 0; + game->gfx.vibrationIdx = 0; + game->gfx.numVibrations = 0; + game->gfx.vibrating = FALSE; + temp = 0; } else { - r1 = gUnknown_082F3290[r3->unk138.unk1][r3->unk138.unk0 + 1]; + temp = sVibrationData[game->gfx.vibrationIdx][game->gfx.counter + 1]; } - r3->unk5C.unk03 = (u8)r1; + game->localState.vibration = (u8)temp; } else { - r3->unk5C.unk03 = 0; + game->localState.vibration = 0; } - r3->unk5C.unk06 = r3->unk26; + game->localState.timer = game->leaderTimer; } -void sub_80236B8(struct BerryCrushGame *r5) +// Checks for input and sends data to group members +static void HandlePlayerInput(struct BerryCrushGame *game) { if (JOY_NEW(A_BUTTON)) - r5->unk5C.unk02_2 = 1; + game->localState.pushedAButton = TRUE; + if (JOY_HELD(A_BUTTON)) { - if (r5->unk98[r5->unk8].unk1A < r5->unk28) - ++r5->unk98[r5->unk8].unk1A; + if (game->players[game->localId].timePressingA < game->timer) + game->players[game->localId].timePressingA++; } - if (r5->unk8 != 0 && r5->unk5C.unk02_2 == 0) + + // Only send data to other players if you are the leader or you pressed A + if (game->localId != 0 && !game->localState.pushedAButton) return; - r5->unk5C.unk00 = 2; - if (r5->unk28 % 30 == 0) + game->localState.sendFlag = SEND_GAME_STATE; + + // Every 30 frames, check whether the sparkles produced should be big, + // depending on how many A presses there were in that time + if (game->timer % 30 == 0) { - if (r5->unk2E > gUnknown_082F4444[r5->unk9 - 2]) + if (game->bigSparkleCounter > sBigSparkleThresholds[game->playerCount - 2]) { - ++r5->unk30; - r5->unk25_4 = 1; + game->numBigSparkles++; + game->bigSparkle = TRUE; } else { - r5->unk25_4 = 0; + game->bigSparkle = FALSE; } - r5->unk2E = 0; - ++r5->unk32; - } - if (r5->unk28 % 15 == 0) - { - if (r5->unk34 < gUnknown_082F4434[r5->unk9 - 2][0]) - r5->unk25_5 = 0; - else if (r5->unk34 < gUnknown_082F4434[r5->unk9 - 2][1]) - r5->unk25_5 = 1; - else if (r5->unk34 < gUnknown_082F4434[r5->unk9 - 2][2]) - r5->unk34 = 2; // typo since r5->unk34 will be reset? - else if (r5->unk34 < gUnknown_082F4434[r5->unk9 - 2][3]) - r5->unk34 = 3; // typo since r5->unk34 will be reset? + game->bigSparkleCounter = 0; + game->numBigSparkleChecks++; + } + + // Every 15 frames, update the amount of sparkles that should be produced, + // depending on how many A presses there were in that time (including the bonus) + if (game->timer % 15 == 0) + { + // BUG: The wrong field is used twice below + // As a result, only a sparkleAmount of 0, 1, or 4 is attainable + #ifdef BUGFIX + #define field sparkleAmount + #else + #define field sparkleCounter + #endif + + if (game->sparkleCounter < sSparkleThresholds[game->playerCount - 2][0]) + game->sparkleAmount = 0; + else if (game->sparkleCounter < sSparkleThresholds[game->playerCount - 2][1]) + game->sparkleAmount = 1; + else if (game->sparkleCounter < sSparkleThresholds[game->playerCount - 2][2]) + game->field = 2; + else if (game->sparkleCounter < sSparkleThresholds[game->playerCount - 2][3]) + game->field = 3; else - r5->unk25_5 = 4; - r5->unk34 = 0; + game->sparkleAmount = 4; + game->sparkleCounter = 0; + + #undef field } else { - ++r5->unk10; - if (r5->unk10 > 60) + game->cmdTimer++; + if (game->cmdTimer > 60) { - if (r5->unk10 > 70) + if (game->cmdTimer > 70) { - sub_8011AC8(); - r5->unk10 = 0; + ClearRecvCommands(); + game->cmdTimer = 0; } - else if (r5->unk5C.unk02_3 == 0) + else if (game->localState.playerPressedAFlags == 0) { - sub_8011AC8(); - r5->unk10 = 0; + ClearRecvCommands(); + game->cmdTimer = 0; } } } - if (r5->unk28 >= 36000) - r5->unk5C.unk02_0 = 1; - r5->unk5C.unk02_1 = r5->unk25_4; - r5->unk5C.unk0A = r5->unk25_5; - memcpy(r5->unk42, &r5->unk5C, sizeof(r5->unk42)); - Rfu_SendPacket(r5->unk42); + if (game->timer >= MAX_TIME) + game->localState.endGame = TRUE; + game->localState.bigSparkle = game->bigSparkle; + game->localState.sparkleAmount = game->sparkleAmount; + memcpy(game->sendCmd, &game->localState, sizeof(game->sendCmd)); + Rfu_SendPacket(game->sendCmd); } -void sub_802385C(struct BerryCrushGame *r5) +static void RecvLinkData(struct BerryCrushGame *game) { - u8 r4 = 0; - struct BerryCrushGame_4E *r4_ = NULL; + u8 i = 0; + struct BerryCrushGame_LinkState *linkState = NULL; + + for (i = 0; i < game->playerCount; i++) + game->players[i].inputState = INPUT_STATE_NONE; - for (r4 = 0; r4 < r5->unk9; r4++) - r5->unk98[r4].unk1C = 0; if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) { - r5->unk25_2 = 0; + game->playedSound = FALSE; return; } if (gRecvCmds[0][1] != 2) { - r5->unk25_2 = 0; + game->playedSound = FALSE; return; } - memcpy(r5->unk4E, gRecvCmds[0], 14); - r4_ = (struct BerryCrushGame_4E *)&r5->unk4E; - r5->unk2A = r4_->unk6; - r5->unk2C = (s16)r4_->unk5; - r5->unk28 = r4_->unk8; - sub_80216E0(r5, &(r5->unk138)); - if (r4_->unk4_0) - { - r5->unk25_3 = 1; - } + memcpy(game->recvCmd, gRecvCmds[0], sizeof(game->recvCmd)); + linkState = (struct BerryCrushGame_LinkState *)&game->recvCmd; + game->depth = linkState->depth; + game->vibration = (s16)linkState->vibration; + game->timer = linkState->timer; + UpdateInputEffects(game, &(game->gfx)); + + if (linkState->endGame) + game->endGame = TRUE; } -static u32 BerryCrushCommand_PlayGame_Master(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_PlayGame_Leader(struct BerryCrushGame *game, u8 *args) { - memset(&r4->unk5C, 0, sizeof(r4->unk5C)); - memset(&r4->unk4E, 0, sizeof(r4->unk4E)); - sub_802385C(r4); - SetGpuReg(REG_OFFSET_BG0VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG2VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG3VOFS, -r4->unk2C); - if (r4->unk25_3) + memset(&game->localState, 0, sizeof(game->localState)); + memset(&game->recvCmd, 0, sizeof(game->recvCmd)); + RecvLinkData(game); + SetGpuReg(REG_OFFSET_BG0VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG2VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG3VOFS, -game->vibration); + if (game->endGame) { - if (r4->unk28 >= 36000) + if (game->timer >= MAX_TIME) { - r4->unk28 = 36000; - BerryCrush_RunOrScheduleCommand(16, 1, NULL); + game->timer = MAX_TIME; + RunOrScheduleCommand(CMD_TIMES_UP, SCHEDULE_CMD, NULL); } else { - BerryCrush_RunOrScheduleCommand(15, 1, NULL); + RunOrScheduleCommand(CMD_FINISH_GAME, SCHEDULE_CMD, NULL); } - r4->unk10 = 0; - r4->unkC = 0; + game->cmdTimer = 0; + game->cmdState = 0; return 0; } else { - ++r4->unk26; - sub_802339C(r4); - sub_8023558(r4); - sub_80236B8(r4); + game->leaderTimer++; + HandlePartnerInput(game); + UpdateLeaderGameState(game); + HandlePlayerInput(game); return 0; } } -static u32 BerryCrushCommand_PlayGame_Slave(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_PlayGame_Member(struct BerryCrushGame *game, u8 *args) { - memset(&r4->unk5C, 0, sizeof(r4->unk5C)); - memset(&r4->unk4E, 0, sizeof(r4->unk4E)); - sub_802385C(r4); - SetGpuReg(REG_OFFSET_BG0VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG2VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG3VOFS, -r4->unk2C); - if (r4->unk25_3) + memset(&game->localState, 0, sizeof(game->localState)); + memset(&game->recvCmd, 0, sizeof(game->recvCmd)); + RecvLinkData(game); + SetGpuReg(REG_OFFSET_BG0VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG2VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG3VOFS, -game->vibration); + if (game->endGame) { - if (r4->unk28 >= 36000) + if (game->timer >= MAX_TIME) { - r4->unk28 = 36000; - BerryCrush_RunOrScheduleCommand(16, 1, NULL); + game->timer = MAX_TIME; + RunOrScheduleCommand(CMD_TIMES_UP, SCHEDULE_CMD, NULL); } else { - BerryCrush_RunOrScheduleCommand(15, 1, NULL); + RunOrScheduleCommand(CMD_FINISH_GAME, SCHEDULE_CMD, NULL); } - r4->unk10 = 0; - r4->unkC = 0; + game->cmdTimer = 0; + game->cmdState = 0; return 0; } else { - sub_80236B8(r4); + HandlePlayerInput(game); return 0; } } -static u32 BerryCrushCommand_FinishGame(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +// Game was 'won', crusher was pushed down fully before time was up +static u32 Cmd_FinishGame(struct BerryCrushGame *game, u8 *args) { - switch (r4->unkC) + switch (game->cmdState) { case 0: - r4->unk12 = 8; + game->gameState = STATE_FINISHED; PlaySE(SE_M_STRENGTH); BlendPalettes(PALETTES_ALL, 8, RGB(31, 31, 0)); - r4->unk138.unk0 = 2; + game->gfx.counter = 2; break; case 1: - if (--r4->unk138.unk0 != 255) + if (--game->gfx.counter != (u8)-1) return 0; BlendPalettes(PALETTES_ALL, 0, RGB(31, 31, 0)); - r4->unk138.unk1 = 4; - r4->unk138.unk0 = 0; - r4->unk138.unk2 = gUnknown_082F326C[r4->unk138.unk1][0]; + game->gfx.vibrationIdx = 4; + game->gfx.counter = 0; + game->gfx.numVibrations = sIntroOutroVibrationData[game->gfx.vibrationIdx][0]; break; case 2: - r4->unk2C = gUnknown_082F326C[r4->unk138.unk1][r4->unk138.unk0]; - SetGpuReg(REG_OFFSET_BG0VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG2VOFS, -r4->unk2C); - SetGpuReg(REG_OFFSET_BG3VOFS, -r4->unk2C); - if (++r4->unk138.unk0 < r4->unk138.unk2) + game->vibration = sIntroOutroVibrationData[game->gfx.vibrationIdx][game->gfx.counter]; + SetGpuReg(REG_OFFSET_BG0VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG2VOFS, -game->vibration); + SetGpuReg(REG_OFFSET_BG3VOFS, -game->vibration); + if (++game->gfx.counter < game->gfx.numVibrations) return 0; - if (r4->unk138.unk1 != 0) + if (game->gfx.vibrationIdx != 0) { - --r4->unk138.unk1; - r4->unk138.unk2 = gUnknown_082F326C[r4->unk138.unk1][0]; - r4->unk138.unk0 = 0; + game->gfx.vibrationIdx--; + game->gfx.numVibrations = sIntroOutroVibrationData[game->gfx.vibrationIdx][0]; + game->gfx.counter = 0; return 0; } break; case 3: - r4->unk2C = 0; + game->vibration = 0; SetGpuReg(REG_OFFSET_BG0VOFS, 0); SetGpuReg(REG_OFFSET_BG2VOFS, 0); SetGpuReg(REG_OFFSET_BG3VOFS, 0); break; case 4: - if (!sub_80218D4(r4, &r4->unk138)) + if (!AreEffectsFinished(game, &game->gfx)) return 0; Rfu_SetLinkStandbyCallback(); - r4->unk10 = 0; + game->cmdTimer = 0; break; case 5: if (!IsLinkTaskFinished()) return 0; - BerryCrush_RunOrScheduleCommand(17, 1, NULL); - r4->unk10 = 0; - r4->unkC = 0; + RunOrScheduleCommand(CMD_CALC_RESULTS, SCHEDULE_CMD, NULL); + game->cmdTimer = 0; + game->cmdState = 0; return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_HandleTimeUp(struct BerryCrushGame *r5, u8 *r6) +static u32 Cmd_HandleTimeUp(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: - r5->unk12 = 9; + game->gameState = STATE_TIMES_UP; PlaySE(SE_FAILURE); BlendPalettes(PALETTES_ALL, 8, RGB(31, 0, 0)); - r5->unk138.unk0 = 4; + game->gfx.counter = 4; break; case 1: - if (--r5->unk138.unk0 != 255) + if (--game->gfx.counter != (u8)-1) return 0; BlendPalettes(PALETTES_ALL, 0, RGB(31, 0, 0)); - r5->unk138.unk0 = 0; + game->gfx.counter = 0; break; case 2: - if (!sub_80218D4(r5, &r5->unk138)) + if (!AreEffectsFinished(game, &game->gfx)) return 0; Rfu_SetLinkStandbyCallback(); - r5->unk10 = 0; + game->cmdTimer = 0; SetGpuReg(REG_OFFSET_BG0VOFS, 0); SetGpuReg(REG_OFFSET_BG2VOFS, 0); SetGpuReg(REG_OFFSET_BG3VOFS, 0); @@ -2713,235 +2976,264 @@ static u32 BerryCrushCommand_HandleTimeUp(struct BerryCrushGame *r5, u8 *r6) case 3: if (!IsLinkTaskFinished()) return 0; - ConvertIntToDecimalStringN(gStringVar1, r5->unk1C, STR_CONV_MODE_LEFT_ALIGN, 6); - BerryCrush_SetShowMessageParams(r6, 7, 1, 0, 0); - r5->unkE = 19; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); - r5->unk10 = 0; - r5->unkC = 0; + ConvertIntToDecimalStringN(gStringVar1, game->powder, STR_CONV_MODE_LEFT_ALIGN, 6); + SetPrintMessageArgs(args, MSG_TIMES_UP, F_MSG_CLEAR, 0, 0); + game->nextCmd = CMD_SAVE; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); + game->cmdTimer = 0; + game->cmdState = 0; return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_TabulateResults(struct BerryCrushGame *r7, __attribute__((unused)) u8 *r1) +static u32 Cmd_TabulateResults(struct BerryCrushGame *game, u8 *args) { - u8 r8, r4_, r3; - s32 r2; - s32 r4; - u16 r6; + u8 i, j, tempPlayerId; + s32 temp1, temp2; + u16 tempStat; - switch (r7->unkC) + switch (game->cmdState) { case 0: - memset(r7->unk42, 0, 2 * sizeof(u16)); - if (r7->unk98[r7->unk8].unk1A > r7->unk28) - r7->unk98[r7->unk8].unk1A = r7->unk28; - r7->unk42[0] = r7->unk98[r7->unk8].unk1A; - SendBlock(0, r7->unk42, 2); + memset(game->sendCmd, 0, 2 * sizeof(u16)); + if (game->players[game->localId].timePressingA > game->timer) + game->players[game->localId].timePressingA = game->timer; + game->sendCmd[0] = game->players[game->localId].timePressingA; + SendBlock(0, game->sendCmd, 2); break; case 1: if (!IsLinkTaskFinished()) return 0; - r7->unk10 = 0; + game->cmdTimer = 0; break; case 2: - if (GetBlockReceivedStatus() != gUnknown_082F4448[r7->unk9 - 2]) + if (GetBlockReceivedStatus() != sReceivedPlayerBitmasks[game->playerCount - 2]) return 0; - for (r8 = 0; r8 < r7->unk9; ++r8) - r7->unk98[r8].unk1A = gBlockRecvBuffer[r8][0]; - r7->unk10 = 0; - r7->unk42[0] = 0; + for (i = 0; i < game->playerCount; i++) + game->players[i].timePressingA = gBlockRecvBuffer[i][0]; + + game->cmdTimer = 0; + game->sendCmd[0] = 0; ResetBlockReceivedFlags(); - if (r7->unk8 == 0) - r7->unkC = 3; + + // If player is not leader, skip the steps + // where the results are calculated and sent. + // Group members just read the results sent + // to them by the leader. + if (game->localId == 0) + game->cmdState = 3; else - r7->unkC = 6; + game->cmdState = 6; return 0; case 3: - memset(&r7->unk68, 0, sizeof(struct BerryCrushGame_68)); - r7->unk68.unk04 = r7->unk28; - r7->unk68.unk06 = r7->unk18 / (r7->unk28 / 60); - r2 = MathUtil_Mul32(Q_24_8(r7->unk30), Q_24_8(50)); - r2 = MathUtil_Div32(r2, Q_24_8(r7->unk32)) + Q_24_8(50); - r2 = Q_24_8_TO_INT(r2); - r7->unk68.unk08 = r2 & 0x7F; - r2 = Q_24_8(r2); - r2 = MathUtil_Div32(r2, Q_24_8(100)); - r4 = Q_24_8(r7->unk1C * r7->unk9); - r4 = MathUtil_Mul32(r4, r2); - r7->unk68.unk00 = r4 >> 8; - r7->unk68.unk20[0][7] = Random() % 3; - for (r8 = 0; r8 < r7->unk9; ++r8) + memset(&game->results, 0, sizeof(game->results)); + game->results.time = game->timer; + game->results.targetPressesPerSec = game->targetAPresses / (game->timer / 60); + + // Calculate silkiness + // Silkiness is the percentage of times big sparkles were produced when possible, + // which itself depends on the number of A presses every 30 frames + temp1 = MathUtil_Mul32(Q_24_8(game->numBigSparkles), Q_24_8(50)); + temp1 = MathUtil_Div32(temp1, Q_24_8(game->numBigSparkleChecks)) + Q_24_8(50); + temp1 = Q_24_8_TO_INT(temp1); + game->results.silkiness = temp1 & 0x7F; + + // Calculate amount of powder + temp1 = Q_24_8(temp1); + temp1 = MathUtil_Div32(temp1, Q_24_8(100)); + temp2 = Q_24_8(game->powder * game->playerCount); + temp2 = MathUtil_Mul32(temp2, temp1); + game->results.powder = Q_24_8_TO_INT(temp2); + + // Choose random second results page + game->results.randomPageId = Random() % NUM_RANDOM_RESULTS_PAGES; + + for (i = 0; i < game->playerCount; i++) { - r7->unk68.unk20[0][r8] = r8; - r7->unk68.unk20[1][r8] = r8; - r7->unk68.unk0C[0][r8] = r7->unk98[r8].unk16; - r7->unk68.unk0A += r7->unk68.unk0C[0][r8]; - switch (r7->unk68.unk20[0][7]) + game->results.playerIdsRanked[RESULTS_PAGE_PRESSES][i] = i; + game->results.playerIdsRanked[RESULTS_PAGE_RANDOM][i] = i; + game->results.stats[RESULTS_PAGE_PRESSES][i] = game->players[i].numAPresses; + game->results.totalAPresses += game->results.stats[RESULTS_PAGE_PRESSES][i]; + + // Calculate value for random second results page + switch (game->results.randomPageId) { - case 0: - if (r7->unk98[r8].unk16 != 0) + case RESULTS_PAGE_NEATNESS: + if (game->players[i].numAPresses != 0) { - r2 = r7->unk98[r8].unk14; - r2 = Q_24_8(r2); - r2 = MathUtil_Mul32(r2, Q_24_8(100)); - r4 = r7->unk98[r8].unk16; - r4 = Q_24_8(r4); - r4 = MathUtil_Div32(r2, r4); + // Calculate percentage of inputs that were in largest "neat" streak + // "Neat" inputs are those done at a regular interval + temp1 = game->players[i].maxNeatInputStreak; + temp1 = Q_24_8(temp1); + temp1 = MathUtil_Mul32(temp1, Q_24_8(100)); + temp2 = game->players[i].numAPresses; + temp2 = Q_24_8(temp2); + temp2 = MathUtil_Div32(temp1, temp2); } else { - r4 = 0; + temp2 = 0; } break; - case 1: - if (r7->unk98[r8].unk16 != 0) + case RESULTS_PAGE_COOPERATIVE: + if (game->players[i].numAPresses != 0) { - r2 = r7->unk98[r8].unk18; - r2 = Q_24_8(r2); - r2 = MathUtil_Mul32(r2, Q_24_8(100)); - r4 = r7->unk98[r8].unk16; - r4 = Q_24_8(r4); - r4 = MathUtil_Div32(r2, r4); + // Calculate percentage of inputs that were + // done at the same time as another player + temp1 = game->players[i].numSyncedAPresses; + temp1 = Q_24_8(temp1); + temp1 = MathUtil_Mul32(temp1, Q_24_8(100)); + temp2 = game->players[i].numAPresses; + temp2 = Q_24_8(temp2); + temp2 = MathUtil_Div32(temp1, temp2); } else { - r4 = 0; + temp2 = 0; } break; - case 2: - if (r7->unk98[r8].unk16 == 0) + case RESULTS_PAGE_POWER: + if (game->players[i].numAPresses == 0) { - r4 = 0; + temp2 = 0; } - else if (r7->unk98[r8].unk1A >= r7->unk28) + else if (game->players[i].timePressingA >= game->timer) { - r4 = 0x6400; + // Spent 100% of the time pressing A + temp2 = Q_24_8(100); } else { - r2 = r7->unk98[r8].unk1A; - r2 = Q_24_8(r2); - r2 = MathUtil_Mul32(r2, Q_24_8(100)); - r4 = r7->unk28; - r4 = Q_24_8(r4); - r4 = MathUtil_Div32(r2, r4); + // Calculate percentage of time the + // player spent pressing A + temp1 = game->players[i].timePressingA; + temp1 = Q_24_8(temp1); + temp1 = MathUtil_Mul32(temp1, Q_24_8(100)); + temp2 = game->timer; + temp2 = Q_24_8(temp2); + temp2 = MathUtil_Div32(temp1, temp2); } break; } - r4 >>= 4; - r7->unk68.unk0C[1][r8] = r4; + temp2 >>= 4; + game->results.stats[RESULTS_PAGE_RANDOM][i] = temp2; } break; case 4: - for (r8 = 0; r8 < r7->unk9 - 1; ++r8) + for (i = 0; i < game->playerCount - 1; i++) { - for (r4_ = r7->unk9 - 1; r4_ > r8; --r4_) + for (j = game->playerCount - 1; j > i; j--) { - if (r7->unk68.unk0C[0][r4_ - 1] < r7->unk68.unk0C[0][r4_]) + // Calculate player rankings for "Number of Presses" by sorting arrays + if (game->results.stats[RESULTS_PAGE_PRESSES][j - 1] < game->results.stats[RESULTS_PAGE_PRESSES][j]) { - r6 = r7->unk68.unk0C[0][r4_]; - r7->unk68.unk0C[0][r4_] = r7->unk68.unk0C[0][r4_ - 1]; - r7->unk68.unk0C[0][r4_ - 1] = r6; - r3 = r7->unk68.unk20[0][r4_]; - r7->unk68.unk20[0][r4_] = r7->unk68.unk20[0][r4_ - 1]; - r7->unk68.unk20[0][r4_ - 1] = r3; + SWAP(game->results.stats[RESULTS_PAGE_PRESSES][j], + game->results.stats[RESULTS_PAGE_PRESSES][j - 1], + tempStat); + SWAP(game->results.playerIdsRanked[RESULTS_PAGE_PRESSES][j], + game->results.playerIdsRanked[RESULTS_PAGE_PRESSES][j - 1], + tempPlayerId); } - if (r7->unk68.unk0C[1][r4_ - 1] < r7->unk68.unk0C[1][r4_]) + // Calculate player rankings for random second results page by sorting arrays + if (game->results.stats[RESULTS_PAGE_RANDOM][j - 1] < game->results.stats[RESULTS_PAGE_RANDOM][j]) { - r6 = r7->unk68.unk0C[1][r4_]; - r7->unk68.unk0C[1][r4_] = r7->unk68.unk0C[1][r4_ - 1]; - r7->unk68.unk0C[1][r4_ - 1] = r6; - r3 = r7->unk68.unk20[1][r4_]; - r7->unk68.unk20[1][r4_] = r7->unk68.unk20[1][r4_ - 1]; - r7->unk68.unk20[1][r4_ - 1] = r3; + SWAP(game->results.stats[RESULTS_PAGE_RANDOM][j], + game->results.stats[RESULTS_PAGE_RANDOM][j - 1], + tempStat); + SWAP(game->results.playerIdsRanked[RESULTS_PAGE_RANDOM][j], + game->results.playerIdsRanked[RESULTS_PAGE_RANDOM][j - 1], + tempPlayerId); } } } - SendBlock(0,&r7->unk68, sizeof(struct BerryCrushGame_68)); + SendBlock(0, &game->results, sizeof(game->results)); break; case 5: if (!IsLinkTaskFinished()) return 0; - r7->unk10 = 0; + game->cmdTimer = 0; break; case 6: if (GetBlockReceivedStatus() != 1) return 0; - memset(&r7->unk68, 0, sizeof(struct BerryCrushGame_68)); - memcpy(&r7->unk68, gBlockRecvBuffer, sizeof(struct BerryCrushGame_68)); + + // Receive results calculated by leader + memset(&game->results, 0, sizeof(game->results)); + memcpy(&game->results, gBlockRecvBuffer, sizeof(game->results)); ResetBlockReceivedFlags(); - r7->unk10 = 0; + game->cmdTimer = 0; break; case 7: - BerryCrush_SaveResults(); - BerryCrush_RunOrScheduleCommand(18, 1, NULL); - r7->unk12 = 11; - r7->unkC = 0; - r7->unk24 = 0; + SaveResults(); + RunOrScheduleCommand(CMD_SHOW_RESULTS, SCHEDULE_CMD, NULL); + game->gameState = STATE_RESULTS_PRESSES; + game->cmdState = 0; + game->newDepth = 0; return 0; } - ++r7->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_ShowResults(struct BerryCrushGame *r5, u8 *r6) +static u32 Cmd_ShowResults(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: - if (!sub_8022070(r5, &r5->unk138)) + if (!OpenResultsWindow(game, &game->gfx)) return 0; break; case 1: CopyBgTilemapBufferToVram(0); - r5->unk138.unk0 = 30; + game->gfx.counter = 30; break; case 2: - if (r5->unk138.unk0 != 0) + if (game->gfx.counter != 0) { - --r5->unk138.unk0; + game->gfx.counter--; return 0; } if (!(JOY_NEW(A_BUTTON))) return 0; PlaySE(SE_SELECT); - sub_802222C(r5); + CloseResultsWindow(game); break; case 3: - if (r5->unk12 <= 12) + // Progress through each page of the results + if (game->gameState < RESULTS_STATE_END) { - ++r5->unk12; - r5->unkC = 0; + game->gameState++; + game->cmdState = 0; return 0; } break; case 4: - ConvertIntToDecimalStringN(gStringVar1, r5->unk1C, STR_CONV_MODE_LEFT_ALIGN, 6); + // Print message showing how much powder was created + ConvertIntToDecimalStringN(gStringVar1, game->powder, STR_CONV_MODE_LEFT_ALIGN, 6); ConvertIntToDecimalStringN(gStringVar2, GetBerryPowder(), STR_CONV_MODE_LEFT_ALIGN, 6); - BerryCrush_SetShowMessageParams(r6, 2, 3, 0, 0); - r5->unkE = 19; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); - r5->unkC = 0; + SetPrintMessageArgs(args, MSG_POWDER, F_MSG_CLEAR | F_MSG_EXPAND, 0, 0); + game->nextCmd = CMD_SAVE; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); + game->cmdState = 0; return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_SaveGame(struct BerryCrushGame *r5, u8 *r4) +static u32 Cmd_SaveGame(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: - if (r5->unk28 >= 36000) - BerryCrush_HideTimerSprites(&r5->unk138); - BerryCrush_SetShowMessageParams(r4, 8, 0, 0, 1); - r5->unkE = 19; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); - r5->unkC = 0; + if (game->timer >= MAX_TIME) + HideTimer(&game->gfx); + SetPrintMessageArgs(args, MSG_COMM_STANDBY, 0, 0, 1); + game->nextCmd = CMD_SAVE; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); + game->cmdState = 0; // State is progressed by CMD_PRINT_MSG return 0; case 1: Rfu_SetLinkStandbyCallback(); @@ -2959,63 +3251,67 @@ static u32 BerryCrushCommand_SaveGame(struct BerryCrushGame *r5, u8 *r4) return 0; break; case 4: - BerryCrush_RunOrScheduleCommand(20, 1, NULL); - r5->unk12 = 15; - r5->unkC = 0; + RunOrScheduleCommand(CMD_ASK_PLAY_AGAIN, SCHEDULE_CMD, NULL); + game->gameState = STATE_PLAY_AGAIN; + game->cmdState = 0; return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_AskPlayAgain(struct BerryCrushGame *r5, u8 *r6) +static u32 Cmd_AskPlayAgain(struct BerryCrushGame *game, u8 *args) { - s8 r4 = 0; + s8 input = 0; - switch (r5->unkC) + switch (game->cmdState) { case 0: - BerryCrush_SetShowMessageParams(r6, 4, 0, 0, 1); - r5->unkE = 20; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); - r5->unkC = 0; // dunno what it's doing because it's already in case 0 + SetPrintMessageArgs(args, MSG_PLAY_AGAIN, 0, 0, 1); + game->nextCmd = CMD_ASK_PLAY_AGAIN; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); + game->cmdState = 0; // State is progressed by CMD_PRINT_MSG return 0; case 1: DisplayYesNoMenuDefaultYes(); break; case 2: - r4 = Menu_ProcessInputNoWrapClearOnChoose(); - if (r4 != -2) + input = Menu_ProcessInputNoWrapClearOnChoose(); + if (input != -2) { - memset(r5->unk42, 0, sizeof(r5->unk42)); - if (r4 == 0) + memset(game->sendCmd, 0, sizeof(game->sendCmd)); + if (input == 0) { + // Selected Yes if (HasAtLeastOneBerry()) - r5->unk14 = 0; + game->playAgainState = PLAY_AGAIN_YES; else - r5->unk14 = 3; + game->playAgainState = PLAY_AGAIN_NO_BERRIES; } else { - r5->unk14 = 1; + // Selected No + game->playAgainState = PLAY_AGAIN_NO; } + + // Close Yes/No and start communication ClearDialogWindowAndFrame(0, 1); - BerryCrush_SetShowMessageParams(r6, 8, 0, 0, 0); - r5->unkE = 21; - BerryCrush_RunOrScheduleCommand(3, 1, NULL); - r5->unkC = 0; + SetPrintMessageArgs(args, MSG_COMM_STANDBY, 0, 0, 0); + game->nextCmd = CMD_COMM_PLAY_AGAIN; + RunOrScheduleCommand(CMD_PRINT_MSG, SCHEDULE_CMD, NULL); + game->cmdState = 0; } return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_CommunicatePlayAgainResponses(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r1) +static u32 Cmd_CommunicatePlayAgainResponses(struct BerryCrushGame *game, u8 *args) { - u8 r5 = 0; + u8 i = 0; - switch (r4->unkC) + switch (game->cmdState) { case 0: Rfu_SetLinkStandbyCallback(); @@ -3023,41 +3319,47 @@ static u32 BerryCrushCommand_CommunicatePlayAgainResponses(struct BerryCrushGame case 1: if (!IsLinkTaskFinished()) return 0; - r4->unk42[0] = r4->unk14; - r4->unk4E[0] = 0; - SendBlock(0, r4->unk42, sizeof(u16)); + + // Send player's Yes/No response to partners + game->sendCmd[0] = game->playAgainState; + game->recvCmd[0] = 0; + SendBlock(0, game->sendCmd, sizeof(u16)); break; case 2: if (!IsLinkTaskFinished()) return 0; - r4->unk10 = 0; + game->cmdTimer = 0; break; case 3: - if (GetBlockReceivedStatus() != gUnknown_082F4448[r4->unk9 - 2]) + // Wait for partners responses + if (GetBlockReceivedStatus() != sReceivedPlayerBitmasks[game->playerCount - 2]) return 0; - for (; r5 < r4->unk9; ++r5) - r4->unk4E[0] += gBlockRecvBuffer[r5][0]; - if (r4->unk4E[0] != 0) - BerryCrush_RunOrScheduleCommand(23, 1, NULL); + + // Read partners responses + for (i = 0; i < game->playerCount; i++) + game->recvCmd[0] += gBlockRecvBuffer[i][0]; + + if (game->recvCmd[0] != PLAY_AGAIN_YES) + RunOrScheduleCommand(CMD_PLAY_AGAIN_NO, SCHEDULE_CMD, NULL); else - BerryCrush_RunOrScheduleCommand(22, 1, NULL); + RunOrScheduleCommand(CMD_PLAY_AGAIN_YES, SCHEDULE_CMD, NULL); ResetBlockReceivedFlags(); - r4->unk42[0] = 0; - r4->unk4E[0] = 0; - r4->unk10 = 0; - r4->unkC = 0; + game->sendCmd[0] = 0; + game->recvCmd[0] = 0; + game->cmdTimer = 0; + game->cmdState = 0; return 0; } - ++r4->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_FadeOutToPlayAgain(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1) +static u32 Cmd_PlayAgain(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: - BeginNormalPaletteFade(PALETTES_ALL, 1, 0, 0x10, RGB_BLACK); + BeginNormalPaletteFade(PALETTES_ALL, 1, 0, 16, RGB_BLACK); UpdatePaletteFade(); break; case 1: @@ -3066,56 +3368,56 @@ static u32 BerryCrushCommand_FadeOutToPlayAgain(struct BerryCrushGame *r5, __att break; case 2: ClearDialogWindowAndFrame(0, 1); - sub_8021488(r5); - BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK); + ResetCrusherPos(game); + BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); UpdatePaletteFade(); break; case 3: if (UpdatePaletteFade()) return 0; - BerryCrush_RunOrScheduleCommand(7, 1, NULL); - r5->unk12 = 3; - r5->unkC = 0; + RunOrScheduleCommand(CMD_ASK_PICK_BERRY, SCHEDULE_CMD, NULL); + game->gameState = STATE_PICK_BERRY; + game->cmdState = 0; return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_PlayAgainFailureMessage(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1) +static u32 Cmd_StopGame(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: DrawDialogueFrame(0, 0); - if (r5->unk14 == 3) - AddTextPrinterParameterized2(0, 1, gUnknown_082F32A4[5], r5->unkB, 0, 2, 1, 3); + if (game->playAgainState == PLAY_AGAIN_NO_BERRIES) + AddTextPrinterParameterized2(0, 1, sMessages[MSG_NO_BERRIES], game->textSpeed, 0, 2, 1, 3); else - AddTextPrinterParameterized2(0, 1, gUnknown_082F32A4[6], r5->unkB, 0, 2, 1, 3); + AddTextPrinterParameterized2(0, 1, sMessages[MSG_DROPPED], game->textSpeed, 0, 2, 1, 3); CopyWindowToVram(0, 3); break; case 1: if (IsTextPrinterActive(0)) return 0; - r5->unk138.unk0 = 120; + game->gfx.counter = 120; break; case 2: - if (r5->unk138.unk0 != 0) - --r5->unk138.unk0; + if (game->gfx.counter != 0) + game->gfx.counter--; else { - BerryCrush_RunOrScheduleCommand(24, 1, NULL); - r5->unkC = 0; + RunOrScheduleCommand(CMD_CLOSE_LINK, SCHEDULE_CMD, NULL); + game->cmdState = 0; } return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_GracefulExit(struct BerryCrushGame *r5, __attribute__((unused)) u8 *r1) +static u32 Cmd_CloseLink(struct BerryCrushGame *game, u8 *args) { - switch (r5->unkC) + switch (game->cmdState) { case 0: Rfu_SetLinkStandbyCallback(); @@ -3128,84 +3430,81 @@ static u32 BerryCrushCommand_GracefulExit(struct BerryCrushGame *r5, __attribute case 2: if (gReceivedRemoteLinkPlayers != 0) return 0; - r5->unkE = 25; - BerryCrush_RunOrScheduleCommand(5, 1, NULL); - r5->unkC = 2; // ??? + game->nextCmd = CMD_QUIT; + RunOrScheduleCommand(CMD_HIDE_GAME, SCHEDULE_CMD, NULL); + game->cmdState = 2; // ??? return 0; } - ++r5->unkC; + game->cmdState++; return 0; } -static u32 BerryCrushCommand_Quit(__attribute__((unused)) struct BerryCrushGame *r0, __attribute__((unused)) u8 *r1) +static u32 Cmd_Quit(struct BerryCrushGame *game, u8 *args) { QuitBerryCrush(NULL); return 0; } -static void sub_8024578(struct BerryCrushGame *r4) -{ - u8 r5 = 0; - - IncrementGameStat(GAME_STAT_51); - r4->unkD = 0; - r4->unk10 = 0; - r4->unk12 = 2; - r4->unk14 = 0; - r4->unk1C = 0; - r4->unk18 = 0; - r4->unk1A = 0; - r4->unk20 = 0; - r4->unk24 = 0; - r4->unk25_0 = 0; - r4->unk25_1 = 0; - r4->unk25_2 = 0; - r4->unk25_3 = 0; - r4->unk25_4 = 0; - r4->unk25_5 = 0; - r4->unk26 = 0; - r4->unk28 = 0; - r4->unk2E = 0; - r4->unk32 = -1; - r4->unk30 = 0; - r4->unk34 = 0; - for (; r5 < 5; ++r5) - { - r4->unk98[r5].unkC = -1; - r4->unk98[r5].unkE = 0; - r4->unk98[r5].unk10 = 0; - r4->unk98[r5].unk12 = 1; - r4->unk98[r5].unk14 = 0; - r4->unk98[r5].unk16 = 0; - r4->unk98[r5].unk18 = 0; - r4->unk98[r5].unk1A = 0; - r4->unk98[r5].unk1B = 0; - r4->unk98[r5].unk1C = 0; - } -} - -static void BerryCrush_SetPaletteFadeParams(u8 *params, bool8 communicateAfter, u32 selectedPals, s8 delay, u8 startY, u8 targetY, u16 palette) -{ - params[0] = ((u8 *)&selectedPals)[0]; - params[1] = ((u8 *)&selectedPals)[1]; - params[2] = ((u8 *)&selectedPals)[2]; - params[3] = ((u8 *)&selectedPals)[3]; - params[4] = delay; - params[5] = startY; - params[6] = targetY; - params[7] = ((u8 *)&palette)[0]; - params[8] = ((u8 *)&palette)[1]; - params[9] = communicateAfter; -} - -static void BerryCrush_SetShowMessageParams(u8 *r0, u32 r1, u32 r2, u32 r3, u32 r5) -{ - u8 sp[4]; - - 0[(u16 *)sp] = r3; - r0[0] = r1; - r0[1] = r2; - r0[2] = sp[0]; - r0[3] = sp[1]; - r0[4] = r5; +static void ResetGame(struct BerryCrushGame *game) +{ + u8 i = 0; + + IncrementGameStat(GAME_STAT_PLAYED_BERRY_CRUSH); + game->unused = 0; + game->cmdTimer = 0; + game->gameState = STATE_RESET; + game->playAgainState = 0; + game->powder = 0; + game->targetAPresses = 0; + game->totalAPresses = 0; + game->targetDepth = 0; + game->newDepth = 0; + game->noRoomForPowder = FALSE; + game->newRecord = FALSE; + game->playedSound = FALSE; + game->endGame = FALSE; + game->bigSparkle = FALSE; + game->sparkleAmount = 0; + game->leaderTimer = 0; + game->timer = 0; + game->bigSparkleCounter = 0; + game->numBigSparkleChecks = -1; + game->numBigSparkles = 0; + game->sparkleCounter = 0; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + game->players[i].berryId = -1; + game->players[i].inputTime = 0; + game->players[i].neatInputStreak = 0; + game->players[i].timeSincePrevInput = 1; + game->players[i].maxNeatInputStreak = 0; + game->players[i].numAPresses = 0; + game->players[i].numSyncedAPresses = 0; + game->players[i].timePressingA = 0; + game->players[i].inputFlags = 0; + game->players[i].inputState = INPUT_STATE_NONE; + } +} + +static void SetPaletteFadeArgs(u8 *args, bool8 communicateAfter, u32 selectedPals, s8 delay, u8 startY, u8 targetY, u16 palette) +{ + args[0] = ((u8 *)&selectedPals)[0]; + args[1] = ((u8 *)&selectedPals)[1]; + args[2] = ((u8 *)&selectedPals)[2]; + args[3] = ((u8 *)&selectedPals)[3]; + args[4] = delay; + args[5] = startY; + args[6] = targetY; + args[7] = ((u8 *)&palette)[0]; + args[8] = ((u8 *)&palette)[1]; + args[9] = communicateAfter; +} + +static void SetPrintMessageArgs(u8 *args, u8 msgId, u8 flags, u16 waitKeys, u8 followupState) +{ + args[0] = msgId; + args[1] = flags; + args[2] = ((u8 *)&waitKeys)[0]; + args[3] = ((u8 *)&waitKeys)[1]; + args[4] = followupState; } diff --git a/src/cable_club.c b/src/cable_club.c index 8b321d670..1d8c6e53d 100644 --- a/src/cable_club.c +++ b/src/cable_club.c @@ -904,7 +904,7 @@ static void Task_StartWirelessCableClubBattle(u8 taskId) { struct LinkPlayer *player = (struct LinkPlayer *)gBlockRecvBuffer[i]; gLinkPlayers[i] = *player; - sub_800B524(&gLinkPlayers[i]); + ConvertLinkPlayerName(&gLinkPlayers[i]); ResetBlockReceivedFlag(i); } tState = 4; diff --git a/src/data/items.h b/src/data/items.h index e4e7e0fbc..fc7792186 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -2250,7 +2250,7 @@ const struct Item gItems[] = .name = _("SOOTHE BELL"), .itemId = ITEM_SOOTHE_BELL, .price = 100, - .holdEffect = HOLD_EFFECT_HAPPINESS_UP, + .holdEffect = HOLD_EFFECT_FRIENDSHIP_UP, .description = sSootheBellDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, diff --git a/src/data/party_menu.h b/src/data/party_menu.h index daf3f4f6c..a4a030e3f 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -543,7 +543,7 @@ static const struct WindowTemplate sLevelUpStatsWindowTemplate = .baseBlock = 0x2E9, }; -static const struct WindowTemplate sUnusedWindowTemplate_08615978 = +static const struct WindowTemplate sUnusedWindowTemplate1 = { .bg = 2, .tilemapLeft = 2, @@ -554,7 +554,7 @@ static const struct WindowTemplate sUnusedWindowTemplate_08615978 = .baseBlock = 0x1DF, }; -static const struct WindowTemplate sUnusedWindowTemplate_08615980 = +static const struct WindowTemplate sUnusedWindowTemplate2 = { .bg = 2, .tilemapLeft = 0, @@ -669,7 +669,7 @@ static const u8 *const sDescriptionStringTable[] = [PARTYBOX_DESC_DONT_HAVE] = gText_DontHave, }; -static const u16 sUnused_08615B94[] = +static const u16 sUnusedData[] = { 0x0108, 0x0151, 0x0160, 0x015b, 0x002e, 0x005c, 0x0102, 0x0153, 0x014b, 0x00ed, 0x00f1, 0x010d, 0x003a, 0x003b, 0x003f, 0x0071, 0x00b6, 0x00f0, 0x00ca, 0x00db, 0x00da, 0x004c, 0x00e7, 0x0055, 0x0057, 0x0059, 0x00d8, 0x005b, 0x005e, 0x00f7, 0x0118, 0x0068, diff --git a/src/data/pointillism_points.h b/src/data/pointillism_points.h new file mode 100644 index 000000000..708f5c02e --- /dev/null +++ b/src/data/pointillism_points.h @@ -0,0 +1,3210 @@ +#define GET_POINT_OFFSET_DL(bits) (((bits) >> 0) & 1) +#define GET_POINT_COLOR_TYPE(bits) (((bits) >> 1) & 3) +#define GET_POINT_DELTA(bits) (((bits) >> 3) & 7) + +#define PT(x, y, delta, colorType, offsetDownLeft) x, y, (delta << 3) | (colorType << 1) | offsetDownLeft + +static const u8 sPointillismPoints[][3] = { + PT( 0, 29, 3, 2, FALSE), + PT(14, 30, 3, 1, TRUE), + PT( 0, 1, 6, 1, FALSE), + PT(46, 30, 6, 3, TRUE), + PT(10, 34, 3, 3, TRUE), + PT( 5, 38, 5, 3, FALSE), + PT(18, 23, 3, 3, FALSE), + PT(26, 3, 2, 0, TRUE), + PT( 5, 17, 3, 0, FALSE), + PT( 5, 39, 5, 3, TRUE), + PT(26, 63, 2, 1, FALSE), + PT(34, 63, 2, 3, FALSE), + PT(43, 47, 5, 3, FALSE), + PT(17, 2, 5, 2, TRUE), + PT(35, 13, 5, 0, FALSE), + PT(23, 12, 3, 0, TRUE), + PT(47, 14, 2, 1, TRUE), + PT(48, 24, 4, 0, FALSE), + PT(45, 40, 4, 1, FALSE), + PT( 1, 3, 3, 0, TRUE), + PT(14, 42, 5, 1, TRUE), + PT(34, 21, 4, 2, TRUE), + PT(34, 10, 4, 3, FALSE), + PT(57, 6, 4, 1, TRUE), + PT(22, 7, 5, 3, TRUE), + PT(34, 58, 3, 1, TRUE), + PT(59, 54, 6, 2, TRUE), + PT(10, 43, 4, 2, FALSE), + PT(54, 9, 2, 1, FALSE), + PT(28, 47, 4, 1, TRUE), + PT(46, 56, 5, 2, FALSE), + PT( 5, 42, 4, 0, FALSE), + PT( 7, 20, 6, 1, FALSE), + PT(49, 8, 2, 3, TRUE), + PT(26, 36, 5, 2, TRUE), + PT(34, 10, 2, 3, FALSE), + PT(27, 38, 5, 1, TRUE), + PT(41, 22, 2, 0, TRUE), + PT(53, 8, 2, 2, FALSE), + PT(30, 8, 2, 2, FALSE), + PT( 5, 49, 2, 2, FALSE), + PT(56, 49, 2, 3, TRUE), + PT(52, 51, 2, 1, FALSE), + PT(17, 9, 3, 3, TRUE), + PT(40, 61, 6, 1, FALSE), + PT(53, 3, 3, 3, FALSE), + PT(60, 43, 5, 3, FALSE), + PT(16, 1, 2, 3, TRUE), + PT( 3, 62, 4, 1, FALSE), + PT(23, 24, 6, 2, FALSE), + PT( 8, 41, 3, 0, TRUE), + PT( 3, 36, 5, 0, FALSE), + PT(61, 51, 5, 3, TRUE), + PT(49, 36, 3, 0, TRUE), + PT(27, 24, 4, 3, FALSE), + PT( 7, 13, 4, 2, TRUE), + PT(45, 63, 2, 1, FALSE), + PT(47, 21, 4, 2, TRUE), + PT(41, 15, 2, 1, FALSE), + PT( 7, 44, 2, 1, FALSE), + PT(44, 11, 4, 3, FALSE), + PT(18, 26, 2, 3, FALSE), + PT( 0, 11, 5, 3, TRUE), + PT(22, 53, 4, 2, FALSE), + PT(31, 28, 4, 1, FALSE), + PT(41, 51, 4, 3, TRUE), + PT(59, 48, 2, 3, TRUE), + PT(17, 6, 6, 2, TRUE), + PT(62, 49, 5, 3, TRUE), + PT(17, 58, 4, 2, TRUE), + PT(42, 2, 3, 0, TRUE), + PT(51, 24, 6, 2, TRUE), + PT(42, 32, 4, 0, TRUE), + PT(46, 50, 3, 1, TRUE), + PT(59, 31, 4, 1, TRUE), + PT(57, 41, 5, 1, FALSE), + PT(46, 49, 5, 0, TRUE), + PT(42, 14, 5, 2, TRUE), + PT(45, 0, 3, 3, TRUE), + PT(56, 40, 3, 1, TRUE), + PT(20, 59, 5, 1, TRUE), + PT(46, 4, 4, 3, FALSE), + PT(54, 48, 2, 0, TRUE), + PT(59, 33, 5, 2, TRUE), + PT(43, 63, 3, 1, TRUE), + PT(32, 19, 6, 0, TRUE), + PT(51, 12, 6, 0, FALSE), + PT(34, 43, 5, 1, TRUE), + PT(22, 2, 3, 3, FALSE), + PT(28, 18, 3, 2, FALSE), + PT(15, 60, 6, 3, FALSE), + PT(56, 16, 5, 2, TRUE), + PT(24, 47, 5, 2, TRUE), + PT(53, 59, 2, 0, TRUE), + PT(55, 49, 2, 1, TRUE), + PT(19, 61, 5, 3, TRUE), + PT(30, 44, 6, 1, TRUE), + PT(46, 55, 2, 1, FALSE), + PT(60, 31, 6, 1, TRUE), + PT(50, 42, 4, 3, TRUE), + PT(13, 59, 3, 2, FALSE), + PT(53, 42, 4, 3, TRUE), + PT( 9, 61, 4, 3, TRUE), + PT(18, 11, 3, 0, FALSE), + PT(12, 21, 3, 2, TRUE), + PT(32, 1, 3, 2, FALSE), + PT( 8, 59, 3, 2, FALSE), + PT(18, 55, 6, 1, TRUE), + PT(21, 3, 5, 2, FALSE), + PT(42, 59, 6, 0, TRUE), + PT(15, 4, 6, 2, TRUE), + PT( 8, 23, 6, 1, TRUE), + PT(56, 61, 5, 1, FALSE), + PT(47, 53, 2, 3, FALSE), + PT(16, 53, 2, 3, FALSE), + PT(35, 19, 5, 2, FALSE), + PT(47, 6, 4, 0, FALSE), + PT(39, 58, 4, 2, FALSE), + PT( 0, 28, 5, 1, FALSE), + PT( 3, 57, 3, 2, TRUE), + PT(40, 7, 3, 1, FALSE), + PT(32, 10, 6, 3, TRUE), + PT( 7, 53, 5, 2, TRUE), + PT(21, 47, 5, 2, FALSE), + PT(16, 44, 4, 1, TRUE), + PT(63, 41, 2, 2, FALSE), + PT(42, 33, 6, 3, FALSE), + PT(52, 26, 5, 2, FALSE), + PT(28, 61, 6, 1, TRUE), + PT(56, 43, 4, 1, FALSE), + PT(53, 40, 3, 3, TRUE), + PT(61, 15, 3, 2, FALSE), + PT(30, 62, 3, 1, TRUE), + PT(12, 62, 3, 3, TRUE), + PT(43, 49, 5, 2, FALSE), + PT(50, 57, 2, 0, TRUE), + PT( 5, 9, 2, 0, TRUE), + PT( 4, 56, 5, 1, FALSE), + PT(50, 0, 2, 3, FALSE), + PT(19, 11, 6, 0, TRUE), + PT(52, 42, 2, 1, TRUE), + PT(44, 34, 4, 0, TRUE), + PT(57, 47, 2, 2, TRUE), + PT(55, 40, 3, 3, FALSE), + PT( 7, 59, 5, 2, TRUE), + PT(17, 3, 5, 0, FALSE), + PT(45, 48, 3, 3, FALSE), + PT(49, 17, 2, 0, TRUE), + PT(35, 1, 3, 3, FALSE), + PT(61, 49, 6, 2, FALSE), + PT(28, 2, 6, 2, FALSE), + PT(33, 14, 4, 2, TRUE), + PT(61, 7, 2, 3, TRUE), + PT(51, 21, 2, 0, FALSE), + PT(41, 50, 6, 1, FALSE), + PT(24, 31, 6, 0, FALSE), + PT(45, 59, 6, 0, FALSE), + PT(39, 62, 2, 3, FALSE), + PT(49, 21, 2, 1, FALSE), + PT(48, 37, 2, 3, TRUE), + PT(51, 6, 6, 2, FALSE), + PT( 0, 41, 3, 0, FALSE), + PT(60, 3, 2, 1, FALSE), + PT(44, 12, 2, 0, TRUE), + PT( 9, 48, 6, 0, FALSE), + PT(16, 14, 2, 0, TRUE), + PT(39, 22, 3, 1, TRUE), + PT(12, 59, 5, 3, FALSE), + PT(43, 51, 3, 3, FALSE), + PT(19, 45, 5, 2, TRUE), + PT(17, 36, 5, 0, TRUE), + PT(52, 62, 5, 1, TRUE), + PT(36, 30, 4, 0, TRUE), + PT(39, 26, 5, 2, TRUE), + PT( 4, 57, 2, 3, FALSE), + PT(62, 51, 4, 3, FALSE), + PT(27, 46, 4, 2, TRUE), + PT(12, 6, 3, 0, TRUE), + PT(37, 25, 3, 0, FALSE), + PT(29, 51, 6, 1, TRUE), + PT(29, 40, 5, 2, TRUE), + PT(28, 16, 5, 1, FALSE), + PT(31, 53, 3, 3, FALSE), + PT(52, 2, 2, 0, FALSE), + PT(43, 58, 2, 2, FALSE), + PT(13, 11, 2, 2, TRUE), + PT(12, 44, 2, 0, FALSE), + PT(55, 58, 3, 0, TRUE), + PT( 6, 19, 2, 3, TRUE), + PT(36, 16, 4, 2, TRUE), + PT(36, 4, 3, 3, FALSE), + PT( 0, 53, 6, 2, FALSE), + PT(58, 0, 6, 3, TRUE), + PT(60, 7, 3, 1, FALSE), + PT(43, 40, 6, 3, FALSE), + PT(52, 57, 5, 3, TRUE), + PT(40, 9, 3, 3, TRUE), + PT(56, 49, 6, 0, FALSE), + PT(22, 37, 6, 0, TRUE), + PT(24, 40, 6, 0, TRUE), + PT(24, 12, 4, 1, FALSE), + PT( 6, 57, 5, 2, TRUE), + PT(61, 32, 4, 2, FALSE), + PT(46, 39, 4, 0, TRUE), + PT(62, 24, 3, 0, FALSE), + PT(21, 60, 4, 2, FALSE), + PT( 6, 27, 4, 3, FALSE), + PT(21, 14, 4, 1, FALSE), + PT(10, 13, 3, 3, TRUE), + PT(24, 22, 6, 2, FALSE), + PT(16, 40, 4, 0, TRUE), + PT(32, 17, 2, 0, TRUE), + PT(54, 50, 2, 2, TRUE), + PT(59, 46, 4, 2, FALSE), + PT(31, 45, 2, 1, FALSE), + PT(54, 46, 4, 0, FALSE), + PT(11, 23, 6, 1, TRUE), + PT(38, 3, 3, 3, TRUE), + PT( 8, 25, 6, 0, TRUE), + PT(42, 24, 4, 2, TRUE), + PT(53, 45, 5, 2, TRUE), + PT(48, 56, 3, 0, FALSE), + PT(28, 37, 2, 2, FALSE), + PT(28, 34, 5, 0, FALSE), + PT( 8, 35, 4, 0, TRUE), + PT(38, 30, 6, 0, FALSE), + PT(25, 15, 2, 2, TRUE), + PT(16, 47, 4, 1, FALSE), + PT(18, 2, 4, 2, TRUE), + PT(60, 1, 3, 2, TRUE), + PT(14, 20, 3, 0, FALSE), + PT(13, 24, 2, 3, TRUE), + PT(34, 11, 6, 0, TRUE), + PT(19, 52, 4, 0, TRUE), + PT(15, 45, 6, 3, FALSE), + PT(57, 31, 4, 2, TRUE), + PT(24, 16, 3, 3, TRUE), + PT(45, 32, 4, 0, FALSE), + PT(25, 11, 6, 0, TRUE), + PT(51, 19, 2, 2, FALSE), + PT(46, 17, 4, 0, TRUE), + PT(45, 10, 6, 3, TRUE), + PT( 7, 21, 3, 1, TRUE), + PT(50, 4, 6, 1, FALSE), + PT( 6, 24, 3, 1, TRUE), + PT(19, 36, 2, 1, FALSE), + PT(54, 34, 2, 3, FALSE), + PT(29, 41, 3, 2, FALSE), + PT(53, 23, 4, 0, TRUE), + PT(54, 23, 5, 1, TRUE), + PT(53, 50, 3, 0, TRUE), + PT(42, 15, 5, 3, FALSE), + PT(16, 0, 6, 2, FALSE), + PT( 2, 14, 5, 0, FALSE), + PT(49, 50, 6, 1, FALSE), + PT(59, 5, 4, 0, FALSE), + PT(54, 38, 2, 1, FALSE), + PT(52, 6, 6, 2, FALSE), + PT(30, 49, 6, 1, FALSE), + PT(53, 5, 6, 2, FALSE), + PT(30, 19, 2, 2, TRUE), + PT(21, 20, 5, 2, FALSE), + PT(41, 28, 3, 0, FALSE), + PT(36, 36, 2, 1, FALSE), + PT(34, 41, 3, 0, FALSE), + PT(52, 54, 6, 0, FALSE), + PT(30, 1, 4, 1, TRUE), + PT(12, 60, 4, 2, FALSE), + PT(10, 61, 2, 3, FALSE), + PT(39, 30, 4, 1, TRUE), + PT(21, 2, 2, 1, FALSE), + PT(17, 25, 5, 1, FALSE), + PT(29, 49, 2, 2, TRUE), + PT( 3, 59, 5, 1, FALSE), + PT(33, 25, 5, 2, FALSE), + PT(10, 35, 2, 0, TRUE), + PT(37, 17, 3, 1, FALSE), + PT(26, 10, 6, 2, FALSE), + PT(59, 11, 6, 1, TRUE), + PT(33, 11, 6, 3, TRUE), + PT( 1, 49, 5, 0, FALSE), + PT(53, 29, 4, 3, TRUE), + PT(44, 48, 6, 0, TRUE), + PT(46, 57, 5, 2, TRUE), + PT(48, 5, 5, 2, FALSE), + PT(18, 42, 5, 1, TRUE), + PT(57, 34, 4, 0, FALSE), + PT(21, 52, 3, 2, FALSE), + PT(28, 1, 2, 2, TRUE), + PT(32, 22, 4, 1, FALSE), + PT(19, 4, 3, 0, FALSE), + PT(30, 19, 2, 0, FALSE), + PT(37, 51, 2, 2, TRUE), + PT(57, 3, 6, 0, TRUE), + PT(63, 54, 3, 0, FALSE), + PT(20, 35, 2, 0, FALSE), + PT(47, 30, 3, 3, TRUE), + PT(31, 23, 5, 2, FALSE), + PT( 2, 22, 6, 0, TRUE), + PT(32, 24, 6, 0, FALSE), + PT(46, 24, 6, 3, TRUE), + PT(59, 14, 6, 0, FALSE), + PT(16, 57, 4, 2, FALSE), + PT(38, 57, 3, 3, FALSE), + PT(48, 38, 5, 3, FALSE), + PT(18, 1, 2, 2, FALSE), + PT(55, 42, 5, 3, FALSE), + PT(33, 6, 3, 2, TRUE), + PT(42, 22, 6, 1, FALSE), + PT( 9, 56, 3, 2, FALSE), + PT( 7, 34, 2, 3, TRUE), + PT(59, 45, 2, 2, TRUE), + PT( 7, 30, 5, 3, FALSE), + PT(27, 46, 3, 2, TRUE), + PT( 4, 9, 6, 0, FALSE), + PT(48, 45, 6, 3, TRUE), + PT(45, 52, 4, 2, FALSE), + PT(24, 36, 4, 2, TRUE), + PT(14, 45, 4, 3, FALSE), + PT(35, 10, 2, 3, FALSE), + PT(18, 45, 2, 0, TRUE), + PT(33, 40, 5, 3, FALSE), + PT(15, 1, 4, 0, TRUE), + PT( 1, 49, 2, 1, FALSE), + PT(63, 27, 3, 3, FALSE), + PT(33, 37, 5, 1, TRUE), + PT(38, 24, 2, 1, TRUE), + PT(21, 45, 6, 2, FALSE), + PT(35, 33, 6, 3, FALSE), + PT(14, 46, 3, 2, FALSE), + PT(20, 34, 3, 2, FALSE), + PT(44, 11, 5, 0, FALSE), + PT(26, 24, 4, 0, TRUE), + PT(33, 7, 3, 1, FALSE), + PT(36, 38, 5, 0, TRUE), + PT(43, 10, 6, 2, FALSE), + PT(62, 39, 6, 1, TRUE), + PT(18, 52, 3, 1, TRUE), + PT(31, 1, 5, 1, FALSE), + PT(46, 6, 4, 1, TRUE), + PT(47, 31, 2, 2, FALSE), + PT(24, 6, 4, 3, FALSE), + PT(49, 31, 5, 1, TRUE), + PT(34, 38, 5, 3, FALSE), + PT(30, 21, 2, 3, FALSE), + PT(32, 34, 5, 0, FALSE), + PT(21, 55, 2, 1, FALSE), + PT(37, 4, 5, 2, FALSE), + PT(31, 4, 5, 3, FALSE), + PT(12, 19, 3, 0, FALSE), + PT( 7, 11, 6, 3, FALSE), + PT(29, 28, 5, 1, FALSE), + PT(48, 34, 3, 2, FALSE), + PT(46, 18, 5, 3, TRUE), + PT(43, 33, 3, 3, FALSE), + PT(22, 56, 6, 0, FALSE), + PT( 4, 2, 2, 3, FALSE), + PT( 5, 20, 4, 0, FALSE), + PT(56, 60, 6, 1, TRUE), + PT(33, 27, 5, 3, TRUE), + PT(20, 42, 4, 3, TRUE), + PT(56, 20, 3, 1, TRUE), + PT(43, 31, 5, 1, TRUE), + PT(41, 43, 4, 2, TRUE), + PT(39, 54, 4, 0, TRUE), + PT(17, 34, 3, 1, TRUE), + PT(41, 3, 3, 1, TRUE), + PT(24, 36, 5, 0, FALSE), + PT(33, 45, 6, 3, FALSE), + PT(60, 44, 4, 2, FALSE), + PT(51, 23, 3, 3, TRUE), + PT(42, 58, 4, 0, TRUE), + PT(10, 35, 6, 3, TRUE), + PT( 0, 11, 4, 0, TRUE), + PT(17, 56, 3, 0, TRUE), + PT(15, 14, 3, 2, FALSE), + PT(31, 15, 6, 3, TRUE), + PT(60, 16, 6, 3, TRUE), + PT(56, 49, 6, 2, TRUE), + PT( 7, 21, 5, 0, FALSE), + PT(30, 46, 3, 0, TRUE), + PT(38, 16, 6, 1, TRUE), + PT(61, 53, 5, 3, TRUE), + PT(58, 4, 6, 2, FALSE), + PT(13, 24, 3, 1, FALSE), + PT( 1, 45, 2, 2, TRUE), + PT(61, 26, 2, 3, TRUE), + PT(23, 63, 6, 1, FALSE), + PT(11, 33, 2, 0, TRUE), + PT(30, 38, 5, 1, TRUE), + PT(13, 25, 4, 2, FALSE), + PT(46, 4, 3, 1, TRUE), + PT(27, 51, 4, 0, FALSE), + PT(21, 33, 3, 2, TRUE), + PT(31, 4, 4, 0, TRUE), + PT(15, 18, 3, 3, TRUE), + PT(45, 42, 6, 1, FALSE), + PT( 3, 55, 3, 3, TRUE), + PT(53, 7, 4, 3, TRUE), + PT(36, 31, 6, 0, TRUE), + PT(47, 48, 2, 2, TRUE), + PT( 6, 0, 4, 2, FALSE), + PT(11, 34, 3, 1, FALSE), + PT(12, 59, 5, 0, TRUE), + PT(20, 26, 2, 3, TRUE), + PT(55, 32, 4, 2, TRUE), + PT(63, 38, 6, 3, TRUE), + PT(58, 62, 2, 0, FALSE), + PT(34, 4, 2, 0, TRUE), + PT(40, 18, 3, 2, FALSE), + PT( 3, 46, 5, 3, FALSE), + PT(14, 56, 5, 0, FALSE), + PT( 1, 41, 4, 1, FALSE), + PT(30, 51, 3, 0, TRUE), + PT( 6, 33, 4, 3, TRUE), + PT(51, 25, 3, 1, FALSE), + PT( 2, 5, 2, 3, TRUE), + PT(17, 17, 5, 2, FALSE), + PT(31, 38, 3, 3, FALSE), + PT(57, 31, 5, 0, FALSE), + PT(46, 47, 2, 1, FALSE), + PT(34, 52, 2, 1, TRUE), + PT(59, 38, 5, 3, TRUE), + PT(52, 0, 2, 2, FALSE), + PT(16, 49, 2, 0, TRUE), + PT(29, 45, 5, 1, FALSE), + PT( 8, 8, 6, 3, TRUE), + PT(21, 24, 6, 2, FALSE), + PT( 4, 43, 4, 2, FALSE), + PT(47, 30, 4, 3, TRUE), + PT(34, 42, 4, 2, FALSE), + PT( 7, 20, 4, 2, TRUE), + PT( 1, 39, 3, 0, TRUE), + PT(41, 10, 5, 0, TRUE), + PT(61, 28, 5, 3, TRUE), + PT(13, 31, 3, 2, FALSE), + PT(36, 61, 6, 1, FALSE), + PT(54, 29, 4, 2, FALSE), + PT(20, 33, 2, 3, FALSE), + PT(26, 13, 5, 0, TRUE), + PT(63, 43, 5, 1, FALSE), + PT(26, 62, 6, 2, TRUE), + PT(17, 40, 3, 0, FALSE), + PT(50, 5, 2, 2, TRUE), + PT(33, 46, 6, 2, FALSE), + PT(45, 20, 5, 1, FALSE), + PT(60, 8, 6, 3, TRUE), + PT(63, 52, 3, 3, FALSE), + PT(39, 36, 3, 2, FALSE), + PT(22, 22, 6, 1, TRUE), + PT(41, 59, 3, 0, TRUE), + PT(54, 47, 3, 2, FALSE), + PT( 3, 37, 5, 2, FALSE), + PT(11, 22, 6, 3, FALSE), + PT(28, 29, 3, 1, TRUE), + PT(44, 39, 3, 1, TRUE), + PT(11, 31, 5, 1, TRUE), + PT( 8, 16, 4, 3, TRUE), + PT(63, 37, 5, 3, TRUE), + PT(51, 19, 3, 3, TRUE), + PT( 4, 49, 6, 3, TRUE), + PT(14, 47, 2, 1, FALSE), + PT( 8, 35, 4, 0, FALSE), + PT(58, 26, 3, 3, FALSE), + PT(47, 11, 3, 3, TRUE), + PT(30, 32, 3, 0, TRUE), + PT(35, 59, 2, 2, FALSE), + PT(37, 0, 4, 3, TRUE), + PT(20, 4, 4, 2, TRUE), + PT(54, 26, 5, 1, TRUE), + PT(39, 33, 2, 2, TRUE), + PT(40, 19, 5, 2, FALSE), + PT(14, 60, 6, 2, TRUE), + PT(12, 45, 5, 1, TRUE), + PT(55, 22, 2, 2, TRUE), + PT(41, 21, 3, 2, TRUE), + PT(23, 52, 6, 3, FALSE), + PT( 9, 10, 6, 0, TRUE), + PT(55, 34, 5, 0, FALSE), + PT(23, 43, 6, 2, TRUE), + PT(20, 43, 2, 1, FALSE), + PT( 8, 19, 3, 3, TRUE), + PT(49, 19, 5, 0, FALSE), + PT( 6, 7, 6, 2, TRUE), + PT(35, 58, 5, 0, TRUE), + PT(15, 36, 5, 3, FALSE), + PT( 7, 53, 4, 3, FALSE), + PT(14, 18, 2, 2, TRUE), + PT(35, 51, 5, 2, FALSE), + PT(14, 33, 4, 3, FALSE), + PT(28, 18, 4, 2, TRUE), + PT(35, 29, 5, 3, TRUE), + PT( 4, 53, 6, 1, TRUE), + PT(22, 1, 4, 2, FALSE), + PT(61, 44, 5, 3, FALSE), + PT(53, 10, 4, 2, TRUE), + PT(17, 19, 4, 2, TRUE), + PT(27, 27, 2, 2, TRUE), + PT(21, 57, 2, 0, FALSE), + PT(11, 53, 4, 2, FALSE), + PT(58, 39, 6, 0, FALSE), + PT(46, 47, 2, 2, TRUE), + PT(16, 31, 6, 2, TRUE), + PT(27, 40, 6, 2, TRUE), + PT(38, 48, 6, 3, TRUE), + PT(52, 55, 5, 1, TRUE), + PT(15, 48, 5, 0, TRUE), + PT(46, 63, 5, 1, TRUE), + PT(56, 52, 5, 1, TRUE), + PT(43, 47, 4, 2, TRUE), + PT(13, 40, 5, 1, FALSE), + PT(51, 24, 2, 0, FALSE), + PT(33, 18, 2, 0, TRUE), + PT(31, 34, 6, 2, FALSE), + PT(17, 37, 4, 1, TRUE), + PT(33, 63, 2, 0, TRUE), + PT(38, 39, 4, 2, TRUE), + PT(40, 54, 2, 1, FALSE), + PT(21, 38, 6, 1, FALSE), + PT(17, 24, 4, 2, FALSE), + PT(50, 37, 6, 3, TRUE), + PT(39, 58, 6, 1, TRUE), + PT(53, 7, 3, 2, FALSE), + PT(26, 14, 5, 1, FALSE), + PT(30, 47, 3, 3, TRUE), + PT( 0, 46, 4, 0, TRUE), + PT(27, 60, 2, 2, FALSE), + PT(47, 58, 5, 3, TRUE), + PT(62, 56, 2, 2, TRUE), + PT(26, 19, 5, 3, TRUE), + PT(41, 13, 5, 3, TRUE), + PT(55, 23, 3, 0, FALSE), + PT(48, 28, 6, 2, TRUE), + PT(21, 52, 2, 2, FALSE), + PT(40, 17, 5, 2, FALSE), + PT(44, 37, 5, 1, FALSE), + PT(32, 63, 5, 0, FALSE), + PT(12, 52, 3, 1, TRUE), + PT(48, 46, 4, 2, TRUE), + PT(55, 28, 4, 2, FALSE), + PT(31, 37, 4, 3, FALSE), + PT(12, 25, 6, 2, FALSE), + PT(24, 16, 6, 2, TRUE), + PT(10, 19, 2, 0, TRUE), + PT(37, 19, 4, 0, FALSE), + PT(19, 25, 2, 0, TRUE), + PT(32, 40, 3, 2, TRUE), + PT(62, 48, 3, 1, TRUE), + PT(35, 36, 4, 0, TRUE), + PT(13, 35, 4, 1, TRUE), + PT(29, 40, 5, 3, FALSE), + PT(45, 18, 3, 3, TRUE), + PT(14, 46, 5, 1, TRUE), + PT(11, 49, 6, 1, FALSE), + PT(36, 60, 5, 2, FALSE), + PT(19, 60, 2, 1, FALSE), + PT(40, 22, 5, 1, FALSE), + PT( 5, 12, 6, 1, FALSE), + PT(57, 11, 6, 1, FALSE), + PT(33, 4, 2, 2, FALSE), + PT(16, 49, 6, 1, FALSE), + PT(18, 31, 4, 1, TRUE), + PT(57, 46, 5, 3, FALSE), + PT(34, 61, 4, 3, TRUE), + PT(12, 30, 3, 0, FALSE), + PT(37, 0, 2, 3, TRUE), + PT( 6, 49, 2, 2, FALSE), + PT(19, 33, 3, 1, FALSE), + PT(20, 32, 6, 2, TRUE), + PT(10, 59, 4, 2, TRUE), + PT(51, 8, 5, 0, FALSE), + PT(61, 2, 6, 1, TRUE), + PT(35, 0, 2, 1, TRUE), + PT(34, 33, 5, 0, FALSE), + PT(48, 20, 5, 3, FALSE), + PT(20, 50, 6, 3, FALSE), + PT(57, 35, 3, 3, FALSE), + PT(28, 17, 6, 0, FALSE), + PT(55, 22, 6, 0, FALSE), + PT(21, 49, 3, 3, TRUE), + PT(52, 40, 5, 2, FALSE), + PT(53, 5, 5, 0, TRUE), + PT(55, 51, 5, 1, FALSE), + PT(28, 23, 5, 3, FALSE), + PT(16, 6, 2, 3, FALSE), + PT(50, 31, 5, 3, TRUE), + PT( 0, 41, 3, 3, FALSE), + PT( 4, 1, 2, 3, FALSE), + PT(59, 35, 3, 3, FALSE), + PT(27, 52, 5, 1, FALSE), + PT(48, 17, 5, 1, TRUE), + PT( 3, 0, 3, 3, TRUE), + PT(29, 55, 3, 1, FALSE), + PT(58, 24, 4, 2, TRUE), + PT(28, 22, 5, 2, FALSE), + PT( 4, 63, 6, 1, TRUE), + PT(38, 35, 5, 2, TRUE), + PT(21, 44, 4, 3, TRUE), + PT( 2, 53, 4, 3, TRUE), + PT( 7, 53, 6, 1, TRUE), + PT(26, 12, 2, 0, FALSE), + PT(40, 38, 5, 2, FALSE), + PT(47, 54, 2, 3, FALSE), + PT(55, 11, 4, 3, TRUE), + PT(27, 61, 3, 0, FALSE), + PT(39, 31, 4, 0, FALSE), + PT(43, 42, 6, 1, TRUE), + PT(11, 15, 4, 0, FALSE), + PT(53, 60, 5, 3, TRUE), + PT(51, 33, 2, 2, TRUE), + PT(45, 38, 6, 2, FALSE), + PT(31, 26, 4, 0, TRUE), + PT(47, 44, 5, 1, FALSE), + PT(26, 50, 3, 1, FALSE), + PT(59, 63, 4, 0, TRUE), + PT(19, 63, 2, 1, TRUE), + PT(15, 36, 4, 1, FALSE), + PT(20, 27, 2, 0, FALSE), + PT(33, 6, 5, 0, FALSE), + PT(37, 52, 2, 0, FALSE), + PT(46, 14, 2, 2, FALSE), + PT(60, 62, 4, 2, TRUE), + PT(22, 6, 6, 0, FALSE), + PT(11, 4, 3, 3, TRUE), + PT(62, 2, 4, 2, FALSE), + PT(12, 23, 4, 2, TRUE), + PT(43, 60, 5, 2, TRUE), + PT(21, 54, 6, 1, TRUE), + PT(24, 35, 5, 1, FALSE), + PT(29, 16, 5, 1, FALSE), + PT(53, 23, 5, 0, FALSE), + PT( 0, 55, 4, 2, FALSE), + PT(10, 59, 2, 2, TRUE), + PT(29, 11, 3, 3, TRUE), + PT(60, 49, 4, 2, TRUE), + PT(29, 15, 3, 2, TRUE), + PT(32, 19, 6, 2, FALSE), + PT(17, 43, 5, 3, FALSE), + PT(35, 12, 5, 3, FALSE), + PT(36, 2, 2, 2, FALSE), + PT(49, 22, 3, 0, TRUE), + PT(14, 35, 6, 2, TRUE), + PT(26, 16, 2, 3, FALSE), + PT(20, 4, 3, 0, TRUE), + PT(45, 39, 6, 3, TRUE), + PT(51, 2, 6, 0, TRUE), + PT( 2, 4, 2, 3, FALSE), + PT(13, 34, 4, 2, TRUE), + PT(37, 0, 2, 3, FALSE), + PT(42, 63, 4, 3, FALSE), + PT(32, 12, 2, 1, FALSE), + PT(47, 46, 6, 2, TRUE), + PT(27, 13, 4, 1, FALSE), + PT(30, 1, 6, 2, FALSE), + PT( 5, 34, 4, 0, TRUE), + PT(52, 42, 6, 1, FALSE), + PT(11, 9, 3, 2, TRUE), + PT(63, 50, 5, 3, TRUE), + PT(61, 24, 5, 2, TRUE), + PT(11, 56, 6, 3, FALSE), + PT(57, 23, 5, 0, FALSE), + PT(52, 4, 4, 2, FALSE), + PT(54, 14, 5, 1, FALSE), + PT(56, 1, 2, 2, FALSE), + PT(60, 36, 4, 1, FALSE), + PT(33, 3, 3, 0, FALSE), + PT(50, 47, 2, 1, FALSE), + PT(41, 36, 6, 0, TRUE), + PT(10, 59, 2, 1, FALSE), + PT(26, 28, 4, 0, FALSE), + PT(48, 49, 3, 1, TRUE), + PT(26, 33, 2, 0, FALSE), + PT( 5, 41, 2, 0, FALSE), + PT(38, 45, 2, 1, TRUE), + PT(22, 12, 3, 2, TRUE), + PT(43, 6, 3, 1, TRUE), + PT( 6, 18, 2, 2, FALSE), + PT(56, 15, 6, 2, TRUE), + PT(35, 58, 5, 2, FALSE), + PT( 0, 25, 6, 1, TRUE), + PT(41, 20, 5, 2, TRUE), + PT(42, 33, 5, 0, TRUE), + PT(20, 49, 2, 2, FALSE), + PT(26, 6, 3, 3, FALSE), + PT(24, 27, 5, 0, FALSE), + PT(59, 22, 5, 0, TRUE), + PT(21, 30, 2, 1, FALSE), + PT(52, 10, 2, 2, FALSE), + PT(27, 5, 4, 3, TRUE), + PT(11, 1, 4, 3, FALSE), + PT(42, 34, 6, 2, TRUE), + PT(33, 32, 3, 0, FALSE), + PT(32, 55, 2, 3, TRUE), + PT(20, 31, 2, 0, TRUE), + PT(29, 17, 4, 2, TRUE), + PT(36, 43, 5, 3, TRUE), + PT( 7, 63, 3, 3, TRUE), + PT(44, 37, 4, 2, TRUE), + PT(42, 41, 3, 0, FALSE), + PT(17, 36, 5, 0, FALSE), + PT(49, 44, 5, 1, FALSE), + PT(57, 11, 4, 3, FALSE), + PT(40, 16, 4, 3, FALSE), + PT(34, 6, 2, 3, FALSE), + PT( 9, 44, 2, 1, TRUE), + PT(52, 25, 2, 2, TRUE), + PT(58, 18, 4, 0, TRUE), + PT(29, 56, 4, 1, TRUE), + PT(18, 37, 4, 2, FALSE), + PT(33, 48, 2, 1, FALSE), + PT(55, 26, 2, 1, FALSE), + PT(36, 59, 4, 2, TRUE), + PT(50, 21, 4, 1, TRUE), + PT(13, 26, 2, 0, FALSE), + PT(22, 46, 4, 3, FALSE), + PT(29, 20, 2, 3, FALSE), + PT(62, 46, 3, 3, TRUE), + PT(10, 22, 2, 0, FALSE), + PT(29, 48, 5, 1, TRUE), + PT( 4, 58, 3, 0, TRUE), + PT( 8, 45, 5, 3, FALSE), + PT(40, 30, 6, 1, TRUE), + PT(10, 18, 5, 3, FALSE), + PT(13, 3, 5, 3, TRUE), + PT(38, 58, 3, 3, FALSE), + PT(53, 59, 5, 1, FALSE), + PT( 3, 26, 3, 0, FALSE), + PT(63, 11, 4, 3, TRUE), + PT( 4, 5, 6, 2, FALSE), + PT(54, 11, 4, 3, TRUE), + PT(59, 23, 2, 0, TRUE), + PT(13, 39, 4, 3, FALSE), + PT(44, 31, 4, 0, FALSE), + PT(38, 16, 4, 0, FALSE), + PT(37, 35, 5, 2, TRUE), + PT(55, 9, 2, 1, TRUE), + PT(20, 23, 5, 2, TRUE), + PT(46, 61, 4, 1, TRUE), + PT(29, 26, 3, 3, TRUE), + PT(33, 51, 5, 3, FALSE), + PT(40, 23, 2, 1, TRUE), + PT(38, 60, 6, 3, FALSE), + PT(20, 26, 6, 1, TRUE), + PT(50, 32, 5, 1, TRUE), + PT(25, 62, 4, 0, FALSE), + PT(12, 2, 5, 2, TRUE), + PT(60, 60, 5, 1, FALSE), + PT(48, 48, 5, 0, FALSE), + PT(37, 63, 3, 3, FALSE), + PT( 3, 23, 3, 3, FALSE), + PT(53, 17, 3, 2, FALSE), + PT(27, 20, 5, 1, FALSE), + PT(40, 58, 4, 1, TRUE), + PT(14, 31, 2, 1, FALSE), + PT(54, 33, 4, 0, FALSE), + PT( 7, 59, 2, 0, FALSE), + PT(35, 25, 6, 2, FALSE), + PT(13, 46, 3, 0, FALSE), + PT(63, 32, 4, 2, TRUE), + PT(62, 59, 2, 2, TRUE), + PT(11, 46, 2, 1, FALSE), + PT(55, 11, 4, 1, TRUE), + PT(61, 50, 3, 3, TRUE), + PT(22, 3, 4, 3, TRUE), + PT(20, 12, 4, 0, TRUE), + PT(24, 3, 6, 0, FALSE), + PT(62, 33, 2, 1, TRUE), + PT(15, 0, 6, 1, FALSE), + PT(63, 35, 2, 3, FALSE), + PT(14, 49, 3, 2, TRUE), + PT(24, 28, 3, 2, TRUE), + PT(48, 14, 3, 3, FALSE), + PT(33, 32, 4, 1, TRUE), + PT(63, 12, 3, 3, FALSE), + PT(20, 51, 4, 1, FALSE), + PT(34, 33, 2, 2, TRUE), + PT(54, 5, 3, 3, FALSE), + PT(29, 49, 2, 2, FALSE), + PT(32, 17, 6, 3, TRUE), + PT(13, 51, 3, 0, TRUE), + PT(37, 5, 6, 3, FALSE), + PT(30, 49, 4, 0, FALSE), + PT(53, 58, 5, 3, TRUE), + PT(50, 47, 6, 0, FALSE), + PT(20, 35, 5, 2, TRUE), + PT(53, 30, 5, 0, TRUE), + PT( 5, 5, 3, 1, TRUE), + PT( 9, 31, 4, 3, FALSE), + PT(47, 11, 2, 2, TRUE), + PT(21, 17, 2, 1, TRUE), + PT(41, 27, 3, 0, FALSE), + PT(28, 19, 6, 2, TRUE), + PT(52, 49, 4, 1, TRUE), + PT(39, 63, 5, 3, TRUE), + PT( 9, 48, 3, 0, TRUE), + PT(35, 18, 6, 2, FALSE), + PT( 2, 42, 4, 0, TRUE), + PT( 9, 60, 3, 2, TRUE), + PT(12, 2, 2, 0, FALSE), + PT(34, 5, 2, 3, TRUE), + PT(34, 8, 3, 1, TRUE), + PT(10, 15, 2, 2, TRUE), + PT( 2, 17, 2, 1, TRUE), + PT( 1, 33, 4, 1, FALSE), + PT(22, 57, 6, 1, TRUE), + PT(36, 56, 6, 2, FALSE), + PT(15, 30, 5, 1, TRUE), + PT(43, 21, 2, 2, TRUE), + PT(32, 34, 5, 3, FALSE), + PT(58, 63, 6, 0, TRUE), + PT(26, 39, 5, 1, TRUE), + PT(41, 52, 2, 2, FALSE), + PT(22, 57, 5, 3, TRUE), + PT(19, 62, 2, 3, FALSE), + PT(54, 33, 6, 0, FALSE), + PT( 0, 36, 5, 1, TRUE), + PT(36, 33, 6, 0, FALSE), + PT(21, 49, 2, 1, TRUE), + PT(16, 55, 4, 2, FALSE), + PT( 8, 7, 4, 1, TRUE), + PT(33, 9, 4, 2, TRUE), + PT( 5, 60, 6, 1, FALSE), + PT(25, 3, 4, 2, TRUE), + PT(15, 41, 5, 1, TRUE), + PT(22, 7, 2, 1, TRUE), + PT(62, 61, 4, 2, TRUE), + PT(54, 11, 5, 0, FALSE), + PT(46, 43, 2, 3, FALSE), + PT(12, 49, 2, 0, TRUE), + PT(48, 19, 5, 2, TRUE), + PT(38, 62, 6, 3, TRUE), + PT(41, 47, 5, 3, FALSE), + PT(21, 61, 2, 3, TRUE), + PT(28, 46, 4, 0, TRUE), + PT(51, 47, 2, 0, FALSE), + PT(13, 5, 3, 2, TRUE), + PT(28, 26, 2, 1, FALSE), + PT(14, 24, 6, 3, TRUE), + PT(27, 17, 2, 2, FALSE), + PT( 6, 20, 4, 0, TRUE), + PT(49, 14, 4, 3, TRUE), + PT(26, 3, 2, 0, FALSE), + PT( 0, 52, 6, 0, TRUE), + PT(63, 11, 3, 2, TRUE), + PT(15, 18, 3, 3, TRUE), + PT(26, 21, 2, 0, FALSE), + PT(15, 0, 4, 2, FALSE), + PT(62, 10, 5, 1, FALSE), + PT(48, 43, 4, 2, FALSE), + PT(38, 49, 2, 0, FALSE), + PT(45, 47, 5, 3, TRUE), + PT(63, 12, 2, 1, TRUE), + PT(18, 11, 2, 3, FALSE), + PT(21, 7, 3, 3, TRUE), + PT(40, 16, 6, 1, FALSE), + PT(15, 23, 2, 2, TRUE), + PT(11, 39, 6, 1, TRUE), + PT(52, 29, 2, 0, FALSE), + PT(28, 58, 2, 1, FALSE), + PT(44, 39, 6, 3, TRUE), + PT(10, 26, 6, 1, FALSE), + PT( 5, 31, 4, 0, TRUE), + PT(36, 13, 3, 3, TRUE), + PT(28, 23, 4, 2, FALSE), + PT(47, 59, 6, 1, FALSE), + PT(59, 37, 2, 0, FALSE), + PT( 3, 47, 4, 0, TRUE), + PT(12, 16, 4, 1, TRUE), + PT(14, 58, 5, 2, FALSE), + PT(51, 3, 5, 2, FALSE), + PT(18, 6, 3, 2, FALSE), + PT(42, 55, 6, 0, FALSE), + PT(63, 1, 3, 3, FALSE), + PT(53, 22, 6, 3, TRUE), + PT(44, 50, 6, 2, TRUE), + PT( 5, 17, 4, 1, FALSE), + PT(41, 9, 4, 0, FALSE), + PT(43, 13, 3, 3, TRUE), + PT(24, 13, 4, 0, FALSE), + PT(35, 57, 2, 3, FALSE), + PT(15, 58, 3, 0, FALSE), + PT(33, 53, 5, 1, TRUE), + PT(54, 38, 5, 1, TRUE), + PT(35, 5, 5, 3, TRUE), + PT(27, 8, 2, 3, TRUE), + PT(62, 9, 2, 3, FALSE), + PT(45, 58, 6, 3, TRUE), + PT(21, 53, 6, 2, TRUE), + PT(41, 10, 2, 1, FALSE), + PT( 2, 57, 3, 3, TRUE), + PT(20, 52, 6, 1, TRUE), + PT(23, 29, 3, 0, FALSE), + PT(22, 29, 3, 1, FALSE), + PT( 1, 57, 4, 1, FALSE), + PT(30, 39, 6, 3, FALSE), + PT(50, 20, 4, 3, FALSE), + PT(10, 57, 6, 3, FALSE), + PT(31, 13, 3, 3, FALSE), + PT(11, 10, 3, 0, TRUE), + PT(53, 29, 6, 2, FALSE), + PT( 3, 18, 2, 3, FALSE), + PT(12, 19, 5, 3, FALSE), + PT(12, 52, 3, 3, FALSE), + PT(16, 20, 3, 3, FALSE), + PT(35, 50, 4, 3, TRUE), + PT( 2, 16, 5, 0, TRUE), + PT(53, 24, 6, 1, TRUE), + PT(51, 29, 3, 1, FALSE), + PT(60, 21, 4, 1, TRUE), + PT(62, 63, 4, 1, FALSE), + PT(42, 2, 5, 2, FALSE), + PT(40, 10, 5, 3, TRUE), + PT(26, 6, 6, 2, TRUE), + PT(60, 23, 5, 1, TRUE), + PT( 3, 18, 2, 3, TRUE), + PT(47, 10, 4, 3, FALSE), + PT(18, 56, 2, 0, TRUE), + PT(54, 27, 4, 1, TRUE), + PT( 1, 57, 6, 2, TRUE), + PT(25, 25, 2, 3, TRUE), + PT( 9, 40, 4, 1, FALSE), + PT(30, 39, 5, 2, FALSE), + PT(53, 51, 5, 2, FALSE), + PT(39, 37, 6, 0, TRUE), + PT( 6, 49, 5, 2, TRUE), + PT(26, 57, 5, 0, FALSE), + PT(45, 4, 3, 3, FALSE), + PT(36, 62, 3, 2, FALSE), + PT(60, 48, 3, 1, TRUE), + PT(63, 62, 6, 3, TRUE), + PT(34, 54, 2, 0, TRUE), + PT( 0, 1, 3, 2, FALSE), + PT(18, 26, 2, 0, FALSE), + PT(18, 30, 5, 2, FALSE), + PT(31, 18, 5, 1, FALSE), + PT(47, 6, 3, 0, TRUE), + PT(53, 26, 3, 0, FALSE), + PT(59, 9, 6, 3, FALSE), + PT(52, 29, 2, 1, TRUE), + PT( 2, 7, 2, 0, FALSE), + PT(32, 47, 3, 2, TRUE), + PT(11, 3, 6, 1, TRUE), + PT(28, 22, 6, 0, TRUE), + PT( 5, 19, 3, 1, TRUE), + PT(41, 6, 2, 1, TRUE), + PT(48, 45, 6, 3, FALSE), + PT(42, 45, 5, 2, FALSE), + PT(25, 52, 3, 2, FALSE), + PT(15, 21, 2, 1, FALSE), + PT(54, 21, 5, 2, FALSE), + PT(58, 6, 3, 2, FALSE), + PT(18, 29, 4, 3, FALSE), + PT( 3, 56, 3, 2, TRUE), + PT( 1, 1, 5, 2, TRUE), + PT(23, 46, 2, 0, FALSE), + PT(20, 23, 3, 2, FALSE), + PT(52, 15, 5, 0, FALSE), + PT( 9, 55, 3, 1, TRUE), + PT(40, 29, 4, 3, FALSE), + PT(41, 45, 6, 3, FALSE), + PT(30, 23, 5, 0, FALSE), + PT(21, 15, 3, 2, FALSE), + PT(32, 45, 2, 0, FALSE), + PT(39, 22, 5, 3, FALSE), + PT(20, 9, 2, 1, FALSE), + PT(59, 61, 4, 0, TRUE), + PT(37, 26, 5, 2, FALSE), + PT( 0, 34, 6, 3, FALSE), + PT(13, 48, 2, 0, FALSE), + PT(23, 25, 3, 1, TRUE), + PT( 0, 59, 4, 0, TRUE), + PT(42, 40, 6, 2, FALSE), + PT(45, 15, 2, 3, FALSE), + PT(10, 48, 5, 0, FALSE), + PT( 6, 0, 4, 2, TRUE), + PT(49, 46, 5, 1, FALSE), + PT(20, 51, 5, 0, FALSE), + PT(54, 16, 5, 3, FALSE), + PT( 5, 46, 3, 0, TRUE), + PT(25, 26, 2, 2, TRUE), + PT(44, 20, 2, 3, TRUE), + PT(55, 15, 2, 1, TRUE), + PT(50, 23, 3, 1, TRUE), + PT(57, 24, 6, 1, FALSE), + PT(46, 50, 3, 3, FALSE), + PT(36, 29, 6, 0, TRUE), + PT(18, 29, 5, 1, TRUE), + PT(20, 12, 4, 3, TRUE), + PT(54, 46, 6, 1, FALSE), + PT( 6, 10, 3, 1, FALSE), + PT(40, 40, 4, 0, FALSE), + PT(58, 58, 2, 3, TRUE), + PT( 8, 39, 6, 3, FALSE), + PT(24, 26, 2, 0, FALSE), + PT(30, 38, 3, 1, TRUE), + PT(31, 51, 3, 3, TRUE), + PT(33, 23, 5, 3, TRUE), + PT( 1, 8, 4, 0, FALSE), + PT(53, 3, 3, 0, TRUE), + PT(59, 2, 4, 0, FALSE), + PT( 2, 45, 4, 1, TRUE), + PT(14, 23, 6, 1, FALSE), + PT(49, 41, 2, 0, TRUE), + PT(34, 23, 4, 1, FALSE), + PT(58, 44, 4, 1, TRUE), + PT(52, 32, 3, 0, FALSE), + PT( 0, 58, 4, 1, FALSE), + PT(37, 51, 4, 0, TRUE), + PT(51, 4, 4, 3, TRUE), + PT( 4, 24, 6, 1, FALSE), + PT(44, 12, 5, 3, TRUE), + PT(40, 20, 5, 2, FALSE), + PT(63, 48, 5, 1, TRUE), + PT(48, 33, 3, 2, TRUE), + PT( 1, 37, 6, 1, FALSE), + PT( 5, 35, 6, 2, FALSE), + PT(36, 16, 6, 0, FALSE), + PT(61, 20, 3, 1, TRUE), + PT(63, 56, 5, 3, TRUE), + PT(34, 27, 6, 1, FALSE), + PT(37, 7, 6, 3, TRUE), + PT(10, 12, 3, 2, TRUE), + PT( 3, 30, 3, 1, FALSE), + PT(15, 60, 2, 1, FALSE), + PT(17, 24, 3, 2, TRUE), + PT( 0, 53, 5, 3, TRUE), + PT(50, 24, 2, 2, FALSE), + PT(35, 48, 3, 1, TRUE), + PT(17, 61, 2, 1, FALSE), + PT(26, 22, 6, 2, TRUE), + PT(40, 5, 4, 2, FALSE), + PT(23, 61, 6, 3, TRUE), + PT(46, 9, 5, 3, FALSE), + PT(24, 29, 2, 3, TRUE), + PT(32, 31, 3, 0, FALSE), + PT(35, 44, 5, 3, TRUE), + PT(32, 63, 2, 3, FALSE), + PT(63, 41, 5, 3, FALSE), + PT(35, 59, 5, 0, TRUE), + PT(24, 57, 2, 1, TRUE), + PT(30, 50, 6, 2, TRUE), + PT(20, 29, 5, 1, FALSE), + PT(53, 1, 3, 2, TRUE), + PT(62, 59, 3, 3, FALSE), + PT(34, 30, 2, 3, FALSE), + PT(24, 34, 2, 1, FALSE), + PT(62, 41, 6, 1, TRUE), + PT(47, 20, 3, 0, TRUE), + PT(59, 7, 2, 2, TRUE), + PT( 6, 61, 5, 0, TRUE), + PT(53, 55, 4, 1, TRUE), + PT(52, 29, 5, 2, TRUE), + PT(24, 18, 3, 1, TRUE), + PT(11, 19, 4, 2, FALSE), + PT(19, 56, 3, 2, FALSE), + PT(31, 11, 3, 1, TRUE), + PT(19, 33, 3, 2, FALSE), + PT( 6, 57, 6, 1, FALSE), + PT(55, 61, 4, 3, FALSE), + PT(41, 38, 2, 2, TRUE), + PT(60, 51, 4, 3, TRUE), + PT( 0, 1, 5, 3, FALSE), + PT(21, 24, 6, 0, TRUE), + PT(13, 44, 2, 1, TRUE), + PT(39, 59, 4, 0, FALSE), + PT(45, 1, 4, 3, FALSE), + PT(35, 21, 6, 0, FALSE), + PT(36, 0, 2, 3, TRUE), + PT(55, 63, 6, 1, TRUE), + PT(37, 36, 6, 0, TRUE), + PT( 6, 59, 6, 3, TRUE), + PT( 3, 24, 3, 1, FALSE), + PT(44, 52, 2, 2, FALSE), + PT(29, 54, 3, 0, FALSE), + PT(58, 4, 4, 1, TRUE), + PT(18, 38, 2, 2, TRUE), + PT(43, 25, 3, 1, FALSE), + PT(41, 44, 6, 3, FALSE), + PT( 1, 25, 3, 2, TRUE), + PT(47, 6, 5, 1, TRUE), + PT(12, 18, 4, 3, FALSE), + PT(54, 50, 3, 2, TRUE), + PT(13, 18, 5, 0, FALSE), + PT( 3, 40, 2, 1, TRUE), + PT(41, 6, 2, 3, TRUE), + PT( 3, 56, 4, 0, TRUE), + PT(48, 44, 2, 0, FALSE), + PT(34, 0, 5, 0, FALSE), + PT(36, 59, 3, 2, FALSE), + PT(32, 62, 2, 1, TRUE), + PT( 2, 12, 3, 0, TRUE), + PT(41, 44, 3, 1, FALSE), + PT(57, 48, 4, 1, FALSE), + PT(42, 31, 4, 1, FALSE), + PT(20, 52, 5, 2, FALSE), + PT(20, 37, 3, 1, TRUE), + PT( 6, 59, 2, 2, TRUE), + PT( 6, 28, 2, 1, TRUE), + PT(21, 3, 3, 0, FALSE), + PT(30, 42, 3, 1, TRUE), + PT(23, 37, 5, 3, TRUE), + PT(28, 41, 5, 3, FALSE), + PT( 2, 50, 3, 3, FALSE), + PT(29, 40, 6, 2, TRUE), + PT(54, 3, 6, 2, FALSE), + PT(22, 61, 5, 1, FALSE), + PT(18, 13, 2, 1, TRUE), + PT(29, 45, 4, 0, TRUE), + PT(50, 23, 5, 3, FALSE), + PT(26, 21, 4, 3, FALSE), + PT(34, 47, 2, 2, TRUE), + PT(60, 14, 4, 0, FALSE), + PT(47, 39, 2, 1, TRUE), + PT( 4, 9, 6, 1, FALSE), + PT(30, 1, 6, 2, FALSE), + PT( 6, 22, 3, 3, FALSE), + PT(46, 27, 3, 2, FALSE), + PT(40, 19, 5, 1, FALSE), + PT(48, 52, 2, 1, FALSE), + PT(18, 50, 3, 0, FALSE), + PT(29, 29, 6, 2, TRUE), + PT( 7, 28, 2, 3, FALSE), + PT(45, 61, 6, 2, TRUE), + PT(28, 27, 4, 2, FALSE), + PT(33, 45, 3, 3, FALSE), + PT(16, 9, 2, 2, FALSE), + PT(61, 17, 2, 1, FALSE), + PT(37, 2, 4, 3, FALSE), + PT(35, 2, 3, 0, TRUE), + PT(25, 5, 2, 2, FALSE), + PT(11, 33, 3, 1, FALSE), + PT( 9, 2, 5, 2, FALSE), + PT(24, 40, 5, 2, TRUE), + PT(30, 16, 2, 1, FALSE), + PT(46, 24, 5, 3, FALSE), + PT(31, 2, 5, 2, FALSE), + PT(20, 23, 4, 2, FALSE), + PT(57, 8, 6, 1, FALSE), + PT(22, 20, 4, 1, FALSE), + PT(22, 40, 4, 0, TRUE), + PT(17, 16, 5, 2, FALSE), + PT(35, 54, 5, 1, TRUE), + PT(57, 33, 4, 3, FALSE), + PT(14, 6, 5, 2, TRUE), + PT(60, 62, 4, 3, FALSE), + PT(42, 27, 3, 3, TRUE), + PT( 0, 60, 6, 1, TRUE), + PT(53, 63, 2, 2, FALSE), + PT( 0, 11, 2, 0, FALSE), + PT(52, 60, 2, 3, TRUE), + PT(45, 7, 3, 3, TRUE), + PT(36, 57, 4, 3, TRUE), + PT(22, 0, 3, 2, TRUE), + PT(51, 43, 3, 3, FALSE), + PT(15, 8, 6, 0, TRUE), + PT(58, 9, 2, 1, TRUE), + PT(12, 33, 3, 2, FALSE), + PT(42, 23, 6, 2, FALSE), + PT(41, 39, 2, 0, FALSE), + PT(55, 27, 3, 0, FALSE), + PT(21, 8, 5, 3, TRUE), + PT(31, 22, 2, 1, FALSE), + PT(31, 40, 6, 2, FALSE), + PT(28, 32, 4, 1, FALSE), + PT(18, 1, 2, 1, FALSE), + PT(33, 49, 2, 0, FALSE), + PT(34, 38, 3, 3, FALSE), + PT( 1, 61, 2, 0, TRUE), + PT(30, 39, 4, 2, TRUE), + PT(61, 48, 4, 2, FALSE), + PT(29, 17, 4, 1, FALSE), + PT(54, 48, 2, 3, FALSE), + PT(31, 62, 5, 1, FALSE), + PT(60, 39, 3, 1, TRUE), + PT(31, 41, 2, 0, FALSE), + PT(30, 5, 5, 1, FALSE), + PT(10, 16, 2, 2, FALSE), + PT(31, 0, 5, 3, FALSE), + PT(11, 59, 3, 0, FALSE), + PT(10, 57, 6, 0, FALSE), + PT(55, 11, 3, 3, TRUE), + PT(29, 10, 5, 0, TRUE), + PT(62, 28, 6, 1, TRUE), + PT(19, 46, 5, 0, FALSE), + PT(39, 27, 3, 3, FALSE), + PT(29, 2, 3, 2, FALSE), + PT( 1, 37, 2, 2, FALSE), + PT(58, 16, 3, 2, FALSE), + PT(18, 5, 5, 1, FALSE), + PT(48, 32, 4, 3, FALSE), + PT(47, 46, 5, 3, FALSE), + PT( 3, 7, 4, 2, FALSE), + PT(54, 4, 5, 1, TRUE), + PT(17, 37, 5, 2, TRUE), + PT(40, 14, 5, 3, FALSE), + PT(15, 29, 2, 2, TRUE), + PT(28, 40, 6, 0, FALSE), + PT(31, 35, 4, 3, FALSE), + PT(54, 18, 6, 3, TRUE), + PT(58, 49, 2, 0, FALSE), + PT(44, 44, 5, 3, TRUE), + PT(26, 13, 2, 2, TRUE), + PT(63, 60, 6, 1, FALSE), + PT(53, 28, 2, 3, FALSE), + PT(51, 22, 5, 0, FALSE), + PT(29, 63, 4, 0, TRUE), + PT(44, 62, 5, 1, TRUE), + PT(36, 35, 5, 3, TRUE), + PT(50, 21, 5, 1, FALSE), + PT(27, 16, 6, 2, TRUE), + PT(24, 55, 2, 0, FALSE), + PT(59, 30, 2, 0, TRUE), + PT(43, 22, 4, 2, FALSE), + PT(29, 22, 4, 3, FALSE), + PT(60, 45, 2, 0, TRUE), + PT(21, 40, 5, 0, FALSE), + PT(39, 39, 4, 3, TRUE), + PT(59, 58, 2, 3, FALSE), + PT(26, 12, 3, 1, FALSE), + PT(21, 8, 4, 2, TRUE), + PT(11, 16, 4, 1, FALSE), + PT(26, 62, 2, 3, TRUE), + PT(40, 31, 3, 3, FALSE), + PT( 1, 30, 3, 3, FALSE), + PT(28, 47, 2, 0, FALSE), + PT(37, 11, 6, 2, FALSE), + PT(62, 12, 3, 1, FALSE), + PT(27, 16, 5, 1, FALSE), + PT(15, 20, 2, 3, TRUE), + PT(15, 63, 2, 3, TRUE), + PT( 3, 21, 3, 3, TRUE), + PT( 2, 54, 2, 3, TRUE), + PT(21, 29, 3, 0, FALSE), + PT( 8, 54, 2, 0, FALSE), + PT(20, 13, 5, 1, TRUE), + PT(10, 5, 3, 2, TRUE), + PT(38, 18, 3, 3, FALSE), + PT(62, 24, 3, 0, TRUE), + PT(54, 24, 6, 3, TRUE), + PT(23, 57, 5, 3, FALSE), + PT(13, 4, 3, 0, TRUE), + PT(22, 34, 2, 2, TRUE), + PT(62, 38, 3, 3, TRUE), + PT( 0, 6, 2, 3, TRUE), + PT(51, 34, 3, 2, TRUE), + PT(43, 57, 5, 1, TRUE), + PT(62, 49, 3, 2, FALSE), + PT(34, 63, 2, 1, TRUE), + PT(48, 28, 6, 0, TRUE), + PT( 7, 43, 2, 2, FALSE), + PT(50, 53, 3, 3, FALSE), + PT( 2, 7, 4, 0, FALSE), + PT(15, 59, 2, 0, TRUE), + PT(32, 7, 2, 1, FALSE), + PT(42, 48, 3, 2, TRUE), + PT(40, 56, 6, 3, FALSE), + PT(32, 1, 2, 3, TRUE), + PT(21, 32, 4, 0, TRUE), + PT(58, 27, 3, 3, FALSE), + PT(56, 18, 4, 2, FALSE), + PT( 3, 62, 3, 3, TRUE), + PT(41, 29, 2, 1, TRUE), + PT(32, 39, 3, 0, TRUE), + PT(18, 37, 4, 0, FALSE), + PT(50, 51, 5, 1, TRUE), + PT(63, 5, 6, 0, TRUE), + PT(53, 60, 5, 2, TRUE), + PT(45, 2, 5, 3, FALSE), + PT(16, 42, 2, 3, FALSE), + PT(23, 8, 6, 0, TRUE), + PT(23, 46, 5, 1, TRUE), + PT(48, 30, 2, 2, TRUE), + PT(49, 21, 4, 3, FALSE), + PT( 8, 16, 6, 1, TRUE), + PT(21, 1, 4, 3, TRUE), + PT(18, 7, 5, 3, TRUE), + PT(41, 39, 6, 2, FALSE), + PT(63, 8, 6, 0, TRUE), + PT(28, 32, 3, 1, FALSE), + PT(51, 12, 2, 1, TRUE), + PT(24, 49, 4, 2, FALSE), + PT(55, 45, 5, 3, FALSE), + PT(33, 24, 4, 2, FALSE), + PT(58, 39, 6, 0, TRUE), + PT(53, 62, 6, 0, FALSE), + PT(58, 20, 6, 1, TRUE), + PT(15, 26, 5, 2, TRUE), + PT(48, 46, 2, 0, TRUE), + PT(26, 49, 3, 2, TRUE), + PT(23, 60, 3, 0, FALSE), + PT(51, 49, 4, 1, TRUE), + PT(29, 57, 5, 2, TRUE), + PT(16, 29, 5, 3, TRUE), + PT(36, 21, 3, 2, FALSE), + PT(37, 1, 5, 1, TRUE), + PT(34, 22, 5, 3, FALSE), + PT(27, 37, 6, 2, TRUE), + PT(55, 16, 4, 3, FALSE), + PT(57, 1, 6, 3, FALSE), + PT(23, 43, 2, 2, FALSE), + PT( 9, 22, 2, 3, TRUE), + PT(32, 40, 4, 1, TRUE), + PT(38, 58, 4, 3, FALSE), + PT(39, 42, 4, 2, FALSE), + PT(54, 2, 5, 2, FALSE), + PT(41, 48, 6, 2, TRUE), + PT(54, 1, 3, 3, TRUE), + PT(40, 59, 3, 2, TRUE), + PT(35, 30, 5, 2, TRUE), + PT(17, 30, 5, 2, FALSE), + PT(47, 50, 3, 0, TRUE), + PT(63, 38, 6, 0, TRUE), + PT(56, 30, 2, 3, TRUE), + PT( 5, 24, 5, 3, FALSE), + PT( 0, 46, 2, 1, FALSE), + PT(52, 63, 6, 2, FALSE), + PT(22, 16, 5, 0, TRUE), + PT(32, 61, 6, 3, FALSE), + PT(47, 22, 4, 2, TRUE), + PT(18, 23, 2, 0, FALSE), + PT(33, 55, 6, 2, TRUE), + PT(37, 55, 5, 2, TRUE), + PT( 1, 8, 4, 3, TRUE), + PT( 3, 31, 5, 0, TRUE), + PT(13, 42, 2, 3, FALSE), + PT(58, 63, 6, 1, TRUE), + PT(43, 25, 3, 2, TRUE), + PT(42, 31, 5, 0, TRUE), + PT(40, 44, 2, 0, FALSE), + PT(40, 48, 2, 0, FALSE), + PT(57, 20, 3, 1, TRUE), + PT( 0, 24, 4, 0, TRUE), + PT(40, 12, 6, 3, TRUE), + PT(17, 16, 2, 0, TRUE), + PT(60, 51, 6, 1, FALSE), + PT(51, 54, 3, 1, FALSE), + PT(54, 0, 3, 2, FALSE), + PT(49, 27, 3, 2, TRUE), + PT(56, 29, 2, 0, FALSE), + PT(60, 57, 4, 3, TRUE), + PT(58, 63, 2, 2, FALSE), + PT(25, 18, 2, 2, FALSE), + PT(13, 31, 3, 0, FALSE), + PT( 0, 37, 3, 0, FALSE), + PT(40, 28, 6, 1, FALSE), + PT(39, 3, 3, 1, FALSE), + PT(38, 45, 5, 1, FALSE), + PT(41, 40, 4, 3, TRUE), + PT(10, 42, 3, 0, FALSE), + PT(10, 26, 6, 0, FALSE), + PT(32, 26, 5, 3, FALSE), + PT( 6, 11, 3, 2, TRUE), + PT(15, 12, 3, 2, FALSE), + PT(53, 40, 3, 2, FALSE), + PT(61, 22, 4, 1, TRUE), + PT(33, 28, 6, 0, TRUE), + PT(20, 28, 5, 3, FALSE), + PT(34, 50, 6, 2, TRUE), + PT( 9, 41, 6, 0, FALSE), + PT(32, 26, 2, 0, FALSE), + PT(49, 63, 5, 2, FALSE), + PT(10, 61, 6, 3, TRUE), + PT(11, 46, 5, 2, TRUE), + PT(31, 34, 6, 0, TRUE), + PT( 6, 7, 5, 0, TRUE), + PT(34, 23, 5, 2, TRUE), + PT(48, 17, 3, 0, FALSE), + PT(12, 25, 2, 2, TRUE), + PT( 7, 10, 6, 2, FALSE), + PT(24, 41, 4, 3, TRUE), + PT(51, 12, 6, 0, FALSE), + PT( 3, 26, 6, 3, TRUE), + PT( 6, 1, 5, 2, TRUE), + PT(15, 59, 5, 1, TRUE), + PT(17, 31, 6, 3, TRUE), + PT(43, 33, 6, 3, FALSE), + PT(63, 35, 2, 3, TRUE), + PT(23, 7, 5, 1, TRUE), + PT(43, 14, 6, 0, FALSE), + PT(17, 57, 3, 2, TRUE), + PT(41, 3, 6, 1, TRUE), + PT(48, 3, 5, 3, TRUE), + PT(60, 32, 4, 3, FALSE), + PT( 3, 34, 2, 2, FALSE), + PT(58, 40, 6, 2, TRUE), + PT( 1, 40, 5, 1, TRUE), + PT(62, 21, 3, 0, FALSE), + PT(48, 7, 2, 3, TRUE), + PT(59, 44, 6, 0, FALSE), + PT(21, 7, 5, 2, FALSE), + PT(23, 39, 3, 2, TRUE), + PT(63, 30, 6, 1, TRUE), + PT(13, 23, 2, 0, FALSE), + PT(21, 14, 6, 0, FALSE), + PT( 9, 5, 6, 0, FALSE), + PT(45, 32, 2, 2, TRUE), + PT(60, 61, 6, 0, FALSE), + PT(12, 23, 3, 2, FALSE), + PT(26, 13, 4, 2, TRUE), + PT(43, 43, 5, 1, FALSE), + PT( 2, 22, 5, 2, TRUE), + PT(23, 49, 2, 3, TRUE), + PT( 0, 8, 2, 1, TRUE), + PT(55, 53, 4, 0, TRUE), + PT(30, 28, 3, 3, TRUE), + PT(43, 50, 3, 2, FALSE), + PT(16, 42, 2, 3, FALSE), + PT(58, 51, 6, 0, TRUE), + PT(23, 43, 5, 1, FALSE), + PT(12, 61, 2, 0, TRUE), + PT(40, 10, 6, 0, FALSE), + PT(35, 10, 4, 3, FALSE), + PT(10, 20, 4, 2, FALSE), + PT(11, 15, 6, 0, FALSE), + PT(27, 30, 5, 0, TRUE), + PT( 2, 53, 5, 0, FALSE), + PT(59, 2, 2, 2, FALSE), + PT( 0, 15, 6, 2, TRUE), + PT(28, 60, 5, 3, FALSE), + PT(40, 56, 3, 0, TRUE), + PT(27, 17, 2, 1, FALSE), + PT( 9, 22, 2, 0, FALSE), + PT(46, 13, 4, 0, FALSE), + PT(61, 4, 6, 1, FALSE), + PT(22, 44, 4, 2, TRUE), + PT( 2, 61, 3, 0, FALSE), + PT(11, 19, 3, 2, FALSE), + PT(34, 42, 3, 2, FALSE), + PT(32, 39, 4, 1, FALSE), + PT( 5, 38, 4, 1, FALSE), + PT(18, 29, 5, 2, FALSE), + PT( 8, 5, 5, 3, FALSE), + PT(63, 28, 2, 3, TRUE), + PT(36, 13, 6, 1, TRUE), + PT(54, 8, 4, 2, FALSE), + PT(16, 34, 5, 0, TRUE), + PT(28, 10, 2, 0, TRUE), + PT(37, 15, 2, 0, FALSE), + PT(36, 56, 5, 3, TRUE), + PT(37, 50, 3, 3, FALSE), + PT( 6, 42, 5, 0, TRUE), + PT(62, 58, 5, 0, FALSE), + PT(52, 23, 6, 1, TRUE), + PT(24, 51, 2, 3, TRUE), + PT( 7, 20, 3, 3, TRUE), + PT(17, 23, 4, 0, FALSE), + PT(19, 14, 2, 2, FALSE), + PT(59, 28, 2, 1, FALSE), + PT(42, 19, 6, 3, TRUE), + PT(42, 53, 6, 1, FALSE), + PT(48, 2, 4, 2, TRUE), + PT( 0, 7, 3, 3, TRUE), + PT(12, 4, 5, 2, FALSE), + PT(55, 55, 6, 0, FALSE), + PT(37, 18, 4, 2, TRUE), + PT(18, 34, 4, 0, TRUE), + PT(34, 53, 6, 1, TRUE), + PT( 7, 32, 5, 2, TRUE), + PT(39, 14, 6, 0, FALSE), + PT(52, 25, 3, 1, FALSE), + PT(10, 60, 4, 2, TRUE), + PT( 7, 29, 5, 1, TRUE), + PT(49, 58, 2, 1, FALSE), + PT(26, 61, 6, 3, TRUE), + PT(22, 21, 2, 3, FALSE), + PT(57, 19, 2, 2, TRUE), + PT(45, 3, 5, 3, FALSE), + PT( 6, 57, 5, 2, FALSE), + PT(22, 0, 2, 1, TRUE), + PT(53, 42, 6, 2, TRUE), + PT(36, 1, 3, 0, FALSE), + PT(36, 55, 5, 0, FALSE), + PT(37, 27, 6, 2, FALSE), + PT(37, 25, 2, 3, TRUE), + PT(39, 47, 3, 1, TRUE), + PT(39, 13, 2, 0, FALSE), + PT(54, 60, 6, 0, FALSE), + PT(60, 51, 4, 1, TRUE), + PT(62, 39, 3, 3, FALSE), + PT(37, 45, 5, 0, TRUE), + PT(31, 18, 4, 0, TRUE), + PT(55, 50, 3, 3, TRUE), + PT(17, 33, 6, 2, TRUE), + PT(48, 12, 3, 0, TRUE), + PT(37, 61, 4, 3, FALSE), + PT(23, 2, 3, 2, TRUE), + PT(20, 46, 2, 0, TRUE), + PT(56, 19, 6, 0, FALSE), + PT(10, 43, 4, 0, FALSE), + PT(30, 16, 2, 2, TRUE), + PT(55, 48, 5, 3, FALSE), + PT(30, 4, 5, 2, FALSE), + PT(20, 52, 3, 0, TRUE), + PT( 8, 20, 3, 0, FALSE), + PT(14, 28, 6, 0, FALSE), + PT(26, 46, 3, 1, TRUE), + PT(31, 57, 6, 0, TRUE), + PT(12, 28, 5, 0, FALSE), + PT(62, 51, 4, 1, TRUE), + PT(15, 19, 2, 3, FALSE), + PT(37, 57, 5, 3, TRUE), + PT(20, 27, 3, 1, FALSE), + PT(40, 62, 4, 0, TRUE), + PT(45, 25, 2, 0, TRUE), + PT(12, 52, 6, 1, FALSE), + PT(57, 49, 3, 0, TRUE), + PT(26, 8, 6, 2, FALSE), + PT( 9, 47, 2, 0, TRUE), + PT(48, 4, 3, 2, FALSE), + PT( 2, 59, 3, 1, TRUE), + PT(51, 33, 6, 1, TRUE), + PT(56, 2, 3, 1, FALSE), + PT(49, 56, 6, 1, FALSE), + PT(31, 29, 2, 3, FALSE), + PT(23, 16, 3, 1, TRUE), + PT(50, 32, 2, 3, TRUE), + PT( 0, 51, 2, 1, FALSE), + PT(33, 15, 4, 3, TRUE), + PT(20, 25, 4, 3, TRUE), + PT(36, 44, 6, 3, TRUE), + PT(37, 5, 5, 3, TRUE), + PT(61, 37, 2, 0, TRUE), + PT(18, 48, 3, 1, FALSE), + PT(22, 3, 3, 1, FALSE), + PT(20, 9, 2, 1, TRUE), + PT( 2, 35, 4, 1, FALSE), + PT( 1, 60, 2, 0, FALSE), + PT(63, 45, 4, 1, TRUE), + PT(49, 63, 4, 1, TRUE), + PT(23, 0, 6, 1, TRUE), + PT(63, 15, 5, 3, TRUE), + PT(38, 7, 2, 2, TRUE), + PT(33, 43, 5, 1, FALSE), + PT(56, 57, 3, 3, FALSE), + PT( 9, 37, 5, 1, TRUE), + PT(59, 48, 4, 2, TRUE), + PT(18, 45, 2, 1, TRUE), + PT(50, 25, 5, 0, FALSE), + PT(36, 28, 5, 2, TRUE), + PT(53, 50, 4, 3, FALSE), + PT(13, 35, 3, 3, FALSE), + PT(29, 7, 4, 0, TRUE), + PT(11, 52, 2, 3, TRUE), + PT(45, 50, 6, 1, FALSE), + PT(58, 60, 6, 2, TRUE), + PT(26, 16, 6, 1, TRUE), + PT(26, 7, 4, 1, FALSE), + PT(59, 27, 5, 1, FALSE), + PT(51, 31, 4, 3, FALSE), + PT(14, 53, 3, 1, FALSE), + PT(59, 10, 3, 2, FALSE), + PT(17, 7, 2, 0, TRUE), + PT(13, 60, 5, 2, TRUE), + PT(30, 55, 5, 0, TRUE), + PT(17, 5, 2, 1, FALSE), + PT(21, 47, 3, 2, FALSE), + PT(36, 49, 2, 3, FALSE), + PT(43, 33, 3, 1, TRUE), + PT(35, 16, 6, 0, TRUE), + PT( 2, 20, 5, 0, TRUE), + PT(38, 32, 2, 3, FALSE), + PT(16, 23, 2, 0, FALSE), + PT(11, 15, 6, 1, TRUE), + PT( 1, 46, 2, 2, FALSE), + PT(33, 14, 6, 3, TRUE), + PT(26, 29, 5, 3, TRUE), + PT(30, 48, 4, 2, FALSE), + PT( 4, 20, 5, 2, TRUE), + PT(17, 0, 6, 0, FALSE), + PT( 8, 42, 3, 2, TRUE), + PT(29, 34, 4, 0, TRUE), + PT(36, 44, 6, 3, TRUE), + PT(36, 17, 2, 1, FALSE), + PT( 4, 46, 5, 0, FALSE), + PT(29, 24, 4, 1, TRUE), + PT(60, 22, 2, 3, FALSE), + PT(16, 23, 6, 0, TRUE), + PT(32, 33, 2, 1, FALSE), + PT(51, 62, 6, 2, FALSE), + PT( 6, 19, 2, 1, TRUE), + PT(23, 56, 5, 1, TRUE), + PT(20, 13, 2, 2, TRUE), + PT(36, 59, 5, 1, TRUE), + PT(52, 59, 3, 3, FALSE), + PT(24, 7, 6, 2, FALSE), + PT(55, 29, 3, 3, TRUE), + PT(11, 41, 4, 0, FALSE), + PT(18, 30, 3, 2, TRUE), + PT(26, 36, 4, 2, FALSE), + PT(61, 40, 4, 2, FALSE), + PT(11, 18, 6, 1, TRUE), + PT(27, 58, 4, 1, FALSE), + PT(20, 19, 5, 1, FALSE), + PT(49, 56, 2, 2, TRUE), + PT(55, 43, 5, 3, FALSE), + PT(25, 30, 5, 2, FALSE), + PT(63, 27, 5, 1, FALSE), + PT(51, 31, 6, 1, TRUE), + PT(63, 21, 5, 0, TRUE), + PT( 1, 30, 3, 0, FALSE), + PT(31, 34, 3, 0, TRUE), + PT(51, 60, 6, 2, FALSE), + PT(30, 18, 4, 1, FALSE), + PT(13, 55, 5, 2, FALSE), + PT(15, 8, 6, 0, TRUE), + PT(46, 9, 6, 3, FALSE), + PT( 1, 5, 3, 3, FALSE), + PT(28, 4, 3, 3, FALSE), + PT(12, 1, 3, 2, FALSE), + PT(41, 40, 5, 3, TRUE), + PT(57, 45, 2, 2, FALSE), + PT( 9, 34, 6, 3, FALSE), + PT( 4, 55, 6, 3, TRUE), + PT(45, 47, 6, 2, TRUE), + PT(36, 35, 3, 1, TRUE), + PT( 8, 32, 6, 1, FALSE), + PT(32, 31, 6, 2, FALSE), + PT( 2, 49, 3, 0, TRUE), + PT(24, 19, 6, 3, FALSE), + PT( 6, 43, 3, 3, FALSE), + PT(14, 27, 2, 0, FALSE), + PT(47, 14, 3, 2, FALSE), + PT(17, 56, 2, 1, TRUE), + PT( 1, 55, 3, 0, TRUE), + PT(20, 17, 4, 3, FALSE), + PT(49, 61, 6, 1, TRUE), + PT(29, 27, 6, 2, FALSE), + PT(37, 49, 5, 3, TRUE), + PT(17, 10, 5, 3, TRUE), + PT(57, 23, 3, 1, TRUE), + PT( 5, 14, 2, 1, TRUE), + PT(41, 37, 4, 1, FALSE), + PT(21, 13, 4, 0, FALSE), + PT(43, 39, 4, 0, TRUE), + PT(62, 36, 4, 3, TRUE), + PT(42, 43, 2, 3, FALSE), + PT(36, 61, 2, 2, TRUE), + PT(21, 48, 6, 0, TRUE), + PT(15, 51, 4, 2, FALSE), + PT( 6, 22, 2, 1, TRUE), + PT( 6, 49, 2, 0, FALSE), + PT(46, 63, 2, 0, FALSE), + PT( 5, 13, 5, 3, TRUE), + PT(60, 31, 3, 0, TRUE), + PT(18, 19, 4, 2, FALSE), + PT(15, 51, 6, 3, FALSE), + PT(21, 59, 6, 1, TRUE), + PT( 3, 15, 5, 1, FALSE), + PT(59, 60, 5, 2, FALSE), + PT(54, 9, 5, 0, TRUE), + PT(17, 59, 4, 3, TRUE), + PT(40, 43, 6, 0, TRUE), + PT(26, 14, 5, 3, TRUE), + PT(57, 44, 6, 0, TRUE), + PT(14, 60, 6, 2, TRUE), + PT(44, 36, 6, 1, TRUE), + PT(61, 17, 5, 1, TRUE), + PT( 7, 60, 6, 3, TRUE), + PT(20, 24, 2, 1, TRUE), + PT(29, 63, 5, 3, FALSE), + PT(48, 18, 4, 2, TRUE), + PT(38, 29, 2, 0, TRUE), + PT( 7, 17, 3, 3, FALSE), + PT(52, 1, 2, 0, TRUE), + PT(11, 57, 4, 0, TRUE), + PT(41, 2, 5, 0, TRUE), + PT(21, 16, 3, 1, FALSE), + PT(48, 31, 6, 2, TRUE), + PT(60, 43, 5, 1, FALSE), + PT(48, 59, 6, 3, FALSE), + PT(32, 26, 4, 1, TRUE), + PT(50, 36, 5, 1, TRUE), + PT(21, 32, 3, 2, FALSE), + PT(37, 61, 6, 3, FALSE), + PT(45, 20, 6, 0, TRUE), + PT(24, 35, 2, 3, TRUE), + PT(24, 5, 2, 1, TRUE), + PT(52, 48, 6, 3, TRUE), + PT(14, 57, 4, 1, TRUE), + PT(29, 31, 2, 3, TRUE), + PT( 1, 21, 5, 3, TRUE), + PT(11, 62, 3, 1, TRUE), + PT(13, 25, 5, 3, FALSE), + PT(49, 56, 3, 2, FALSE), + PT(21, 52, 2, 2, TRUE), + PT(19, 25, 5, 0, TRUE), + PT(25, 20, 4, 3, TRUE), + PT(21, 24, 4, 1, TRUE), + PT(41, 12, 4, 3, TRUE), + PT(45, 14, 2, 3, TRUE), + PT(52, 24, 2, 0, FALSE), + PT(59, 30, 5, 0, TRUE), + PT(52, 44, 4, 1, FALSE), + PT(49, 8, 2, 1, TRUE), + PT(29, 24, 3, 1, FALSE), + PT(28, 11, 5, 1, FALSE), + PT(25, 30, 3, 1, FALSE), + PT(35, 39, 2, 3, TRUE), + PT(59, 14, 6, 3, TRUE), + PT(25, 43, 2, 3, FALSE), + PT(47, 8, 4, 0, TRUE), + PT(55, 2, 4, 0, FALSE), + PT(11, 50, 6, 0, FALSE), + PT(22, 5, 6, 0, FALSE), + PT(19, 5, 3, 1, FALSE), + PT( 7, 57, 3, 0, TRUE), + PT(12, 59, 5, 1, FALSE), + PT(21, 5, 6, 0, FALSE), + PT(48, 5, 3, 0, TRUE), + PT(19, 0, 2, 1, FALSE), + PT(39, 22, 5, 1, FALSE), + PT(15, 40, 4, 3, TRUE), + PT(12, 35, 5, 3, TRUE), + PT(57, 40, 5, 1, FALSE), + PT(36, 37, 3, 3, TRUE), + PT(24, 41, 2, 2, FALSE), + PT(22, 5, 3, 1, FALSE), + PT(53, 47, 4, 3, FALSE), + PT(10, 58, 5, 0, TRUE), + PT(52, 44, 6, 3, FALSE), + PT(46, 58, 2, 2, TRUE), + PT(26, 10, 5, 2, TRUE), + PT(22, 20, 5, 3, FALSE), + PT(53, 40, 5, 1, FALSE), + PT(53, 15, 2, 0, TRUE), + PT(17, 50, 3, 0, TRUE), + PT(32, 26, 5, 0, FALSE), + PT(23, 26, 5, 0, FALSE), + PT(22, 51, 4, 2, TRUE), + PT(19, 44, 5, 0, TRUE), + PT( 9, 22, 6, 1, TRUE), + PT(29, 39, 4, 3, FALSE), + PT(21, 12, 5, 3, TRUE), + PT(34, 28, 3, 0, TRUE), + PT(41, 51, 2, 0, FALSE), + PT(45, 17, 3, 1, TRUE), + PT(22, 25, 5, 3, FALSE), + PT(13, 12, 5, 0, FALSE), + PT(55, 58, 6, 2, FALSE), + PT(42, 29, 6, 3, TRUE), + PT(48, 10, 6, 3, FALSE), + PT(36, 57, 3, 1, TRUE), + PT(57, 10, 6, 1, FALSE), + PT(17, 3, 5, 2, TRUE), + PT(50, 29, 6, 0, FALSE), + PT(56, 30, 4, 3, TRUE), + PT(46, 23, 3, 0, FALSE), + PT(22, 23, 5, 1, FALSE), + PT(54, 59, 6, 0, TRUE), + PT(23, 4, 3, 0, TRUE), + PT(58, 37, 5, 2, TRUE), + PT( 0, 54, 4, 3, TRUE), + PT(37, 18, 6, 1, TRUE), + PT( 6, 10, 2, 2, FALSE), + PT(17, 5, 5, 3, TRUE), + PT( 3, 53, 5, 3, TRUE), + PT(11, 52, 5, 0, TRUE), + PT( 0, 49, 2, 1, TRUE), + PT(39, 15, 3, 2, FALSE), + PT(29, 6, 5, 2, TRUE), + PT(28, 48, 4, 3, TRUE), + PT(47, 42, 4, 3, TRUE), + PT(22, 32, 6, 0, TRUE), + PT(51, 43, 5, 1, TRUE), + PT( 5, 48, 6, 3, FALSE), + PT(41, 35, 6, 2, TRUE), + PT(16, 22, 5, 3, TRUE), + PT(45, 32, 5, 0, TRUE), + PT(55, 19, 4, 2, FALSE), + PT(45, 14, 4, 2, TRUE), + PT( 8, 10, 3, 0, FALSE), + PT(15, 3, 3, 1, TRUE), + PT(49, 12, 6, 3, TRUE), + PT(30, 52, 6, 0, TRUE), + PT(27, 14, 4, 2, TRUE), + PT(26, 7, 6, 2, FALSE), + PT(13, 60, 6, 1, TRUE), + PT( 0, 58, 6, 3, FALSE), + PT( 4, 39, 2, 1, FALSE), + PT(35, 24, 4, 2, FALSE), + PT(13, 11, 3, 0, FALSE), + PT(49, 50, 6, 3, TRUE), + PT( 0, 13, 4, 0, TRUE), + PT(50, 16, 2, 1, FALSE), + PT(38, 13, 3, 0, TRUE), + PT(41, 36, 5, 1, TRUE), + PT(61, 33, 3, 3, TRUE), + PT(30, 27, 5, 0, FALSE), + PT(13, 18, 5, 0, FALSE), + PT(53, 30, 4, 1, TRUE), + PT(10, 46, 4, 1, FALSE), + PT(39, 39, 6, 2, TRUE), + PT( 1, 14, 4, 0, FALSE), + PT(49, 57, 5, 0, TRUE), + PT(59, 36, 6, 3, FALSE), + PT(20, 16, 6, 1, TRUE), + PT(24, 44, 4, 3, FALSE), + PT( 4, 45, 2, 2, TRUE), + PT(26, 17, 6, 3, TRUE), + PT(15, 11, 2, 2, FALSE), + PT(14, 44, 5, 2, FALSE), + PT(33, 23, 5, 2, FALSE), + PT(22, 33, 6, 2, TRUE), + PT(62, 16, 2, 0, FALSE), + PT(10, 5, 3, 3, FALSE), + PT(59, 9, 2, 1, TRUE), + PT(38, 24, 3, 3, FALSE), + PT(35, 12, 3, 1, FALSE), + PT(51, 55, 3, 3, TRUE), + PT( 9, 18, 6, 2, TRUE), + PT(61, 13, 2, 2, TRUE), + PT(54, 6, 4, 2, FALSE), + PT(51, 48, 5, 0, TRUE), + PT(59, 15, 5, 0, FALSE), + PT(52, 42, 5, 2, FALSE), + PT( 2, 18, 6, 2, TRUE), + PT( 9, 34, 6, 0, TRUE), + PT(59, 49, 3, 2, FALSE), + PT(51, 34, 4, 3, TRUE), + PT(61, 52, 2, 2, TRUE), + PT(20, 34, 5, 0, FALSE), + PT(40, 16, 3, 3, FALSE), + PT(33, 49, 2, 0, FALSE), + PT(45, 22, 4, 0, TRUE), + PT(30, 5, 6, 1, TRUE), + PT(15, 48, 6, 0, TRUE), + PT(14, 26, 6, 2, TRUE), + PT(56, 46, 5, 0, FALSE), + PT(38, 55, 3, 3, FALSE), + PT(43, 19, 6, 1, TRUE), + PT(31, 30, 6, 3, TRUE), + PT(10, 40, 4, 2, FALSE), + PT(50, 28, 3, 1, FALSE), + PT(31, 63, 3, 0, TRUE), + PT(57, 57, 5, 0, TRUE), + PT(44, 27, 2, 2, FALSE), + PT(21, 42, 2, 3, TRUE), + PT(50, 15, 4, 0, TRUE), + PT(48, 33, 3, 0, FALSE), + PT(35, 42, 4, 3, TRUE), + PT(61, 7, 2, 0, FALSE), + PT(11, 63, 5, 3, TRUE), + PT(49, 2, 5, 3, FALSE), + PT( 8, 57, 5, 3, TRUE), + PT(63, 32, 3, 0, FALSE), + PT(45, 52, 2, 0, TRUE), + PT(46, 52, 2, 0, FALSE), + PT(38, 18, 4, 1, TRUE), + PT(37, 10, 6, 3, TRUE), + PT(52, 9, 4, 2, TRUE), + PT(10, 62, 2, 3, FALSE), + PT(26, 23, 2, 0, TRUE), + PT(56, 28, 4, 0, FALSE), + PT(17, 33, 4, 3, FALSE), + PT( 5, 15, 3, 0, FALSE), + PT(38, 43, 6, 1, FALSE), + PT(10, 12, 2, 3, FALSE), + PT( 3, 41, 3, 2, TRUE), + PT(41, 59, 4, 1, TRUE), + PT(22, 27, 5, 0, TRUE), + PT( 7, 9, 2, 3, TRUE), + PT(23, 44, 3, 2, FALSE), + PT(53, 51, 6, 0, FALSE), + PT(23, 18, 3, 3, FALSE), + PT(61, 26, 5, 1, TRUE), + PT(33, 29, 2, 0, FALSE), + PT(10, 8, 2, 3, TRUE), + PT(20, 60, 6, 3, FALSE), + PT(40, 54, 6, 3, FALSE), + PT(59, 32, 3, 1, TRUE), + PT(19, 34, 3, 2, TRUE), + PT(19, 58, 2, 2, TRUE), + PT( 2, 35, 5, 2, FALSE), + PT(62, 25, 2, 2, FALSE), + PT(57, 60, 3, 1, FALSE), + PT(16, 8, 3, 3, FALSE), + PT(10, 19, 5, 0, TRUE), + PT(63, 56, 5, 2, FALSE), + PT( 7, 35, 3, 3, TRUE), + PT(25, 42, 4, 2, FALSE), + PT(20, 60, 3, 3, TRUE), + PT(13, 4, 6, 3, TRUE), + PT(26, 47, 5, 0, FALSE), + PT(42, 29, 3, 3, FALSE), + PT(17, 55, 5, 0, TRUE), + PT(40, 39, 2, 1, FALSE), + PT(13, 0, 4, 3, FALSE), + PT(10, 60, 4, 3, FALSE), + PT(31, 28, 6, 1, TRUE), + PT( 4, 58, 5, 2, FALSE), + PT(36, 61, 5, 1, TRUE), + PT(38, 49, 5, 3, TRUE), + PT(19, 28, 4, 0, TRUE), + PT(62, 18, 4, 1, TRUE), + PT(54, 10, 3, 1, FALSE), + PT(45, 30, 3, 0, TRUE), + PT( 5, 31, 3, 1, TRUE), + PT(30, 10, 3, 3, TRUE), + PT(32, 8, 4, 2, FALSE), + PT(44, 12, 6, 1, TRUE), + PT(29, 31, 2, 0, TRUE), + PT(14, 18, 2, 0, FALSE), + PT(39, 18, 3, 0, TRUE), + PT(42, 19, 6, 0, TRUE), + PT(28, 4, 6, 0, FALSE), + PT(26, 56, 3, 3, TRUE), + PT(44, 53, 4, 2, TRUE), + PT( 7, 11, 6, 1, TRUE), + PT(45, 2, 3, 1, FALSE), + PT(42, 53, 6, 2, TRUE), + PT(22, 47, 2, 2, FALSE), + PT(17, 49, 6, 1, TRUE), + PT(44, 49, 3, 3, FALSE), + PT(60, 58, 4, 3, TRUE), + PT(60, 43, 2, 1, FALSE), + PT(39, 29, 2, 1, FALSE), + PT(54, 44, 5, 1, TRUE), + PT(37, 59, 6, 2, TRUE), + PT(18, 61, 4, 3, TRUE), + PT(19, 35, 3, 0, TRUE), + PT(51, 44, 4, 3, FALSE), + PT( 9, 60, 2, 1, FALSE), + PT(21, 26, 4, 1, TRUE), + PT(33, 7, 3, 1, FALSE), + PT(34, 37, 4, 0, FALSE), + PT(25, 27, 5, 2, FALSE), + PT(58, 25, 6, 2, TRUE), + PT( 5, 38, 3, 2, TRUE), + PT(35, 34, 4, 2, TRUE), + PT(14, 30, 2, 0, TRUE), + PT(19, 48, 2, 1, FALSE), + PT(44, 34, 4, 2, TRUE), + PT(10, 29, 3, 0, FALSE), + PT(35, 62, 3, 2, TRUE), + PT( 2, 40, 4, 2, TRUE), + PT(33, 14, 4, 0, FALSE), + PT(33, 34, 6, 3, TRUE), + PT(24, 51, 4, 3, TRUE), + PT(35, 35, 6, 0, TRUE), + PT(36, 26, 3, 1, FALSE), + PT(62, 37, 4, 2, FALSE), + PT(36, 1, 3, 0, FALSE), + PT(52, 16, 4, 1, FALSE), + PT( 7, 0, 6, 3, TRUE), + PT( 6, 32, 4, 0, FALSE), + PT(58, 2, 5, 1, TRUE), + PT( 7, 44, 5, 2, FALSE), + PT( 9, 47, 5, 1, FALSE), + PT( 1, 50, 5, 2, FALSE), + PT( 0, 53, 2, 1, TRUE), + PT(43, 60, 3, 3, TRUE), + PT(54, 55, 3, 3, FALSE), + PT(32, 53, 3, 2, TRUE), + PT(12, 7, 6, 1, TRUE), + PT(22, 8, 2, 1, FALSE), + PT(63, 54, 2, 0, TRUE), + PT(11, 31, 5, 2, TRUE), + PT(33, 32, 6, 1, TRUE), + PT(23, 26, 5, 3, FALSE), + PT(22, 1, 5, 3, TRUE), + PT(47, 28, 6, 2, FALSE), + PT(41, 49, 5, 3, FALSE), + PT(59, 56, 6, 0, TRUE), + PT(13, 22, 2, 1, FALSE), + PT( 7, 41, 4, 2, FALSE), + PT(51, 60, 6, 2, FALSE), + PT(62, 30, 3, 0, FALSE), + PT(48, 2, 6, 2, FALSE), + PT(42, 52, 3, 1, TRUE), + PT(46, 35, 3, 0, FALSE), + PT(52, 0, 3, 3, TRUE), + PT(32, 14, 5, 0, FALSE), + PT(21, 51, 6, 3, TRUE), + PT(39, 53, 4, 1, TRUE), + PT(55, 62, 2, 0, TRUE), + PT(50, 46, 6, 3, FALSE), + PT(58, 2, 5, 1, TRUE), + PT( 0, 54, 3, 2, TRUE), + PT(19, 41, 2, 3, FALSE), + PT( 8, 43, 6, 3, TRUE), + PT( 8, 2, 4, 3, TRUE), + PT(50, 45, 6, 2, FALSE), + PT(48, 54, 5, 0, TRUE), + PT(46, 16, 2, 1, FALSE), + PT(60, 46, 5, 1, FALSE), + PT( 4, 51, 6, 0, FALSE), + PT(63, 1, 4, 1, FALSE), + PT(55, 20, 3, 2, TRUE), + PT(39, 0, 5, 3, TRUE), + PT(12, 57, 4, 3, FALSE), + PT(39, 4, 4, 0, TRUE), + PT(25, 8, 3, 2, TRUE), + PT( 1, 4, 3, 3, FALSE), + PT(39, 27, 5, 1, TRUE), + PT(49, 23, 3, 3, TRUE), + PT( 7, 1, 5, 2, TRUE), + PT(46, 59, 3, 3, TRUE), + PT(52, 36, 6, 0, TRUE), + PT(50, 43, 4, 2, FALSE), + PT(14, 7, 3, 3, FALSE), + PT(15, 51, 2, 0, FALSE), + PT(22, 33, 6, 1, FALSE), + PT(57, 2, 3, 1, FALSE), + PT(51, 61, 4, 1, FALSE), + PT(12, 37, 3, 1, FALSE), + PT(41, 41, 5, 0, FALSE), + PT(58, 50, 4, 3, FALSE), + PT(11, 19, 4, 1, FALSE), + PT(31, 15, 3, 2, FALSE), + PT( 4, 44, 4, 0, FALSE), + PT(57, 26, 3, 1, TRUE), + PT(26, 42, 3, 3, TRUE), + PT(36, 19, 3, 1, FALSE), + PT(49, 59, 6, 1, TRUE), + PT(57, 35, 5, 0, FALSE), + PT(49, 7, 6, 0, TRUE), + PT(31, 16, 4, 0, FALSE), + PT(41, 23, 6, 1, FALSE), + PT(38, 59, 5, 2, TRUE), + PT( 2, 60, 3, 2, FALSE), + PT(14, 0, 4, 0, FALSE), + PT(20, 62, 6, 3, TRUE), + PT( 1, 15, 5, 2, TRUE), + PT( 6, 18, 4, 3, TRUE), + PT(48, 19, 3, 0, TRUE), + PT( 0, 51, 5, 1, FALSE), + PT(12, 7, 4, 3, TRUE), + PT(17, 58, 3, 2, FALSE), + PT(21, 10, 2, 1, TRUE), + PT(31, 13, 5, 1, FALSE), + PT(55, 7, 5, 1, FALSE), + PT(52, 53, 6, 2, FALSE), + PT(40, 22, 4, 3, TRUE), + PT( 6, 2, 6, 3, FALSE), + PT( 9, 35, 6, 0, FALSE), + PT(20, 2, 5, 0, FALSE), + PT(57, 50, 6, 2, FALSE), + PT(36, 53, 2, 1, FALSE), + PT(18, 34, 4, 3, FALSE), + PT( 9, 7, 6, 1, TRUE), + PT(15, 62, 3, 3, FALSE), + PT( 0, 60, 6, 1, TRUE), + PT(16, 55, 2, 2, FALSE), + PT(58, 3, 4, 2, TRUE), + PT(45, 30, 4, 2, FALSE), + PT(54, 54, 4, 3, FALSE), + PT(31, 60, 3, 1, FALSE), + PT(55, 51, 4, 2, TRUE), + PT(35, 19, 3, 3, TRUE), + PT(51, 13, 2, 1, TRUE), + PT(37, 48, 3, 3, FALSE), + PT(23, 3, 3, 0, FALSE), + PT(24, 24, 2, 2, FALSE), + PT(48, 7, 4, 1, FALSE), + PT(62, 51, 4, 0, TRUE), + PT(20, 55, 2, 3, FALSE), + PT(22, 0, 2, 1, FALSE), + PT(44, 18, 5, 3, TRUE), + PT(37, 63, 3, 3, FALSE), + PT(36, 25, 2, 3, FALSE), + PT(22, 15, 6, 2, TRUE), + PT(45, 16, 2, 0, TRUE), + PT(36, 42, 5, 0, FALSE), + PT(25, 37, 5, 3, FALSE), + PT(12, 22, 3, 3, TRUE), + PT(56, 33, 6, 3, FALSE), + PT(61, 26, 5, 3, TRUE), + PT(59, 50, 2, 1, FALSE), + PT(54, 19, 5, 0, TRUE), + PT(14, 48, 6, 0, TRUE), + PT(25, 7, 5, 3, TRUE), + PT(37, 35, 5, 0, FALSE), + PT(32, 8, 5, 0, TRUE), + PT(42, 0, 6, 0, FALSE), + PT(48, 56, 4, 1, TRUE), + PT(30, 15, 3, 3, TRUE), + PT(59, 27, 6, 0, FALSE), + PT(58, 55, 5, 3, TRUE), + PT(57, 55, 6, 2, TRUE), + PT(57, 45, 5, 3, TRUE), + PT(31, 46, 3, 3, FALSE), + PT(26, 43, 3, 3, FALSE), + PT(20, 23, 4, 0, FALSE), + PT(47, 3, 2, 0, TRUE), + PT(29, 0, 6, 0, FALSE), + PT(23, 43, 3, 2, TRUE), + PT(53, 40, 4, 2, TRUE), + PT(59, 15, 2, 0, TRUE), + PT( 9, 4, 5, 3, FALSE), + PT(35, 17, 3, 3, FALSE), + PT(19, 55, 3, 3, FALSE), + PT(55, 55, 3, 3, FALSE), + PT( 7, 1, 6, 1, FALSE), + PT(20, 6, 6, 1, FALSE), + PT(17, 12, 5, 3, FALSE), + PT(54, 46, 4, 2, FALSE), + PT(21, 42, 3, 2, FALSE), + PT(34, 21, 6, 2, FALSE), + PT(44, 30, 6, 2, TRUE), + PT(34, 39, 6, 1, TRUE), + PT(25, 63, 5, 2, TRUE), + PT(33, 51, 2, 2, TRUE), + PT(38, 26, 2, 0, TRUE), + PT(22, 62, 2, 1, FALSE), + PT(43, 36, 2, 2, TRUE), + PT(60, 15, 5, 2, TRUE), + PT(49, 21, 6, 3, FALSE), + PT(63, 36, 3, 2, TRUE), + PT(37, 1, 6, 3, TRUE), + PT(51, 22, 3, 1, FALSE), + PT(31, 14, 2, 0, FALSE), + PT(47, 11, 2, 1, FALSE), + PT(42, 26, 4, 2, TRUE), + PT(23, 10, 6, 2, TRUE), + PT( 9, 40, 6, 2, TRUE), + PT( 2, 19, 6, 3, FALSE), + PT(52, 47, 2, 3, TRUE), + PT( 3, 4, 6, 0, TRUE), + PT(62, 38, 2, 0, TRUE), + PT(53, 51, 6, 0, TRUE), + PT(34, 23, 4, 1, TRUE), + PT(29, 5, 5, 1, TRUE), + PT(46, 39, 4, 0, FALSE), + PT( 3, 43, 3, 2, TRUE), + PT( 1, 25, 3, 3, FALSE), + PT(14, 5, 3, 0, FALSE), + PT(22, 37, 2, 3, TRUE), + PT( 2, 40, 3, 0, FALSE), + PT(25, 11, 4, 2, FALSE), + PT(62, 53, 2, 3, FALSE), + PT(46, 41, 4, 2, TRUE), + PT(62, 56, 3, 3, FALSE), + PT(58, 47, 2, 1, FALSE), + PT(20, 23, 5, 2, TRUE), + PT(17, 18, 6, 0, FALSE), + PT(21, 49, 3, 0, FALSE), + PT( 8, 11, 5, 0, TRUE), + PT(45, 0, 6, 1, TRUE), + PT(44, 6, 3, 1, FALSE), + PT(20, 28, 5, 3, FALSE), + PT( 4, 8, 2, 1, FALSE), + PT(27, 43, 5, 2, TRUE), + PT(42, 55, 6, 1, TRUE), + PT(16, 39, 5, 2, FALSE), + PT(29, 14, 6, 2, FALSE), + PT(32, 2, 2, 1, FALSE), + PT(30, 26, 5, 3, FALSE), + PT( 7, 11, 2, 0, FALSE), + PT(54, 30, 6, 1, TRUE), + PT(43, 40, 3, 1, TRUE), + PT(49, 37, 3, 3, TRUE), + PT(56, 58, 5, 3, TRUE), + PT(57, 48, 5, 3, TRUE), + PT(18, 9, 2, 2, FALSE), + PT(14, 8, 3, 0, TRUE), + PT( 0, 13, 5, 2, FALSE), + PT(27, 14, 6, 2, FALSE), + PT(17, 37, 2, 2, TRUE), + PT(12, 45, 4, 3, FALSE), + PT(54, 44, 2, 3, FALSE), + PT(49, 49, 5, 2, FALSE), + PT( 3, 26, 2, 3, FALSE), + PT(28, 50, 2, 2, FALSE), + PT(10, 62, 6, 3, FALSE), + PT(51, 27, 4, 3, TRUE), + PT(31, 50, 3, 0, FALSE), + PT(51, 38, 6, 1, TRUE), + PT(26, 19, 3, 1, FALSE), + PT(15, 52, 3, 2, FALSE), + PT(53, 44, 5, 3, TRUE), + PT(56, 3, 3, 0, FALSE), + PT(21, 15, 4, 3, TRUE), + PT(49, 41, 4, 0, FALSE), + PT(40, 14, 5, 0, FALSE), + PT(49, 44, 5, 3, FALSE), + PT(21, 25, 3, 1, TRUE), + PT(16, 3, 5, 3, TRUE), + PT(46, 42, 6, 1, FALSE), + PT(42, 39, 3, 1, TRUE), + PT(54, 4, 3, 3, FALSE), + PT(59, 4, 4, 0, TRUE), + PT( 7, 47, 3, 0, TRUE), + PT(39, 29, 3, 2, TRUE), + PT(60, 61, 5, 3, FALSE), + PT(37, 8, 6, 1, FALSE), + PT(59, 52, 5, 1, FALSE), + PT(12, 16, 2, 1, TRUE), + PT(37, 53, 3, 1, FALSE), + PT(47, 25, 5, 0, FALSE), + PT(23, 0, 5, 1, TRUE), + PT(10, 28, 2, 3, TRUE), + PT(10, 17, 3, 1, TRUE), + PT(53, 19, 6, 3, TRUE), + PT(41, 28, 5, 0, FALSE), + PT(12, 49, 6, 2, TRUE), + PT(60, 16, 3, 1, FALSE), + PT(27, 58, 5, 2, TRUE), + PT(58, 28, 3, 0, FALSE), + PT(34, 16, 5, 2, TRUE), + PT(28, 60, 2, 1, FALSE), + PT(23, 24, 5, 1, FALSE), + PT(11, 43, 5, 3, TRUE), + PT(45, 4, 5, 3, FALSE), + PT(60, 19, 4, 1, TRUE), + PT( 1, 28, 5, 3, FALSE), + PT(20, 22, 4, 1, FALSE), + PT(12, 36, 2, 1, TRUE), + PT(53, 55, 6, 2, FALSE), + PT(27, 48, 3, 3, FALSE), + PT(58, 28, 4, 0, FALSE), + PT( 6, 6, 6, 3, FALSE), + PT( 9, 21, 3, 1, FALSE), + PT(27, 26, 4, 3, TRUE), + PT(15, 51, 6, 2, TRUE), + PT(55, 6, 4, 1, TRUE), + PT(58, 18, 3, 2, TRUE), + PT( 0, 22, 5, 0, TRUE), + PT(14, 29, 6, 2, TRUE), + PT(63, 56, 2, 3, FALSE), + PT(42, 60, 6, 2, FALSE), + PT(19, 50, 2, 0, FALSE), + PT(23, 44, 6, 3, TRUE), + PT(41, 42, 3, 3, FALSE), + PT(53, 47, 5, 2, TRUE), + PT(60, 42, 2, 0, TRUE), + PT(40, 19, 4, 0, TRUE), + PT(25, 30, 6, 2, FALSE), + PT(12, 6, 5, 2, TRUE), + PT( 9, 4, 3, 2, FALSE), + PT(29, 47, 4, 3, FALSE), + PT(57, 7, 2, 3, FALSE), + PT(20, 4, 5, 2, TRUE), + PT(58, 47, 5, 3, FALSE), + PT(41, 21, 6, 2, TRUE), + PT(36, 2, 6, 3, FALSE), + PT(63, 2, 3, 1, FALSE), + PT(15, 24, 4, 2, FALSE), + PT(22, 29, 3, 0, TRUE), + PT(20, 22, 2, 0, FALSE), + PT(41, 27, 2, 1, TRUE), + PT(21, 14, 3, 0, TRUE), + PT(58, 46, 5, 1, TRUE), + PT( 8, 48, 2, 2, TRUE), + PT(53, 22, 6, 0, FALSE), + PT(46, 24, 6, 2, TRUE), + PT(59, 11, 3, 2, FALSE), + PT(58, 24, 2, 1, TRUE), + PT(41, 19, 3, 3, FALSE), + PT(32, 19, 4, 3, TRUE), + PT( 4, 29, 6, 2, FALSE), + PT( 0, 56, 3, 0, TRUE), + PT( 8, 57, 6, 1, FALSE), + PT(32, 16, 4, 3, FALSE), + PT( 8, 2, 5, 0, FALSE), + PT(63, 15, 2, 3, FALSE), + PT(48, 31, 3, 0, TRUE), + PT(32, 45, 2, 0, FALSE), + PT(56, 23, 3, 2, FALSE), + PT(24, 49, 4, 3, TRUE), + PT(51, 56, 6, 0, FALSE), + PT(22, 51, 4, 1, TRUE), + PT( 0, 1, 6, 3, FALSE), + PT(13, 2, 4, 1, TRUE), + PT(57, 4, 3, 3, TRUE), + PT(14, 48, 4, 2, FALSE), + PT( 6, 1, 5, 2, FALSE), + PT(52, 51, 6, 2, TRUE), + PT(22, 52, 5, 3, FALSE), + PT(50, 22, 4, 2, FALSE), + PT(38, 57, 6, 2, FALSE), + PT(31, 60, 3, 2, TRUE), + PT(40, 29, 6, 3, TRUE), + PT(23, 21, 5, 1, TRUE), + PT(39, 57, 6, 0, FALSE), + PT(11, 27, 3, 0, FALSE), + PT(53, 32, 5, 2, TRUE), + PT(11, 53, 3, 2, FALSE), + PT( 3, 14, 4, 0, TRUE), + PT( 6, 12, 4, 0, FALSE), + PT( 2, 24, 6, 2, FALSE), + PT(30, 54, 5, 2, TRUE), + PT(22, 12, 3, 0, TRUE), + PT(37, 9, 5, 2, FALSE), + PT(55, 5, 5, 3, FALSE), + PT(46, 43, 5, 2, FALSE), + PT(36, 26, 2, 2, FALSE), + PT(39, 4, 2, 0, FALSE), + PT(50, 56, 6, 1, TRUE), + PT(55, 21, 6, 2, TRUE), + PT(17, 63, 3, 2, TRUE), + PT(35, 35, 3, 3, TRUE), + PT(41, 63, 3, 2, TRUE), + PT(26, 60, 5, 1, TRUE), + PT(27, 44, 5, 2, FALSE), + PT(56, 59, 6, 3, FALSE), + PT( 4, 19, 6, 1, TRUE), + PT(44, 20, 2, 1, FALSE), + PT(26, 9, 3, 1, TRUE), + PT(54, 17, 4, 2, FALSE), + PT(58, 63, 2, 0, TRUE), + PT( 1, 14, 5, 1, TRUE), + PT(59, 3, 5, 1, FALSE), + PT( 8, 13, 5, 1, TRUE), + PT(43, 19, 4, 3, TRUE), + PT(58, 60, 3, 2, FALSE), + PT(58, 21, 5, 1, FALSE), + PT(36, 0, 2, 3, TRUE), + PT(62, 10, 2, 2, TRUE), + PT(12, 41, 5, 2, TRUE), + PT(31, 21, 6, 0, FALSE), + PT(53, 24, 3, 0, TRUE), + PT(61, 55, 6, 3, TRUE), + PT(18, 56, 3, 1, TRUE), + PT(59, 2, 4, 0, FALSE), + PT( 8, 33, 3, 0, TRUE), + PT(46, 54, 3, 2, TRUE), + PT(21, 61, 4, 2, FALSE), + PT(34, 12, 4, 3, TRUE), + PT(54, 63, 6, 1, TRUE), + PT(51, 18, 2, 0, TRUE), + PT(26, 25, 3, 3, TRUE), + PT(43, 36, 2, 1, FALSE), + PT(17, 42, 3, 0, FALSE), + PT(37, 50, 5, 1, FALSE), + PT(44, 26, 2, 1, FALSE), + PT(38, 6, 2, 0, FALSE), + PT(17, 41, 6, 1, TRUE), + PT(44, 9, 2, 2, FALSE), + PT(43, 18, 5, 1, TRUE), + PT(29, 3, 4, 2, FALSE), + PT( 0, 18, 2, 2, TRUE), + PT(34, 61, 4, 3, FALSE), + PT(21, 55, 3, 1, FALSE), + PT(15, 18, 6, 3, TRUE), + PT(36, 1, 3, 0, FALSE), + PT(42, 23, 2, 1, TRUE), + PT(20, 59, 5, 0, TRUE), + PT(42, 25, 6, 1, FALSE), + PT(45, 23, 2, 3, TRUE), + PT(11, 44, 6, 1, TRUE), + PT( 7, 45, 6, 2, FALSE), + PT( 7, 56, 3, 2, TRUE), + PT(31, 54, 4, 1, FALSE), + PT(17, 10, 2, 3, TRUE), + PT(20, 17, 2, 1, TRUE), + PT(42, 23, 4, 2, TRUE), + PT( 1, 58, 3, 2, FALSE), + PT(38, 39, 6, 0, FALSE), + PT(45, 59, 6, 2, TRUE), + PT(58, 48, 6, 2, FALSE), + PT( 6, 58, 3, 2, FALSE), + PT(45, 5, 2, 1, TRUE), + PT(33, 50, 2, 1, FALSE), + PT(62, 30, 5, 2, FALSE), + PT(58, 63, 5, 2, TRUE), + PT(32, 42, 6, 2, FALSE), + PT(38, 3, 3, 1, FALSE), + PT(25, 39, 5, 3, FALSE), + PT(49, 4, 4, 3, FALSE), + PT(42, 63, 6, 0, FALSE), + PT(37, 35, 5, 1, FALSE), + PT( 8, 8, 6, 2, TRUE), + PT(44, 48, 3, 3, FALSE), + PT( 8, 5, 3, 0, FALSE), + PT( 6, 9, 5, 2, TRUE), + PT(25, 0, 4, 3, TRUE), + PT(13, 16, 3, 0, TRUE), + PT(28, 0, 2, 1, TRUE), + PT(61, 11, 4, 2, FALSE), + PT(46, 31, 2, 3, FALSE), + PT(61, 24, 6, 2, FALSE), + PT(18, 30, 2, 2, TRUE), + PT(21, 57, 4, 2, TRUE), + PT(51, 15, 2, 3, TRUE), + PT(26, 28, 3, 1, TRUE), + PT(55, 41, 3, 1, TRUE), + PT(59, 56, 2, 1, FALSE), + PT(29, 34, 6, 2, FALSE), + PT(38, 10, 6, 0, TRUE), + PT(22, 45, 2, 1, TRUE), + PT(13, 32, 4, 3, TRUE), + PT(36, 29, 2, 3, FALSE), + PT(46, 43, 3, 0, FALSE), + PT(22, 42, 3, 1, TRUE), + PT(36, 23, 6, 3, FALSE), + PT( 2, 5, 5, 1, TRUE), + PT(55, 26, 2, 3, TRUE), + PT(17, 61, 5, 2, FALSE), + PT(30, 47, 4, 1, FALSE), + PT(44, 41, 3, 1, FALSE), + PT(47, 4, 4, 2, TRUE), + PT(54, 12, 6, 2, TRUE), + PT(48, 62, 2, 1, FALSE), + PT(17, 48, 6, 3, TRUE), + PT(18, 33, 5, 3, FALSE), + PT(33, 48, 2, 3, TRUE), + PT(44, 61, 4, 2, FALSE), + PT(17, 35, 2, 2, FALSE), + PT(26, 50, 2, 3, TRUE), + PT(57, 39, 3, 0, FALSE), + PT(15, 36, 3, 0, TRUE), + PT( 0, 61, 6, 3, TRUE), + PT(44, 60, 3, 2, FALSE), + PT(11, 57, 4, 1, TRUE), + PT(14, 4, 3, 3, TRUE), + PT(28, 49, 2, 2, FALSE), + PT( 0, 4, 2, 2, TRUE), + PT(38, 42, 5, 1, FALSE), + PT(32, 37, 5, 1, FALSE), + PT(11, 60, 6, 1, TRUE), + PT(17, 11, 5, 3, FALSE), + PT(55, 34, 5, 3, FALSE), + PT(14, 34, 4, 3, FALSE), + PT(24, 45, 4, 3, TRUE), + PT( 6, 12, 3, 2, FALSE), + PT(38, 24, 5, 3, TRUE), + PT(58, 1, 5, 1, FALSE), + PT(47, 49, 6, 2, FALSE), + PT(31, 52, 3, 1, FALSE), + PT(49, 5, 2, 0, FALSE), + PT(46, 23, 6, 2, FALSE), + PT(24, 34, 4, 1, TRUE), + PT(35, 33, 6, 1, FALSE), + PT( 7, 8, 4, 1, FALSE), + PT(38, 28, 4, 1, FALSE), + PT(49, 18, 5, 3, TRUE), + PT( 8, 31, 2, 0, FALSE), + PT(39, 21, 5, 1, FALSE), + PT(31, 11, 4, 3, FALSE), + PT(47, 20, 6, 2, TRUE), + PT(36, 31, 4, 3, FALSE), + PT(59, 35, 6, 1, TRUE), + PT(32, 62, 5, 2, TRUE), + PT(23, 12, 2, 2, TRUE), + PT(19, 57, 3, 1, FALSE), + PT(48, 20, 4, 2, TRUE), + PT( 9, 7, 2, 3, TRUE), + PT(56, 56, 3, 3, TRUE), + PT(41, 36, 4, 3, TRUE), + PT(23, 39, 5, 0, FALSE), + PT(27, 18, 5, 1, FALSE), + PT(43, 61, 5, 2, TRUE), + PT(25, 52, 3, 2, FALSE), + PT( 1, 29, 2, 0, FALSE), + PT( 8, 57, 2, 0, TRUE), + PT(14, 54, 3, 1, TRUE), + PT(38, 19, 2, 0, FALSE), + PT(22, 40, 3, 3, FALSE), + PT(60, 40, 2, 3, TRUE), + PT(62, 57, 6, 2, FALSE), + PT(10, 3, 5, 3, FALSE), + PT(55, 26, 2, 1, TRUE), + PT(43, 51, 4, 3, FALSE), + PT(19, 44, 4, 0, TRUE), + PT(37, 20, 2, 0, FALSE), + PT(22, 11, 6, 2, TRUE), + PT(29, 53, 6, 1, TRUE), + PT(33, 8, 6, 1, TRUE), + PT(40, 33, 3, 1, FALSE), + PT(18, 12, 3, 1, TRUE), + PT(54, 42, 3, 0, TRUE), + PT(44, 43, 4, 1, TRUE), + PT( 1, 15, 4, 3, FALSE), + PT(23, 12, 3, 0, FALSE), + PT( 9, 15, 2, 0, TRUE), + PT(43, 36, 3, 2, FALSE), + PT( 9, 9, 2, 2, TRUE), + PT(54, 8, 2, 1, TRUE), + PT(32, 57, 4, 0, TRUE), + PT( 0, 58, 3, 3, TRUE), + PT(43, 54, 6, 0, TRUE), + PT( 2, 55, 2, 1, TRUE), + PT( 4, 52, 6, 2, TRUE), + PT(55, 61, 3, 1, FALSE), + PT(23, 61, 2, 1, TRUE), + PT(43, 54, 5, 3, TRUE), + PT(19, 30, 2, 1, TRUE), + PT(62, 17, 6, 1, TRUE), + PT(39, 58, 5, 2, TRUE), + PT(30, 49, 3, 1, FALSE), + PT( 3, 3, 5, 2, TRUE), + PT(37, 55, 3, 3, TRUE), + PT(17, 1, 4, 1, FALSE), + PT(28, 18, 2, 3, TRUE), + PT(48, 58, 6, 0, FALSE), + PT(23, 29, 5, 0, TRUE), + PT(14, 19, 4, 3, TRUE), + PT(26, 46, 4, 2, FALSE), + PT(45, 0, 3, 2, FALSE), + PT(23, 40, 3, 2, TRUE), + PT( 9, 31, 5, 3, FALSE), + PT(26, 45, 4, 3, FALSE), + PT(10, 19, 6, 1, FALSE), + PT(62, 0, 4, 3, TRUE), + PT(11, 59, 6, 0, FALSE), + PT( 8, 58, 5, 2, TRUE), + PT(34, 18, 3, 3, FALSE), + PT(52, 29, 5, 1, TRUE), + PT(38, 34, 6, 2, TRUE), + PT(23, 44, 2, 3, TRUE), + PT(41, 19, 5, 2, TRUE), + PT(45, 16, 2, 0, FALSE), + PT(32, 49, 4, 1, TRUE), + PT(30, 51, 3, 0, FALSE), + PT(51, 6, 5, 2, TRUE), + PT(38, 20, 4, 3, TRUE), + PT(34, 29, 5, 1, FALSE), + PT(45, 6, 3, 0, FALSE), + PT( 7, 9, 5, 3, FALSE), + PT(33, 21, 5, 3, FALSE), + PT(33, 56, 4, 1, TRUE), + PT(53, 11, 6, 2, FALSE), + PT(36, 11, 4, 1, FALSE), + PT(30, 1, 2, 3, TRUE), + PT(11, 36, 2, 0, TRUE), + PT(23, 7, 4, 0, FALSE), + PT(20, 37, 6, 1, FALSE), + PT(26, 14, 5, 3, TRUE), + PT(53, 23, 3, 3, TRUE), + PT(12, 8, 4, 0, TRUE), + PT(48, 53, 3, 3, TRUE), + PT(12, 11, 4, 0, FALSE), + PT( 4, 16, 2, 0, TRUE), + PT(53, 17, 3, 3, FALSE), + PT(51, 61, 2, 3, FALSE), + PT(30, 43, 3, 2, TRUE), + PT(26, 25, 2, 0, FALSE), + PT( 4, 6, 4, 1, FALSE), + PT( 3, 61, 4, 2, FALSE), + PT(42, 14, 6, 2, TRUE), + PT( 3, 62, 2, 3, TRUE), + PT(11, 24, 6, 3, FALSE), + PT(61, 13, 4, 3, FALSE), + PT(53, 18, 4, 0, FALSE), + PT(31, 13, 2, 3, FALSE), + PT(35, 50, 3, 1, FALSE), + PT( 0, 61, 4, 3, FALSE), + PT(48, 25, 6, 3, FALSE), + PT(18, 14, 4, 1, TRUE), + PT( 1, 35, 5, 0, FALSE), + PT(59, 49, 2, 0, TRUE), + PT(45, 28, 6, 3, FALSE), + PT(42, 5, 2, 3, FALSE), + PT(20, 14, 6, 0, FALSE), + PT(58, 55, 3, 0, TRUE), + PT(31, 48, 4, 2, TRUE), + PT(16, 38, 5, 3, TRUE), + PT(34, 17, 3, 3, TRUE), + PT(46, 43, 3, 3, FALSE), + PT(22, 22, 4, 0, TRUE), + PT(50, 24, 6, 2, TRUE), + PT(35, 50, 3, 1, FALSE), + PT(61, 13, 3, 0, TRUE), + PT(57, 9, 4, 1, TRUE), + PT(48, 46, 4, 2, FALSE), + PT(30, 15, 4, 2, FALSE), + PT( 9, 33, 6, 0, TRUE), + PT( 5, 3, 2, 0, TRUE), + PT( 5, 34, 5, 1, FALSE), + PT( 3, 7, 6, 3, TRUE), + PT( 4, 8, 2, 1, TRUE), + PT( 5, 16, 6, 2, FALSE), + PT(55, 20, 5, 0, TRUE), + PT(10, 36, 6, 1, FALSE), + PT(52, 30, 3, 1, TRUE), + PT(18, 23, 5, 3, FALSE), + PT( 1, 2, 2, 1, TRUE), + PT(10, 12, 2, 0, TRUE), + PT( 2, 20, 2, 1, TRUE), + PT(13, 37, 4, 1, TRUE), + PT( 0, 7, 3, 1, FALSE), + PT(28, 40, 6, 2, TRUE), + PT( 8, 14, 5, 2, FALSE), + PT(27, 60, 2, 2, TRUE), + PT(28, 25, 3, 2, TRUE), + PT(50, 19, 3, 1, FALSE), + PT(28, 0, 6, 3, TRUE), + PT(34, 27, 6, 2, TRUE), + PT(57, 62, 2, 2, FALSE), + PT(50, 6, 6, 0, TRUE), + PT(23, 5, 5, 1, TRUE), + PT( 1, 15, 4, 0, FALSE), + PT(30, 15, 6, 2, FALSE), + PT(24, 3, 3, 3, TRUE), + PT(43, 0, 2, 2, FALSE), + PT(21, 58, 6, 0, FALSE), + PT(37, 48, 4, 0, TRUE), + PT(11, 0, 6, 3, TRUE), + PT(36, 55, 3, 2, TRUE), + PT(41, 33, 2, 3, FALSE), + PT(36, 15, 5, 2, FALSE), + PT(62, 21, 6, 3, FALSE), + PT(60, 45, 4, 1, TRUE), + PT(61, 60, 2, 3, TRUE), + PT(26, 28, 2, 1, TRUE), + PT(10, 41, 4, 1, FALSE), + PT(37, 63, 4, 3, FALSE), + PT(59, 57, 5, 3, TRUE), + PT(29, 8, 2, 3, FALSE), + PT(11, 25, 2, 2, FALSE), + PT(18, 1, 5, 2, FALSE), + PT(53, 17, 5, 1, FALSE), + PT( 2, 0, 2, 1, TRUE), + PT(57, 42, 6, 2, TRUE), + PT( 7, 26, 2, 0, TRUE), + PT(36, 14, 3, 3, FALSE), + PT(14, 44, 2, 2, TRUE), + PT( 8, 49, 3, 1, TRUE), + PT(33, 29, 4, 3, FALSE), + PT(29, 28, 5, 1, FALSE), + PT(29, 36, 2, 1, TRUE), + PT( 1, 0, 3, 0, FALSE), + PT(40, 42, 6, 3, TRUE), + PT(21, 15, 2, 1, TRUE), + PT(16, 50, 6, 3, FALSE), + PT(34, 19, 6, 0, TRUE), + PT(19, 5, 3, 3, FALSE), + PT(23, 53, 6, 2, TRUE), + PT(59, 14, 4, 2, FALSE), + PT(53, 58, 3, 2, TRUE), + PT(27, 54, 3, 1, TRUE), + PT( 3, 29, 4, 2, FALSE), + PT(15, 22, 6, 0, FALSE), + PT(45, 9, 4, 2, TRUE), + PT( 5, 33, 2, 1, TRUE), + PT(10, 39, 6, 3, FALSE), + PT( 4, 13, 3, 2, FALSE), + PT( 6, 62, 4, 0, TRUE), + PT(42, 39, 6, 1, TRUE), + PT(40, 14, 2, 2, TRUE), + PT(11, 23, 3, 2, TRUE), + PT(29, 50, 5, 2, TRUE), + PT( 8, 61, 5, 0, TRUE), + PT(33, 50, 2, 3, TRUE), + PT(51, 49, 4, 1, FALSE), + PT(14, 3, 4, 0, TRUE), + PT(13, 11, 2, 3, FALSE), + PT(62, 42, 5, 3, FALSE), + PT(25, 54, 5, 1, FALSE), + PT(13, 0, 2, 2, FALSE), + PT(34, 7, 6, 3, FALSE), + PT(10, 9, 2, 2, TRUE), + PT(20, 16, 4, 1, FALSE), + PT( 7, 22, 5, 2, FALSE), + PT(54, 19, 2, 2, TRUE), + PT( 9, 47, 3, 1, TRUE), + PT(32, 59, 5, 3, FALSE), + PT(58, 58, 2, 3, FALSE), + PT(13, 21, 5, 1, FALSE), + PT(57, 19, 5, 1, TRUE), + PT(11, 1, 5, 1, FALSE), + PT(19, 23, 3, 3, FALSE), + PT( 8, 23, 3, 3, FALSE), + PT(12, 15, 6, 2, FALSE), + PT(31, 49, 2, 1, FALSE), + PT( 7, 58, 3, 2, TRUE), + PT(53, 30, 2, 1, FALSE), + PT(36, 44, 2, 2, TRUE), + PT(14, 33, 3, 0, TRUE), + PT(52, 59, 6, 1, TRUE), + PT(25, 15, 5, 0, FALSE), + PT(16, 47, 5, 3, FALSE), + PT(35, 39, 6, 0, TRUE), + PT(57, 46, 3, 0, FALSE), + PT(60, 63, 4, 2, FALSE), + PT( 7, 35, 6, 0, FALSE), + PT(40, 19, 6, 2, TRUE), + PT(19, 10, 2, 0, FALSE), + PT(53, 25, 6, 1, TRUE), + PT(35, 40, 5, 0, TRUE), + PT(19, 47, 3, 1, FALSE), + PT(58, 25, 2, 2, FALSE), + PT(55, 54, 4, 3, FALSE), + PT(32, 59, 2, 2, TRUE), + PT(55, 57, 2, 0, FALSE), + PT(60, 33, 6, 2, FALSE), + PT(28, 56, 6, 0, FALSE), + PT(21, 7, 4, 3, FALSE), + PT(39, 33, 3, 0, TRUE), + PT(24, 17, 4, 1, TRUE), + PT(48, 40, 6, 3, TRUE), + PT(50, 45, 3, 3, TRUE), + PT(44, 63, 6, 0, FALSE), + PT(29, 47, 4, 3, FALSE), + PT( 1, 17, 3, 2, FALSE), + PT(59, 15, 2, 1, FALSE), + PT(42, 23, 4, 3, TRUE), + PT( 5, 0, 3, 1, TRUE), + PT(37, 28, 6, 1, FALSE), + PT( 4, 34, 5, 2, TRUE), + PT(16, 15, 4, 2, TRUE), + PT(13, 57, 6, 0, FALSE), + PT(11, 46, 4, 3, TRUE), + PT(45, 52, 2, 2, TRUE), + PT(62, 48, 6, 3, FALSE), + PT(22, 38, 5, 1, FALSE), + PT( 5, 63, 5, 1, TRUE), + PT(32, 59, 5, 3, FALSE), + PT(59, 28, 5, 3, TRUE), + PT( 1, 24, 2, 3, FALSE), + PT(22, 61, 2, 0, FALSE), + PT(10, 31, 3, 0, FALSE), + PT(23, 15, 4, 1, FALSE), + PT( 6, 19, 2, 0, TRUE), + PT(56, 33, 2, 3, TRUE), + PT(23, 10, 6, 3, TRUE), + PT(28, 25, 6, 0, FALSE), + PT(22, 56, 6, 0, TRUE), + PT(48, 16, 6, 3, FALSE), + PT(49, 47, 4, 3, FALSE), + PT(60, 27, 4, 1, TRUE), + PT(51, 47, 3, 0, TRUE), + PT(22, 53, 4, 2, TRUE), + PT(58, 24, 3, 3, TRUE), + PT(55, 1, 3, 3, FALSE), + PT(13, 24, 2, 1, FALSE), + PT(31, 28, 3, 1, TRUE), + PT( 7, 52, 5, 2, TRUE), + PT(11, 63, 6, 1, TRUE), + PT(30, 52, 3, 2, TRUE), + PT(44, 19, 5, 2, FALSE), + PT(32, 32, 2, 1, TRUE), + PT(32, 15, 6, 0, TRUE), + PT( 8, 15, 4, 2, FALSE), + PT(24, 61, 3, 2, FALSE), + PT(54, 52, 4, 3, TRUE), + PT(51, 42, 4, 2, TRUE), + PT(45, 48, 4, 3, FALSE), + PT(61, 55, 4, 3, FALSE), + PT(37, 17, 2, 0, TRUE), + PT( 3, 5, 3, 0, FALSE), + PT(16, 4, 5, 0, TRUE), + PT( 7, 46, 6, 3, FALSE), + PT(42, 41, 2, 2, TRUE), + PT(58, 14, 6, 1, TRUE), + PT(42, 6, 5, 0, TRUE), + PT(61, 1, 5, 0, TRUE), + PT(39, 14, 2, 3, FALSE), + PT(29, 40, 3, 1, TRUE), + PT(16, 51, 5, 1, TRUE), + PT(12, 20, 3, 2, TRUE), + PT(21, 63, 4, 2, TRUE), + PT(55, 35, 3, 3, FALSE), + PT( 4, 44, 3, 2, FALSE), + PT(21, 52, 5, 1, FALSE), + PT( 9, 47, 2, 2, TRUE), + PT( 2, 63, 2, 2, FALSE), + PT(25, 44, 6, 1, TRUE), + PT(57, 50, 4, 0, FALSE), + PT(42, 24, 6, 1, FALSE), + PT(23, 35, 4, 0, TRUE), + PT(11, 45, 4, 2, TRUE), + PT(36, 58, 5, 2, TRUE), + PT(49, 63, 6, 2, FALSE), + PT(24, 25, 4, 2, FALSE), + PT(30, 21, 3, 1, FALSE), + PT(23, 51, 5, 1, TRUE), + PT(35, 9, 4, 3, FALSE), + PT(27, 13, 2, 2, TRUE), + PT(54, 38, 5, 0, FALSE), + PT(58, 28, 2, 2, FALSE), + PT(12, 62, 2, 0, FALSE), + PT(24, 6, 6, 2, TRUE), + PT(55, 38, 6, 3, FALSE), + PT(33, 38, 2, 3, TRUE), + PT(61, 28, 5, 2, FALSE), + PT(22, 37, 3, 2, TRUE), + PT(30, 11, 3, 3, FALSE), + PT(29, 13, 6, 1, FALSE), + PT( 8, 31, 3, 1, TRUE), + PT(18, 28, 2, 1, FALSE), + PT(32, 42, 5, 0, FALSE), + PT( 6, 59, 6, 2, TRUE), + PT(57, 14, 3, 3, FALSE), + PT(49, 48, 5, 0, FALSE), + PT( 2, 33, 2, 2, FALSE), + PT( 6, 30, 5, 0, TRUE), + PT(22, 9, 3, 2, FALSE), + PT(39, 50, 5, 2, TRUE), + PT(57, 3, 4, 3, TRUE), + PT(41, 9, 3, 3, FALSE), + PT(27, 17, 3, 2, FALSE), + PT(40, 58, 5, 2, FALSE), + PT( 3, 3, 3, 0, FALSE), + PT(35, 9, 5, 3, TRUE), + PT(48, 23, 4, 1, TRUE), + PT(15, 37, 6, 1, TRUE), + PT( 6, 36, 6, 3, TRUE), + PT(34, 9, 6, 1, TRUE), + PT(44, 9, 5, 1, FALSE), + PT(12, 18, 5, 1, FALSE), + PT(40, 32, 2, 0, FALSE), + PT(21, 41, 6, 1, TRUE), + PT(15, 26, 2, 1, TRUE), + PT(19, 24, 6, 3, FALSE), + PT(46, 22, 2, 1, TRUE), + PT(60, 26, 2, 2, TRUE), + PT(58, 17, 6, 1, FALSE), + PT( 2, 10, 5, 2, FALSE), + PT(25, 57, 2, 0, TRUE), + PT(49, 62, 3, 2, TRUE), + PT(50, 20, 6, 1, FALSE), + PT(18, 46, 6, 2, FALSE), + PT(62, 54, 4, 1, TRUE), + PT(55, 62, 2, 2, TRUE), + PT(21, 53, 6, 2, FALSE), + PT( 1, 58, 5, 2, FALSE), + PT(38, 37, 4, 1, FALSE), + PT( 1, 43, 6, 3, TRUE), + PT(28, 61, 6, 1, TRUE), + PT(62, 16, 3, 2, FALSE), + PT(38, 51, 3, 0, TRUE), + PT( 5, 25, 2, 3, TRUE), + PT(18, 56, 3, 2, FALSE), + PT(21, 60, 6, 1, FALSE), + PT(63, 15, 6, 3, TRUE), + PT( 2, 57, 6, 1, FALSE), + PT(19, 0, 3, 2, TRUE), + PT(29, 44, 2, 0, FALSE), + PT(57, 19, 6, 0, TRUE), + PT(15, 55, 3, 0, TRUE), + PT( 9, 13, 5, 1, FALSE), + PT(32, 47, 6, 1, FALSE), + PT(59, 52, 4, 1, FALSE), + PT(38, 20, 2, 0, FALSE), + PT(36, 61, 4, 1, FALSE), + PT(11, 49, 4, 1, TRUE), + PT(47, 45, 5, 1, FALSE), + PT(48, 4, 6, 2, TRUE), + PT(25, 32, 5, 1, FALSE), + PT(22, 54, 6, 3, TRUE), + PT(20, 40, 6, 3, TRUE), + PT(17, 11, 4, 3, TRUE), + PT(29, 6, 5, 0, TRUE), + PT(53, 22, 5, 3, FALSE), + PT(36, 46, 5, 0, TRUE), + PT(54, 20, 5, 1, FALSE), + PT(33, 12, 3, 3, TRUE), + PT(63, 57, 3, 0, TRUE), + PT(39, 16, 5, 1, FALSE), + PT(30, 18, 6, 2, FALSE), + PT(16, 36, 6, 2, FALSE), + PT(29, 19, 3, 2, TRUE), + PT(23, 22, 6, 3, TRUE), + PT(39, 27, 4, 3, TRUE), + PT( 7, 36, 4, 0, TRUE), + PT(55, 33, 2, 0, TRUE), + PT(55, 40, 4, 2, FALSE), + PT(25, 2, 3, 2, FALSE), + PT(20, 18, 3, 2, TRUE), + PT(27, 36, 5, 3, FALSE), + PT(46, 58, 2, 2, TRUE), + PT(55, 52, 4, 0, TRUE), + PT(51, 45, 5, 0, TRUE), + PT(47, 30, 6, 2, FALSE), + PT(41, 60, 2, 1, FALSE), + PT( 5, 21, 4, 0, FALSE), + PT( 5, 62, 3, 0, TRUE), + PT(24, 11, 6, 0, FALSE), + PT(47, 2, 4, 3, TRUE), + PT(20, 28, 6, 2, FALSE), + PT(18, 32, 6, 0, FALSE), + PT(43, 34, 3, 1, TRUE), + PT( 6, 49, 5, 0, FALSE), + PT(21, 45, 2, 1, FALSE), + PT( 1, 14, 2, 1, TRUE), + PT(19, 12, 5, 0, FALSE), + PT( 7, 42, 2, 2, FALSE), + PT(29, 54, 2, 2, FALSE), + PT(21, 43, 4, 3, FALSE), + PT( 3, 37, 2, 2, TRUE), + PT(62, 59, 4, 0, FALSE), + PT(53, 12, 4, 2, TRUE), + PT(43, 22, 6, 2, TRUE), + PT(30, 49, 5, 2, FALSE), + PT( 6, 3, 5, 0, TRUE), + PT(36, 7, 3, 3, TRUE), + PT(50, 47, 3, 0, TRUE), + PT(37, 33, 6, 0, TRUE), + PT(34, 38, 3, 2, TRUE), + PT( 0, 27, 3, 0, FALSE), + PT(42, 36, 6, 0, TRUE), + PT(32, 6, 5, 3, TRUE), + PT(30, 50, 4, 3, FALSE), + PT(50, 57, 2, 1, FALSE), + PT(32, 1, 3, 0, TRUE), + PT(15, 21, 2, 2, TRUE), + PT(39, 16, 5, 3, FALSE), + PT( 9, 37, 3, 0, TRUE), + PT(41, 55, 6, 0, FALSE), + PT(19, 28, 3, 2, TRUE), + PT(41, 45, 4, 3, FALSE), + PT( 2, 26, 2, 3, FALSE), + PT(29, 43, 3, 2, FALSE), + PT(24, 4, 6, 2, FALSE), + PT(40, 42, 4, 0, TRUE), + PT(21, 27, 5, 3, FALSE), + PT(22, 1, 2, 0, FALSE), + PT( 5, 9, 2, 2, FALSE), + PT(34, 3, 4, 1, FALSE), + PT( 2, 27, 6, 2, FALSE), + PT(41, 42, 4, 1, TRUE), + PT(38, 54, 2, 1, TRUE), + PT(35, 61, 3, 1, FALSE), + PT(29, 16, 4, 2, FALSE), + PT(37, 43, 6, 3, TRUE), + PT(25, 36, 4, 3, FALSE), + PT(40, 19, 2, 3, FALSE), + PT(23, 20, 3, 0, TRUE), + PT(11, 47, 4, 2, TRUE), + PT(55, 52, 6, 3, TRUE), + PT(57, 33, 3, 1, TRUE), + PT(15, 61, 5, 2, TRUE), + PT(13, 16, 4, 0, FALSE), + PT( 5, 11, 5, 2, TRUE), + PT( 1, 18, 4, 2, FALSE), + PT(24, 61, 6, 1, FALSE), + PT( 9, 33, 4, 3, FALSE), + PT(26, 14, 3, 3, TRUE), + PT(48, 6, 3, 3, TRUE), + PT(11, 60, 5, 0, TRUE), + PT( 7, 62, 4, 3, TRUE), + PT(19, 30, 3, 1, FALSE), + PT(19, 7, 4, 1, TRUE), + PT(16, 52, 3, 3, FALSE), + PT(50, 23, 4, 1, TRUE), + PT(53, 22, 6, 0, TRUE), + PT(50, 46, 3, 1, TRUE), + PT(40, 14, 4, 1, FALSE), + PT(20, 58, 4, 1, TRUE), + PT(34, 3, 5, 0, TRUE), + PT(42, 16, 4, 0, FALSE), + PT(62, 60, 4, 3, TRUE), + PT(22, 32, 2, 1, FALSE), + PT(63, 36, 6, 0, TRUE), + PT(13, 46, 6, 1, FALSE), + PT(47, 23, 5, 2, TRUE), + PT(54, 59, 2, 3, TRUE), + PT(36, 35, 3, 0, FALSE), + PT(55, 29, 2, 1, TRUE), + PT(23, 58, 3, 1, FALSE), + PT(10, 61, 3, 3, FALSE), + PT( 5, 18, 2, 3, FALSE), + PT(51, 50, 4, 2, TRUE), + PT(29, 31, 5, 0, TRUE), + PT(52, 44, 4, 3, FALSE), + PT(32, 41, 6, 2, TRUE), + PT(14, 50, 2, 3, TRUE), + PT( 1, 57, 5, 2, TRUE), + PT(39, 36, 4, 1, TRUE), + PT(40, 63, 3, 0, FALSE), + PT(57, 56, 4, 2, TRUE), + PT(35, 17, 2, 0, TRUE), + PT(25, 44, 5, 0, TRUE), + PT(48, 8, 5, 0, FALSE), + PT(37, 39, 3, 2, TRUE), + PT(23, 37, 4, 0, TRUE), + PT( 9, 61, 2, 3, FALSE), + PT(27, 15, 5, 2, FALSE), + PT(27, 18, 4, 1, FALSE), + PT(40, 62, 4, 3, FALSE), + PT(52, 16, 3, 1, TRUE), + PT( 2, 52, 2, 2, TRUE), + PT(26, 41, 3, 0, TRUE), + PT(41, 17, 6, 0, TRUE), + PT(18, 39, 2, 3, TRUE), + PT(39, 39, 5, 3, TRUE), + PT(52, 39, 4, 2, FALSE), + PT( 3, 25, 6, 3, FALSE), + PT(23, 29, 6, 1, TRUE), + PT(25, 37, 3, 1, FALSE), + PT(43, 57, 2, 1, TRUE), + PT(59, 51, 3, 2, TRUE), + PT(39, 49, 6, 2, FALSE), + PT(40, 51, 6, 3, TRUE), + PT( 9, 48, 3, 1, TRUE), + PT( 3, 58, 4, 3, TRUE), + PT(25, 17, 3, 3, TRUE), + PT(11, 26, 6, 2, FALSE), + PT(61, 42, 2, 2, TRUE), + PT( 4, 36, 6, 3, FALSE), + PT(48, 35, 6, 0, FALSE), + PT(15, 34, 3, 1, TRUE), + PT(61, 61, 4, 2, FALSE), + PT(41, 29, 2, 1, FALSE), + PT(22, 25, 5, 3, FALSE), + PT( 3, 18, 2, 3, TRUE), + PT(24, 37, 6, 1, TRUE), + PT(47, 35, 3, 1, FALSE), + PT(26, 53, 4, 3, TRUE), + PT(33, 38, 3, 0, TRUE), + PT(27, 48, 3, 0, FALSE), + PT(43, 34, 5, 2, TRUE), + PT(44, 26, 6, 2, FALSE), + PT(62, 18, 3, 0, TRUE), + PT(40, 39, 2, 2, TRUE), + PT(27, 17, 2, 1, FALSE), + PT(23, 21, 2, 0, FALSE), + PT(52, 55, 4, 2, TRUE), + PT(18, 63, 2, 2, TRUE), + PT(49, 13, 6, 3, TRUE), + PT(62, 42, 5, 2, TRUE), + PT(15, 36, 4, 2, FALSE), + PT(60, 63, 3, 3, TRUE), + PT(29, 52, 2, 3, TRUE), + PT(26, 35, 3, 3, TRUE), + PT(55, 15, 2, 0, FALSE), + PT(50, 52, 6, 2, TRUE), + PT(25, 5, 4, 1, FALSE), + PT(51, 22, 6, 2, FALSE), + PT(30, 20, 3, 3, FALSE), + PT( 8, 19, 5, 0, TRUE), + PT(58, 55, 6, 0, FALSE), + PT(29, 54, 2, 2, TRUE), + PT(41, 46, 3, 2, TRUE), + PT(50, 46, 4, 1, TRUE), + PT(53, 23, 3, 2, FALSE), + PT(54, 29, 2, 1, TRUE), + PT(35, 52, 6, 2, FALSE), + PT(36, 26, 6, 3, TRUE), + PT(47, 38, 5, 3, FALSE), + PT(30, 23, 3, 1, FALSE), + PT(31, 21, 3, 3, TRUE), + PT(43, 31, 3, 0, TRUE), + PT(10, 51, 3, 1, FALSE), + PT(53, 49, 4, 2, FALSE), + PT(45, 23, 5, 2, FALSE), + PT(12, 33, 6, 3, FALSE), + PT(44, 53, 6, 2, TRUE), + PT(27, 3, 4, 3, TRUE), + PT( 1, 13, 3, 2, TRUE), + PT(28, 14, 2, 0, TRUE), + PT(17, 43, 2, 0, FALSE), + PT(37, 59, 4, 0, FALSE), + PT(31, 23, 3, 0, TRUE), + PT(32, 8, 6, 3, FALSE), + PT(19, 56, 3, 0, TRUE), + PT(27, 43, 4, 2, FALSE), + PT(11, 31, 5, 0, TRUE), + PT(39, 21, 5, 2, FALSE), + PT(55, 57, 2, 0, FALSE), + PT(58, 21, 5, 3, FALSE), + PT(47, 17, 6, 3, FALSE), + PT(36, 4, 4, 0, FALSE), + PT(59, 42, 6, 2, TRUE), + PT(39, 53, 6, 2, FALSE), + PT(13, 27, 4, 0, FALSE), + PT(16, 34, 6, 3, TRUE), + PT(31, 56, 4, 3, TRUE), + PT(49, 15, 5, 0, FALSE), + PT(40, 37, 2, 2, TRUE), + PT( 0, 29, 4, 2, TRUE), + PT(49, 40, 5, 0, FALSE), + PT(11, 58, 3, 2, TRUE), + PT(45, 19, 3, 1, TRUE), + PT( 3, 55, 5, 3, FALSE), + PT(29, 40, 3, 0, TRUE), + PT( 8, 45, 4, 1, FALSE), + PT(39, 57, 6, 1, FALSE), + PT(63, 47, 3, 2, TRUE), + PT(51, 52, 5, 0, FALSE), + PT(24, 8, 6, 0, TRUE), + PT(35, 31, 2, 1, TRUE), + PT(13, 44, 4, 1, TRUE), + PT(58, 45, 3, 1, FALSE), + PT( 2, 37, 2, 1, TRUE), + PT(32, 54, 6, 2, FALSE), + PT(18, 43, 5, 2, TRUE), + PT(53, 53, 6, 2, FALSE), + PT(35, 32, 4, 0, TRUE), + PT(58, 25, 3, 1, TRUE), + PT(31, 43, 3, 0, TRUE), + PT(53, 14, 3, 0, TRUE), + PT(38, 36, 6, 3, TRUE), + PT(24, 8, 2, 0, FALSE), + PT(12, 22, 5, 2, TRUE), + PT(31, 52, 4, 0, TRUE), + PT( 5, 56, 3, 0, TRUE), + PT(20, 33, 4, 2, FALSE), + PT(17, 49, 2, 2, FALSE), + PT(62, 56, 5, 0, TRUE), + PT(63, 8, 4, 2, TRUE), + PT(42, 31, 4, 2, TRUE), + PT(37, 6, 5, 0, FALSE), + PT(11, 30, 2, 2, FALSE), + PT(26, 56, 4, 1, FALSE), + PT(36, 24, 5, 0, TRUE), + PT(26, 17, 4, 0, FALSE), + PT(59, 58, 3, 3, FALSE), + PT(28, 38, 3, 1, FALSE), + PT( 5, 50, 3, 0, TRUE), + PT(57, 42, 6, 0, TRUE), + PT( 9, 7, 4, 2, TRUE), + PT( 5, 62, 2, 3, FALSE), + PT(52, 38, 2, 2, FALSE), + PT(27, 50, 4, 3, FALSE), + PT( 5, 8, 6, 3, TRUE), + PT(15, 3, 4, 0, FALSE), + PT(42, 57, 6, 0, TRUE), + PT( 8, 1, 3, 3, FALSE), + PT(29, 35, 6, 0, TRUE), + PT(40, 27, 5, 0, FALSE), + PT(30, 55, 2, 2, FALSE), + PT(19, 14, 5, 0, FALSE), + PT(42, 59, 6, 3, TRUE), + PT(47, 28, 5, 0, FALSE), + PT(48, 48, 3, 1, FALSE), + PT(54, 31, 2, 3, FALSE), + PT(62, 13, 2, 2, TRUE), + PT(46, 22, 3, 0, FALSE), + PT(21, 55, 4, 0, FALSE), + PT(42, 51, 6, 0, FALSE), + PT(43, 14, 4, 2, TRUE), + PT(24, 32, 2, 3, FALSE), + PT( 2, 25, 4, 2, TRUE), + PT(10, 46, 6, 0, FALSE), + PT(22, 3, 2, 0, TRUE), + PT( 4, 39, 4, 2, TRUE), + PT(27, 28, 4, 0, TRUE), + PT(41, 4, 4, 3, TRUE), + PT(61, 32, 3, 3, FALSE), + PT(40, 51, 6, 0, TRUE), + PT(30, 57, 2, 0, FALSE), + PT(49, 41, 3, 3, FALSE), + PT( 6, 37, 5, 0, FALSE), + PT(25, 59, 2, 1, FALSE), + PT(11, 27, 3, 2, FALSE), + PT(62, 55, 4, 0, FALSE), + PT(10, 55, 6, 1, TRUE), + PT( 2, 44, 4, 2, TRUE), + PT(21, 24, 2, 2, FALSE), + PT(59, 32, 3, 2, FALSE), + PT(34, 59, 3, 2, FALSE), + PT(36, 52, 6, 2, TRUE), + PT(15, 47, 6, 0, TRUE), + PT(59, 23, 6, 2, TRUE), + PT(48, 57, 6, 3, TRUE), + PT(13, 21, 2, 0, TRUE), + PT(16, 3, 3, 3, FALSE), + PT(26, 57, 6, 1, TRUE), + PT(47, 46, 5, 0, FALSE), + PT(28, 40, 6, 3, FALSE), + PT(40, 24, 3, 3, TRUE), + PT(21, 1, 6, 0, FALSE), + PT(62, 50, 5, 0, FALSE), + PT(52, 47, 4, 1, TRUE), + PT( 7, 12, 6, 3, FALSE), + PT(40, 44, 6, 2, FALSE), + PT(42, 12, 3, 3, TRUE), + PT(63, 32, 2, 1, TRUE), + PT(43, 23, 4, 3, TRUE), + PT(40, 41, 5, 1, FALSE), + PT(60, 19, 6, 3, FALSE), + PT(38, 45, 5, 1, FALSE), + PT(10, 6, 3, 3, FALSE), + PT(32, 4, 3, 1, FALSE), + PT( 2, 7, 6, 2, TRUE), + PT(14, 24, 6, 0, FALSE), + PT( 0, 52, 6, 2, FALSE), + PT(47, 20, 6, 3, TRUE), + PT(33, 48, 3, 3, TRUE), + PT(21, 55, 3, 1, TRUE), + PT(58, 11, 6, 1, FALSE), + PT(34, 34, 4, 0, TRUE), + PT(27, 53, 4, 1, TRUE), + PT(13, 3, 3, 2, FALSE), + PT(35, 59, 2, 1, TRUE), + PT(14, 29, 3, 3, TRUE), + PT(29, 63, 5, 3, FALSE), + PT(57, 39, 5, 3, FALSE), + PT(15, 56, 4, 0, FALSE), + PT(49, 60, 6, 2, TRUE), + PT(11, 15, 5, 3, FALSE), + PT( 6, 6, 5, 0, FALSE), + PT(37, 57, 4, 1, TRUE), + PT(10, 50, 2, 2, TRUE), + PT(15, 29, 4, 2, TRUE), + PT(12, 13, 6, 2, FALSE), + PT(18, 46, 4, 0, TRUE), + PT(54, 24, 3, 3, TRUE), + PT(31, 52, 3, 1, TRUE), + PT( 5, 58, 6, 3, FALSE), + PT(43, 1, 2, 3, TRUE), + PT(14, 22, 5, 1, TRUE), + PT(14, 11, 4, 3, FALSE), + PT(13, 45, 2, 0, FALSE), + PT(33, 17, 4, 3, TRUE), + PT(61, 19, 6, 1, FALSE), + PT(21, 37, 5, 1, FALSE), + PT(27, 45, 6, 2, TRUE), + PT(44, 43, 4, 3, FALSE), + PT(38, 31, 4, 0, FALSE), + PT(34, 43, 2, 1, FALSE), + PT(63, 61, 4, 3, TRUE), + PT(48, 10, 6, 3, FALSE), + PT(53, 31, 2, 3, TRUE), + PT(33, 8, 5, 0, TRUE), + PT(29, 32, 6, 1, TRUE), + PT(52, 17, 2, 3, FALSE), + PT( 5, 56, 5, 2, TRUE), +}; + +#undef PT diff --git a/src/dodrio_berry_picking.c b/src/dodrio_berry_picking.c index 47839a79a..d3244f4b9 100644 --- a/src/dodrio_berry_picking.c +++ b/src/dodrio_berry_picking.c @@ -25,301 +25,459 @@ #include "constants/items.h" #include "constants/songs.h" -struct DodrioSubstruct_0160 -{ - /*0x0000 : 0x3000*/ u16 ALIGNED(4) tilemapBuffers[3][BG_SCREEN_SIZE]; - /*0x3000 : 0x3160*/ bool32 finished; - /*0x3004 : 0x3164*/ u8 ALIGNED(4) unk3004; - /*0x3008 : 0x3168*/ u8 ALIGNED(4) unk3008[10]; - /*0x3014 : 0x3174*/ u8 ALIGNED(4) state; - /*0x3018 : 0x3178*/ u8 ALIGNED(4) unk3018; - /*0x301C : 0x317C*/ u16 ALIGNED(4) unk301C; - /*0x3020 : 0x3180*/ u8 ALIGNED(4) unk3020; - /*0x3024 : 0x3184*/ u8 ALIGNED(4) unk3024; - /*0x3024 : 0x3184*/ void (*unk3028)(void); +// Note that in this file 'Dodrio Berry Picking' is often +// shortened to DodrioGame or just Game for convenience + +#define MAX_SCORE 999990 +#define MAX_BERRIES 9999 + +// The minimum score needed to receive a prize +#define PRIZE_SCORE 3000 + +// Difficulty increases as berries are eaten. The rate of new berries increases and the types of berries changes +// When the max difficulty is reached it starts again from the beginning +#define NUM_DIFFICULTIES 7 + +#define MAX_FALL_DIST 10 // The number of times a berry needs to fall before hitting the ground +#define EAT_FALL_DIST 7 // The number of times a berry needs to fall to be available to eat + +enum { + BG_INTERFACE, + BG_TREE_LEFT, + BG_TREE_RIGHT, + BG_SCENERY +}; + +enum { + FUNC_INTRO, + FUNC_INIT_COUNTDOWN, + FUNC_COUNTDOWN, + FUNC_WAIT_START, + FUNC_PLAY_GAME, + FUNC_INIT_RESULTS, + FUNC_RESULTS, + FUNC_ASK_PLAY_AGAIN, + FUNC_END_LINK, + FUNC_EXIT, + FUNC_RESET_GAME, + FUNC_WAIT_END_GAME, +}; + +enum { + GFXFUNC_LOAD, + GFXFUNC_SHOW_NAMES, + GFXFUNC_SHOW_RESULTS, + GFXFUNC_MSG_PLAY_AGAIN, + GFXFUNC_MSG_SAVING, + GFXFUNC_MSG_COMM_STANDBY, + GFXFUNC_ERASE_MSG, + GFXFUNC_MSG_PLAYER_DROPPED, + GFXFUNC_STOP, + GFXFUNC_IDLE, +}; + +enum { + PACKET_READY_START = 1, + PACKET_GAME_STATE, + PACKET_PICK_STATE, + PACKET_READY_END, +}; + +enum { + PLAY_AGAIN_NONE, + PLAY_AGAIN_YES, + PLAY_AGAIN_NO, + PLAY_AGAIN_DROPPED = 5, +}; + +enum { + PICK_NONE, // Dodrio standing still + PICK_RIGHT, // Dodrio reaching right + PICK_MIDDLE, // Dodrio reaching up + PICK_LEFT, // Dodrio reaching left + PICK_DISABLED, // Dodrio down after game over +}; + +enum { + BERRY_BLUE, + BERRY_GREEN, + BERRY_GOLD, + BERRY_MISSED, + BERRY_PRIZE, + BERRY_IN_ROW, + NUM_BERRY_IDS +}; + +#define NUM_BERRY_TYPES 4 // Blue, Green, Gold, and 'missed' + + // Eaten anim comes after the normal & missed versions of other berries +#define ANIM_EATEN (BERRY_MISSED * 2) + +enum { + BERRYSTATE_NONE, + BERRYSTATE_PICKED, // Berry has been picked by a Dodrio, replaced with blue hit sprite (still falling) + BERRYSTATE_EATEN, // Berry has been eaten (after being picked), berry is gone now + BERRYSTATE_SQUISHED, // Berry has hit the ground +}; + +enum { + INPUTSTATE_NONE, + INPUTSTATE_TRY_PICK, + INPUTSTATE_PICKED, + INPUTSTATE_ATE_BERRY, + INPUTSTATE_BAD_MISS, +}; + +// Colors for status bar squares +// Colored gray when a berry is missed +// Flash red when few yellow squares remain +enum { + STATUS_YELLOW, + STATUS_GRAY, + STATUS_RED, +}; + +#define NUM_STATUS_SQUARES 10 + +// Berries fall in predefined columns. +// A total of 10 are available, though fewer will be used with < 5 players +// The 11th column is a repeat of the 1st column wrapped around, so only +// the values 0-9 are unique 'valid' columns +#define NUM_BERRY_COLUMNS 11 + +#define GFXTAG_DODRIO 0 +#define GFXTAG_STATUS 1 +#define GFXTAG_BERRIES 2 +#define GFXTAG_CLOUD 5 +#define GFXTAG_COUNTDOWN 7 + +#define PALTAG_DODRIO_NORMAL 0 +#define PALTAG_DODRIO_SHINY 1 +#define PALTAG_STATUS 2 +#define PALTAG_BERRIES 3 +#define PALTAG_CLOUD 6 +#define PALTAG_COUNTDOWN 8 + +#define NUM_CLOUDS 2 + +#define PLAYER_NONE 0xFF + +struct DodrioGame_Gfx +{ + u16 ALIGNED(4) tilemapBuffers[3][BG_SCREEN_SIZE]; + bool32 finished; + u8 ALIGNED(4) taskId; + u8 ALIGNED(4) windowIds[MAX_RFU_PLAYERS + 5]; // The latter 5 are never used + u8 ALIGNED(4) state; + u8 ALIGNED(4) loadState; + u16 ALIGNED(4) timer; + u8 ALIGNED(4) cursorSelection; + u8 ALIGNED(4) playAgainState; + void (*func)(void); }; // size = 0x302C -struct DodrioStruct_2022CF4 +struct StatusBar { - u8 filler_00[0xc]; - u8 unkC[10]; - s16 unk16[10]; - u16 unk2A[10]; - u16 unk3E; + u8 unused[12]; + bool8 entered[NUM_STATUS_SQUARES]; + s16 yChange[NUM_STATUS_SQUARES]; + u16 spriteIds[NUM_STATUS_SQUARES]; + u16 flashTimer; }; // size = 0x40 -struct DodrioSubstruct_31A0_14 +struct DodrioGame_Berries { - u8 unk0[11]; - u8 unkB[11]; + u8 ids[NUM_BERRY_COLUMNS]; + u8 fallDist[NUM_BERRY_COLUMNS]; }; -struct DodrioSubstruct_31A0_2C +struct DodrioGame_PlayerCommData { - u8 unk0; - u8 ALIGNED(4) unk4; - u8 ALIGNED(4) unk8; + u8 pickState; + bool8 ALIGNED(4) ateBerry; + bool8 ALIGNED(4) missedBerry; }; -struct DodrioSubstruct_31A0 +struct DodrioGame_Player { - u8 name[0x10]; - u32 unk10; - struct DodrioSubstruct_31A0_14 unk14; - struct DodrioSubstruct_31A0_2C unk2C; - u8 filler_35[4]; + u8 name[16]; + bool32 receivedGameStatePacket; // Never read + struct DodrioGame_Berries berries; + struct DodrioGame_PlayerCommData comm; + u32 unused; }; // size = 0x3C -struct DodrioSubstruct_318C +// Because Dodrio is required for this minigame, +// the only relevant information about the selected +// Pokémon is whether or not it's shiny +struct DodrioGame_MonInfo { bool8 isShiny; }; -struct DodrioSubstruct_3308 +struct DodrioGame_ScoreResults { - u8 unk0; - u32 unk4; + u8 ranking; + u32 score; }; -struct DodrioStruct -{ - /*0x0000*/ void (*savedCallback)(void); - /*0x0004*/ u8 ALIGNED(4) unk04; - /*0x0008*/ u8 ALIGNED(4) unk08; - /*0x000C*/ u8 ALIGNED(4) unk0C; - /*0x0010*/ u8 ALIGNED(4) unk10; - /*0x0014*/ u8 ALIGNED(4) unk14; - /*0x0018*/ u8 ALIGNED(4) unk18; - /*0x001C*/ u8 ALIGNED(4) unk1C; - /*0x0020*/ u8 ALIGNED(4) unk20; - /*0x0024*/ u8 ALIGNED(4) unk24; +struct DodrioGame +{ + /*0x0000*/ void (*exitCallback)(void); + /*0x0004*/ u8 ALIGNED(4) taskId; + /*0x0008*/ u8 ALIGNED(4) playersReceived; + /*0x000C*/ u8 ALIGNED(4) startState; + /*0x0010*/ u8 ALIGNED(4) state; + /*0x0014*/ u8 ALIGNED(4) timer; + /*0x0018*/ u8 ALIGNED(4) funcId; + /*0x001C*/ u8 ALIGNED(4) prevFuncId; // Set, never read + /*0x0020*/ bool8 ALIGNED(4) isLeader; + /*0x0024*/ u8 ALIGNED(4) numPlayers; /*0x0028*/ u8 ALIGNED(4) multiplayerId; - /*0x0029*/ u8 filler_0029[7]; - /*0x0030*/ u8 ALIGNED(4) unk30; - /*0x0034*/ u8 ALIGNED(4) unk34[5]; - /*0x003C*/ u8 ALIGNED(4) unk3C; - /*0x0040*/ u8 ALIGNED(4) unk40; - /*0x0044*/ u8 ALIGNED(4) unk44; - /*0x0048*/ u8 ALIGNED(4) unk48; - /*0x004A*/ u16 unk4A[5][6]; - /*0x0086*/ u16 unk86[5]; - /*0x0090*/ u8 ALIGNED(4) unk90[5]; - /*0x0098*/ u8 ALIGNED(4) unk98[4]; - /*0x009C*/ u8 ALIGNED(4) unk9C[11]; - /*0x00A8*/ u8 ALIGNED(4) unkA8[5]; - /*0x00B0*/ u8 ALIGNED(4) unkB0[5]; - /*0x00B8*/ u8 ALIGNED(4) unkB8[11]; - /*0x00C4*/ u8 ALIGNED(4) unkC4[11]; - /*0x00D0*/ u8 ALIGNED(4) unkD0[11]; - /*0x00DC*/ u8 ALIGNED(4) unkDC[11]; - /*0x00E8*/ u8 ALIGNED(4) unkE8[11]; - /*0x00F4*/ u8 ALIGNED(4) unkF4[11][2]; - /*0x010C*/ u8 ALIGNED(4) unk10C[5]; - /*0x0112*/ u16 unk112; - /*0x0114*/ u16 unk114; - /*0x0118*/ u32 unk118; - /*0x011C*/ u32 unk11C; - /*0x0120*/ u32 unk120; - /*0x0124*/ u8 ALIGNED(4) unk124; - /*0x0128*/ u8 ALIGNED(4) unk128; - /*0x012C*/ u32 unk12C; - /*0x0130*/ u32 unk130[5]; - /*0x0144*/ u8 ALIGNED(4) unk144; - /*0x0148*/ u8 ALIGNED(4) unk148[11]; - /*0x0154*/ u8 ALIGNED(4) unk154; - /*0x0158*/ u8 ALIGNED(4) unk158[5]; - /*0x0160*/ struct DodrioSubstruct_0160 unk160; - /*0x318C*/ struct DodrioSubstruct_318C unk318C[5]; - /*0x31A0*/ struct DodrioSubstruct_31A0 unk31A0[5]; - /*0x32CC*/ struct DodrioSubstruct_31A0 unk32CC; - /*0x3308*/ struct DodrioSubstruct_3308 unk3308[5]; + /*0x0029*/ u8 unused1[7]; + /*0x0030*/ u8 ALIGNED(4) countdownEndDelay; + /*0x0034*/ u8 ALIGNED(4) posToPlayerId[MAX_RFU_PLAYERS]; + /*0x003C*/ u8 ALIGNED(4) unused2; // Set to 0, never read + /*0x0040*/ u8 ALIGNED(4) numGraySquares; + /*0x0044*/ u8 ALIGNED(4) berryColStart; + /*0x0048*/ u8 ALIGNED(4) berryColEnd; + /*0x004A*/ u16 berryResults[MAX_RFU_PLAYERS][NUM_BERRY_IDS]; + /*0x0086*/ u16 berriesEaten[MAX_RFU_PLAYERS]; + /*0x0090*/ u8 ALIGNED(4) difficulty[MAX_RFU_PLAYERS]; + /*0x0098*/ u8 ALIGNED(4) pickStateQueue[4]; + /*0x009C*/ u8 ALIGNED(4) eatTimer[NUM_BERRY_COLUMNS]; + /*0x00A8*/ u8 ALIGNED(4) inputState[MAX_RFU_PLAYERS]; + /*0x00B0*/ u8 ALIGNED(4) inputDelay[MAX_RFU_PLAYERS]; + /*0x00B8*/ u8 ALIGNED(4) berryEatenBy[NUM_BERRY_COLUMNS]; + /*0x00C4*/ u8 ALIGNED(4) berryState[NUM_BERRY_COLUMNS]; + /*0x00D0*/ u8 ALIGNED(4) fallTimer[NUM_BERRY_COLUMNS]; + /*0x00DC*/ u8 ALIGNED(4) newBerryTimer[NUM_BERRY_COLUMNS]; + /*0x00E8*/ u8 ALIGNED(4) prevBerryIds[NUM_BERRY_COLUMNS]; + /*0x00F4*/ u8 ALIGNED(4) playersAttemptingPick[NUM_BERRY_COLUMNS][2]; + /*0x010C*/ u8 ALIGNED(4) playAgainStates[MAX_RFU_PLAYERS]; + /*0x0112*/ u16 berriesPickedInRow; + /*0x0114*/ u16 maxBerriesPickedInRow; + /*0x0118*/ bool32 startCountdown; // Never read + /*0x011C*/ bool32 startGame; + /*0x0120*/ bool32 berriesFalling; + /*0x0124*/ u8 ALIGNED(4) clearRecvCmdTimer; + /*0x0128*/ bool8 ALIGNED(4) clearRecvCmds; + /*0x012C*/ bool32 allReadyToEnd; + /*0x0130*/ bool32 readyToEnd[MAX_RFU_PLAYERS]; + /*0x0144*/ bool8 ALIGNED(4) playingPickSound; + /*0x0148*/ bool8 ALIGNED(4) playingSquishSound[NUM_BERRY_COLUMNS]; + /*0x0154*/ u8 ALIGNED(4) endSoundState; + /*0x0158*/ bool8 ALIGNED(4) readyToStart[MAX_RFU_PLAYERS]; + /*0x0160*/ struct DodrioGame_Gfx gfx; + /*0x318C*/ struct DodrioGame_MonInfo monInfo[MAX_RFU_PLAYERS]; + /*0x31A0*/ struct DodrioGame_Player players[MAX_RFU_PLAYERS]; + /*0x32CC*/ struct DodrioGame_Player player; + /*0x3308*/ struct DodrioGame_ScoreResults scoreResults[MAX_RFU_PLAYERS]; }; // size = 0x3330 -EWRAM_DATA static struct DodrioStruct * gUnknown_02022C98 = NULL; -EWRAM_DATA static u16 *gUnknown_02022C9C[5] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CB0[2] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CB8[11] = {NULL}; -EWRAM_DATA static u16 *gUnknown_02022CE4[4] = {NULL}; -EWRAM_DATA static struct DodrioStruct_2022CF4 *gUnknown_02022CF4 = NULL; -EWRAM_DATA static struct DodrioSubstruct_0160 *gUnknown_02022CF8 = NULL; - -static bool32 gUnknown_03000DB0; - -static void sub_8024A1C(void); -static void sub_8024A30(struct DodrioStruct *); -static void sub_8024BC8(u8 taskId); -static void sub_8024DBC(void); -static void sub_8024E00(void); -static void sub_8024E38(void); -static void sub_8024F10(void); -static void sub_8024F38(void); -static void sub_8024FFC(void); -static void sub_80250D4(void); -static void sub_8025158(void); -static void sub_8025198(void); -static void sub_8025230(void); -static void sub_8025324(void); -static void sub_8025470(void); -static void sub_8025644(void); -static void sub_80256AC(void); -static void sub_8025758(void); -static void sub_802589C(u8 taskId); -static void sub_8025910(u8 taskId); -static void sub_8025D04(void); -static void sub_8025D50(void); -static void sub_8025E0C(void); -static void sub_8025ED8(void); -static void sub_8025F48(void); -static void sub_8026044(void); -static void sub_80261CC(void); -static void sub_80261E4(void); -static void sub_80261F8(struct DodrioSubstruct_318C *, struct Pokemon *); -static void sub_802620C(TaskFunc, u8); -static void sub_802621C(TaskFunc); -static void sub_8026240(u8); -static bool32 sub_8026264(void); -static void sub_80262C0(void); -static bool32 sub_8026634(u8, u8, u8); -static void sub_802671C(void); -static void sub_8026AF4(void); -static void sub_8026B28(void); -static void sub_8026B5C(u8, u8*, u8*); -static bool32 sub_8026BB8(void); -static void sub_8026C28(void); -static bool32 sub_8026C50(void); -static bool32 sub_8026C90(void); -static void sub_8026D1C(u8); -static u8 sub_8026D8C(u8); -static u8 sub_8026DB0(u8, u8); -static void sub_8026F1C(u8, u8, u8); -static void sub_8027234(bool32 arg0); -static void sub_80272A4(void); -static void sub_80272E8(void); -static void sub_80273F0(void); -static void sub_802749C(void); -static u8 sub_8027518(u8); -static void sub_8027554(void); -static void sub_8027608(void); -static u32 sub_8027748(void); -static void sub_8027DD0(u32 arg0); -static void sub_8027E30(struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 arg6, u32 arg7, u32 arg8); -static u32 sub_8028164(u32 unused, struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 *arg6, u32 *arg7, u32 *arg8); -static void sub_80282EC(u8); -static u32 sub_8028318(u32 arg0, u8 *arg1); -static void sub_8028350(u32 arg0); -static u32 sub_8028374(u32 arg0); -static void sub_80283A8(void); -static void sub_8028408(struct DodrioSubstruct_318C *arg0, u8 arg1, u8 id, u8 arg3); -static void sub_80284CC(u8); -static void sub_8028504(u8); -static void sub_8028614(u8 count); -static void sub_802868C(bool8 invisible, u8 count); -static void sub_8028734(void); -static void sub_80287E4(void); -static void sub_80289E8(bool8 invisible); -static void sub_80286E4(void); -static bool32 sub_8028828(void); -static void sub_8028A34(void); -static void sub_8028A88(void); -static void sub_8028B80(void); -static void sub_8028D44(void); -static void sub_8028DFC(void); -static void sub_8028E4C(void); -static void sub_8028E84(void); -static void sub_8028EC8(bool8 invisible); -static void sub_8028FCC(void); -static void sub_802903C(void); -static void sub_8029274(struct DodrioSubstruct_0160 *PTR); -static void sub_80292E0(u8); -static bool32 sub_802A770(void); -static u8 sub_802A794(void); -static void sub_8028BF8(u8 id, bool8 invisible); -static void sub_8028C30(bool8 invisible); -static void sub_8028CA4(u16 id, u8 frameNum); -static void sub_8028C7C(u8 id, u8 y); -static void sub_80286B4(u8 id, u8 frameNum); -static u8 sub_8026E70(u8 arg0, u8 arg1); -static void sub_80288D4(u8 arg0); -static u32 sub_8027DFC(u32 arg0); -static u32 IncrementWithLimit(u32 arg0, u32 arg1); -static u32 Min(u32 arg0, u32 arg1); -static u32 sub_80276C0(u8 arg0); -static void Task_ShowDodrioBerryPickingRecords(u8 taskId); -static void sub_8029314(u8 taskId); -static void sub_8027BEC(u8 windowId, s32 width); -static void nullsub_15(struct Sprite *sprite); -static void sub_80284A8(struct Sprite *sprite); -static u32 sub_802853C(struct Sprite *sprite); -static u32 sub_80285AC(struct Sprite *sprite); -static s16 sub_8028F14(u8 arg0, u8 arg1); -static void sub_8028654(bool8 invisible, u8 id); -static void sub_8029338(void); -static bool32 sub_802A8E8(void); -static void sub_802A7A8(void); -static void sub_802A72C(void (*func)(void)); -static void (*sub_802A75C(void))(void); -static void sub_8029338(void); -static void sub_8029440(void); -static void sub_802988C(void); -static void sub_802A010(void); -static void sub_802A380(void); -static void sub_802A454(void); -static void sub_802A534(void); -static void sub_802A588(void); -static void sub_802A6FC(void); -static void nullsub_16(void); - -// const rom data -static const u8 gUnknown_082F449C[5][5][11] = -{ - { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, +EWRAM_DATA static struct DodrioGame * sGame = NULL; +EWRAM_DATA static u16 * sDodrioSpriteIds[MAX_RFU_PLAYERS] = {NULL}; +EWRAM_DATA static u16 * sCloudSpriteIds[NUM_CLOUDS] = {NULL}; +EWRAM_DATA static u16 * sBerrySpriteIds[NUM_BERRY_COLUMNS] = {NULL}; +EWRAM_DATA static u16 * sBerryIconSpriteIds[NUM_BERRY_TYPES] = {NULL}; +EWRAM_DATA static struct StatusBar * sStatusBar = NULL; +EWRAM_DATA static struct DodrioGame_Gfx * sGfx = NULL; + +static bool32 sExitingGame; + +static void ResetTasksAndSprites(void); +static void InitDodrioGame(struct DodrioGame *); +static void Task_StartDodrioGame(u8); +static void DoGameIntro(void); +static void InitCountdown(void); +static void DoCountdown(void); +static void WaitGameStart(void); +static void PlayGame_Leader(void); +static void PlayGame_Member(void); +static void WaitEndGame_Leader(void); +static void WaitEndGame_Member(void); +static void InitResults_Leader(void); +static void InitResults_Member(void); +static void DoResults(void); +static void AskPlayAgain(void); +static void EndLink(void); +static void ExitGame(void); +static void ResetGame(void); +static void Task_NewGameIntro(u8); +static void Task_CommunicateMonInfo(u8); +static void RecvLinkData_Leader(void); +static void SendLinkData_Leader(void); +static void RecvLinkData_Member(void); +static void SendLinkData_Member(void); +static void HandleSound_Leader(void); +static void HandleSound_Member(void); +static void CB2_DodrioGame(void); +static void VBlankCB_DodrioGame(void); +static void InitMonInfo(struct DodrioGame_MonInfo *, struct Pokemon *); +static void CreateTask_(TaskFunc, u8); +static void CreateDodrioGameTask(TaskFunc); +static void SetGameFunc(u8); +static bool32 SlideTreeBordersOut(void); +static void InitFirstWaveOfBerries(void); +static bool32 TryPickBerry(u8, u8, u8); +static void UpdateFallingBerries(void); +static void UpdateGame_Leader(void); +static void UpdateGame_Member(void); +static void GetActiveBerryColumns(u8, u8*, u8*); +static bool32 AllPlayersReadyToStart(void); +static void ResetReadyToStart(void); +static bool32 ReadyToEndGame_Leader(void); +static bool32 ReadyToEndGame_Member(void); +static void TryIncrementDifficulty(u8); +static u8 GetPlayerIdAtColumn(u8); +static u8 GetNewBerryId(u8, u8); +static void IncrementBerryResult(u8, u8, u8); +static void UpdateBerriesPickedInRow(bool32); +static void SetMaxBerriesPickedInRow(void); +static void ResetForPlayAgainPrompt(void); +static void SetRandomPrize(void); +static void TryUpdateRecords(void); +static u8 UpdatePickStateQueue(u8); +static void HandleWaitPlayAgainInput(void); +static void ResetPickState(void); +static u32 GetHighestScore(void); +static void SendPacket_ReadyToStart(bool32); +static void SendPacket_GameState(struct DodrioGame_Player *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + u8 , bool32 , bool32 ); +static bool32 RecvPacket_GameState(u32, + struct DodrioGame_Player *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + struct DodrioGame_PlayerCommData *, + u8 *, bool32 *, bool32 *); +static void SendPacket_PickState(u8); +static bool32 RecvPacket_PickState(u32, u8 *); +static void SendPacket_ReadyToEnd(bool32); +static bool32 RecvPacket_ReadyToEnd(u32); +static void LoadDodrioGfx(void); +static void CreateDodrioSprite(struct DodrioGame_MonInfo *, u8, u8, u8); +static void StartDodrioMissedAnim(u8); +static void StartDodrioIntroAnim(u8); +static void FreeDodrioSprites(u8); +static void SetAllDodrioInvisibility(bool8, u8); +static void CreateStatusBarSprites(void); +static void FreeStatusBar(void); +static void SetStatusBarInvisibility(bool8); +static void InitStatusBarPos(void); +static bool32 DoStatusBarIntro(void); +static void LoadBerryGfx(void); +static void CreateBerrySprites(void); +static void FreeBerrySprites(void); +static void CreateCloudSprites(void); +static void ResetCloudPos(void); +static void StartCloudMovement(void); +static void FreeCloudSprites(void); +static void SetCloudInvisibility(bool8); +static void ResetBerryAndStatusBarSprites(void); +static void ResetGfxState(void); +static void InitGameGfx(struct DodrioGame_Gfx *); +static void SetGfxFuncById(u8); +static bool32 IsGfxFuncActive(void); +static u8 GetPlayAgainState(void); +static void SetBerryInvisibility(u8, bool8); +static void SetBerryIconsInvisibility(bool8); +static void SetBerryAnim(u16, u8); +static void SetBerryYPos(u8, u8); +static void SetDodrioAnim(u8, u8); +static u8 GetNewBerryIdByDifficulty(u8, u8); +static void UpdateStatusBarAnim(u8); +static u32 RecvPacket_ReadyToStart(u32); +static u32 IncrementWithLimit(u32, u32); +static u32 Min(u32, u32); +static u32 GetScore(u8); +static void Task_ShowDodrioBerryPickingRecords(u8); +static void Task_TryRunGfxFunc(u8); +static void PrintRecordsText(u8, s32); +static void SpriteCB_Status(struct Sprite *); +static void SpriteCB_Dodrio(struct Sprite *); +static u32 DoDodrioMissedAnim(struct Sprite *); +static u32 DoDodrioIntroAnim(struct Sprite *); +static s16 GetDodrioXPos(u8, u8); +static void SetDodrioInvisibility(bool8, u8); +static void LoadGfx(void); +static bool32 LoadBgGfx(void); +static void InitBgs(void); +static void SetGfxFunc(void (*func)(void)); +static void (*GetGfxFunc(void))(void); +static void ShowNames(void); +static void ShowResults(void); +static void Msg_WantToPlayAgain(void); +static void Msg_SavingDontTurnOff(void); +static void Msg_CommunicationStandby(void); +static void EraseMessage(void); +static void Msg_SomeoneDroppedOut(void); +static void StopGfxFuncs(void); +static void GfxIdle(void); + +// For each player, the array is a list of all the columns starting with the column to their left +// Only the range of active columns is read from the array (dependent on the number of players), +// so the arrays are spaced such that the numbers in the center are where the data that's read starts and end. +static const u8 sActiveColumnMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = +{ + { // 1 player (never used), columns 4-6. + // Sometimes read to get default order regardless of the current number of players + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, }, - { - {0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0}, - {0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0}, + { // 2 players (never used), columns 3-6 + {0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0}, + {0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0}, }, - { - {0, 1, 2, 3, 4, 5, 6, 7, 2, 9, 0}, - {0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0}, - {0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0}, + { // 3 players, columns 2-7 + {0, 1, 2, 3, 4, 5, 6, 7, 2, 9, 0}, + {0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0}, + {0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0}, }, - { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0}, - {0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0}, - {0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0}, - {0, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0}, + { // 4 players, columns 1-8 + {0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0}, + {0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0}, + {0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0}, + {0, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0}, }, - { - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, - {2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, - {4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}, - {6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, - {8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8}, + { // 5 players, all columns (0-9) + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, + { 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2 }, + { 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4 }, + { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 }, + { 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }, }, }; -static const u8 gUknnown_082F45AF[5][5][3] = +// A table for which falling berry column corresponds to which Dodrio head for each player +// The numbers in each array are the column number for each head, {left, middle, right} +// Dependent on the number of players +static const u8 sDodrioHeadToColumnMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = { - { + { // 1 player (never used) {4, 5, 6}, }, - { + { // 2 players (never used) {3, 4, 5}, {5, 6, 3}, }, - { + { // 3 players {4, 5, 6}, {6, 7, 2}, {2, 3, 4}, }, - { + { // 4 players {3, 4, 5}, {5, 6, 7}, {7, 8, 1}, {1, 2, 3}, }, - { + { // 5 players {4, 5, 6}, {6, 7, 8}, {8, 9, 0}, @@ -328,27 +486,29 @@ static const u8 gUknnown_082F45AF[5][5][3] = }, }; -static const u8 gUnknown_082F45FA[5][5][3] = +// A table of player ids and their neighbor, dependent on the total number of players +// {L, M, R}, where M is the player in question, L is their neighbor to the left, and R is their neighbor to the right +static const u8 sDodrioNeighborMap[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = { - { + { // 1 player (never used) {1, 0, 1}, }, - { + { // 2 players (never used) {1, 0, 1}, {0, 1, 0}, }, - { + { // 3 players {2, 0, 1}, {0, 1, 2}, {1, 2, 0}, }, - { + { // 4 players {3, 0, 1}, {0, 1, 2}, {1, 2, 3}, {2, 3, 0}, }, - { + { // 5 players {4, 0, 1}, {0, 1, 2}, {1, 2, 3}, @@ -357,208 +517,259 @@ static const u8 gUnknown_082F45FA[5][5][3] = }, }; +#define __ 9 // No player at this column. This may go out of bounds if this is returned + +// Takes the number of players and a column and returns the player id at that column. +// Note that the assignment is somewhat arbitrary as players share neighboring columns. ALIGNED(4) -static const u8 gUnknown_082F4648[5][11] = +static const u8 sPlayerIdAtColumn[MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = { - {9, 9, 9, 9, 1, 1, 1, 9, 9, 9, 9}, - {9, 9, 9, 0, 0, 1, 1, 0, 9, 9, 9}, - {9, 9, 2, 2, 0, 0, 1, 1, 1, 9, 9}, - {9, 3, 3, 0, 0, 1, 1, 2, 2, 3, 9}, - {3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, + {__, __, __, __, 1, 1, 1, __, __, __, __}, // 1 player + {__, __, __, 0, 0, 1, 1, 0, __, __, __}, // 2 players + {__, __, 2, 2, 0, 0, 1, 1, 1, __, __}, // 3 players + {__, 3, 3, 0, 0, 1, 1, 2, 2, 3, __}, // 4 players + { 3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, // 5 players }; -static const u8 gUnknown_082F467F[5][5] = +#undef __ + +// Each array contains the columns that belong solely to one player, dependent on the number of players +// When determing how difficult the berries in a column should be, the highest +// difficulty of the players sharing that column is used. +// This table is used to skip that check, and instead automatically use the +// difficulty of the only player who can use the column. +static const u8 sUnsharedColumns[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS] = { {5}, {4, 6}, {3, 5, 7}, {2, 4, 6, 8}, - {1, 3, 5, 6, 9}, +#ifndef BUGFIX + {1, 3, 5, 6, 9}, // BUG: Column 6 is shared, 7 is not. As a result, the player in column 7 will have their difficulty influenced by their neighbors +#else + {1, 3, 5, 7, 9}, +#endif }; // Duplicate and unused gfx. Feel free to remove. -static const u32 sDuplicateGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.gbapal", - "graphics/link_games/dodrioberry_bg2.gbapal", - "graphics/link_games/dodrioberry_pkmn.gbapal", - "graphics/link_games/dodrioberry_shiny.gbapal", - "graphics/link_games/dodrioberry_status.gbapal", - "graphics/link_games/dodrioberry_berrysprites.gbapal", - "graphics/link_games/dodrioberry_berrysprites.4bpp.lz", - "graphics/link_games/dodrioberry_platform.gbapal", - "graphics/link_games/dodrioberry_bg1.4bpp.lz", - "graphics/link_games/dodrioberry_bg2.4bpp.lz", - "graphics/link_games/dodrioberry_status.4bpp.lz", - "graphics/link_games/dodrioberry_platform.4bpp.lz", - "graphics/link_games/dodrioberry_pkmn.4bpp.lz", - "graphics/link_games/dodrioberry_bg1.bin.lz", - "graphics/link_games/dodrioberry_bg2right.bin.lz", - "graphics/link_games/dodrioberry_bg2left.bin.lz"); - - -static const u8 gUnknown_082F7A88[][3] = -{ - {40, 24, 13}, - {32, 19, 10}, - {22, 13, 7}, +static const u32 sDuplicateGfx[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.gbapal", + "graphics/dodrio_berry_picking/tree_border.gbapal", + "graphics/dodrio_berry_picking/dodrio.gbapal", + "graphics/dodrio_berry_picking/shiny.gbapal", + "graphics/dodrio_berry_picking/status.gbapal", + "graphics/dodrio_berry_picking/berries.gbapal", + "graphics/dodrio_berry_picking/berries.4bpp.lz", + "graphics/dodrio_berry_picking/cloud.gbapal", + "graphics/dodrio_berry_picking/bg.4bpp.lz", + "graphics/dodrio_berry_picking/tree_border.4bpp.lz", + "graphics/dodrio_berry_picking/status.4bpp.lz", + "graphics/dodrio_berry_picking/cloud.4bpp.lz", + "graphics/dodrio_berry_picking/dodrio.4bpp.lz", + "graphics/dodrio_berry_picking/bg.bin.lz", + "graphics/dodrio_berry_picking/tree_border_right.bin.lz", + "graphics/dodrio_berry_picking/tree_border_left.bin.lz"); + + +static const u8 sBerryFallDelays[][3] = +{ + { [BERRY_BLUE] = 40, [BERRY_GREEN] = 24, [BERRY_GOLD] = 13 }, + { [BERRY_BLUE] = 32, [BERRY_GREEN] = 19, [BERRY_GOLD] = 10 }, + { [BERRY_BLUE] = 22, [BERRY_GREEN] = 13, [BERRY_GOLD] = 7 }, }; +// How far the outer tree borders should slide to reveal the game screen. +// Dependent on how many players are playing. +// Curiously the 2-player screen is narrower than the 1-player, though neither +// gets used as there's a 3 player minimum ALIGNED(4) -static const u8 gUnknown_082F7A94[] = {8, 5, 8, 11, 15}; +static const u8 sTreeBorderXPos[MAX_RFU_PLAYERS] = {8, 5, 8, 11, 15}; +// The number of berries eaten needed to progress to the next difficulty ALIGNED(4) -static const u8 gUnknown_082F7A9C[] = {5, 10, 20, 30, 50, 70, 100}; +static const u8 sDifficultyThresholds[NUM_DIFFICULTIES] = {5, 10, 20, 30, 50, 70, 100}; ALIGNED(4) -static const u8 gUnknown_082F7AA4[][10] = -{ - {15, 16, 17, 18, 19, 19, 18, 17, 16, 15}, - {20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, - {30, 31, 32, 33, 34, 34, 33, 32, 31, 30}, +static const u8 sPrizeBerryIds[][10] = +{ + { // Possible prizes with 3 players + ITEM_TO_BERRY(ITEM_RAZZ_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BLUK_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NANAB_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WEPEAR_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PINAP_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PINAP_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WEPEAR_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NANAB_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BLUK_BERRY) - 1, + ITEM_TO_BERRY(ITEM_RAZZ_BERRY) - 1 + }, + { // Possible prizes with 4 players + ITEM_TO_BERRY(ITEM_POMEG_BERRY) - 1, + ITEM_TO_BERRY(ITEM_KELPSY_BERRY) - 1, + ITEM_TO_BERRY(ITEM_QUALOT_BERRY) - 1, + ITEM_TO_BERRY(ITEM_HONDEW_BERRY) - 1, + ITEM_TO_BERRY(ITEM_GREPA_BERRY) - 1, + ITEM_TO_BERRY(ITEM_TAMATO_BERRY) - 1, + ITEM_TO_BERRY(ITEM_CORNN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_MAGOST_BERRY) - 1, + ITEM_TO_BERRY(ITEM_RABUTA_BERRY) - 1, + ITEM_TO_BERRY(ITEM_NOMEL_BERRY) - 1 + }, + { // Possible prizes with 5 players + ITEM_TO_BERRY(ITEM_SPELON_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PAMTRE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WATMEL_BERRY) - 1, + ITEM_TO_BERRY(ITEM_DURIN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BELUE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_BELUE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_DURIN_BERRY) - 1, + ITEM_TO_BERRY(ITEM_WATMEL_BERRY) - 1, + ITEM_TO_BERRY(ITEM_PAMTRE_BERRY) - 1, + ITEM_TO_BERRY(ITEM_SPELON_BERRY) - 1 + }, }; -static void (*const gUnknown_082F7AC4[])(void) = -{ - sub_8024DBC, - sub_8024E00, - sub_8024E38, - sub_8024F10, - sub_8024F38, - sub_8025198, - sub_8025324, - sub_8025470, - sub_8025644, - sub_80256AC, - sub_8025758, - sub_80250D4 +static void (*const sLeaderFuncs[])(void) = +{ + [FUNC_INTRO] = DoGameIntro, + [FUNC_INIT_COUNTDOWN] = InitCountdown, + [FUNC_COUNTDOWN] = DoCountdown, + [FUNC_WAIT_START] = WaitGameStart, + [FUNC_PLAY_GAME] = PlayGame_Leader, + [FUNC_INIT_RESULTS] = InitResults_Leader, + [FUNC_RESULTS] = DoResults, + [FUNC_ASK_PLAY_AGAIN] = AskPlayAgain, + [FUNC_END_LINK] = EndLink, + [FUNC_EXIT] = ExitGame, + [FUNC_RESET_GAME] = ResetGame, + [FUNC_WAIT_END_GAME] = WaitEndGame_Leader }; -static void (*const gUnknown_082F7AF4[])(void) = -{ - sub_8024DBC, - sub_8024E00, - sub_8024E38, - sub_8024F10, - sub_8024FFC, - sub_8025230, - sub_8025324, - sub_8025470, - sub_8025644, - sub_80256AC, - sub_8025758, - sub_8025158 +static void (*const sMemberFuncs[])(void) = +{ + [FUNC_INTRO] = DoGameIntro, + [FUNC_INIT_COUNTDOWN] = InitCountdown, + [FUNC_COUNTDOWN] = DoCountdown, + [FUNC_WAIT_START] = WaitGameStart, + [FUNC_PLAY_GAME] = PlayGame_Member, + [FUNC_INIT_RESULTS] = InitResults_Member, + [FUNC_RESULTS] = DoResults, + [FUNC_ASK_PLAY_AGAIN] = AskPlayAgain, + [FUNC_END_LINK] = EndLink, + [FUNC_EXIT] = ExitGame, + [FUNC_RESET_GAME] = ResetGame, + [FUNC_WAIT_END_GAME] = WaitEndGame_Member }; -// code -void StartDodrioBerryPicking(u16 a0, void (*callback)(void)) +void StartDodrioBerryPicking(u16 partyId, void (*exitCallback)(void)) { - gUnknown_03000DB0 = FALSE; + sExitingGame = FALSE; - if (gReceivedRemoteLinkPlayers != 0 && (gUnknown_02022C98 = AllocZeroed(sizeof(*gUnknown_02022C98))) != NULL) + if (gReceivedRemoteLinkPlayers != 0 && (sGame = AllocZeroed(sizeof(*sGame)))) { - sub_8024A1C(); - sub_8024A30(gUnknown_02022C98); - gUnknown_02022C98->savedCallback = callback; - gUnknown_02022C98->multiplayerId = GetMultiplayerId(); - gUnknown_02022C98->unk32CC = gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - sub_80261F8(&gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId], &gPlayerParty[a0]); - CreateTask(sub_8024BC8, 1); - SetMainCallback2(sub_80261CC); - sub_80273F0(); - sub_8026B5C(gUnknown_02022C98->unk24, &gUnknown_02022C98->unk44, &gUnknown_02022C98->unk48); + ResetTasksAndSprites(); + InitDodrioGame(sGame); + sGame->exitCallback = exitCallback; + sGame->multiplayerId = GetMultiplayerId(); + sGame->player = sGame->players[sGame->multiplayerId]; + InitMonInfo(&sGame->monInfo[sGame->multiplayerId], &gPlayerParty[partyId]); + CreateTask(Task_StartDodrioGame, 1); + SetMainCallback2(CB2_DodrioGame); + SetRandomPrize(); + GetActiveBerryColumns(sGame->numPlayers, &sGame->berryColStart, &sGame->berryColEnd); StopMapMusic(); PlayNewMapMusic(MUS_RG_BERRY_PICK); } else { - SetMainCallback2(callback); + // Exit - Alloc failed, or players not connected + SetMainCallback2(exitCallback); return; } } -static void sub_8024A1C(void) +static void ResetTasksAndSprites(void) { ResetTasks(); ResetSpriteData(); FreeAllSpritePalettes(); } -static void sub_8024A30(struct DodrioStruct * data) +static void InitDodrioGame(struct DodrioGame * game) { u8 i; - data->unk0C = 0; - data->unk10 = 0; - data->unk14 = 0; - data->unk18 = 0; - data->unk1C = 0; - data->unk11C = 0; - data->unk120 = 0; - data->unk30 = 0; - data->unk40 = 0; - data->unk3C = 0; - data->unk12C = 0; - - for (i = 0; i < 4; i++) - { - data->unk98[i] = 0; + game->startState = 0; + game->state = 0; + game->timer = 0; + game->funcId = FUNC_INTRO; + game->prevFuncId = FUNC_INTRO; + game->startGame = FALSE; + game->berriesFalling = FALSE; + game->countdownEndDelay = 0; + game->numGraySquares = 0; + game->unused2 = 0; + game->allReadyToEnd = FALSE; + + for (i = 0; i < ARRAY_COUNT(game->pickStateQueue); i++) + game->pickStateQueue[i] = PICK_NONE; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + game->inputState[i] = INPUTSTATE_NONE; + game->inputDelay[i] = 0; + game->berryResults[i][BERRY_BLUE] = 0; + game->berryResults[i][BERRY_GREEN] = 0; + game->berryResults[i][BERRY_GOLD] = 0; + game->berryResults[i][BERRY_MISSED] = 0; + game->berryResults[i][BERRY_IN_ROW] = 0; + game->playAgainStates[i] = PLAY_AGAIN_NONE; + game->readyToEnd[i] = FALSE; } - for (i = 0; i < 5; i++) - { - data->unkA8[i] = 0; - data->unkB0[i] = 0; - data->unk4A[i][0] = 0; - data->unk4A[i][1] = 0; - data->unk4A[i][2] = 0; - data->unk4A[i][3] = 0; - data->unk4A[i][5] = 0; - data->unk10C[i] = 0; - data->unk130[i] = 0; - } - - for (i = 0; i < 11; i++) + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - data->unkD0[i] = 0; - data->unkDC[i] = 0; - data->unkC4[i] = 0; - data->unkF4[i][0] = 0xFF; - data->unkF4[i][1] = 0xFF; + game->fallTimer[i] = 0; + game->newBerryTimer[i] = 0; + game->berryState[i] = BERRYSTATE_NONE; + game->playersAttemptingPick[i][0] = PLAYER_NONE; + game->playersAttemptingPick[i][1] = PLAYER_NONE; } - data->unk20 = GetMultiplayerId() == 0 ? 1 : 0; - data->unk24 = GetLinkPlayerCount(); - data->unk34[0] = GetMultiplayerId(); - for (i = 1; i < data->unk24; i++) + game->isLeader = GetMultiplayerId() == 0 ? TRUE : FALSE; + game->numPlayers = GetLinkPlayerCount(); + game->posToPlayerId[0] = GetMultiplayerId(); + for (i = 1; i < game->numPlayers; i++) { - data->unk34[i] = data->unk34[i - 1] + 1; - if (data->unk34[i] > data->unk24 - 1) - data->unk34[i] %= data->unk24; + game->posToPlayerId[i] = game->posToPlayerId[i - 1] + 1; + if (game->posToPlayerId[i] > game->numPlayers - 1) + game->posToPlayerId[i] %= game->numPlayers; } } -static void sub_8024BC8(u8 taskId) +static void Task_StartDodrioGame(u8 taskId) { - u8 r4, r5; + u8 i, numPlayers; - switch (gUnknown_02022C98->unk0C) + switch (sGame->startState) { case 0: SetVBlankCallback(NULL); - sub_802620C(sub_8025910, 4); - gUnknown_02022C98->unk0C++; + CreateTask_(Task_CommunicateMonInfo, 4); + sGame->startState++; break; case 1: - if (!FuncIsActiveTask(sub_8025910)) + if (!FuncIsActiveTask(Task_CommunicateMonInfo)) { - sub_8029274(&gUnknown_02022C98->unk160); - gUnknown_02022C98->unk0C++; + InitGameGfx(&sGame->gfx); + sGame->startState++; } break; case 2: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk0C++; + sGame->startState++; } break; case 3: @@ -569,267 +780,261 @@ static void sub_8024BC8(u8 taskId) LoadWirelessStatusIndicatorSpriteGfx(); CreateWirelessStatusIndicatorSprite(0, 0); } - gUnknown_02022C98->unk0C++; + sGame->startState++; } break; case 4: - r5 = gUnknown_02022C98->unk24; - sub_80283A8(); - for (r4 = 0; r4 < r5; r4++) - { - sub_8028408(&gUnknown_02022C98->unk318C[gUnknown_02022C98->unk34[r4]], r4, gUnknown_02022C98->unk34[r4], gUnknown_02022C98->unk24); - } - sub_802868C(FALSE, gUnknown_02022C98->unk24); - gUnknown_02022C98->unk0C++; + numPlayers = sGame->numPlayers; + LoadDodrioGfx(); + for (i = 0; i < numPlayers; i++) + CreateDodrioSprite(&sGame->monInfo[sGame->posToPlayerId[i]], i, sGame->posToPlayerId[i], sGame->numPlayers); + + SetAllDodrioInvisibility(FALSE, sGame->numPlayers); + sGame->startState++; break; case 5: - sub_8028A34(); - sub_8028A88(); - sub_8028D44(); - sub_8028734(); - gUnknown_02022C98->unk0C++; + LoadBerryGfx(); + CreateBerrySprites(); + CreateCloudSprites(); + CreateStatusBarSprites(); + sGame->startState++; break; case 6: BlendPalettes(PALETTES_ALL, 0x10, 0x00); BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); - SetVBlankCallback(sub_80261E4); - gUnknown_02022C98->unk0C++; + SetVBlankCallback(VBlankCB_DodrioGame); + sGame->startState++; break; case 7: UpdatePaletteFade(); if (!gPaletteFade.active) - { - gUnknown_02022C98->unk0C++; - } + sGame->startState++; break; default: DestroyTask(taskId); - sub_802621C(sub_802589C); + CreateDodrioGameTask(Task_NewGameIntro); break; } } -static void sub_8024D4C(u8 taskId) +static void Task_DodrioGame_Leader(u8 taskId) { - sub_8025D04(); - gUnknown_082F7AC4[gUnknown_02022C98->unk18](); - if (!gUnknown_03000DB0) - { - sub_8026AF4(); - } - sub_8025D50(); + RecvLinkData_Leader(); + sLeaderFuncs[sGame->funcId](); + if (!sExitingGame) + UpdateGame_Leader(); + + SendLinkData_Leader(); } -static void sub_8024D84(u8 taskId) +static void Task_DodrioGame_Member(u8 taskId) { - sub_8025E0C(); - gUnknown_082F7AF4[gUnknown_02022C98->unk18](); - if (!gUnknown_03000DB0) - { - sub_8026B28(); - } - sub_8025ED8(); + RecvLinkData_Member(); + sMemberFuncs[sGame->funcId](); + if (!sExitingGame) + UpdateGame_Member(); + + SendLinkData_Member(); } -static void sub_8024DBC(void) +static void DoGameIntro(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - sub_8028504(1); - sub_80292E0(1); - gUnknown_02022C98->unk10++; + StartDodrioIntroAnim(1); + SetGfxFuncById(GFXFUNC_SHOW_NAMES); + sGame->state++; break; case 1: - if (!sub_802A770()) - sub_8026240(1); + if (!IsGfxFuncActive()) + SetGameFunc(FUNC_INIT_COUNTDOWN); break; } } -static void sub_8024E00(void) +static void InitCountdown(void) { - if (gUnknown_02022C98->unk10 == 0) + switch (sGame->state) { - sub_80262C0(); - gUnknown_02022C98->unk10++; - } - else - { - gUnknown_02022C98->unk118 = 1; - sub_8026240(2); + case 0: + InitFirstWaveOfBerries(); + sGame->state++; + break; + default: + sGame->startCountdown = TRUE; + SetGameFunc(FUNC_COUNTDOWN); + break; } } -static void sub_8024E38(void) +static void DoCountdown(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - StartMinigameCountdown(7, 8, 120, 80, 0); - gUnknown_02022C98->unk10++; + StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0); + sGame->state++; break; case 1: Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 2: if (IsLinkTaskFinished()) { - gUnknown_02022C98->unk10++; - gUnknown_02022C98->unk30 = 0; + sGame->state++; + sGame->countdownEndDelay = 0; } break; case 3: if (!IsMinigameCountdownRunning()) - { - gUnknown_02022C98->unk10++; - } + sGame->state++; break; case 4: - if (++gUnknown_02022C98->unk30 > 5) + if (++sGame->countdownEndDelay > 5) { Rfu_SetLinkStandbyCallback(); - gUnknown_02022C98->unk10++; + sGame->state++; } break; case 5: if (IsLinkTaskFinished()) - { - sub_8026240(3); - } + SetGameFunc(FUNC_WAIT_START); break; } } -static void sub_8024F10(void) +static void WaitGameStart(void) { - if (gUnknown_02022C98->unk10 == 0) + switch (sGame->state) { - if (gUnknown_02022C98->unk11C != 0) - { - sub_8026240(4); - } + case 0: + if (sGame->startGame) + SetGameFunc(FUNC_PLAY_GAME); + break; } } -static void sub_8024F38(void) +static void PlayGame_Leader(void) { - if (gUnknown_02022C98->unk10 == 0) + switch (sGame->state) { - if (gUnknown_02022C98->unk40 < 10) + case 0: + if (sGame->numGraySquares < NUM_STATUS_SQUARES) { - if (gUnknown_02022C98->unkA8[0] == 0) + if (sGame->inputState[0] == INPUTSTATE_NONE) { if (JOY_NEW(DPAD_UP)) { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) + if (sGame->players[0].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(2); + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_MIDDLE); } } else if (JOY_NEW(DPAD_RIGHT)) { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) + if (sGame->players[0].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(1); + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_RIGHT); } } else if (JOY_NEW(DPAD_LEFT)) { - if (gUnknown_02022C98->unk31A0[0].unk2C.unk0 == 0) + if (sGame->players[0].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk31A0[0].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(3); + sGame->players[0].comm.ateBerry = FALSE; + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_LEFT); } } else { - gUnknown_02022C98->unk31A0[0].unk2C.unk0 = sub_8027518(0); + sGame->players[0].comm.pickState = UpdatePickStateQueue(PICK_NONE); } } } else { - sub_8026240(11); + SetGameFunc(FUNC_WAIT_END_GAME); } - sub_802671C(); - sub_8025F48(); + UpdateFallingBerries(); + HandleSound_Leader(); + break; } } -static void sub_8024FFC(void) +static void PlayGame_Member(void) { - if (gUnknown_02022C98->unk40 < 10) + if (sGame->numGraySquares < NUM_STATUS_SQUARES) { if (JOY_NEW(DPAD_UP)) { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 2; + sGame->player.comm.pickState = PICK_MIDDLE; } } else if (JOY_NEW(DPAD_RIGHT)) { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 1; + sGame->player.comm.pickState = PICK_RIGHT; } } else if (JOY_NEW(DPAD_LEFT)) { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 3; + sGame->player.comm.pickState = PICK_LEFT; } } else { - gUnknown_02022C98->unk32CC.unk2C.unk0 = 0; + sGame->player.comm.pickState = PICK_NONE; } } else { - sub_8026240(11); + SetGameFunc(FUNC_WAIT_END_GAME); } - sub_8026044(); + HandleSound_Member(); } -static void sub_80250D4(void) +static void WaitEndGame_Leader(void) { u8 i; - sub_802671C(); - sub_8025F48(); - if (sub_8026C50() == 1) + UpdateFallingBerries(); + HandleSound_Leader(); + if (ReadyToEndGame_Leader() == TRUE) { - sub_80272A4(); - sub_8026240(5); + SetMaxBerriesPickedInRow(); + SetGameFunc(FUNC_INIT_RESULTS); } else { - gUnknown_02022C98->unk12C = 1; - for (i = 1; i < gUnknown_02022C98->unk24; i++) + sGame->allReadyToEnd = TRUE; + for (i = 1; i < sGame->numPlayers; i++) { - if (gUnknown_02022C98->unk130[i] != 1) + if (sGame->readyToEnd[i] != TRUE) { - gUnknown_02022C98->unk12C = 0; + sGame->allReadyToEnd = FALSE; break; } } } } -static void sub_8025158(void) +static void WaitEndGame_Member(void) { - sub_8026044(); - if (sub_8026C90() == 1) - sub_8026240(5); + HandleSound_Member(); + if (ReadyToEndGame_Member() == TRUE) + SetGameFunc(FUNC_INIT_RESULTS); } -static bool32 sub_8025170(void) +static bool32 AllLinkBlocksReceived(void) { u8 recvStatus = GetBlockReceivedStatus(); u8 playerFlags = GetLinkPlayerCountAsBitFlags(); @@ -844,317 +1049,306 @@ static bool32 sub_8025170(void) } } -static void sub_8025198(void) +static void InitResults_Leader(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - if (SendBlock(0, gUnknown_02022C98->unk4A, sizeof(gUnknown_02022C98->unk4A))) + if (SendBlock(0, sGame->berryResults, sizeof(sGame->berryResults))) { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; + sGame->playersReceived = 0; + sGame->state++; } break; case 1: if (IsLinkTaskFinished()) { - gUnknown_02022C98->unk10++; + sGame->state++; } break; case 2: - if (sub_8025170()) + if (AllLinkBlocksReceived()) { - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; + sGame->playersReceived = sGame->numPlayers; } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) + if (sGame->playersReceived >= sGame->numPlayers) { - gUnknown_02022C98->unk14++; - gUnknown_02022C98->unk10++; + sGame->timer++; + sGame->state++; } break; default: if (WaitFanfare(TRUE)) { - sub_8026240(6); + SetGameFunc(FUNC_RESULTS); FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); } break; } } -static void sub_8025230(void) +static void InitResults_Member(void) { u8 i; - switch (gUnknown_02022C98->unk10) { + switch (sGame->state) { case 0: - if (SendBlock(0, gUnknown_02022C98->unk4A[gUnknown_02022C98->unk14], - sizeof(gUnknown_02022C98->unk4A))) { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; + if (SendBlock(0, sGame->berryResults[sGame->timer], sizeof(sGame->berryResults))) { + sGame->playersReceived = 0; + sGame->state++; } break; case 1: if (IsLinkTaskFinished()) { - gUnknown_02022C98->unk10++; + sGame->state++; } break; case 2: - if (sub_8025170()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) { - memcpy(gUnknown_02022C98->unk4A, gBlockRecvBuffer, sizeof(gUnknown_02022C98->unk4A)); - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; + if (AllLinkBlocksReceived()) { + for (i = 0; i < sGame->numPlayers; i++) { + memcpy(sGame->berryResults, gBlockRecvBuffer, sizeof(sGame->berryResults)); + sGame->playersReceived = sGame->numPlayers; } } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - gUnknown_02022C98->unk14++; - gUnknown_02022C98->unk10++; + if (sGame->playersReceived >= sGame->numPlayers) { + sGame->timer++; + sGame->state++; } break; default: if (WaitFanfare(TRUE)) { - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk4A[gUnknown_02022C98->multiplayerId][5]; - sub_8026240(6); + sGame->maxBerriesPickedInRow = sGame->berryResults[sGame->multiplayerId][BERRY_IN_ROW]; + SetGameFunc(FUNC_RESULTS); FadeOutAndPlayNewMapMusic(MUS_RG_VICTORY_WILD, 4); } break; } } -static void sub_8025324(void) +static void DoResults(void) { - u8 sp00 = 1; + u8 playAgainState = PLAY_AGAIN_YES; u8 i; - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - sub_802749C(); - sub_80289E8(TRUE); - sub_8028DFC(); - sub_8028EC8(TRUE); - sub_80292E0(2); - gUnknown_02022C98->unk10++; + TryUpdateRecords(); + SetStatusBarInvisibility(TRUE); + ResetCloudPos(); + SetCloudInvisibility(TRUE); + SetGfxFuncById(GFXFUNC_SHOW_RESULTS); + sGame->state++; break; case 1: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { - sub_80292E0(5); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_MSG_COMM_STANDBY); + sGame->state++; } break; case 2: - sp00 = sub_802A794(); - if (SendBlock(0, &sp00, sizeof(sp00))) - { - gUnknown_02022C98->unk10++; - } + playAgainState = GetPlayAgainState(); + if (SendBlock(0, &playAgainState, sizeof(playAgainState))) + sGame->state++; break; case 3: if (IsLinkTaskFinished()) { - gUnknown_02022C98->unk10++; - gUnknown_02022C98->unk08 = 0; + sGame->state++; + sGame->playersReceived = 0; } break; case 4: - if (sub_8025170()) + if (AllLinkBlocksReceived()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) + for (i = 0; i < sGame->numPlayers; i++) { - *(gUnknown_02022C98->unk10C + i) = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; + *(&sGame->playAgainStates[i]) = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; } } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - if (++gUnknown_02022C98->unk14 >= 120) + if (sGame->playersReceived >= sGame->numPlayers) + { + if (++sGame->timer >= 120) { - sub_80292E0(6); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; } } break; default: - if (!sub_802A770()) - { - sub_8026240(7); - } + if (!IsGfxFuncActive()) + SetGameFunc(FUNC_ASK_PLAY_AGAIN); break; } } -static void sub_8025470(void) +static void AskPlayAgain(void) { - u8 sp0; + u8 playAgainState; u8 i; - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - if (sub_8027748() >= 3000) + if (GetHighestScore() >= PRIZE_SCORE) { - sub_80292E0(4); + SetGfxFuncById(GFXFUNC_MSG_SAVING); } - gUnknown_02022C98->unk10++; + sGame->state++; break; case 1: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { - sub_80292E0(3); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_MSG_PLAY_AGAIN); + sGame->state++; } break; case 2: - sub_8028FCC(); - sub_80272E8(); - gUnknown_02022C98->unk10++; + ResetBerryAndStatusBarSprites(); + ResetForPlayAgainPrompt(); + sGame->state++; break; case 3: - if ((sp0 = sub_802A794()) != 0) + if ((playAgainState = GetPlayAgainState()) != PLAY_AGAIN_NONE) { - gUnknown_02022C98->unk10++; + sGame->state++; } break; case 4: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { - sub_80292E0(5); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_MSG_COMM_STANDBY); + sGame->state++; } break; case 5: - sp0 = sub_802A794(); - if (SendBlock(0, &sp0, sizeof(sp0))) + playAgainState = GetPlayAgainState(); + if (SendBlock(0, &playAgainState, sizeof(playAgainState))) { - gUnknown_02022C98->unk08 = 0; - gUnknown_02022C98->unk10++; + sGame->playersReceived = 0; + sGame->state++; } break; case 6: if (IsLinkTaskFinished()) - { - gUnknown_02022C98->unk10++; - } + sGame->state++; break; case 7: - if (sub_8025170()) + if (AllLinkBlocksReceived()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) + for (i = 0; i < sGame->numPlayers; i++) { - *(gUnknown_02022C98->unk10C + i) = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; + *(&sGame->playAgainStates[i]) = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; } } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) { - if (++gUnknown_02022C98->unk14 >= 120) + if (sGame->playersReceived >= sGame->numPlayers) + { + if (++sGame->timer >= 120) { - sub_8027608(); - sub_80292E0(6); - gUnknown_02022C98->unk10++; + ResetPickState(); + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; } } else { - sub_8027554(); + HandleWaitPlayAgainInput(); } break; default: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) + for (i = 0; i < sGame->numPlayers; i++) { - if (gUnknown_02022C98->unk10C[i] == 2) + if (sGame->playAgainStates[i] == PLAY_AGAIN_NO) { - sub_8026240(8); + SetGameFunc(FUNC_END_LINK); return; } } - sub_8026240(10); + SetGameFunc(FUNC_RESET_GAME); } break; } } -static void sub_8025644(void) +static void EndLink(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: SetCloseLinkCallback(); - sub_80292E0(7); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_MSG_PLAYER_DROPPED); + sGame->state++; break; case 1: - if (!sub_802A770()) - { - gUnknown_02022C98->unk10++; - } + if (!IsGfxFuncActive()) + sGame->state++; break; case 2: - if (sub_802A794() == 5) - { - gUnknown_02022C98->unk10++; - } + if (GetPlayAgainState() == PLAY_AGAIN_DROPPED) + sGame->state++; break; default: if (gReceivedRemoteLinkPlayers == 0) { - sub_8026240(9); + SetGameFunc(FUNC_EXIT); } break; } } -static void sub_80256AC(void) +static void ExitGame(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 1: UpdatePaletteFade(); if (!gPaletteFade.active) - { - gUnknown_02022C98->unk10++; - } + sGame->state++; break; case 2: - sub_8028B80(); - sub_80287E4(); - sub_8028614(gUnknown_02022C98->unk24); - sub_8028E84(); - gUnknown_03000DB0 = TRUE; - sub_80292E0(8); - gUnknown_02022C98->unk10++; + FreeBerrySprites(); + FreeStatusBar(); + FreeDodrioSprites(sGame->numPlayers); + FreeCloudSprites(); + sExitingGame = TRUE; + SetGfxFuncById(GFXFUNC_STOP); + sGame->state++; break; default: - if (!sub_802A770()) + if (!IsGfxFuncActive()) { - SetMainCallback2(gUnknown_02022C98->savedCallback); - DestroyTask(gUnknown_02022C98->unk04); - Free(gUnknown_02022C98); + SetMainCallback2(sGame->exitCallback); + DestroyTask(sGame->taskId); + Free(sGame); FreeAllWindowBuffers(); } break; } } -static void sub_8025758(void) +static void ResetGame(void) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - sub_80292E0(9); + SetGfxFuncById(GFXFUNC_IDLE); BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, 0); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 1: UpdatePaletteFade(); if (!gPaletteFade.active) { - gUnknown_02022C98->unk10++; + sGame->state++; } break; case 2: @@ -1166,383 +1360,427 @@ static void sub_8025758(void) ChangeBgY(2, 0, 0); ChangeBgX(3, 0, 0); ChangeBgY(3, 0, 0); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 3: StopMapMusic(); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 4: PlayNewMapMusic(MUS_RG_BERRY_PICK); - sub_8028E4C(); - gUnknown_02022C98->unk10++; + StartCloudMovement(); + sGame->state++; break; case 5: BlendPalettes(PALETTES_ALL, 16, 0); BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, 0); - gUnknown_02022C98->unk10++; + sGame->state++; break; case 6: UpdatePaletteFade(); if (!gPaletteFade.active) - { - gUnknown_02022C98->unk10++; - } + sGame->state++; break; default: - DestroyTask(gUnknown_02022C98->unk04); - sub_802621C(sub_802589C); - sub_802903C(); - sub_8024A30(gUnknown_02022C98); + DestroyTask(sGame->taskId); + CreateDodrioGameTask(Task_NewGameIntro); + ResetGfxState(); + InitDodrioGame(sGame); if (gReceivedRemoteLinkPlayers == 0) - { - gUnknown_02022C98->unk24 = 1; - } - sub_80273F0(); - sub_8028EC8(FALSE); + sGame->numPlayers = 1; + + SetRandomPrize(); + SetCloudInvisibility(FALSE); break; } } -static void sub_802589C(u8 taskId) +static void Task_NewGameIntro(u8 taskId) { - switch (gUnknown_02022C98->unk10) + switch (sGame->state) { case 0: - if (sub_8026264() == 1) - { - gUnknown_02022C98->unk10++; - } + if (SlideTreeBordersOut() == TRUE) + sGame->state++; break; case 1: - sub_80286E4(); - gUnknown_02022C98->unk10++; + InitStatusBarPos(); + sGame->state++; break; case 2: - if (sub_8028828() == TRUE) - { - gUnknown_02022C98->unk10++; - } + if (DoStatusBarIntro() == TRUE) + sGame->state++; break; default: - if (gUnknown_02022C98->unk20 != 0) - { - sub_802621C(sub_8024D4C); - } + if (sGame->isLeader) + CreateDodrioGameTask(Task_DodrioGame_Leader); else - { - sub_802621C(sub_8024D84); - } + CreateDodrioGameTask(Task_DodrioGame_Member); + DestroyTask(taskId); break; } } -static void sub_8025910(u8 taskId) +#define tState data[0] + +static void Task_CommunicateMonInfo(u8 taskId) { s16 * data = gTasks[taskId].data; u8 i; - switch (data[0]) + switch (tState) { case 0: - if (SendBlock(0, &gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId].isShiny, sizeof(gUnknown_02022C98->unk318C[gUnknown_02022C98->multiplayerId].isShiny))) + if (SendBlock(0, &sGame->monInfo[sGame->multiplayerId].isShiny, sizeof(sGame->monInfo[sGame->multiplayerId].isShiny))) { - gUnknown_02022C98->unk08 = 0; - data[0]++; + sGame->playersReceived = 0; + tState++; } break; case 1: if (IsLinkTaskFinished()) - { - data[0]++; - } + tState++; break; case 2: - if (sub_8025170()) + if (AllLinkBlocksReceived()) { - for (i = 0; i < gUnknown_02022C98->unk24; i++) + for (i = 0; i < sGame->numPlayers; i++) { - *(u8 *)&gUnknown_02022C98->unk318C[i] = *(u8 *)gBlockRecvBuffer[i]; - gUnknown_02022C98->unk08 = gUnknown_02022C98->unk24; + *(u8 *)&sGame->monInfo[i] = *(u8 *)gBlockRecvBuffer[i]; + sGame->playersReceived = sGame->numPlayers; } } - if (gUnknown_02022C98->unk08 >= gUnknown_02022C98->unk24) + if (sGame->playersReceived >= sGame->numPlayers) { DestroyTask(taskId); - sub_80292E0(6); - gUnknown_02022C98->unk10++; + SetGfxFuncById(GFXFUNC_ERASE_MSG); + sGame->state++; } break; } } -static void sub_80259FC(void) +#undef tState + +static void RecvLinkData_Gameplay(void) { u8 i; - u8 r7 = gUnknown_02022C98->unk24; - - gUnknown_02022C98->unk31A0[0].unk10 = sub_8028164(0, &gUnknown_02022C98->unk31A0[0], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - gUnknown_02022C98->unk128 = 1; - - for (i = 1; i < r7; i++) - { - if ( gUnknown_02022C98->unkA8[i] == 0 - && sub_8028318(i, &gUnknown_02022C98->unk31A0[i].unk2C.unk0) == 0) + u8 numPlayers = sGame->numPlayers; + + sGame->players[0].receivedGameStatePacket = RecvPacket_GameState(0, + &sGame->players[0], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + sGame->clearRecvCmds = TRUE; + + for (i = 1; i < numPlayers; i++) + { + if (sGame->inputState[i] == INPUTSTATE_NONE && !RecvPacket_PickState(i, &sGame->players[i].comm.pickState)) { - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk128 = 0; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->clearRecvCmds = FALSE; } } - if (++gUnknown_02022C98->unk124 >= 60) + if (++sGame->clearRecvCmdTimer >= 60) { - if (gUnknown_02022C98->unk128 != 0) + if (sGame->clearRecvCmds) { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; } - else if (gUnknown_02022C98->unk124 > 70) + else if (sGame->clearRecvCmdTimer > 70) { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; } } - for (i = 0; i < r7; i++) + for (i = 0; i < numPlayers; i++) { - if ( gUnknown_02022C98->unk31A0[i].unk2C.unk0 != 0 - && gUnknown_02022C98->unkA8[i] == 0) + if (sGame->players[i].comm.pickState != PICK_NONE && sGame->inputState[i] == INPUTSTATE_NONE) { - gUnknown_02022C98->unkA8[i] = 1; + sGame->inputState[i] = INPUTSTATE_TRY_PICK; } - switch (gUnknown_02022C98->unkA8[i]) + switch (sGame->inputState[i]) { - case 0: + case INPUTSTATE_NONE: default: break; - case 1 ... 3: - if (++gUnknown_02022C98->unkB0[i] >= 6) + case INPUTSTATE_TRY_PICK: + case INPUTSTATE_PICKED: + case INPUTSTATE_ATE_BERRY: + if (++sGame->inputDelay[i] >= 6) { - gUnknown_02022C98->unkB0[i] = 0; - gUnknown_02022C98->unkA8[i] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk8 = 0; + sGame->inputDelay[i] = 0; + sGame->inputState[i] = INPUTSTATE_NONE; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->players[i].comm.missedBerry = FALSE; } break; - case 4: - if (++gUnknown_02022C98->unkB0[i] >= 40) + case INPUTSTATE_BAD_MISS: + // Tried to pick with no berry in range, long delay until next input + if (++sGame->inputDelay[i] >= 40) { - gUnknown_02022C98->unkB0[i] = 0; - gUnknown_02022C98->unkA8[i] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk8 = 0; + sGame->inputDelay[i] = 0; + sGame->inputState[i] = INPUTSTATE_NONE; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->players[i].comm.missedBerry = FALSE; } break; } } } -static void sub_8025C0C(void) +static void RecvLinkData_ReadyToEnd(void) { u8 i; - u8 r6 = gUnknown_02022C98->unk24; - - gUnknown_02022C98->unk31A0[0].unk10 = sub_8028164(0, &gUnknown_02022C98->unk31A0[0], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - gUnknown_02022C98->unk128 = 1; - - for (i = 1; i < r6; i++) - { - if (sub_8028374(i) != 0) + u8 numPlayers = sGame->numPlayers; + + sGame->players[0].receivedGameStatePacket = RecvPacket_GameState(0, + &sGame->players[0], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + sGame->clearRecvCmds = TRUE; + + for (i = 1; i < numPlayers; i++) + { + if (RecvPacket_ReadyToEnd(i)) { - gUnknown_02022C98->unk130[i] = 1; - gUnknown_02022C98->unk128 = 0; + sGame->readyToEnd[i] = TRUE; + sGame->clearRecvCmds = FALSE; } } - if (++gUnknown_02022C98->unk124 >= 60) + if (++sGame->clearRecvCmdTimer >= 60) { - if (gUnknown_02022C98->unk128 != 0) + if (sGame->clearRecvCmds) { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; } - else if (gUnknown_02022C98->unk124 > 70) + else if (sGame->clearRecvCmdTimer > 70) { - sub_8011AC8(); - gUnknown_02022C98->unk124 = 0; + ClearRecvCommands(); + sGame->clearRecvCmdTimer = 0; } } } -static void sub_8025D04(void) +static void RecvLinkData_Leader(void) { - switch (gUnknown_02022C98->unk18) + switch (sGame->funcId) { - case 3: - if (sub_8026BB8() == TRUE) + case FUNC_WAIT_START: + if (AllPlayersReadyToStart() == TRUE) { - sub_8026C28(); - gUnknown_02022C98->unk11C = 1; + ResetReadyToStart(); + sGame->startGame = TRUE; } break; - case 4: - sub_80259FC(); + case FUNC_PLAY_GAME: + RecvLinkData_Gameplay(); break; - case 11: - sub_8025C0C(); + case FUNC_WAIT_END_GAME: + RecvLinkData_ReadyToEnd(); break; } } -static void sub_8025D50(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 4: - sub_8027E30(&gUnknown_02022C98->unk32CC, &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, gUnknown_02022C98->unk40, gUnknown_02022C98->unk120, gUnknown_02022C98->unk12C); - break; - case 11: - sub_8027E30(&gUnknown_02022C98->unk32CC, &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, gUnknown_02022C98->unk40, gUnknown_02022C98->unk120, gUnknown_02022C98->unk12C); +static void SendLinkData_Leader(void) +{ + switch (sGame->funcId) + { + case FUNC_PLAY_GAME: + SendPacket_GameState(&sGame->player, + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + sGame->numGraySquares, + sGame->berriesFalling, + sGame->allReadyToEnd); + break; + case FUNC_WAIT_END_GAME: + SendPacket_GameState(&sGame->player, + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + sGame->numGraySquares, + sGame->berriesFalling, + sGame->allReadyToEnd); break; } } -static void sub_8025E0C(void) -{ - switch (gUnknown_02022C98->unk18) - { - case 4: - sub_8028164(gUnknown_02022C98->multiplayerId, &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); - break; - case 11: - sub_8028164(gUnknown_02022C98->multiplayerId, &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId], &gUnknown_02022C98->unk31A0[0].unk2C, &gUnknown_02022C98->unk31A0[1].unk2C, &gUnknown_02022C98->unk31A0[2].unk2C, &gUnknown_02022C98->unk31A0[3].unk2C, &gUnknown_02022C98->unk31A0[4].unk2C, &gUnknown_02022C98->unk40, &gUnknown_02022C98->unk120, &gUnknown_02022C98->unk12C); +static void RecvLinkData_Member(void) +{ + switch (sGame->funcId) + { + case FUNC_PLAY_GAME: + RecvPacket_GameState(sGame->multiplayerId, + &sGame->players[sGame->multiplayerId], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); + break; + case FUNC_WAIT_END_GAME: + RecvPacket_GameState(sGame->multiplayerId, + &sGame->players[sGame->multiplayerId], + &sGame->players[0].comm, + &sGame->players[1].comm, + &sGame->players[2].comm, + &sGame->players[3].comm, + &sGame->players[4].comm, + &sGame->numGraySquares, + &sGame->berriesFalling, + &sGame->allReadyToEnd); break; } } -static void sub_8025ED8(void) +static void SendLinkData_Member(void) { - switch (gUnknown_02022C98->unk18) + switch (sGame->funcId) { - case 3: - sub_8027DD0(1); - gUnknown_02022C98->unk11C = 1; + case FUNC_WAIT_START: + SendPacket_ReadyToStart(TRUE); + sGame->startGame = TRUE; break; - case 4: - if (gUnknown_02022C98->unk32CC.unk2C.unk0 != 0) + case FUNC_PLAY_GAME: + if (sGame->player.comm.pickState != PICK_NONE) { - sub_80282EC(gUnknown_02022C98->unk32CC.unk2C.unk0); + SendPacket_PickState(sGame->player.comm.pickState); } break; - case 11: - if (gUnknown_02022C98->unk120 == 0 && gUnknown_02022C98->unk12C == 0) - { - sub_8028350(1); - } + case FUNC_WAIT_END_GAME: + if (!sGame->berriesFalling && !sGame->allReadyToEnd) + SendPacket_ReadyToEnd(TRUE); break; } } -static void sub_8025F48(void) +static void HandleSound_Leader(void) { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) { if (!IsSEPlaying()) - { - gUnknown_02022C98->unk144 = 0; - } + sGame->playingPickSound = FALSE; } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 == 1) + else if (sGame->players[sGame->multiplayerId].comm.ateBerry == TRUE) { - if (gUnknown_02022C98->unk144 == 0) + if (!sGame->playingPickSound) { m4aSongNumStop(SE_SUCCESS); PlaySE(SE_SUCCESS); - gUnknown_02022C98->unk144 = 1; + sGame->playingPickSound = TRUE; } } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 == 1) + else if (sGame->players[sGame->multiplayerId].comm.missedBerry == TRUE) { - if (gUnknown_02022C98->unk144 == 0 && !IsSEPlaying()) + if (!sGame->playingPickSound && !IsSEPlaying()) { PlaySE(SE_BOO); - sub_80284CC(1); - gUnknown_02022C98->unk144 = 1; + StartDodrioMissedAnim(1); + sGame->playingPickSound = TRUE; } } - if (gUnknown_02022C98->unk154 == 0 && gUnknown_02022C98->unk40 >= 10) + if (sGame->endSoundState == 0 && sGame->numGraySquares >= NUM_STATUS_SQUARES) { + // Ready to play game over sound StopMapMusic(); - gUnknown_02022C98->unk154 = 1; + sGame->endSoundState = 1; } - else if (gUnknown_02022C98->unk154 == 1) + else if (sGame->endSoundState == 1) { - PlayFanfareByFanfareNum(11); // MUS_TOO_BAD - gUnknown_02022C98->unk154 = 2; + // Play game over sound + PlayFanfareByFanfareNum(FANFARE_TOO_BAD); + sGame->endSoundState = 2; } } -static void sub_8026044(void) +static void HandleSound_Member(void) { - u8 r8 = gUnknown_02022C98->unk44; - u8 r7 = gUnknown_02022C98->unk48; - u8 r4; - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 == 0) + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 i; + if (sGame->players[sGame->multiplayerId].comm.pickState == PICK_NONE) { - if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 != 1 && gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 != 1) - { - gUnknown_02022C98->unk144 = 0; - } + if (sGame->players[sGame->multiplayerId].comm.ateBerry != TRUE + && sGame->players[sGame->multiplayerId].comm.missedBerry != TRUE) + sGame->playingPickSound = 0; } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk4 == 1) + else if (sGame->players[sGame->multiplayerId].comm.ateBerry == TRUE) { - if (gUnknown_02022C98->unk144 == 0) + if (!sGame->playingPickSound) { m4aSongNumStop(SE_SUCCESS); PlaySE(SE_SUCCESS); - gUnknown_02022C98->unk144 = 1; + sGame->playingPickSound = TRUE; } } - else if (gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk8 == 1) + else if (sGame->players[sGame->multiplayerId].comm.missedBerry == TRUE) { - if (gUnknown_02022C98->unk144 == 0 && !IsSEPlaying()) + if (!sGame->playingPickSound && !IsSEPlaying()) { PlaySE(SE_BOO); - sub_80284CC(1); - gUnknown_02022C98->unk144 = 1; + StartDodrioMissedAnim(1); + sGame->playingPickSound = TRUE; } } - for (r4 = r8; r4 < r7; r4++) + for (i = berryStart; i < berryEnd; i++) { - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk14; - if (ptr->unkB[r4] >= 10) + struct DodrioGame_Berries * berries = &sGame->players[sGame->multiplayerId].berries; + if (berries->fallDist[i] >= MAX_FALL_DIST) { - if (gUnknown_02022C98->unk148[r4] == 0) + if (!sGame->playingSquishSound[i]) { - PlaySE(SE_BALLOON_RED + ptr->unk0[r4]); - gUnknown_02022C98->unk148[r4] = 1; + PlaySE(SE_BALLOON_RED + berries->ids[i]); + sGame->playingSquishSound[i] = TRUE; } } else { - gUnknown_02022C98->unk148[r4] = 0; + sGame->playingSquishSound[i] = FALSE; } } - if (gUnknown_02022C98->unk154 == 0 && gUnknown_02022C98->unk40 >= 10) + if (sGame->endSoundState == 0 && sGame->numGraySquares >= NUM_STATUS_SQUARES) { + // Ready to play game over sound StopMapMusic(); - gUnknown_02022C98->unk154 = 1; + sGame->endSoundState = 1; } - else if (gUnknown_02022C98->unk154 == 1) + else if (sGame->endSoundState == 1) { - PlayFanfareByFanfareNum(11); // MUS_TOO_BAD - gUnknown_02022C98->unk154 = 2; + // Play game over sound + PlayFanfareByFanfareNum(FANFARE_TOO_BAD); + sGame->endSoundState = 2; } } -static void sub_80261CC(void) +static void CB2_DodrioGame(void) { RunTasks(); AnimateSprites(); @@ -1550,53 +1788,55 @@ static void sub_80261CC(void) UpdatePaletteFade(); } -static void sub_80261E4(void) +static void VBlankCB_DodrioGame(void) { TransferPlttBuffer(); LoadOam(); ProcessSpriteCopyRequests(); } -static void sub_80261F8(struct DodrioSubstruct_318C * a0, struct Pokemon * a1) +static void InitMonInfo(struct DodrioGame_MonInfo * monInfo, struct Pokemon * mon) { - a0->isShiny = IsMonShiny(a1); + monInfo->isShiny = IsMonShiny(mon); } -static void sub_802620C(TaskFunc func, u8 priority) +static void CreateTask_(TaskFunc func, u8 priority) { CreateTask(func, priority); } -static void sub_802621C(TaskFunc func) +static void CreateDodrioGameTask(TaskFunc func) { - gUnknown_02022C98->unk04 = CreateTask(func, 1); - gUnknown_02022C98->unk10 = 0; - gUnknown_02022C98->unk0C = 0; - gUnknown_02022C98->unk14 = 0; + sGame->taskId = CreateTask(func, 1); + sGame->state = 0; + sGame->startState = 0; + sGame->timer = 0; } -static void sub_8026240(u8 a0) +static void SetGameFunc(u8 funcId) { - gUnknown_02022C98->unk1C = gUnknown_02022C98->unk18; - gUnknown_02022C98->unk18 = a0; - gUnknown_02022C98->unk10 = 0; - gUnknown_02022C98->unk14 = 0; + sGame->prevFuncId = sGame->funcId; + sGame->funcId = funcId; + sGame->state = 0; + sGame->timer = 0; } -static bool32 sub_8026264(void) +static bool32 SlideTreeBordersOut(void) { - u8 r2 = gUnknown_02022C98->unk14 / 4; - gUnknown_02022C98->unk14++; - if (r2 != 0 && gUnknown_02022C98->unk14 % 4 == 0) + u8 x = sGame->timer / 4; + sGame->timer++; + if (x != 0 && sGame->timer % 4 == 0) { - if (r2 < gUnknown_082F7A94[gUnknown_02022C98->unk24 - 1]) + if (x < sTreeBorderXPos[sGame->numPlayers - 1]) { - SetGpuReg(REG_OFFSET_BG1HOFS, (r2 * 8)); - SetGpuReg(REG_OFFSET_BG2HOFS, -(r2 * 8)); + // Update position + SetGpuReg(REG_OFFSET_BG1HOFS, (x * 8)); // BG_TREE_LEFT + SetGpuReg(REG_OFFSET_BG2HOFS, -(x * 8)); // BG_TREE_RIGHT return FALSE; } else { + // Animation finished return TRUE; } } @@ -1606,413 +1846,452 @@ static bool32 sub_8026264(void) } } -static void sub_80262C0(void) +static void InitFirstWaveOfBerries(void) { u8 i; - u8 start = gUnknown_02022C98->unk44; - u8 finish = gUnknown_02022C98->unk48; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; - for (i = start; i < finish; i++) + for (i = berryStart; i < berryEnd; i++) { - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk32CC.unk14; - ptr->unkB[i] = (i % 2 == 0) ? 1 : 0; - ptr->unk0[i] = 0; + struct DodrioGame_Berries * berries = &sGame->player.berries; + berries->fallDist[i] = (i % 2 == 0) ? 1 : 0; + berries->ids[i] = BERRY_BLUE; } } -static void sub_8026324(void) +// This function checks every berry and resolves if it should be eaten or not. +// It's run in a loop that handles moving each individual berry, which means +// that every time any berry moves, every single berry is checked. +static void HandlePickBerries(void) { - u8 sp0 = gUnknown_02022C98->unk44; - u8 sp4 = gUnknown_02022C98->unk48; - u8 sp8 = gUnknown_02022C98->unk24; - u8 i, j, k, r5; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 numPlayers = sGame->numPlayers; + u8 i, j, k, column; - if (gUnknown_02022C98->unk40 >= 10) + // Game is already over + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) return; - for (i = 0; i < sp8; i++) + for (i = 0; i < numPlayers; i++) { - u8 *ptr = &gUnknown_02022C98->unk31A0[i].unk2C.unk0; - if (*ptr != 0 && gUnknown_02022C98->unkA8[i] == 1) + u8 *pickState = &sGame->players[i].comm.pickState; + if (*pickState != PICK_NONE && sGame->inputState[i] == INPUTSTATE_TRY_PICK) { - for (j = sp0; j < sp4; j++) + // Player is attempting to pick a berry + for (j = berryStart; j < berryEnd; j++) { - r5 = gUnknown_082F449C[0][0][j]; - if (gUnknown_02022C98->unkF4[r5][0] == i || gUnknown_02022C98->unkF4[r5][1] == i) + column = sActiveColumnMap[0][0][j]; + + // Attempt has already been checked + if (sGame->playersAttemptingPick[column][0] == i + || sGame->playersAttemptingPick[column][1] == i) break; - if (sub_8026634(i, *ptr, r5) == TRUE) + + // Check berry pick attempt + if (TryPickBerry(i, *pickState, column) == TRUE) { - for (k = 0; k < 2; k++) + // Attempt was successful + for (k = 0; k < ARRAY_COUNT(sGame->playersAttemptingPick[0]); k++) { - if (gUnknown_02022C98->unkF4[r5][k] == 0xFF) + if (sGame->playersAttemptingPick[column][k] == PLAYER_NONE) { - gUnknown_02022C98->unkF4[r5][k] = i; - gUnknown_02022C98->unkA8[i] = 2; - gUnknown_02022C98->unkC4[r5] = 1; + sGame->playersAttemptingPick[column][k] = i; + sGame->inputState[i] = INPUTSTATE_PICKED; + sGame->berryState[column] = BERRYSTATE_PICKED; break; } } break; } - if (gUnknown_02022C98->unk31A0[i].unk2C.unk8 == 1) + if (sGame->players[i].comm.missedBerry == TRUE) break; } } } - for (j = sp0; j < sp4; j++) + for (j = berryStart; j < berryEnd; j++) { - u8 id = 0xFF; - r5 = gUnknown_082F449C[0][0][j]; - if (gUnknown_02022C98->unkC4[r5] == 1) + u8 playerIdMissed = PLAYER_NONE; + column = sActiveColumnMap[0][0][j]; + if (sGame->berryState[column] == BERRYSTATE_PICKED) { - s32 r2; - u8 r4, r3 = gUnknown_02022C98->unk90[sub_8026D8C(r5)] / 7; - if (r3 >= ARRAY_COUNT(gUnknown_082F7A88) - 1) - r3 = ARRAY_COUNT(gUnknown_082F7A88) - 1; + s32 delayRemaining; + u8 playerIdPicked, delayStage = sGame->difficulty[GetPlayerIdAtColumn(column)] / NUM_DIFFICULTIES; + if (delayStage >= ARRAY_COUNT(sBerryFallDelays) - 1) + delayStage = ARRAY_COUNT(sBerryFallDelays) - 1; - r2 = gUnknown_082F7A88[r3][gUnknown_02022C98->unk31A0[0].unk14.unk0[r5]] - gUnknown_02022C98->unkD0[r5]; - if (r2 < 6) - gUnknown_02022C98->unk9C[r5] += r2; + delayRemaining = sBerryFallDelays[delayStage][sGame->players[0].berries.ids[column]] - sGame->fallTimer[column]; + if (delayRemaining < 6) + sGame->eatTimer[column] += delayRemaining; - if (++gUnknown_02022C98->unk9C[r5] >= 6) + if (++sGame->eatTimer[column] >= 6) { - gUnknown_02022C98->unk9C[r5] = 0; - if (gUnknown_02022C98->unkF4[r5][0] == 0xFF && gUnknown_02022C98->unkF4[r5][1] == 0xFF) + sGame->eatTimer[column] = 0; + + if (sGame->playersAttemptingPick[column][0] == PLAYER_NONE + && sGame->playersAttemptingPick[column][1] == PLAYER_NONE) { + // No players attempting to pick this berry continue; } - else if (gUnknown_02022C98->unkF4[r5][0] != 0xFF && gUnknown_02022C98->unkF4[r5][1] == 0xFF) + else if (sGame->playersAttemptingPick[column][0] != PLAYER_NONE + && sGame->playersAttemptingPick[column][1] == PLAYER_NONE) { - r4 = gUnknown_02022C98->unkF4[r5][0]; + // One player attempting to pick this berry + playerIdPicked = sGame->playersAttemptingPick[column][0]; } else { - u8 unk0 = gUnknown_02022C98->unkF4[r5][0]; - i = gUnknown_02022C98->unkF4[r5][1]; // Have to re-use the variable to match. + // Two players attempting to pick this berry + // Randomly give it to one of them + u8 playerId1 = sGame->playersAttemptingPick[column][0]; + i = sGame->playersAttemptingPick[column][1]; // playerId2. Have to re-use the variable to match. if (!(Random() & 1)) { - r4 = unk0; - id = i; + playerIdPicked = playerId1; + playerIdMissed = i; } else { - r4 = i; - id = unk0; + playerIdPicked = i; + playerIdMissed = playerId1; } } - gUnknown_02022C98->unk32CC.unk14.unkB[r5] = 7; - gUnknown_02022C98->unkC4[r5] = 2; - gUnknown_02022C98->unkA8[r4] = 3; - gUnknown_02022C98->unkB8[r5] = r4; - gUnknown_02022C98->unk31A0[r4].unk2C.unk4 = 1; - gUnknown_02022C98->unk31A0[id].unk2C.unk8 = 1; - gUnknown_02022C98->unk86[r4]++; - sub_8026F1C(0, r5, r4); - sub_8027234(TRUE); - sub_8026D1C(r4); - gUnknown_02022C98->unkE8[r5] = gUnknown_02022C98->unk32CC.unk14.unk0[r5]; - gUnknown_02022C98->unk32CC.unk14.unk0[r5] = 3; - gUnknown_02022C98->unkF4[r5][0] = 0xFF; - gUnknown_02022C98->unkF4[r5][1] = 0xFF; + + // Eat berry + sGame->player.berries.fallDist[column] = EAT_FALL_DIST; + sGame->berryState[column] = BERRYSTATE_EATEN; + sGame->inputState[playerIdPicked] = INPUTSTATE_ATE_BERRY; + sGame->berryEatenBy[column] = playerIdPicked; + sGame->players[playerIdPicked].comm.ateBerry = TRUE; +#ifdef UBFIX + if (playerIdMissed != PLAYER_NONE) +#endif + sGame->players[playerIdMissed].comm.missedBerry = TRUE; // UB: playerIdMissed can be PLAYER_NONE here, which is out of bounds + + sGame->berriesEaten[playerIdPicked]++; + IncrementBerryResult(0, column, playerIdPicked); + UpdateBerriesPickedInRow(TRUE); + TryIncrementDifficulty(playerIdPicked); + sGame->prevBerryIds[column] = sGame->player.berries.ids[column]; + sGame->player.berries.ids[column] = BERRY_MISSED; // Just to clear berry id, wasn't actually missed + sGame->playersAttemptingPick[column][0] = PLAYER_NONE; + sGame->playersAttemptingPick[column][1] = PLAYER_NONE; } } } } -static bool32 sub_8026634(u8 a0, u8 a1, u8 a2) +static bool32 TryPickBerry(u8 playerId, u8 pickState, u8 column) { - s32 r7 = 0; - u8 r5 = gUnknown_02022C98->unk24 - 1; - struct DodrioSubstruct_31A0_14 * ptr = &gUnknown_02022C98->unk32CC.unk14; + s32 pick = 0; + u8 numPlayersIdx = sGame->numPlayers - 1; + struct DodrioGame_Berries * berries = &sGame->player.berries; - switch (a1) + switch (pickState) { - case 3: + case PICK_LEFT: default: - r7 = 0; + pick = 0; break; - case 2: - r7 = 1; + case PICK_MIDDLE: + pick = 1; break; - case 1: - r7 = 2; + case PICK_RIGHT: + pick = 2; break; } - if (ptr->unkB[a2] == 6 || ptr->unkB[a2] == 7) + + // Check if berry is within range to be picked + if (berries->fallDist[column] == EAT_FALL_DIST - 1 || berries->fallDist[column] == EAT_FALL_DIST) { - if (a2 == gUknnown_082F45AF[r5][a0][r7]) + // Check if this berry is the one the player is trying to pick + if (column == sDodrioHeadToColumnMap[numPlayersIdx][playerId][pick]) { - if (gUnknown_02022C98->unkC4[a2] == 1 || gUnknown_02022C98->unkC4[a2] == 2) + // Check if berry has been picked/eaten by another player + if (sGame->berryState[column] == BERRYSTATE_PICKED || sGame->berryState[column] == BERRYSTATE_EATEN) { - gUnknown_02022C98->unk31A0[a0].unk2C.unk8 = 1; + // Missed berry, picked by someone else + sGame->players[playerId].comm.missedBerry = TRUE; return FALSE; } else { + // Successfully picked berry return TRUE; } } } else { - if (a2 == gUknnown_082F45AF[r5][a0][r7]) + // Check if this berry is the one the player is trying to pick + if (column == sDodrioHeadToColumnMap[numPlayersIdx][playerId][pick]) { - gUnknown_02022C98->unkA8[a0] = 4; - gUnknown_02022C98->unk31A0[a0].unk2C.unk8 = 1; + // Missed berry, out of range + sGame->inputState[playerId] = INPUTSTATE_BAD_MISS; + sGame->players[playerId].comm.missedBerry = TRUE; } } return FALSE; } -static void sub_802671C(void) +static void UpdateFallingBerries(void) { - u8 r1 = gUnknown_02022C98->unk44; - u8 r9 = gUnknown_02022C98->unk48; - u8 r3 = 0; - u8 r10 = 0; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; + u8 delayStage = 0; + u8 otherBerryMissed = 0; u8 i; - u8 r2; - struct DodrioStruct *ptr; - gUnknown_02022C98->unk120 = 0; + sGame->berriesFalling = FALSE; - for (i = r1; i < r9 - 1; i++) + for (i = berryStart; i < berryEnd - 1; i++) { - ptr = gUnknown_02022C98; + struct DodrioGame *game = sGame; - if (gUnknown_02022C98->unkC4[i] == 0 || gUnknown_02022C98->unkC4[i] == 1) + if (sGame->berryState[i] == BERRYSTATE_NONE || sGame->berryState[i] == BERRYSTATE_PICKED) { - gUnknown_02022C98->unk120 = 1; - if (ptr->unk32CC.unk14.unkB[i] >= 10) + sGame->berriesFalling = TRUE; + + if (game->player.berries.fallDist[i] >= MAX_FALL_DIST) { - ptr->unk32CC.unk14.unkB[i] = 10; - gUnknown_02022C98->unkC4[i] = 3; - if (gUnknown_02022C98->unk148[i] == 0) + // Berry hit the ground + game->player.berries.fallDist[i] = MAX_FALL_DIST; + sGame->berryState[i] = BERRYSTATE_SQUISHED; + if (!sGame->playingSquishSound[i]) { - gUnknown_02022C98->unk148[i] = 1; - PlaySE(SE_BALLOON_RED + ptr->unk32CC.unk14.unk0[i]); + sGame->playingSquishSound[i] = TRUE; + PlaySE(SE_BALLOON_RED + game->player.berries.ids[i]); } - if (gUnknown_02022C98->unk40 < 10 || r10 == 1) + if (sGame->numGraySquares < NUM_STATUS_SQUARES || otherBerryMissed == TRUE) { - r10 = 1; - gUnknown_02022C98->unk148[i] = 0; - if (gUnknown_02022C98->unk40 < 10) - { - gUnknown_02022C98->unk40++; - } - sub_8026F1C(3, i, 0); - sub_8027234(FALSE); + otherBerryMissed = TRUE; + sGame->playingSquishSound[i] = FALSE; + if (sGame->numGraySquares < NUM_STATUS_SQUARES) + sGame->numGraySquares++; + + IncrementBerryResult(BERRY_MISSED, i, 0); + UpdateBerriesPickedInRow(FALSE); } } else { - r3 = gUnknown_02022C98->unk90[sub_8026D8C(i)] / 7; - if (r3 >= 2) - { - r3 = 2; - } - r2 = gUnknown_082F7A88[r3][ptr->unk32CC.unk14.unk0[i]]; - if (++gUnknown_02022C98->unkD0[i] >= r2) + // Berry is still falling + u8 delay; + delayStage = sGame->difficulty[GetPlayerIdAtColumn(i)] / NUM_DIFFICULTIES; + if (delayStage >= ARRAY_COUNT(sBerryFallDelays) - 1) + delayStage = ARRAY_COUNT(sBerryFallDelays) - 1; + + delay = sBerryFallDelays[delayStage][game->player.berries.ids[i]]; + if (++sGame->fallTimer[i] >= delay) { - ptr->unk32CC.unk14.unkB[i]++; - gUnknown_02022C98->unkD0[i] = 0; + game->player.berries.fallDist[i]++; + sGame->fallTimer[i] = 0; } - sub_8026324(); + HandlePickBerries(); } } - else if (gUnknown_02022C98->unkC4[i] == 2) + else if (sGame->berryState[i] == BERRYSTATE_EATEN) { - gUnknown_02022C98->unk120 = 1; - if (++gUnknown_02022C98->unkDC[i] >= 20) + // Berry has been eaten, wait and create a new berry + sGame->berriesFalling = TRUE; + if (++sGame->newBerryTimer[i] >= 20) { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->unkB8[i]].unk2C.unk4 = 0; - gUnknown_02022C98->unkDC[i] = 0; - gUnknown_02022C98->unkD0[i] = 0; - gUnknown_02022C98->unkC4[i] = 0; - ptr->unk32CC.unk14.unkB[i] = 1; - ptr->unk32CC.unk14.unk0[i] = sub_8026DB0(sub_8026D8C(i), i); + sGame->players[sGame->berryEatenBy[i]].comm.ateBerry = FALSE; + sGame->newBerryTimer[i] = 0; + sGame->fallTimer[i] = 0; + sGame->berryState[i] = BERRYSTATE_NONE; + game->player.berries.fallDist[i] = 1; + game->player.berries.ids[i] = GetNewBerryId(GetPlayerIdAtColumn(i), i); } } - else if (gUnknown_02022C98->unkC4[i] == 3) + else if (sGame->berryState[i] == BERRYSTATE_SQUISHED) { - if (++gUnknown_02022C98->unkDC[i] >= 20) + // Berry has already hit the ground, wait and create a new berry + if (++sGame->newBerryTimer[i] >= 20) { - if (gUnknown_02022C98->unk40 < 10) + if (sGame->numGraySquares < NUM_STATUS_SQUARES) { - gUnknown_02022C98->unkDC[i] = 0; - gUnknown_02022C98->unkD0[i] = 0; - gUnknown_02022C98->unkC4[i] = 0; - ptr->unk32CC.unk14.unkB[i] = 1; - gUnknown_02022C98->unkE8[i] = ptr->unk32CC.unk14.unk0[i]; - ptr->unk32CC.unk14.unk0[i] = sub_8026DB0(sub_8026D8C(i), i); + sGame->newBerryTimer[i] = 0; + sGame->fallTimer[i] = 0; + sGame->berryState[i] = BERRYSTATE_NONE; + game->player.berries.fallDist[i] = 1; + sGame->prevBerryIds[i] = game->player.berries.ids[i]; + game->player.berries.ids[i] = GetNewBerryId(GetPlayerIdAtColumn(i), i); } } } } } -static void sub_8026988(void) +static void UpdateBerrySprites(void) { - u8 i, first, count; + u8 i; + u8 berryStart = sGame->berryColStart; + u8 berryEnd = sGame->berryColEnd; - first = gUnknown_02022C98->unk44; - count = gUnknown_02022C98->unk48; - for (i = first; i < count; i++) + for (i = berryStart; i < berryEnd; i++) { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - u8 var = gUnknown_082F449C[gUnknown_02022C98->unk24 - 1][gUnknown_02022C98->multiplayerId][i]; + struct DodrioGame_Player *player = &sGame->players[sGame->multiplayerId]; + u8 column = sActiveColumnMap[sGame->numPlayers - 1][sGame->multiplayerId][i]; - if (ptr->unk14.unkB[var] != 0) - sub_8028BF8(i, FALSE); + if (player->berries.fallDist[column] != 0) + SetBerryInvisibility(i, FALSE); else - sub_8028BF8(i, TRUE); + SetBerryInvisibility(i, TRUE); - if (ptr->unk14.unkB[var] > 9) + if (player->berries.fallDist[column] >= MAX_FALL_DIST) { - sub_8028CA4(i, ptr->unk14.unk0[var] + 3); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2 - 1); + // Berry was missed, set squished anim + SetBerryAnim(i, player->berries.ids[column] + BERRY_MISSED); + SetBerryYPos(i, player->berries.fallDist[column] * 2 - 1); } - else if (ptr->unk14.unk0[var] == 3) + else if (player->berries.ids[column] == 3) { - ptr->unk14.unkB[var] = 7; - sub_8028CA4(i, 6); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2 - 1); + // Berry was picked, set eaten anim + player->berries.fallDist[column] = EAT_FALL_DIST; + SetBerryAnim(i, ANIM_EATEN); + SetBerryYPos(i, player->berries.fallDist[column] * 2 - 1); } else { - sub_8028CA4(i, ptr->unk14.unk0[var]); - sub_8028C7C(i, ptr->unk14.unkB[var] * 2); + // Berry is still falling + SetBerryAnim(i, player->berries.ids[column]); + SetBerryYPos(i, player->berries.fallDist[column] * 2); } } } -static void sub_8026A88(void) +static void UpdateAllDodrioAnims(void) { - u8 i, count; + u8 i, numPlayers; - count = gUnknown_02022C98->unk24; - for (i = 0; i < count; i++) + numPlayers = sGame->numPlayers; + for (i = 0; i < numPlayers; i++) { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[i]; - sub_80286B4(i, ptr->unk2C.unk0); + struct DodrioGame_Player *player = &sGame->players[i]; + SetDodrioAnim(i, player->comm.pickState); } } -static void sub_8026AC8(void) +static void SetAllDodrioDisabled(void) { - u8 i, count; + u8 i, numPlayers; - count = gUnknown_02022C98->unk24; - for (i = 0; i < count; i++) - sub_80286B4(i, 4); + numPlayers = sGame->numPlayers; + for (i = 0; i < numPlayers; i++) + SetDodrioAnim(i, PICK_DISABLED); } -static void sub_8026AF4(void) +static void UpdateGame_Leader(void) { - sub_8026988(); - if (gUnknown_02022C98->unk40 > 9) - sub_8026AC8(); + UpdateBerrySprites(); + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + SetAllDodrioDisabled(); else - sub_8026A88(); + UpdateAllDodrioAnims(); - sub_80288D4(gUnknown_02022C98->unk40); + UpdateStatusBarAnim(sGame->numGraySquares); } -// This function is literally the same as the one above...Why? -static void sub_8026B28(void) +// Identical to UpdateGame_Leader +static void UpdateGame_Member(void) { - sub_8026988(); - if (gUnknown_02022C98->unk40 > 9) - sub_8026AC8(); + UpdateBerrySprites(); + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) + SetAllDodrioDisabled(); else - sub_8026A88(); + UpdateAllDodrioAnims(); - sub_80288D4(gUnknown_02022C98->unk40); + UpdateStatusBarAnim(sGame->numGraySquares); } -static void sub_8026B5C(u8 arg0, u8 *arg1, u8 *arg2) +static void GetActiveBerryColumns(u8 numPlayers, u8 *start, u8 *end) { - switch (arg0) + switch (numPlayers) { case 1: - *arg1 = 4, *arg2 = 7; + *start = 4, *end = 7; break; case 2: - *arg1 = 3, *arg2 = 8; + *start = 3, *end = 8; break; case 3: - *arg1 = 2, *arg2 = 9; + *start = 2, *end = 9; break; case 4: - *arg1 = 1, *arg2 = 10; + *start = 1, *end = 10; break; case 5: - *arg1 = 0, *arg2 = 11; + *start = 0, *end = 11; break; } } -static bool32 sub_8026BB8(void) +static bool32 AllPlayersReadyToStart(void) { - u8 i, count; + u8 i, numPlayers; - count = gUnknown_02022C98->unk24; - for (i = 1; i < count; i++) + numPlayers = sGame->numPlayers; + for (i = 1; i < numPlayers; i++) { - if (gUnknown_02022C98->unk158[i] == 0) - gUnknown_02022C98->unk158[i] = sub_8027DFC(i); + if (sGame->readyToStart[i] == FALSE) + sGame->readyToStart[i] = RecvPacket_ReadyToStart(i); } - // This loop won't ever run, the seemingly poitnless assingment below is to make the compiler - // generate code for it. - count = count; - for (; i < count; i++) + numPlayers = numPlayers; // Needed to force compiler to keep loop below + +#ifdef BUGFIX + i = 1; // i isn't reset, loop below never runs. As a result, game can begin before all players ready +#endif + for (; i < numPlayers; i++) { - if (gUnknown_02022C98->unk158[i] == 0) + if (sGame->readyToStart[i] == FALSE) return FALSE; } return TRUE; } -static void sub_8026C28(void) +static void ResetReadyToStart(void) { u8 i; - for (i = 0; i < 5; i++) - gUnknown_02022C98->unk158[i] = 0; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + sGame->readyToStart[i] = FALSE; } -static bool32 sub_8026C50(void) +static bool32 ReadyToEndGame_Leader(void) { - if (gUnknown_02022C98->unk40 > 9 && gUnknown_02022C98->unk120 == 0) + if (sGame->numGraySquares >= NUM_STATUS_SQUARES && !sGame->berriesFalling) { - gUnknown_02022C98->unk40 = 10; - if (gUnknown_02022C98->unk12C != 0) + sGame->numGraySquares = NUM_STATUS_SQUARES; + if (sGame->allReadyToEnd) return TRUE; } return FALSE; } -static bool32 sub_8026C90(void) +static bool32 ReadyToEndGame_Member(void) { - u8 i, first, count; + u8 i, berryStart, berryEnd; - if (gUnknown_02022C98->unk40 > 9) + if (sGame->numGraySquares >= NUM_STATUS_SQUARES) { - first = gUnknown_02022C98->unk44; - count = gUnknown_02022C98->unk48; - gUnknown_02022C98->unk40 = 10; - if (gUnknown_02022C98->unk12C != 0) + berryStart = sGame->berryColStart; + berryEnd = sGame->berryColEnd; + sGame->numGraySquares = NUM_STATUS_SQUARES; + if (sGame->allReadyToEnd) { - for (i = first; i < count; i++) + for (i = berryStart; i < berryEnd; i++) { - struct DodrioSubstruct_31A0 *ptr = &gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId]; - u8 var = gUnknown_082F449C[gUnknown_02022C98->unk24 - 1][gUnknown_02022C98->multiplayerId][i]; + struct DodrioGame_Player *player = &sGame->players[sGame->multiplayerId]; + u8 column = sActiveColumnMap[sGame->numPlayers - 1][sGame->multiplayerId][i]; - if (ptr->unk14.unkB[var] != 10) + if (player->berries.fallDist[column] != MAX_FALL_DIST) return FALSE; } return TRUE; @@ -2022,222 +2301,230 @@ static bool32 sub_8026C90(void) return FALSE; } -static void sub_8026D1C(u8 arg0) +static void TryIncrementDifficulty(u8 playerId) { - u8 var = gUnknown_082F7A9C[gUnknown_02022C98->unk90[arg0] % 7] + (gUnknown_02022C98->unk90[arg0] / 7) * 100; - if (gUnknown_02022C98->unk86[arg0] >= var) - gUnknown_02022C98->unk90[arg0]++; + u8 threshold = sDifficultyThresholds[sGame->difficulty[playerId] % NUM_DIFFICULTIES] + (sGame->difficulty[playerId] / NUM_DIFFICULTIES) * 100; + if (sGame->berriesEaten[playerId] >= threshold) + sGame->difficulty[playerId]++; } -static u8 sub_8026D8C(u8 arg0) +static u8 GetPlayerIdAtColumn(u8 column) { - return gUnknown_082F4648[gUnknown_02022C98->unk24 - 1][arg0]; + return sPlayerIdAtColumn[sGame->numPlayers - 1][column]; } -static u8 sub_8026DB0(u8 arg0, u8 arg1) +// Get a berry id for when a new falling berry is created. +// What type of berry it is depends on the current difficulty +// level of players who can pick berries from that column. +static u8 GetNewBerryId(u8 playerId, u8 column) { - u8 i, var3; - u8 count = gUnknown_02022C98->unk24 - 1; - u8 var0 = gUnknown_082F45FA[count][arg0][0]; - u8 var1 = gUnknown_082F45FA[count][arg0][1]; - u8 var2 = gUnknown_082F45FA[count][arg0][2]; + u8 i, highestDifficulty; + u8 numPlayersIdx = sGame->numPlayers - 1; + u8 leftPlayer = sDodrioNeighborMap[numPlayersIdx][playerId][0]; + u8 middlePlayer = sDodrioNeighborMap[numPlayersIdx][playerId][1]; + u8 rightPlayer = sDodrioNeighborMap[numPlayersIdx][playerId][2]; - for (i = 0; gUnknown_082F467F[count][i] != 0; i++) + for (i = 0; sUnsharedColumns[numPlayersIdx][i] != 0; i++) { - if (arg1 == gUnknown_082F467F[count][i]) - return sub_8026E70(gUnknown_02022C98->unk90[var1], arg1); + // If only one player can use this column, just use their difficulty + if (column == sUnsharedColumns[numPlayersIdx][i]) + return GetNewBerryIdByDifficulty(sGame->difficulty[middlePlayer], column); } - // Gets the highest of the three. - if (gUnknown_02022C98->unk90[var0] > gUnknown_02022C98->unk90[var1]) - var3 = gUnknown_02022C98->unk90[var0]; + // This column is shared, get the highest difficulty of adjacent players + if (sGame->difficulty[leftPlayer] > sGame->difficulty[middlePlayer]) + highestDifficulty = sGame->difficulty[leftPlayer]; else - var3 = gUnknown_02022C98->unk90[var1]; + highestDifficulty = sGame->difficulty[middlePlayer]; - if (gUnknown_02022C98->unk90[var2] > var3) - var3 = gUnknown_02022C98->unk90[var2]; + if (sGame->difficulty[rightPlayer] > highestDifficulty) + highestDifficulty = sGame->difficulty[rightPlayer]; - return sub_8026E70(var3, arg1); + return GetNewBerryIdByDifficulty(highestDifficulty, column); } -static u8 sub_8026E70(u8 arg0, u8 arg1) +// The berry types cycle through different distributions depending on the difficulty +static u8 GetNewBerryIdByDifficulty(u8 difficulty, u8 column) { - u8 var = gUnknown_02022C98->unkE8[arg1]; - switch (arg0 % 7) + u8 prevBerryId = sGame->prevBerryIds[column]; + switch (difficulty % NUM_DIFFICULTIES) { - default: return 0; - case 0: return 0; - case 1: return 1; - case 2: return 2; + default: return BERRY_BLUE; + case 0: return BERRY_BLUE; + case 1: return BERRY_GREEN; + case 2: return BERRY_GOLD; case 3: - if (var == 0) - return 1; + if (prevBerryId == BERRY_BLUE) + return BERRY_GREEN; else - return 0; + return BERRY_BLUE; case 4: - if (var == 0) - return 2; + if (prevBerryId == BERRY_BLUE) + return BERRY_GOLD; else - return 0; + return BERRY_BLUE; case 5: - if (var == 2) - return 1; + if (prevBerryId == BERRY_GOLD) + return BERRY_GREEN; else - return 2; + return BERRY_GOLD; case 6: - if (var == 0) - return 1; - else if (var == 1) - return 2; + if (prevBerryId == BERRY_BLUE) + return BERRY_GREEN; + else if (prevBerryId == BERRY_GREEN) + return BERRY_GOLD; else - return 0; + return BERRY_BLUE; } } -static bool32 sub_8026EEC(u16 arg0[5][6]) +static bool32 IsTotalBerriesMissedOver10(u16 berryResults[MAX_RFU_PLAYERS][NUM_BERRY_IDS]) { - int sum, i; - for (sum = 0, i = 0; i < GetLinkPlayerCount(); sum += arg0[i][3], i++) + int missed = 0, i = 0; + for (; i < GetLinkPlayerCount(); missed += berryResults[i][BERRY_MISSED], i++) ; - if (sum >= 11) + if (missed > 10) return TRUE; else return FALSE; } -static void sub_8026F1C(u8 arg0, u8 arg1, u8 arg2) +// Despite being set up to take a berry id as an argument, this +// function is only ever given BERRY_BLUE or BERRY_MISSED. +// It reads the actual berry id (if necessary) from ids +static void IncrementBerryResult(u8 berryIdArg, u8 column, u8 playerId) { - u8 var; - u8 count = gUnknown_02022C98->unk24; - switch (arg0) + u8 berryId; + u8 numPlayers = sGame->numPlayers; + switch (berryIdArg) { - case 0: - case 1: - case 2: - var = gUnknown_02022C98->unk31A0[0].unk14.unk0[arg1]; - gUnknown_02022C98->unk4A[arg2][var] = IncrementWithLimit(gUnknown_02022C98->unk4A[arg2][var], 20000); + case BERRY_BLUE: + case BERRY_GREEN: + case BERRY_GOLD: + berryId = sGame->players[0].berries.ids[column]; + sGame->berryResults[playerId][berryId] = IncrementWithLimit(sGame->berryResults[playerId][berryId], 20000); break; - case 3: - if (sub_8026EEC(gUnknown_02022C98->unk4A)) + case BERRY_MISSED: + if (IsTotalBerriesMissedOver10(sGame->berryResults)) break; - switch (count) + switch (numPlayers) { case 5: - switch (arg1) + switch (column) { case 0: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[3][3]++; + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[3][BERRY_MISSED]++; break; case 1: - gUnknown_02022C98->unk4A[3][3]++; + sGame->berryResults[3][BERRY_MISSED]++; break; case 2: - gUnknown_02022C98->unk4A[3][3]++; - gUnknown_02022C98->unk4A[4][3]++; + sGame->berryResults[3][BERRY_MISSED]++; + sGame->berryResults[4][BERRY_MISSED]++; break; case 3: - gUnknown_02022C98->unk4A[4][3]++; + sGame->berryResults[4][BERRY_MISSED]++; break; case 4: - gUnknown_02022C98->unk4A[4][3]++; - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[4][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 5: - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 6: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 7: - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 8: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; break; case 9: - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[2][BERRY_MISSED]++; break; } break; case 4: - switch (arg1) + switch (column) { case 1: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[3][3]++; + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[3][BERRY_MISSED]++; break; case 2: - gUnknown_02022C98->unk4A[3][3]++; + sGame->berryResults[3][BERRY_MISSED]++; break; case 3: - gUnknown_02022C98->unk4A[3][3]++; - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[3][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 4: - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 5: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 6: - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 7: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; break; case 8: - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[2][BERRY_MISSED]++; break; } break; case 3: - switch (arg1) + switch (column) { case 2: - gUnknown_02022C98->unk4A[1][3]++; - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[1][BERRY_MISSED]++; + sGame->berryResults[2][BERRY_MISSED]++; break; case 3: - gUnknown_02022C98->unk4A[2][3]++; + sGame->berryResults[2][BERRY_MISSED]++; break; case 4: - gUnknown_02022C98->unk4A[2][3]++; - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[2][BERRY_MISSED]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 5: - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 6: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 7: - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[1][BERRY_MISSED]++; break; } break; case 2: - switch (arg1) + switch (column) { case 3: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 4: - gUnknown_02022C98->unk4A[0][3]++; + sGame->berryResults[0][BERRY_MISSED]++; break; case 5: - gUnknown_02022C98->unk4A[0][3]++; - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[0][BERRY_MISSED]++; + sGame->berryResults[1][BERRY_MISSED]++; break; case 6: - gUnknown_02022C98->unk4A[1][3]++; + sGame->berryResults[1][BERRY_MISSED]++; break; } break; @@ -2246,317 +2533,352 @@ static void sub_8026F1C(u8 arg0, u8 arg1, u8 arg2) } } -static void sub_8027234(bool32 arg0) +static void UpdateBerriesPickedInRow(bool32 picked) { - if (gUnknown_02022C98->unk24 != 5) + // The 'berries picked in row' stat is only + // counted for games with all 5 players + if (sGame->numPlayers != MAX_RFU_PLAYERS) return; - if (arg0 == TRUE) + if (picked == TRUE) { - if (++gUnknown_02022C98->unk112 > gUnknown_02022C98->unk114) - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk112; - if (gUnknown_02022C98->unk112 > 9999) - gUnknown_02022C98->unk112 = 9999; + if (++sGame->berriesPickedInRow > sGame->maxBerriesPickedInRow) + sGame->maxBerriesPickedInRow = sGame->berriesPickedInRow; + if (sGame->berriesPickedInRow > MAX_BERRIES) + sGame->berriesPickedInRow = MAX_BERRIES; } - else + else // missed { - if (gUnknown_02022C98->unk112 > gUnknown_02022C98->unk114) - gUnknown_02022C98->unk114 = gUnknown_02022C98->unk112; - gUnknown_02022C98->unk112 = 0; + if (sGame->berriesPickedInRow > sGame->maxBerriesPickedInRow) + sGame->maxBerriesPickedInRow = sGame->berriesPickedInRow; + sGame->berriesPickedInRow = 0; } } -static void sub_80272A4(void) +static void SetMaxBerriesPickedInRow(void) { u8 i; - for (i = 0; i < gUnknown_02022C98->unk24; i++) - gUnknown_02022C98->unk4A[i][5] = gUnknown_02022C98->unk114; + for (i = 0; i < sGame->numPlayers; i++) + sGame->berryResults[i][BERRY_IN_ROW] = sGame->maxBerriesPickedInRow; } -static void sub_80272E8(void) +static void ResetForPlayAgainPrompt(void) { u8 i, j; - for (i = 0; i < 5; i++) - { - for (j = 0; j < 11; j++) - gUnknown_02022C98->unk31A0[i].unk14.unkB[j] = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk0 = 0; - gUnknown_02022C98->unk31A0[i].unk2C.unk4 = 0; - gUnknown_02022C98->unk90[i] = 0; - gUnknown_02022C98->unk86[i] = 0; - gUnknown_02022C98->unk3308[i].unk0 = 0; - gUnknown_02022C98->unk3308[i].unk4 = 0; - gUnknown_02022C98->unk4A[i][0] = 0; - gUnknown_02022C98->unk4A[i][1] = 0; - gUnknown_02022C98->unk4A[i][2] = 0; - gUnknown_02022C98->unk4A[i][3] = 0; - gUnknown_02022C98->unk4A[i][4] = 0; - gUnknown_02022C98->unk4A[i][5] = 0; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + for (j = 0; j < NUM_BERRY_COLUMNS; j++) + sGame->players[i].berries.fallDist[j] = 0; + sGame->players[i].comm.pickState = PICK_NONE; + sGame->players[i].comm.ateBerry = FALSE; + sGame->difficulty[i] = 0; + sGame->berriesEaten[i] = 0; + sGame->scoreResults[i].ranking = 0; + sGame->scoreResults[i].score = 0; + sGame->berryResults[i][BERRY_BLUE] = 0; + sGame->berryResults[i][BERRY_GREEN] = 0; + sGame->berryResults[i][BERRY_GOLD] = 0; + sGame->berryResults[i][BERRY_MISSED] = 0; + sGame->berryResults[i][BERRY_PRIZE] = 0; + sGame->berryResults[i][BERRY_IN_ROW] = 0; } - gUnknown_02022C98->unk154 = 0; - gUnknown_02022C98->unk112 = 0; - gUnknown_02022C98->unk40 = 0; - sub_8026A88(); - sub_8026988(); -} - -static const s16 gUnknown_082F7B24[] = {10, 30, 50, 50}; + sGame->endSoundState = 0; + sGame->berriesPickedInRow = 0; + sGame->numGraySquares = 0; + UpdateAllDodrioAnims(); + UpdateBerrySprites(); +} + +static const s16 sBerryScoreMultipliers[] = { + [BERRY_BLUE] = 10, + [BERRY_GREEN] = 30, + [BERRY_GOLD] = 50, + [BERRY_MISSED] = 50 // Subtracted +}; -static void sub_80273F0(void) +static void SetRandomPrize(void) { - u8 i, var = 0, var2 = 0; + u8 i, prizeSet = 0, prizeIdx = 0; - switch (gUnknown_02022C98->unk24) + switch (sGame->numPlayers) { - case 4: var = 1; break; - case 5: var = 2; break; + case 4: prizeSet = 1; break; + case 5: prizeSet = 2; break; } - var2 = Random() % 10; - for (i = 0; i < 5; i++) - gUnknown_02022C98->unk4A[i][4] = gUnknown_082F7AA4[var][var2]; + prizeIdx = Random() % ARRAY_COUNT(sPrizeBerryIds[0]); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + sGame->berryResults[i][BERRY_PRIZE] = sPrizeBerryIds[prizeSet][prizeIdx]; } -static u32 sub_802745C(u8 arg0) +static u32 GetBerriesPicked(u8 playerId) { - u32 sum = gUnknown_02022C98->unk4A[arg0][0] - + gUnknown_02022C98->unk4A[arg0][1] - + gUnknown_02022C98->unk4A[arg0][2]; - return min(sum, 9999); + u32 sum = sGame->berryResults[playerId][BERRY_BLUE] + + sGame->berryResults[playerId][BERRY_GREEN] + + sGame->berryResults[playerId][BERRY_GOLD]; + return min(sum, MAX_BERRIES); } -static void sub_802749C(void) +static void TryUpdateRecords(void) { - u32 berriesPicked = Min(sub_802745C(gUnknown_02022C98->multiplayerId), 9999); - u32 score = Min(sub_80276C0(gUnknown_02022C98->multiplayerId), 999990); + u32 berriesPicked = Min(GetBerriesPicked(sGame->multiplayerId), MAX_BERRIES); // Min here is redundant + u32 score = Min(GetScore(sGame->multiplayerId), MAX_SCORE); if (gSaveBlock2Ptr->berryPick.bestScore < score) gSaveBlock2Ptr->berryPick.bestScore = score; if (gSaveBlock2Ptr->berryPick.berriesPicked < berriesPicked) gSaveBlock2Ptr->berryPick.berriesPicked = berriesPicked; - if (gSaveBlock2Ptr->berryPick.berriesPickedInRow < gUnknown_02022C98->unk114) - gSaveBlock2Ptr->berryPick.berriesPickedInRow = gUnknown_02022C98->unk114; + if (gSaveBlock2Ptr->berryPick.berriesPickedInRow < sGame->maxBerriesPickedInRow) + gSaveBlock2Ptr->berryPick.berriesPickedInRow = sGame->maxBerriesPickedInRow; } -static u8 sub_8027518(u8 arg0) +// Enqueue the given state, and dequeue and return +// the state that should be used next +static u8 UpdatePickStateQueue(u8 pickState) { - u8 i, saved; + u8 i, nextState; - saved = gUnknown_02022C98->unk98[3]; - for (i = 3; i != 0; i--) - gUnknown_02022C98->unk98[i] = gUnknown_02022C98->unk98[i - 1]; - gUnknown_02022C98->unk98[0] = arg0; - return saved; + nextState = sGame->pickStateQueue[ARRAY_COUNT(sGame->pickStateQueue) - 1]; + for (i = ARRAY_COUNT(sGame->pickStateQueue) - 1; i != 0; i--) + sGame->pickStateQueue[i] = sGame->pickStateQueue[i - 1]; + sGame->pickStateQueue[0] = pickState; + return nextState; } -static void sub_8027554(void) +// The player may extend their Dodrio's heads while they wait for +// other players to respond to the "Play again?" prompt +static void HandleWaitPlayAgainInput(void) { - if (gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] == 0) + if (sGame->inputDelay[sGame->multiplayerId] == 0) { if (JOY_NEW(DPAD_UP)) { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 2; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; + sGame->players[sGame->multiplayerId].comm.pickState = PICK_MIDDLE; + sGame->inputDelay[sGame->multiplayerId] = 6; PlaySE(SE_M_CHARM); } else if (JOY_NEW(DPAD_LEFT)) { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 3; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; + sGame->players[sGame->multiplayerId].comm.pickState = PICK_LEFT; + sGame->inputDelay[sGame->multiplayerId] = 6; PlaySE(SE_M_CHARM); } else if (JOY_NEW(DPAD_RIGHT)) { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 1; - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId] = 6; + sGame->players[sGame->multiplayerId].comm.pickState = PICK_RIGHT; + sGame->inputDelay[sGame->multiplayerId] = 6; PlaySE(SE_M_CHARM); } else { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 0; + sGame->players[sGame->multiplayerId].comm.pickState = PICK_NONE; } } else { - gUnknown_02022C98->unkB0[gUnknown_02022C98->multiplayerId]--; + sGame->inputDelay[sGame->multiplayerId]--; } } -static void sub_8027608(void) +static void ResetPickState(void) { - gUnknown_02022C98->unk31A0[gUnknown_02022C98->multiplayerId].unk2C.unk0 = 0; + sGame->players[sGame->multiplayerId].comm.pickState = PICK_NONE; } -static u16 sub_802762C(void) +static u16 GetPrizeItemId(void) { - return gUnknown_02022C98->unk4A[gUnknown_02022C98->multiplayerId][4] + FIRST_BERRY_INDEX; + return sGame->berryResults[sGame->multiplayerId][BERRY_PRIZE] + FIRST_BERRY_INDEX; } -static u8 sub_8027650(void) +static u8 GetNumPlayers(void) { - return gUnknown_02022C98->unk24; + return sGame->numPlayers; } -static u8 *sub_8027660(u8 id) +static u8 *GetPlayerName(u8 id) { if (gReceivedRemoteLinkPlayers) return gLinkPlayers[id].name; else - return gUnknown_02022C98->unk31A0[id].name; + return sGame->players[id].name; } -static u16 sub_80276A0(u8 arg0, u8 arg1) +static u16 GetBerryResult(u8 playerId, u8 berryId) { - return gUnknown_02022C98->unk4A[arg0][arg1]; + return sGame->berryResults[playerId][berryId]; } -static u32 sub_80276C0(u8 arg0) +static u32 GetScore(u8 playerId) { u8 i; - u32 var, sum = 0; + u32 scoreLost, score = 0; + + // Sum up points for berries picked + for (i = 0; i < BERRY_MISSED; i++) + score += sGame->berryResults[playerId][i] * sBerryScoreMultipliers[i]; - for (i = 0; i < 3; i++) - sum += gUnknown_02022C98->unk4A[arg0][i] * gUnknown_082F7B24[i]; + // Get points lost for berries missed + scoreLost = sGame->berryResults[playerId][BERRY_MISSED] * sBerryScoreMultipliers[BERRY_MISSED]; - var = gUnknown_02022C98->unk4A[arg0][3] * gUnknown_082F7B24[3]; - if (sum <= var) + if (score <= scoreLost) return 0; else - return sum - var; + return score - scoreLost; } -static u32 sub_8027748(void) +static u32 GetHighestScore(void) { - u8 i, count = gUnknown_02022C98->unk24; - u32 maxVar = sub_80276C0(0); + u8 i, numPlayers = sGame->numPlayers; + u32 maxScore = GetScore(0); - for (i = 1; i < count; i++) + for (i = 1; i < numPlayers; i++) { - u32 var = sub_80276C0(i); - if (var > maxVar) - maxVar = var; + u32 score = GetScore(i); + if (score > maxScore) + maxScore = score; } - return Min(maxVar, 999990); + return Min(maxScore, MAX_SCORE); } -static u32 sub_802778C(u8 arg0) +static u32 GetHighestBerryResult(u8 berryId) { - u8 i, count = gUnknown_02022C98->unk24; - u16 maxVar = gUnknown_02022C98->unk4A[0][arg0]; + u8 i, numPlayers = sGame->numPlayers; + u16 maxScore = sGame->berryResults[0][berryId]; - for (i = 0; i < count; i++) + for (i = 0; i < numPlayers; i++) { - u16 var = gUnknown_02022C98->unk4A[i][arg0]; - if (var > maxVar) - maxVar = var; + u16 score = sGame->berryResults[i][berryId]; + if (score > maxScore) + maxScore = score; } - return maxVar; + return maxScore; } -static u32 sub_80277D0(u8 arg0) +static u32 GetScoreByRanking(u8 ranking) { - u32 vals[5], temp; - s16 r6 = TRUE; - u8 i, count = gUnknown_02022C98->unk24; + u32 scores[MAX_RFU_PLAYERS], temp; + s16 unsorted = TRUE; + u8 i; + u8 numPlayers = sGame->numPlayers; - for (i = 0; i < count; i++) - vals[i] = temp = sub_80276C0(i); + for (i = 0; i < numPlayers; i++) + scores[i] = temp = GetScore(i); - while (r6) + // Sort the scores in the array highest to lowest + while (unsorted) { - r6 = FALSE; - for (i = 0; i < count - 1; i++) + unsorted = FALSE; + for (i = 0; i < numPlayers - 1; i++) { - if (vals[i] < vals[i + 1]) + if (scores[i] < scores[i + 1]) { - SWAP(vals[i], vals[i + 1], temp); - r6 = TRUE; + SWAP(scores[i], scores[i + 1], temp); + unsorted = TRUE; } } } - return vals[arg0]; + return scores[ranking]; } -static u32 sub_802784C(void) +static u32 SetScoreResults(void) { - u8 i, r10 = 0, r8 = 0, r9 = 0, count = gUnknown_02022C98->unk24; + u8 i, ranking = 0, nextRanking = 0, playersRanked = 0; + u8 numPlayers = sGame->numPlayers; - // Function called two times for some reason. - sub_8027748(); - if (sub_8027748() == 0) + GetHighestScore(); // Useless call + + if (GetHighestScore() == 0) { - for (i = 0; i < count; i++) + // No one scored any points, put everyone in last place with a score of 0. + // Presumably this was supposed to then return, as the assignments in this + // loop are then overwritten by the rest of the function + for (i = 0; i < numPlayers; i++) { - gUnknown_02022C98->unk3308[i].unk0 = 4; - gUnknown_02022C98->unk3308[i].unk4 = 0; + sGame->scoreResults[i].ranking = MAX_RFU_PLAYERS - 1; + sGame->scoreResults[i].score = 0; } } - for (i = 0; i < count; i++) - gUnknown_02022C98->unk3308[i].unk4 = Min(sub_80276C0(i), 999990); + // Set scores + for (i = 0; i < numPlayers; i++) + sGame->scoreResults[i].score = Min(GetScore(i), MAX_SCORE); + // Set rankings do { - u32 r6 = sub_80277D0(r10); - u8 r3 = r8; - for (i = 0; i < count; i++) + u32 score = GetScoreByRanking(ranking); + u8 curRanking = nextRanking; + + // Find all players with the score for this ranking. + // Increment nextRanking but not curRanking to allow + // for ties + for (i = 0; i < numPlayers; i++) { - if (r6 == gUnknown_02022C98->unk3308[i].unk4) + if (score == sGame->scoreResults[i].score) { - gUnknown_02022C98->unk3308[i].unk0 = r3; - r8++; - r9++; + sGame->scoreResults[i].ranking = curRanking; + nextRanking++; + playersRanked++; } } - r10 = r8; - } while (r9 < count); + ranking = nextRanking; + } while (playersRanked < numPlayers); return 0; } -static void sub_802793C(struct DodrioSubstruct_3308 *dst, u8 id) +static void GetScoreResults(struct DodrioGame_ScoreResults *dst, u8 playerId) { - *dst = gUnknown_02022C98->unk3308[id]; + *dst = sGame->scoreResults[playerId]; } -// Unused function -static u8 sub_802795C(u8 arg0) +// Unused +// Returns where the specified player's score ranks, 0 being first (highest score) +static u8 GetScoreRanking(u8 playerId) { - u8 i, ret = 0, count = gUnknown_02022C98->unk24; - u32 var, vars[5] = {0}; + u8 i, ranking = 0; + u8 numPlayers = sGame->numPlayers; + u32 playersScore; + u32 scores[MAX_RFU_PLAYERS] = {0}; - for (i = 0; i < count; i++) - vars[i] = sub_80276C0(i); + for (i = 0; i < numPlayers; i++) + scores[i] = GetScore(i); - var = vars[arg0]; - for (i = 0; i < 5; i++) + playersScore = scores[playerId]; + for (i = 0; i < MAX_RFU_PLAYERS; i++) { - if (i != arg0 && var < vars[i]) - ret++; + if (i != playerId && playersScore < scores[i]) + ranking++; } - return ret; + return ranking; } -static u8 sub_80279C8(void) +enum { + PRIZE_RECEIVED, + PRIZE_FILLED_BAG, + PRIZE_NO_ROOM, + NO_PRIZE, +}; + +static u8 TryGivePrize(void) { - u8 multiplayerId = gUnknown_02022C98->multiplayerId; - u16 itemId = sub_802762C(); + u8 multiplayerId = sGame->multiplayerId; + u16 itemId = GetPrizeItemId(); - if (sub_80276C0(multiplayerId) != sub_8027748()) - return 3; + if (GetScore(multiplayerId) != GetHighestScore()) + return NO_PRIZE; if (!CheckBagHasSpace(itemId, 1)) - return 2; + return PRIZE_NO_ROOM; AddBagItem(itemId, 1); if (!CheckBagHasSpace(itemId, 1)) - return 1; - return 0; + return PRIZE_FILLED_BAG; + return PRIZE_RECEIVED; } -// Really? What next, u32 Add(u32 a)return a+1;? static u32 IncrementWithLimit(u32 a, u32 max) { if (a < max) @@ -2565,7 +2887,6 @@ static u32 IncrementWithLimit(u32 a, u32 max) return max; } -// Gamefreak pls, min(a, b) ((a) < (b) ? (a) : (b)) is a well-known macro static u32 Min(u32 a, u32 b) { if (a < b) @@ -2574,9 +2895,9 @@ static u32 Min(u32 a, u32 b) return b; } -static u8 sub_8027A48(u8 id) +static u8 GetPlayerIdByPos(u8 id) { - return gUnknown_02022C98->unk34[id]; + return sGame->posToPlayerId[id]; } void IsDodrioInParty(void) @@ -2595,14 +2916,15 @@ void IsDodrioInParty(void) gSpecialVar_Result = FALSE; } +#define NUM_RECORD_TYPES 3 + void ShowDodrioBerryPickingRecords(void) { u8 taskId = CreateTask(Task_ShowDodrioBerryPickingRecords, 0); Task_ShowDodrioBerryPickingRecords(taskId); } -// Data related to printing saved results. -static const struct WindowTemplate gUnknown_082F7B2C = +static const struct WindowTemplate sWindowTemplates_Records = { .bg = 0, .tilemapLeft = 5, @@ -2613,12 +2935,14 @@ static const struct WindowTemplate gUnknown_082F7B2C = .baseBlock = 0x1, }; -static const u8 *const gUnknown_082F7B34[3] = {gText_BerriesPicked, gText_BestScore, gText_BerriesInRowFivePlayers}; -static const u8 gUnknown_082F7B40[] = {4, 7, 4}; - +static const u8 *const sRecordsTexts[NUM_RECORD_TYPES] = {gText_BerriesPicked, gText_BestScore, gText_BerriesInRowFivePlayers}; +static const u8 sRecordNumMaxDigits[NUM_RECORD_TYPES] = {4, 7, 4}; ALIGNED(4) -static const u8 gUnknown_082F7B44[][2] = {{25}, {41}, {57}}; -static const u8 gUnknown_082F7B4A[][2] = {{25}, {41}, {73}}; +static const u8 sRecordTextYCoords[NUM_RECORD_TYPES][2] = {{25}, {41}, {57}}; +static const u8 sRecordNumYCoords[NUM_RECORD_TYPES][2] = {{25}, {41}, {73}}; + +#define tState data[0] +#define tWindowId data[1] static void Task_ShowDodrioBerryPickingRecords(u8 taskId) { @@ -2626,14 +2950,14 @@ static void Task_ShowDodrioBerryPickingRecords(u8 taskId) s32 i, width, widthCurr; s16 *data = gTasks[taskId].data; - switch (data[0]) + switch (tState) { case 0: - window = gUnknown_082F7B2C; + window = sWindowTemplates_Records; width = GetStringWidth(1, gText_BerryPickingRecords, 0); - for (i = 0; i < ARRAY_COUNT(gUnknown_082F7B34); i++) + for (i = 0; i < ARRAY_COUNT(sRecordsTexts); i++) { - widthCurr = GetStringWidth(1, gUnknown_082F7B34[i], 0) + 50; + widthCurr = GetStringWidth(1, sRecordsTexts[i], 0) + 50; if (widthCurr > width) width = widthCurr; } @@ -2642,27 +2966,27 @@ static void Task_ShowDodrioBerryPickingRecords(u8 taskId) width++; window.tilemapLeft = (30 - width) / 2; window.width = width; - data[1] = AddWindow(&window); - sub_8027BEC(data[1], width); - CopyWindowToVram(data[1], 3); - data[0]++; + tWindowId = AddWindow(&window); + PrintRecordsText(tWindowId, width); + CopyWindowToVram(tWindowId, 3); + tState++; break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) - data[0]++; + tState++; break; case 2: if (JOY_NEW(A_BUTTON | B_BUTTON)) { - rbox_fill_rectangle(data[1]); - CopyWindowToVram(data[1], 1); - data[0]++; + rbox_fill_rectangle(tWindowId); + CopyWindowToVram(tWindowId, 1); + tState++; } break; case 3: if (!IsDma3ManagerBusyWithBgCopy()) { - RemoveWindow(data[1]); + RemoveWindow(tWindowId); DestroyTask(taskId); EnableBothScriptContexts(); } @@ -2670,44 +2994,72 @@ static void Task_ShowDodrioBerryPickingRecords(u8 taskId) } } -static void sub_8027BEC(u8 windowId, s32 width) +#undef tState +#undef tWindowId + +static void PrintRecordsText(u8 windowId, s32 width) { s32 i, x, numWidth; - s32 results[3]; - results[0] = gSaveBlock2Ptr->berryPick.berriesPicked; - results[1] = gSaveBlock2Ptr->berryPick.bestScore; - results[2] = gSaveBlock2Ptr->berryPick.berriesPickedInRow; + s32 recordNums[NUM_RECORD_TYPES]; + recordNums[0] = gSaveBlock2Ptr->berryPick.berriesPicked; + recordNums[1] = gSaveBlock2Ptr->berryPick.bestScore; + recordNums[2] = gSaveBlock2Ptr->berryPick.berriesPickedInRow; LoadUserWindowBorderGfx_(windowId, 0x21D, 0xD0); DrawTextBorderOuter(windowId, 0x21D, 0xD); FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); AddTextPrinterParameterized(windowId, 1, gText_BerryPickingRecords, GetStringCenterAlignXOffset(1, gText_BerryPickingRecords, width * 8), 1, TEXT_SPEED_FF, NULL); - for (i = 0; i < 3; i++) + for (i = 0; i < NUM_RECORD_TYPES; i++) { - ConvertIntToDecimalStringN(gStringVar1, results[i], STR_CONV_MODE_LEFT_ALIGN, gUnknown_082F7B40[i]); + ConvertIntToDecimalStringN(gStringVar1, recordNums[i], STR_CONV_MODE_LEFT_ALIGN, sRecordNumMaxDigits[i]); numWidth = GetStringWidth(1, gStringVar1, -1); - AddTextPrinterParameterized(windowId, 1, gUnknown_082F7B34[i], 0, gUnknown_082F7B44[i][0], TEXT_SPEED_FF, NULL); + AddTextPrinterParameterized(windowId, 1, sRecordsTexts[i], 0, sRecordTextYCoords[i][0], TEXT_SPEED_FF, NULL); x = (width * 8) - numWidth; - AddTextPrinterParameterized(windowId, 1, gStringVar1, x, gUnknown_082F7B4A[i][0], TEXT_SPEED_FF, NULL); + AddTextPrinterParameterized(windowId, 1, gStringVar1, x, sRecordNumYCoords[i][0], TEXT_SPEED_FF, NULL); } PutWindowTilemap(windowId); } // Debug functions? -static const u16 gUnknown_082F7B50[][4] = -{ - {9999, 0, 90, 9999}, - {9999, 9999, 70, 9999}, - {9999, 0, 9999, 0}, - {9999, 9999, 60, 0}, - {9999, 9999, 9999, 0}, +static const u16 sDebug_BerryResults[MAX_RFU_PLAYERS][4] = +{ + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = 0, + [BERRY_GOLD] = 90, + [BERRY_MISSED] = MAX_BERRIES + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = 70, + [BERRY_MISSED] = MAX_BERRIES + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = 0, + [BERRY_GOLD] = MAX_BERRIES, + [BERRY_MISSED] = 0 + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = 60, + [BERRY_MISSED] = 0 + }, + { + [BERRY_BLUE] = MAX_BERRIES, + [BERRY_GREEN] = MAX_BERRIES, + [BERRY_GOLD] = MAX_BERRIES, + [BERRY_MISSED] = 0 + }, }; static const u8 sJPText_Vowels[] = _("あいうえおかき"); static const u8 sText_ABCDEFG[] = _("ABCDEFG"); static const u8 sText_0123456[] = _("0123456"); -static const u8 *const sPlaceholderPlayerNames[] = +static const u8 *const sDebug_PlayerNames[] = { sJPText_Vowels, sJPText_Vowels, @@ -2716,277 +3068,293 @@ static const u8 *const sPlaceholderPlayerNames[] = sText_0123456 }; -static void sub_8027D20(void) +static void Debug_UpdateNumPlayers(void) { - gUnknown_02022C98->unk24 = GetLinkPlayerCount(); + sGame->numPlayers = GetLinkPlayerCount(); } -static void sub_8027D38(void) +static void Debug_SetPlayerNamesAndResults(void) { u8 i, playerId; - for (playerId = gUnknown_02022C98->unk24; playerId < ARRAY_COUNT(sPlaceholderPlayerNames); playerId++) - StringCopy(gLinkPlayers[playerId].name, sPlaceholderPlayerNames[playerId]); + for (playerId = sGame->numPlayers; playerId < ARRAY_COUNT(sDebug_PlayerNames); playerId++) + StringCopy(gLinkPlayers[playerId].name, sDebug_PlayerNames[playerId]); - gUnknown_02022C98->unk24 = 5; - for (i = 0; i < 4; i++) + sGame->numPlayers = MAX_RFU_PLAYERS; + for (i = 0; i < NUM_BERRY_TYPES; i++) { - for (playerId = 0; playerId < gUnknown_02022C98->unk24; playerId++) - gUnknown_02022C98->unk4A[playerId][i] = gUnknown_082F7B50[playerId][i]; + for (playerId = 0; playerId < sGame->numPlayers; playerId++) + sGame->berryResults[playerId][i] = sDebug_BerryResults[playerId][i]; } } -struct UnkPacket1 +struct ReadyToStartPacket { u8 id; - u8 ALIGNED(4) unk4; + bool8 ALIGNED(4) ready; }; -static void sub_8027DD0(u32 arg0) +static void SendPacket_ReadyToStart(bool32 ready) { - struct UnkPacket1 packet; - packet.id = 1; - packet.unk4 = arg0; + struct ReadyToStartPacket packet; + packet.id = PACKET_READY_START; + packet.ready = ready; Rfu_SendPacket(&packet); } -static u32 sub_8027DFC(u32 arg0) +static u32 RecvPacket_ReadyToStart(u32 playerId) { - struct UnkPacket1 *packet; + struct ReadyToStartPacket *packet; if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; + return FALSE; - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 1) - return packet->unk4; + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_READY_START) + return packet->ready; - return 0; + return FALSE; } -struct UnkPacket2 +struct GameStatePacket { u8 id; - u8 unk1_0:4; - u8 unk1_1:4; - u16 unk2_0:4; - u16 unk2_1:4; - u16 unk3_0:4; - u16 unk3_1:4; - u16 unk4_0:4; - u16 unk4_1:4; - u16 unk5_0:4; - u16 unk5_1:4; - u16 unk6_0:2; - u16 unk6_1:2; - u16 unk6_2:2; - u16 unk6_3:2; - u16 unk7_0:2; - u16 unk7_1:2; - u16 unk7_2:2; - u16 unk7_3:2; - u8 unk8_0:2; - u8 unk8_1:2; - u8 unk8_2:2; - u8 unk8_3:2; - u8 unk9_0:2; - u8 unk9_1:2; - u8 unk9_2:2; - u8 unk9_3:1; - u8 unk9_4:1; - u8 unkA_0:1; - u8 unkA_1:1; - u8 unkA_2:1; - u8 unkA_3:5; - u8 unkB_0:1; - u8 unkB_1:1; - u8 unkB_2:1; - u8 unkB_3:1; - u8 unkB_4:1; - u8 unkB_5:1; - u8 unkB_6:1; + u8 fallDist_Col0:4; + u8 fallDist_Col1:4; + u16 fallDist_Col2:4; + u16 fallDist_Col3:4; + u16 fallDist_Col4:4; + u16 fallDist_Col5:4; + u16 fallDist_Col6:4; + u16 fallDist_Col7:4; + u16 fallDist_Col8:4; + u16 fallDist_Col9:4; + u16 berryId_Col0:2; + u16 berryId_Col1:2; + u16 berryId_Col2:2; + u16 berryId_Col3:2; + u16 berryId_Col4:2; + u16 berryId_Col5:2; + u16 berryId_Col6:2; + u16 berryId_Col7:2; + u8 berryId_Col8:2; + u8 berryId_Col9:2; + u8 pickState_Player1:2; + u8 pickState_Player2:2; + u8 pickState_Player3:2; + u8 pickState_Player4:2; + u8 pickState_Player5:2; + bool8 ateBerry_Player1:1; + bool8 ateBerry_Player2:1; + bool8 ateBerry_Player3:1; + bool8 ateBerry_Player4:1; + bool8 ateBerry_Player5:1; + u8 numGraySquares:5; + bool8 allReadyToEnd:1; + bool8 berriesFalling:1; + bool8 missedBerry_Player1:1; + bool8 missedBerry_Player2:1; + bool8 missedBerry_Player3:1; + bool8 missedBerry_Player4:1; + bool8 missedBerry_Player5:1; }; -static void sub_8027E30(struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 arg6, u32 arg7, u32 arg8) -{ - struct UnkPacket2 packet; - struct DodrioSubstruct_31A0_14 *ptr = &arg0->unk14; - - packet.id = 2; - packet.unk1_0 = ptr->unkB[0]; - packet.unk1_1 = ptr->unkB[1]; - packet.unk2_0 = ptr->unkB[2]; - packet.unk2_1 = ptr->unkB[3]; - packet.unk3_0 = ptr->unkB[4]; - packet.unk3_1 = ptr->unkB[5]; - packet.unk4_0 = ptr->unkB[6]; - packet.unk4_1 = ptr->unkB[7]; - packet.unk5_0 = ptr->unkB[8]; - packet.unk5_1 = ptr->unkB[9]; - - packet.unk6_0 = ptr->unk0[0]; - packet.unk6_1 = ptr->unk0[1]; - packet.unk6_2 = ptr->unk0[2]; - packet.unk6_3 = ptr->unk0[3]; - packet.unk7_0 = ptr->unk0[4]; - packet.unk7_1 = ptr->unk0[5]; - packet.unk7_2 = ptr->unk0[6]; - packet.unk7_3 = ptr->unk0[7]; - packet.unk8_0 = ptr->unk0[8]; - packet.unk8_1 = ptr->unk0[9]; - - packet.unk8_2 = arg1->unk0; - packet.unk8_3 = arg2->unk0; - packet.unk9_0 = arg3->unk0; - packet.unk9_1 = arg4->unk0; - packet.unk9_2 = arg5->unk0; - - packet.unk9_3 = arg1->unk4; - packet.unk9_4 = arg2->unk4; - packet.unkA_0 = arg3->unk4; - packet.unkA_1 = arg4->unk4; - packet.unkA_2 = arg5->unk4; - - packet.unkB_2 = arg1->unk8; - packet.unkB_3 = arg2->unk8; - packet.unkB_4 = arg3->unk8; - packet.unkB_5 = arg4->unk8; - packet.unkB_6 = arg5->unk8; - - packet.unkA_3 = arg6; - packet.unkB_1 = arg7; - packet.unkB_0 = arg8; +static void SendPacket_GameState(struct DodrioGame_Player *player, + struct DodrioGame_PlayerCommData *player1, + struct DodrioGame_PlayerCommData *player2, + struct DodrioGame_PlayerCommData *player3, + struct DodrioGame_PlayerCommData *player4, + struct DodrioGame_PlayerCommData *player5, + u8 numGraySquares, + bool32 berriesFalling, + bool32 allReadyToEnd) +{ + struct GameStatePacket packet; + struct DodrioGame_Berries *berries = &player->berries; + + packet.id = PACKET_GAME_STATE; + packet.fallDist_Col0 = berries->fallDist[0]; + packet.fallDist_Col1 = berries->fallDist[1]; + packet.fallDist_Col2 = berries->fallDist[2]; + packet.fallDist_Col3 = berries->fallDist[3]; + packet.fallDist_Col4 = berries->fallDist[4]; + packet.fallDist_Col5 = berries->fallDist[5]; + packet.fallDist_Col6 = berries->fallDist[6]; + packet.fallDist_Col7 = berries->fallDist[7]; + packet.fallDist_Col8 = berries->fallDist[8]; + packet.fallDist_Col9 = berries->fallDist[9]; + + packet.berryId_Col0 = berries->ids[0]; + packet.berryId_Col1 = berries->ids[1]; + packet.berryId_Col2 = berries->ids[2]; + packet.berryId_Col3 = berries->ids[3]; + packet.berryId_Col4 = berries->ids[4]; + packet.berryId_Col5 = berries->ids[5]; + packet.berryId_Col6 = berries->ids[6]; + packet.berryId_Col7 = berries->ids[7]; + packet.berryId_Col8 = berries->ids[8]; + packet.berryId_Col9 = berries->ids[9]; + + packet.pickState_Player1 = player1->pickState; + packet.pickState_Player2 = player2->pickState; + packet.pickState_Player3 = player3->pickState; + packet.pickState_Player4 = player4->pickState; + packet.pickState_Player5 = player5->pickState; + + packet.ateBerry_Player1 = player1->ateBerry; + packet.ateBerry_Player2 = player2->ateBerry; + packet.ateBerry_Player3 = player3->ateBerry; + packet.ateBerry_Player4 = player4->ateBerry; + packet.ateBerry_Player5 = player5->ateBerry; + + packet.missedBerry_Player1 = player1->missedBerry; + packet.missedBerry_Player2 = player2->missedBerry; + packet.missedBerry_Player3 = player3->missedBerry; + packet.missedBerry_Player4 = player4->missedBerry; + packet.missedBerry_Player5 = player5->missedBerry; + + packet.numGraySquares = numGraySquares; + packet.berriesFalling = berriesFalling; + packet.allReadyToEnd = allReadyToEnd; Rfu_SendPacket(&packet); } -static u32 sub_8028164(u32 unused, struct DodrioSubstruct_31A0 *arg0, struct DodrioSubstruct_31A0_2C *arg1, struct DodrioSubstruct_31A0_2C *arg2, struct DodrioSubstruct_31A0_2C *arg3, struct DodrioSubstruct_31A0_2C *arg4, struct DodrioSubstruct_31A0_2C *arg5, u8 *arg6, u32 *arg7, u32 *arg8) +static bool32 RecvPacket_GameState(u32 playerId, + struct DodrioGame_Player *player, + struct DodrioGame_PlayerCommData *player1, + struct DodrioGame_PlayerCommData *player2, + struct DodrioGame_PlayerCommData *player3, + struct DodrioGame_PlayerCommData *player4, + struct DodrioGame_PlayerCommData *player5, + u8 *numGraySquares, + bool32 *berriesFalling, + bool32 *allReadyToEnd) { - struct UnkPacket2 *packet; - struct DodrioSubstruct_31A0_14 *ptr = &arg0->unk14; + struct GameStatePacket *packet; + struct DodrioGame_Berries *berries = &player->berries; if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; + return FALSE; packet = (void *)&gRecvCmds[0][1]; - if (packet->id == 2) - { - ptr->unkB[0] = packet->unk1_0; - ptr->unkB[1] = packet->unk1_1; - ptr->unkB[2] = packet->unk2_0; - ptr->unkB[3] = packet->unk2_1; - ptr->unkB[4] = packet->unk3_0; - ptr->unkB[5] = packet->unk3_1; - ptr->unkB[6] = packet->unk4_0; - ptr->unkB[7] = packet->unk4_1; - ptr->unkB[8] = packet->unk5_0; - ptr->unkB[9] = packet->unk5_1; - ptr->unkB[10] = packet->unk1_0; - - ptr->unk0[0] = packet->unk6_0; - ptr->unk0[1] = packet->unk6_1; - ptr->unk0[2] = packet->unk6_2; - ptr->unk0[3] = packet->unk6_3; - ptr->unk0[4] = packet->unk7_0; - ptr->unk0[5] = packet->unk7_1; - ptr->unk0[6] = packet->unk7_2; - ptr->unk0[7] = packet->unk7_3; - ptr->unk0[8] = packet->unk8_0; - ptr->unk0[9] = packet->unk8_1; - ptr->unk0[10] = packet->unk6_0; - - arg1->unk0 = packet->unk8_2; - arg1->unk4 = packet->unk9_3; - arg1->unk8 = packet->unkB_2; - - arg2->unk0 = packet->unk8_3; - arg2->unk4 = packet->unk9_4; - arg2->unk8 = packet->unkB_3; - - arg3->unk0 = packet->unk9_0; - arg3->unk4 = packet->unkA_0; - arg3->unk8 = packet->unkB_4; - - arg4->unk0 = packet->unk9_1; - arg4->unk4 = packet->unkA_1; - arg4->unk8 = packet->unkB_5; - - arg5->unk0 = packet->unk9_2; - arg5->unk4 = packet->unkA_2; - arg5->unk8 = packet->unkB_6; - - *arg6 = packet->unkA_3; - *arg7 = packet->unkB_1; - *arg8 = packet->unkB_0; - return 1; + if (packet->id == PACKET_GAME_STATE) + { + berries->fallDist[0] = packet->fallDist_Col0; + berries->fallDist[1] = packet->fallDist_Col1; + berries->fallDist[2] = packet->fallDist_Col2; + berries->fallDist[3] = packet->fallDist_Col3; + berries->fallDist[4] = packet->fallDist_Col4; + berries->fallDist[5] = packet->fallDist_Col5; + berries->fallDist[6] = packet->fallDist_Col6; + berries->fallDist[7] = packet->fallDist_Col7; + berries->fallDist[8] = packet->fallDist_Col8; + berries->fallDist[9] = packet->fallDist_Col9; + berries->fallDist[10] = packet->fallDist_Col0; + + berries->ids[0] = packet->berryId_Col0; + berries->ids[1] = packet->berryId_Col1; + berries->ids[2] = packet->berryId_Col2; + berries->ids[3] = packet->berryId_Col3; + berries->ids[4] = packet->berryId_Col4; + berries->ids[5] = packet->berryId_Col5; + berries->ids[6] = packet->berryId_Col6; + berries->ids[7] = packet->berryId_Col7; + berries->ids[8] = packet->berryId_Col8; + berries->ids[9] = packet->berryId_Col9; + berries->ids[10] = packet->berryId_Col0; + + player1->pickState = packet->pickState_Player1; + player1->ateBerry = packet->ateBerry_Player1; + player1->missedBerry = packet->missedBerry_Player1; + + player2->pickState = packet->pickState_Player2; + player2->ateBerry = packet->ateBerry_Player2; + player2->missedBerry = packet->missedBerry_Player2; + + player3->pickState = packet->pickState_Player3; + player3->ateBerry = packet->ateBerry_Player3; + player3->missedBerry = packet->missedBerry_Player3; + + player4->pickState = packet->pickState_Player4; + player4->ateBerry = packet->ateBerry_Player4; + player4->missedBerry = packet->missedBerry_Player4; + + player5->pickState = packet->pickState_Player5; + player5->ateBerry = packet->ateBerry_Player5; + player5->missedBerry = packet->missedBerry_Player5; + + *numGraySquares = packet->numGraySquares; + *berriesFalling = packet->berriesFalling; + *allReadyToEnd = packet->allReadyToEnd; + return TRUE; } - return 0; + return FALSE; } -struct UnkPacket3 +struct PickStatePacket { u8 id; - u8 ALIGNED(4) unk4; + u8 ALIGNED(4) pickState; }; -static void sub_80282EC(u8 arg0) +static void SendPacket_PickState(u8 pickState) { - struct UnkPacket3 packet; - packet.id = 3; - packet.unk4 = arg0; + struct PickStatePacket packet; + packet.id = PACKET_PICK_STATE; + packet.pickState = pickState; Rfu_SendPacket(&packet); } -static u32 sub_8028318(u32 arg0, u8 *arg1) +static bool32 RecvPacket_PickState(u32 playerId, u8 *pickState) { - struct UnkPacket3 *packet; + struct PickStatePacket *packet; if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; + return FALSE; - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 3) + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_PICK_STATE) { - *arg1 = packet->unk4; - return 1; + *pickState = packet->pickState; + return TRUE; } - return 0; + return FALSE; } -struct UnkPacket4 +struct ReadyToEndPacket { u8 id; - u32 unk4; + bool32 ready; }; -static void sub_8028350(u32 arg0) +static void SendPacket_ReadyToEnd(bool32 ready) { - struct UnkPacket4 packet; - packet.id = 4; - packet.unk4 = arg0; + struct ReadyToEndPacket packet; + packet.id = PACKET_READY_END; + packet.ready = ready; Rfu_SendPacket(&packet); } -static u32 sub_8028374(u32 arg0) +static bool32 RecvPacket_ReadyToEnd(u32 playerId) { - struct UnkPacket4 *packet; + struct ReadyToEndPacket *packet; if ((gRecvCmds[0][0] & 0xFF00) != RFUCMD_SEND_PACKET) - return 0; + return FALSE; - packet = (void *)&gRecvCmds[arg0][1]; - if (packet->id == 4) - return packet->unk4; + packet = (void *)&gRecvCmds[playerId][1]; + if (packet->id == PACKET_READY_END) + return packet->ready; - return 0; + return FALSE; } -// Large chunk of data -static const struct BgTemplate gUnknown_082F7BA4[] = +static const struct BgTemplate sBgTemplates[] = { { - .bg = 0, + .bg = BG_INTERFACE, .charBaseIndex = 0, .mapBaseIndex = 30, .screenSize = 0, @@ -2995,7 +3363,7 @@ static const struct BgTemplate gUnknown_082F7BA4[] = .baseTile = 0 }, { - .bg = 1, + .bg = BG_TREE_LEFT, .charBaseIndex = 2, .mapBaseIndex = 12, .screenSize = 1, @@ -3004,7 +3372,7 @@ static const struct BgTemplate gUnknown_082F7BA4[] = .baseTile = 0 }, { - .bg = 2, + .bg = BG_TREE_RIGHT, .charBaseIndex = 2, .mapBaseIndex = 14, .screenSize = 1, @@ -3013,7 +3381,7 @@ static const struct BgTemplate gUnknown_082F7BA4[] = .baseTile = 0 }, { - .bg = 3, + .bg = BG_SCENERY, .charBaseIndex = 3, .mapBaseIndex = 31, .screenSize = 0, @@ -3023,13 +3391,12 @@ static const struct BgTemplate gUnknown_082F7BA4[] = }, }; -// Unknown unreferenced data, feel free to remove. -static const u32 sUnused[] = {255, 0}; +static const struct WindowTemplate sWindowTemplate_Dummy = DUMMY_WIN_TEMPLATE; -static const struct WindowTemplate gUnknown_082F7BBC[] = +static const struct WindowTemplate sWindowTemplates_Results[] = { { - .bg = 0, + .bg = BG_INTERFACE, .tilemapLeft = 1, .tilemapTop = 1, .width = 28, @@ -3038,7 +3405,7 @@ static const struct WindowTemplate gUnknown_082F7BBC[] = .baseBlock = 0x13, }, { - .bg = 0, + .bg = BG_INTERFACE, .tilemapLeft = 1, .tilemapTop = 5, .width = 28, @@ -3047,9 +3414,10 @@ static const struct WindowTemplate gUnknown_082F7BBC[] = .baseBlock = 0x4B, } }; -static const struct WindowTemplate gUnknown_082F7BCC = + +static const struct WindowTemplate sWindowTemplate_Prize = { - .bg = 0, + .bg = BG_INTERFACE, .tilemapLeft = 1, .tilemapTop = 5, .width = 28, @@ -3057,10 +3425,16 @@ static const struct WindowTemplate gUnknown_082F7BCC = .paletteNum = 13, .baseBlock = 0x4B, }; -static const struct WindowTemplate gUnknown_082F7BD4[] = + +enum { + WIN_PLAY_AGAIN, + WIN_YES_NO, +}; + +static const struct WindowTemplate sWindowTemplates_PlayAgain[] = { - { - .bg = 0, + [WIN_PLAY_AGAIN] = { + .bg = BG_INTERFACE, .tilemapLeft = 1, .tilemapTop = 8, .width = 19, @@ -3068,8 +3442,8 @@ static const struct WindowTemplate gUnknown_082F7BD4[] = .paletteNum = 13, .baseBlock = 0x13, }, - { - .bg = 0, + [WIN_YES_NO] = { + .bg = BG_INTERFACE, .tilemapLeft = 22, .tilemapTop = 7, .width = 6, @@ -3078,9 +3452,10 @@ static const struct WindowTemplate gUnknown_082F7BD4[] = .baseBlock = 0x4C, } }; -static const struct WindowTemplate gUnknown_082F7BE4 = + +static const struct WindowTemplate sWindowTemplate_DroppedOut = { - .bg = 0, + .bg = BG_INTERFACE, .tilemapLeft = 4, .tilemapTop = 6, .width = 22, @@ -3088,9 +3463,10 @@ static const struct WindowTemplate gUnknown_082F7BE4 = .paletteNum = 13, .baseBlock = 0x13, }; -static const struct WindowTemplate gUnknown_082F7BEC = + +static const struct WindowTemplate sWindowTemplate_CommStandby = { - .bg = 0, + .bg = BG_INTERFACE, .tilemapLeft = 5, .tilemapTop = 8, .width = 19, @@ -3099,42 +3475,135 @@ static const struct WindowTemplate gUnknown_082F7BEC = .baseBlock = 0x13, }; -// This is an unused copy of the tables from the top of the file. Feel free to remove. -static const u8 sDuplicateArray[] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0, 0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 2, 9, - 0, 0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0, 0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0, 0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0, 0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0, 0, 7, - 8, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0, - 1, 2, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 4, 5, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 5, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 6, 7, 2, 2, 3, 4, 0, 0, 0, 0, 0, 0, - 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2, 3, 0, 0, 0, 4, 5, 6, 6, 7, 8, 8, 9, 0, 0, 1, 2, 2, 3, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 0, 1, - 2, 1, 2, 3, 2, 3, 0, 0, 0, 0, 4, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 0, 0, 0, 0, 9, 9, 9, 9, 1, 1, 1, 9, 9, 9, 9, 9, - 9, 9, 0, 0, 1, 1, 0, 9, 9, 9, 9, 9, 2, 2, 0, 0, 1, 1, 1, 9, 9, 9, 3, 3, 0, 0, 1, 1, 2, 2, 3, 9, 3, 3, 4, 4, 0, 0, 1, 1, - 2, 2, 3, 5, 0, 0, 0, 0, 4, 6, 0, 0, 0, 3, 5, 7, 0, 0, 2, 4, 6, 8, 0, 1, 3, 5, 6, 9 +// Unused duplicate of sActiveColumnMap +static const u8 sActiveColumnMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = +{ + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + }, + { + {0, 1, 2, 3, 4, 5, 6, 3, 8, 9, 0}, + {0, 1, 2, 5, 6, 3, 4, 5, 8, 9, 0}, + }, + { + {0, 1, 2, 3, 4, 5, 6, 7, 2, 9, 0}, + {0, 1, 4, 5, 6, 7, 2, 3, 4, 9, 0}, + {0, 1, 6, 7, 2, 3, 4, 5, 6, 9, 0}, + }, + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 0}, + {0, 3, 4, 5, 6, 7, 8, 1, 2, 3, 0}, + {0, 5, 6, 7, 8, 1, 2, 3, 4, 5, 0}, + {0, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0}, + }, + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, + {2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2}, + {4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4}, + {6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, + {8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8}, + }, +}; + +// Unused duplicate of sDodrioHeadToColumnMap +static const u8 sDodrioHeadToColumnMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = +{ + { + {4, 5, 6}, + }, + { + {3, 4, 5}, + {5, 6, 3}, + }, + { + {4, 5, 6}, + {6, 7, 2}, + {2, 3, 4}, + }, + { + {3, 4, 5}, + {5, 6, 7}, + {7, 8, 1}, + {1, 2, 3}, + }, + { + {4, 5, 6}, + {6, 7, 8}, + {8, 9, 0}, + {0, 1, 2}, + {2, 3, 4}, + }, +}; + +// Unused duplicate of sDodrioNeighborMap +static const u8 sDodrioNeighborMap_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS][3] = +{ + { + {1, 0, 1}, + }, + { + {1, 0, 1}, + {0, 1, 0}, + }, + { + {2, 0, 1}, + {0, 1, 2}, + {1, 2, 0}, + }, + { + {3, 0, 1}, + {0, 1, 2}, + {1, 2, 3}, + {2, 3, 0}, + }, + { + {4, 0, 1}, + {0, 1, 2}, + {1, 2, 3}, + {2, 3, 4}, + {3, 4, 0}, + }, +}; + +// Unused duplicate of sPlayerIdAtColumn +ALIGNED(4) +static const u8 sPlayerIdAtColumn_Duplicate[MAX_RFU_PLAYERS][NUM_BERRY_COLUMNS] = +{ + {9, 9, 9, 9, 1, 1, 1, 9, 9, 9, 9}, + {9, 9, 9, 0, 0, 1, 1, 0, 9, 9, 9}, + {9, 9, 2, 2, 0, 0, 1, 1, 1, 9, 9}, + {9, 3, 3, 0, 0, 1, 1, 2, 2, 3, 9}, + {3, 3, 4, 4, 0, 0, 1, 1, 2, 2, 3}, }; -static const u16 gDodrioBerryBgPal1[] = INCBIN_U16("graphics/link_games/dodrioberry_bg1.gbapal", - "graphics/link_games/dodrioberry_bg2.gbapal"); -static const u16 gDodrioBerryPkmnPal[] = INCBIN_U16("graphics/link_games/dodrioberry_pkmn.gbapal"); -static const u16 gDodrioBerryShinyPal[] = INCBIN_U16("graphics/link_games/dodrioberry_shiny.gbapal"); -static const u16 gDodrioBerryStatusPal[] = INCBIN_U16("graphics/link_games/dodrioberry_status.gbapal"); -static const u16 gDodrioBerrySpritesPal[] = INCBIN_U16("graphics/link_games/dodrioberry_berrysprites.gbapal"); -static const u32 gDodrioBerrySpritesGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_berrysprites.4bpp.lz"); -static const u16 gDodrioBerryPlatformPal[] = INCBIN_U16("graphics/link_games/dodrioberry_platform.gbapal"); -static const u32 gDodrioBerryBgGfx1[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.4bpp.lz"); -static const u32 gDodrioBerryBgGfx2[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2.4bpp.lz"); -static const u32 gDodrioBerryStatusGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_status.4bpp.lz"); -static const u32 gDodrioBerryPlatformGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_platform.4bpp.lz"); -static const u32 gDodrioBerryPkmnGfx[] = INCBIN_U32("graphics/link_games/dodrioberry_pkmn.4bpp.lz"); -static const u32 gDodrioBerryBgTilemap1[] = INCBIN_U32("graphics/link_games/dodrioberry_bg1.bin.lz"); -static const u32 gDodrioBerryBgTilemap2Right[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2right.bin.lz"); -static const u32 gDodrioBerryBgTilemap2Left[] = INCBIN_U32("graphics/link_games/dodrioberry_bg2left.bin.lz"); - -static const struct OamData sOamData_82FB1E0 = +// Unused duplicate of sUnsharedColumns +static const u8 sUnsharedColumns_Duplicate[MAX_RFU_PLAYERS][MAX_RFU_PLAYERS] = +{ + {5}, + {4, 6}, + {3, 5, 7}, + {2, 4, 6, 8}, + {1, 3, 5, 6, 9}, +}; + +static const u16 sBg_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/bg.gbapal", + "graphics/dodrio_berry_picking/tree_border.gbapal"); +static const u16 sDodrioNormal_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/dodrio.gbapal"); +static const u16 sDodrioShiny_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/shiny.gbapal"); +static const u16 sStatus_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/status.gbapal"); +static const u16 sBerries_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/berries.gbapal"); +static const u32 sBerries_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/berries.4bpp.lz"); +static const u16 sCloud_Pal[] = INCBIN_U16("graphics/dodrio_berry_picking/cloud.gbapal"); +static const u32 sBg_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.4bpp.lz"); +static const u32 sTreeBorder_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border.4bpp.lz"); +static const u32 sStatus_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/status.4bpp.lz"); +static const u32 sCloud_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/cloud.4bpp.lz"); +static const u32 sDodrio_Gfx[] = INCBIN_U32("graphics/dodrio_berry_picking/dodrio.4bpp.lz"); +static const u32 sBg_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/bg.bin.lz"); +static const u32 sTreeBorderRight_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border_right.bin.lz"); +static const u32 sTreeBorderLeft_Tilemap[] = INCBIN_U32("graphics/dodrio_berry_picking/tree_border_left.bin.lz"); + +static const struct OamData sOamData_Dodrio = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3151,7 +3620,8 @@ static const struct OamData sOamData_82FB1E0 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1E8 = +// Used by the status bar and the results screen berry icons +static const struct OamData sOamData_16x16_Priority0 = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3168,7 +3638,7 @@ static const struct OamData sOamData_82FB1E8 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1F0 = +static const struct OamData sOamData_Berry = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3185,7 +3655,7 @@ static const struct OamData sOamData_82FB1F0 = .affineParam = 0 }; -static const struct OamData sOamData_82FB1F8 = +static const struct OamData sOamData_Cloud = { .y = 0, .affineMode = ST_OAM_AFFINE_OFF, @@ -3202,533 +3672,589 @@ static const struct OamData sOamData_82FB1F8 = .affineParam = 0 }; -static const union AnimCmd sSpriteAnim_82FB200[] = +static const union AnimCmd sAnim_Dodrio_Normal[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB208[] = +static const union AnimCmd sAnim_Dodrio_PickRight[] = { ANIMCMD_FRAME(64, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB210[] = +static const union AnimCmd sAnim_Dodrio_PickMiddle[] = { ANIMCMD_FRAME(128, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB218[] = +static const union AnimCmd sAnim_Dodrio_PickLeft[] = { ANIMCMD_FRAME(192, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB220[] = +static const union AnimCmd sAnim_Dodrio_Down[] = { ANIMCMD_FRAME(256, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB228[] = +static const union AnimCmd *const sAnims_Dodrio[] = { - sSpriteAnim_82FB200, - sSpriteAnim_82FB208, - sSpriteAnim_82FB210, - sSpriteAnim_82FB218, - sSpriteAnim_82FB220 + [PICK_NONE] = sAnim_Dodrio_Normal, + [PICK_RIGHT] = sAnim_Dodrio_PickRight, + [PICK_MIDDLE] = sAnim_Dodrio_PickMiddle, + [PICK_LEFT] = sAnim_Dodrio_PickLeft, + [PICK_DISABLED] = sAnim_Dodrio_Down, + // There is an unused 6th frame of Dodrio's graphic }; -static const union AnimCmd sSpriteAnim_82FB23C[] = +static const union AnimCmd sAnims_StatusBar_Yellow[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB244[] = +static const union AnimCmd sAnims_StatusBar_Gray[] = { ANIMCMD_FRAME(4, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB24C[] = +static const union AnimCmd sAnims_StatusBar_Red[] = { ANIMCMD_FRAME(8, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB254[] = +static const union AnimCmd *const sAnims_StatusBar[] = { - sSpriteAnim_82FB23C, - sSpriteAnim_82FB244, - sSpriteAnim_82FB24C + [STATUS_YELLOW] = sAnims_StatusBar_Yellow, + [STATUS_GRAY] = sAnims_StatusBar_Gray, + [STATUS_RED] = sAnims_StatusBar_Red }; -static const union AnimCmd sSpriteAnim_82FB260[] = +static const union AnimCmd sAnim_Berry_Blue[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB268[] = +static const union AnimCmd sAnim_Berry_Green[] = { ANIMCMD_FRAME(4, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB270[] = +static const union AnimCmd sAnim_Berry_Gold[] = { ANIMCMD_FRAME(8, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB278[] = +static const union AnimCmd sAnim_Berry_BlueSquished[] = { ANIMCMD_FRAME(12, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB280[] = +static const union AnimCmd sAnim_Berry_GreenSquished[] = { ANIMCMD_FRAME(16, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB288[] = +static const union AnimCmd sAnim_Berry_GoldSquished[] = { ANIMCMD_FRAME(20, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB290[] = +static const union AnimCmd sAnim_Berry_Eaten[] = { ANIMCMD_FRAME(24, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB298[] = +static const union AnimCmd sAnim_Berry_Empty1[] = { ANIMCMD_FRAME(28, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd sSpriteAnim_82FB2A0[] = +static const union AnimCmd sAnim_Berry_Empty2[] = { ANIMCMD_FRAME(32, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB2A8[] = -{ - sSpriteAnim_82FB260, - sSpriteAnim_82FB268, - sSpriteAnim_82FB270, - sSpriteAnim_82FB278, - sSpriteAnim_82FB280, - sSpriteAnim_82FB288, - sSpriteAnim_82FB290, - sSpriteAnim_82FB298, - sSpriteAnim_82FB2A0 +static const union AnimCmd *const sAnims_Berry[] = +{ + [BERRY_BLUE] = sAnim_Berry_Blue, + [BERRY_GREEN] = sAnim_Berry_Green, + [BERRY_GOLD] = sAnim_Berry_Gold, + + [BERRY_BLUE + BERRY_MISSED] = sAnim_Berry_BlueSquished, + [BERRY_GREEN + BERRY_MISSED] = sAnim_Berry_GreenSquished, + [BERRY_GOLD + BERRY_MISSED] = sAnim_Berry_GoldSquished, + + [ANIM_EATEN] = sAnim_Berry_Eaten, + + sAnim_Berry_Empty1, + sAnim_Berry_Empty2 }; -static const union AnimCmd sSpriteAnim_82FB2CC[] = +static const union AnimCmd sAnim_Cloud[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_JUMP(0) }; -static const union AnimCmd *const sSpriteAnimTable_82FB2D4[] = +static const union AnimCmd *const sAnims_Cloud[] = { - sSpriteAnim_82FB2CC + sAnim_Cloud }; -static void sub_80283A8(void) +static void LoadDodrioGfx(void) { void *ptr = AllocZeroed(0x3000); - struct SpritePalette pal1 = {gDodrioBerryPkmnPal, 0}; - struct SpritePalette pal2 = {gDodrioBerryShinyPal, 1}; + struct SpritePalette normal = {sDodrioNormal_Pal, PALTAG_DODRIO_NORMAL}; + struct SpritePalette shiny = {sDodrioShiny_Pal, PALTAG_DODRIO_SHINY}; - LZ77UnCompWram(gDodrioBerryPkmnGfx, ptr); - // This check should be one line up. - if (ptr != NULL) + LZ77UnCompWram(sDodrio_Gfx, ptr); + if (ptr) { - struct SpriteSheet sheet = {ptr, 0x3000, 0}; + struct SpriteSheet sheet = {ptr, 0x3000, GFXTAG_DODRIO}; LoadSpriteSheet(&sheet); Free(ptr); } - LoadSpritePalette(&pal1); - LoadSpritePalette(&pal2); + LoadSpritePalette(&normal); + LoadSpritePalette(&shiny); } -static void sub_8028408(struct DodrioSubstruct_318C *arg0, u8 arg1, u8 id, u8 arg3) +static void CreateDodrioSprite(struct DodrioGame_MonInfo * monInfo, u8 playerId, u8 id, u8 numPlayers) { - struct SpriteTemplate sprTemplate = + struct SpriteTemplate template = { - .tileTag = 0, - .paletteTag = arg0->isShiny, - .oam = &sOamData_82FB1E0, - .anims = sSpriteAnimTable_82FB228, + .tileTag = GFXTAG_DODRIO, + .paletteTag = monInfo->isShiny, // PALTAG_DODRIO_NORMAL / PALTAG_DODRIO_SHINY + .oam = &sOamData_Dodrio, + .anims = sAnims_Dodrio, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_80284A8, + .callback = SpriteCB_Dodrio, }; - gUnknown_02022C9C[id] = AllocZeroed(4); - *gUnknown_02022C9C[id] = CreateSprite(&sprTemplate, sub_8028F14(arg1, arg3), 136, 3); - sub_8028654(TRUE, id); + sDodrioSpriteIds[id] = AllocZeroed(4); + *sDodrioSpriteIds[id] = CreateSprite(&template, GetDodrioXPos(playerId, numPlayers), 136, 3); + SetDodrioInvisibility(TRUE, id); } -static void sub_80284A8(struct Sprite *sprite) +#define sState data[0] +#define sTimer data[1] +#define sUnused1 data[2] +#define sUnused2 data[3] +#define sUnused3 data[4] + +static void SpriteCB_Dodrio(struct Sprite *sprite) { - switch (sprite->data[0]) + switch (sprite->sState) { case 0: break; case 1: - sub_802853C(sprite); + DoDodrioMissedAnim(sprite); break; case 2: - sub_80285AC(sprite); + DoDodrioIntroAnim(sprite); break; } } -static void sub_80284CC(u8 unused) +static void StartDodrioMissedAnim(u8 unused) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[GetMultiplayerId()]]; - sprite->data[0] = 1; - sprite->data[1] = 0; - sprite->data[2] = 0; - sprite->data[3] = 0; - sprite->data[4] = 0; + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[GetMultiplayerId()]]; + sprite->sState = 1; + sprite->sTimer = 0; + sprite->sUnused1 = 0; + sprite->sUnused2 = 0; + sprite->sUnused3 = 0; } -static void sub_8028504(u8 unused) +static void StartDodrioIntroAnim(u8 unused) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[GetMultiplayerId()]]; - sprite->data[0] = 2; - sprite->data[1] = 0; - sprite->data[2] = 0; - sprite->data[3] = 0; - sprite->data[4] = 0; + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[GetMultiplayerId()]]; + sprite->sState = 2; + sprite->sTimer = 0; + sprite->sUnused1 = 0; + sprite->sUnused2 = 0; + sprite->sUnused3 = 0; } -static u32 sub_802853C(struct Sprite *sprite) +// Do animation where Dodrio shakes horizontally after reaching for a berry and missing +static u32 DoDodrioMissedAnim(struct Sprite *sprite) { - s8 var; - u8 mod = (++sprite->data[1] / 2) % 4; + s8 x; + u8 state = (++sprite->sTimer / 2) % 4; - if (sprite->data[1] >= 3) + if (sprite->sTimer >= 3) { - switch (mod) + switch (state) { default: - var = 1; + x = 1; break; case 1: case 2: - var = -1; + x = -1; break; } - sprite->pos1.x += var; - if (++sprite->data[1] >= 40) + sprite->pos1.x += x; + if (++sprite->sTimer >= 40) { - sprite->data[0] = 0; - sprite->pos1.x = sub_8028F14(0, sub_8027650()); + sprite->sState = 0; + sprite->pos1.x = GetDodrioXPos(0, GetNumPlayers()); } } return 0; } -static u32 sub_80285AC(struct Sprite *sprite) +// Does the intro animation where the player's Dodrio +// cycles through extending each head twice +#define FRAMES_PER_STATE 13 +#define NUM_INTRO_PICK_STATES PICK_DISABLED // Cycle through 'Normal' and each head, but exclude the Disabled state + +static u32 DoDodrioIntroAnim(struct Sprite *sprite) { - u8 mod = (++sprite->data[1] / 13) % 4; + u8 pickState = (++sprite->sTimer / FRAMES_PER_STATE) % NUM_INTRO_PICK_STATES; - if (sprite->data[1] % 13 == 0 && mod != 0) + // Play a sound effect at the start of each head extension + if (sprite->sTimer % FRAMES_PER_STATE == 0 && pickState != PICK_NONE) PlaySE(SE_M_CHARM); - if (sprite->data[1] >= 104) + + if (sprite->sTimer >= FRAMES_PER_STATE * NUM_INTRO_PICK_STATES * 2) { - sprite->data[0] = 0; - mod = 0; + // End animation + sprite->sState = 0; + pickState = PICK_NONE; } - sub_80286B4(GetMultiplayerId(), mod); + SetDodrioAnim(GetMultiplayerId(), pickState); return 0; } -static void sub_8028614(u8 count) +#undef sState +#undef sTimer +#undef sUnused1 +#undef sUnused2 +#undef sUnused3 + +static void FreeDodrioSprites(u8 numPlayers) { u8 i; - for (i = 0; i < count; i++) + for (i = 0; i < numPlayers; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022C9C[i]]; - if (sprite != NULL) + struct Sprite *sprite = &gSprites[*sDodrioSpriteIds[i]]; + if (sprite) DestroySpriteAndFreeResources(sprite); - // Memory should be freed here but is not. +#ifdef BUGFIX + FREE_AND_SET_NULL(sDodrioSpriteIds[i]); // Memory should be freed here but is not. +#endif } } -static void sub_8028654(bool8 invisible, u8 id) +static void SetDodrioInvisibility(bool8 invisible, u8 id) { - gSprites[*gUnknown_02022C9C[id]].invisible = invisible; + gSprites[*sDodrioSpriteIds[id]].invisible = invisible; } -static void sub_802868C(bool8 invisible, u8 count) +static void SetAllDodrioInvisibility(bool8 invisible, u8 count) { u8 i; for (i = 0; i < count; i++) - sub_8028654(invisible, i); + SetDodrioInvisibility(invisible, i); } -static void sub_80286B4(u8 id, u8 frameNum) +static void SetDodrioAnim(u8 id, u8 pickState) { - StartSpriteAnim(&gSprites[*gUnknown_02022C9C[id]], frameNum); + StartSpriteAnim(&gSprites[*sDodrioSpriteIds[id]], pickState); } -static void nullsub_15(struct Sprite *sprite) +static void SpriteCB_Status(struct Sprite *sprite) { } -static void sub_80286E4(void) +static void InitStatusBarPos(void) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; sprite->pos1.x = (i * 16) + 48; sprite->pos1.y = -8 - (i * 8); - gUnknown_02022CF4->unkC[i] = 0; + sStatusBar->entered[i] = FALSE; } } -static void sub_8028734(void) +static void CreateStatusBarSprites(void) { u8 i; void *ptr = AllocZeroed(0x180); - struct SpritePalette spPal = {gDodrioBerryStatusPal, 2}; + struct SpritePalette pal = {sStatus_Pal, PALTAG_STATUS}; - LZ77UnCompWram(gDodrioBerryStatusGfx, ptr); + LZ77UnCompWram(sStatus_Gfx, ptr); // This check should be one line up. - if (ptr != NULL) + if (ptr) { - struct SpriteSheet spSheet = {ptr, 0x180, 1}; - struct SpriteTemplate spTemplate = + struct SpriteSheet sheet = {ptr, 0x180, GFXTAG_STATUS}; + struct SpriteTemplate template = { - .tileTag = 1, - .paletteTag = 2, - .oam = &sOamData_82FB1E8, - .anims = sSpriteAnimTable_82FB254, + .tileTag = GFXTAG_STATUS, + .paletteTag = PALTAG_STATUS, + .oam = &sOamData_16x16_Priority0, + .anims = sAnims_StatusBar, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = nullsub_15, + .callback = SpriteCB_Status, }; - gUnknown_02022CF4 = AllocZeroed(sizeof(*gUnknown_02022CF4)); - LoadSpriteSheet(&spSheet); - LoadSpritePalette(&spPal); - for (i = 0; i < 10; i++) - gUnknown_02022CF4->unk2A[i] = CreateSprite(&spTemplate, (i * 16) + 48, -8 - (i * 8), 0); + sStatusBar = AllocZeroed(sizeof(*sStatusBar)); + LoadSpriteSheet(&sheet); + LoadSpritePalette(&pal); + for (i = 0; i < NUM_STATUS_SQUARES; i++) + sStatusBar->spriteIds[i] = CreateSprite(&template, (i * 16) + 48, -8 - (i * 8), 0); } Free(ptr); } -static void sub_80287E4(void) +static void FreeStatusBar(void) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; - if (sprite != NULL) + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; + if (sprite) DestroySpriteAndFreeResources(sprite); } - FREE_AND_SET_NULL(gUnknown_02022CF4); + FREE_AND_SET_NULL(sStatusBar); } -static bool32 sub_8028828(void) +// Progress an animation where each square of the +// status bar drops down into view, bounces up, +// then settles into position. +// Returns TRUE if the animation is complete +static bool32 DoStatusBarIntro(void) { u8 i; - bool32 r3 = FALSE; - for (i = 0; i < 10; i++) + bool32 animActive = FALSE; + for (i = 0; i < NUM_STATUS_SQUARES; i++) { - struct Sprite *sprite = &gSprites[gUnknown_02022CF4->unk2A[i]]; - gUnknown_02022CF4->unk16[i] = 2; - if (gUnknown_02022CF4->unkC[i] != 0 && sprite->pos1.y == 8) + struct Sprite *sprite = &gSprites[sStatusBar->spriteIds[i]]; + sStatusBar->yChange[i] = 2; + if (sStatusBar->entered[i] && sprite->pos1.y == 8) continue; - r3 = TRUE; + + animActive = TRUE; if (sprite->pos1.y == 8) { - if (gUnknown_02022CF4->unkC[i] != 0) + if (sStatusBar->entered[i]) continue; - gUnknown_02022CF4->unkC[i] = 1; - gUnknown_02022CF4->unk16[i] = -16; + + // Square has entered screen, play click + // sound and reverse direction + sStatusBar->entered[i] = TRUE; + sStatusBar->yChange[i] = -16; PlaySE(SE_CLICK); } - sprite->pos1.y += gUnknown_02022CF4->unk16[i]; + sprite->pos1.y += sStatusBar->yChange[i]; } - if (r3) + if (animActive) return FALSE; else return TRUE; } -static void sub_80288D4(u8 arg0) +// The status bar at the top changes color depending on the game performance. +// The squares start out yellow. For every berry missed, a square is colored gray. +// If there are 4 or fewer yellow squares left they also flash red +static void UpdateStatusBarAnim(u8 numEmpty) { u8 i; - if (arg0 > 10) + if (numEmpty > NUM_STATUS_SQUARES) { - for (i = 0; i < 10; i++) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 1); + // All squares gray + for (i = 0; i < NUM_STATUS_SQUARES; i++) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_GRAY); } else { - for (i = 0; i < 10 - arg0; i++) + // At least 1 square is yellow + for (i = 0; i < NUM_STATUS_SQUARES - numEmpty; i++) { - if (arg0 > 6) + if (numEmpty > 6) { - gUnknown_02022CF4->unk3E += arg0 - 6; - if (gUnknown_02022CF4->unk3E > 30) - gUnknown_02022CF4->unk3E = 0; - else if (gUnknown_02022CF4->unk3E > 10) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 2); + // Flash the yellow squares red + // The flash cycles faster the fewer yellow squares remain + sStatusBar->flashTimer += numEmpty - 6; + if (sStatusBar->flashTimer > 30) + sStatusBar->flashTimer = 0; + else if (sStatusBar->flashTimer > 10) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_RED); else - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 0); + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_YELLOW); } else { - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 0); + // Set yellow squares, no flash + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_YELLOW); } } - for (; i < 10; i++) - StartSpriteAnim(&gSprites[gUnknown_02022CF4->unk2A[i]], 1); + + // Set remaining squares gray + for (; i < NUM_STATUS_SQUARES; i++) + StartSpriteAnim(&gSprites[sStatusBar->spriteIds[i]], STATUS_GRAY); } } -static void sub_80289E8(bool8 invisible) +static void SetStatusBarInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 10; i++) - gSprites[gUnknown_02022CF4->unk2A[i]].invisible = invisible; -} - -// Unknown unused data, feel free to remove. -static const u8 sUnused2[] = {0xD4, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0xFB, 0x0, 0x0}; + for (i = 0; i < NUM_STATUS_SQUARES; i++) + gSprites[sStatusBar->spriteIds[i]].invisible = invisible; +} + +static const u8 sUnusedSounds[] = { + SE_M_CHARM, + SE_NOTE_C, + SE_NOTE_D, + SE_NOTE_E, + SE_NOTE_F, + SE_NOTE_G, + SE_NOTE_A, + SE_NOTE_B, + SE_NOTE_C_HIGH, + SE_RG_CARD_OPEN +}; -static void sub_8028A34(void) +static void LoadBerryGfx(void) { void *ptr = AllocZeroed(0x480); - struct SpritePalette sprPal = {gDodrioBerrySpritesPal, 3}; + struct SpritePalette pal = {sBerries_Pal, PALTAG_BERRIES}; - LZ77UnCompWram(gDodrioBerrySpritesGfx, ptr); - if (ptr != NULL) + LZ77UnCompWram(sBerries_Gfx, ptr); + if (ptr) { - struct SpriteSheet sprSheet = {ptr, 0x480, 2}; - LoadSpriteSheet(&sprSheet); + struct SpriteSheet sheet = {ptr, 0x480, GFXTAG_BERRIES}; + LoadSpriteSheet(&sheet); } - LoadSpritePalette(&sprPal); + LoadSpritePalette(&pal); Free(ptr); } -static const s16 gUnknown_082FB31C[] = {88, 128, 168, 208}; +static const s16 sBerryIconXCoords[] = {88, 128, 168, 208}; -static void sub_8028A88(void) +static void CreateBerrySprites(void) { u8 i; s16 x; - struct SpriteTemplate sprTemplate1 = + struct SpriteTemplate berry = { - .tileTag = 2, - .paletteTag = 3, - .oam = &sOamData_82FB1F0, - .anims = sSpriteAnimTable_82FB2A8, + .tileTag = GFXTAG_BERRIES, + .paletteTag = PALTAG_BERRIES, + .oam = &sOamData_Berry, + .anims = sAnims_Berry, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; - struct SpriteTemplate sprTemplate2 = + struct SpriteTemplate berryIcon = { - .tileTag = 2, - .paletteTag = 3, - .oam = &sOamData_82FB1E8, - .anims = sSpriteAnimTable_82FB2A8, + .tileTag = GFXTAG_BERRIES, + .paletteTag = PALTAG_BERRIES, + .oam = &sOamData_16x16_Priority0, + .anims = sAnims_Berry, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; - for (i = 0; i < 11; i++) + // Create berry sprites that fall during gameplay + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - gUnknown_02022CB8[i] = AllocZeroed(4); + sBerrySpriteIds[i] = AllocZeroed(4); x = i * 16; - *gUnknown_02022CB8[i] = CreateSprite(&sprTemplate1, x + (i * 8), 8, 1); - sub_8028BF8(i, TRUE); + *sBerrySpriteIds[i] = CreateSprite(&berry, x + (i * 8), 8, 1); + SetBerryInvisibility(i, TRUE); } - for (i = 0; i < 4; i++) + + // Create berry icon sprites for results screen + for (i = 0; i < NUM_BERRY_TYPES; i++) { - gUnknown_02022CE4[i] = AllocZeroed(4); - if (i == 3) - *gUnknown_02022CE4[i] = CreateSprite(&sprTemplate2, gUnknown_082FB31C[i], 49, 0); + sBerryIconSpriteIds[i] = AllocZeroed(4); + if (i == BERRY_MISSED) + *sBerryIconSpriteIds[i] = CreateSprite(&berryIcon, sBerryIconXCoords[i], 49, 0); else - *gUnknown_02022CE4[i] = CreateSprite(&sprTemplate2, gUnknown_082FB31C[i], 52, 0); - StartSpriteAnim(&gSprites[*gUnknown_02022CE4[i]], i); + *sBerryIconSpriteIds[i] = CreateSprite(&berryIcon, sBerryIconXCoords[i], 52, 0); + StartSpriteAnim(&gSprites[*sBerryIconSpriteIds[i]], i); } - - sub_8028C30(TRUE); + SetBerryIconsInvisibility(TRUE); } -static void sub_8028B80(void) +static void FreeBerrySprites(void) { struct Sprite *sprite; u8 i; - for (i = 0; i < 11; i++) + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - sprite = &gSprites[*gUnknown_02022CB8[i]]; - if (sprite != NULL) + sprite = &gSprites[*sBerrySpriteIds[i]]; + if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CB8[i]); + FREE_AND_SET_NULL(sBerrySpriteIds[i]); } - for (i = 0; i < 4; i++) + for (i = 0; i < NUM_BERRY_TYPES; i++) { - sprite = &gSprites[*gUnknown_02022CE4[i]]; - if (sprite != NULL) + sprite = &gSprites[*sBerryIconSpriteIds[i]]; + if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CE4[i]); + FREE_AND_SET_NULL(sBerryIconSpriteIds[i]); } } -static void sub_8028BF8(u8 id, bool8 invisible) +static void SetBerryInvisibility(u8 id, bool8 invisible) { - gSprites[*gUnknown_02022CB8[id]].invisible = invisible; + gSprites[*sBerrySpriteIds[id]].invisible = invisible; } -static void sub_8028C30(bool8 invisible) +static void SetBerryIconsInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 4; i++) - gSprites[*gUnknown_02022CE4[i]].invisible = invisible; + for (i = 0; i < NUM_BERRY_TYPES; i++) + gSprites[*sBerryIconSpriteIds[i]].invisible = invisible; } -static void sub_8028C7C(u8 id, u8 y) +static void SetBerryYPos(u8 id, u8 y) { - gSprites[*gUnknown_02022CB8[id]].pos1.y = y * 8; + gSprites[*sBerrySpriteIds[id]].pos1.y = y * 8; } -static void sub_8028CA4(u16 id, u8 frameNum) +static void SetBerryAnim(u16 id, u8 animNum) { - StartSpriteAnim(&gSprites[*gUnknown_02022CB8[id]], frameNum); + StartSpriteAnim(&gSprites[*sBerrySpriteIds[id]], animNum); } // Unused -static void sub_8028CD0(u8 spriteId) +static void UnusedSetSpritePos(u8 spriteId) { gSprites[spriteId].pos1.x = 20 * spriteId + 50; gSprites[spriteId].pos1.y = 50; @@ -3736,125 +4262,129 @@ static void sub_8028CD0(u8 spriteId) // Gamefreak made a mistake there and goes out of bounds for the data array as it holds 8 elements // in turn overwriting sprite's subpriority and subsprites fields. -#if defined(NONMATCHING) || MODERN - #define sKeepPosX data[1] +#ifdef UBFIX + #define sFrozen data[1] #else - #define sKeepPosX data[10] -#endif // NONMATCHING + #define sFrozen data[10] +#endif // UBFIX -static void sub_8028CF4(struct Sprite *sprite) +static void SpriteCB_Cloud(struct Sprite *sprite) { u8 i; - static const u8 array[] = {30, 20}; + static const u8 moveDelays[] = {30, 20}; - if (sprite->sKeepPosX != TRUE) + if (sprite->sFrozen != TRUE) { - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - if (++gUnknown_02022CB0[i][1] > array[i]) + if (++sCloudSpriteIds[i][1] > moveDelays[i]) { sprite->pos1.x--; - gUnknown_02022CB0[i][1] = 0; + sCloudSpriteIds[i][1] = 0; } } } } -static const s16 gUnknown_082FB356[][2] = {{230, 55}, {30, 74}}; +static const s16 sCloudStartCoords[NUM_CLOUDS][2] = +{ + {230, 55}, + { 30, 74} +}; -static void sub_8028D44(void) +static void CreateCloudSprites(void) { u8 i; void *ptr = AllocZeroed(0x400); - struct SpritePalette sprPal = {gDodrioBerryPlatformPal, 6}; + struct SpritePalette pal = {sCloud_Pal, PALTAG_CLOUD}; - LZ77UnCompWram(gDodrioBerryPlatformGfx, ptr); - if (ptr != NULL) + LZ77UnCompWram(sCloud_Gfx, ptr); + if (ptr) { - struct SpriteSheet sprSheet = {ptr, 0x400, 5}; - struct SpriteTemplate sprTemplate = + struct SpriteSheet sheet = {ptr, 0x400, GFXTAG_CLOUD}; + struct SpriteTemplate template = { - .tileTag = 5, - .paletteTag = 6, - .oam = &sOamData_82FB1F8, - .anims = sSpriteAnimTable_82FB2D4, + .tileTag = GFXTAG_CLOUD, + .paletteTag = PALTAG_CLOUD, + .oam = &sOamData_Cloud, + .anims = sAnims_Cloud, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, - .callback = sub_8028CF4, + .callback = SpriteCB_Cloud, }; - LoadSpriteSheet(&sprSheet); - LoadSpritePalette(&sprPal); - for (i = 0; i < 2; i++) + LoadSpriteSheet(&sheet); + LoadSpritePalette(&pal); + for (i = 0; i < NUM_CLOUDS; i++) { - gUnknown_02022CB0[i] = AllocZeroed(4); - *gUnknown_02022CB0[i] = CreateSprite(&sprTemplate, gUnknown_082FB356[i][0], gUnknown_082FB356[i][1], 4); + sCloudSpriteIds[i] = AllocZeroed(4); + *sCloudSpriteIds[i] = CreateSprite(&template, sCloudStartCoords[i][0], sCloudStartCoords[i][1], 4); } } Free(ptr); } -static void sub_8028DFC(void) +static void ResetCloudPos(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; - sprite->sKeepPosX = TRUE; - sprite->pos1.x = gUnknown_082FB356[i][0]; - sprite->pos1.y = gUnknown_082FB356[i][1]; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; + sprite->sFrozen = TRUE; + sprite->pos1.x = sCloudStartCoords[i][0]; + sprite->pos1.y = sCloudStartCoords[i][1]; } } -static void sub_8028E4C(void) +static void StartCloudMovement(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; - sprite->sKeepPosX = FALSE; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; + sprite->sFrozen = FALSE; } } -static void sub_8028E84(void) +static void FreeCloudSprites(void) { u8 i; - for (i = 0; i < 2; i++) + for (i = 0; i < NUM_CLOUDS; i++) { - struct Sprite *sprite = &gSprites[*gUnknown_02022CB0[i]]; + struct Sprite *sprite = &gSprites[*sCloudSpriteIds[i]]; if (sprite) DestroySprite(sprite); - FREE_AND_SET_NULL(gUnknown_02022CB0[i]); + FREE_AND_SET_NULL(sCloudSpriteIds[i]); } } -static void sub_8028EC8(bool8 invisible) +static void SetCloudInvisibility(bool8 invisible) { u8 i; - for (i = 0; i < 2; i++) - gSprites[*gUnknown_02022CB0[i]].invisible = invisible; + for (i = 0; i < NUM_CLOUDS; i++) + gSprites[*sCloudSpriteIds[i]].invisible = invisible; } -#undef sKeepPosX +#undef sFrozen -static s16 sub_8028F14(u8 arg0, u8 arg1) +static s16 GetDodrioXPos(u8 playerId, u8 numPlayers) { s16 x = 0; - switch (arg1) + switch (numPlayers) { case 1: x = 15; break; case 2: - switch (arg0) + switch (playerId) { case 0: x = 12; break; case 1: x = 18; break; } break; case 3: - switch (arg0) + switch (playerId) { case 0: x = 15; break; case 1: x = 21; break; @@ -3862,7 +4392,7 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) } break; case 4: - switch (arg0) + switch (playerId) { case 0: x = 12; break; case 1: x = 18; break; @@ -3871,7 +4401,7 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) } break; case 5: - switch (arg0) + switch (playerId) { case 0: x = 15; break; case 1: x = 21; break; @@ -3885,78 +4415,79 @@ static s16 sub_8028F14(u8 arg0, u8 arg1) return x * 8; } -static void sub_8028FCC(void) +static void ResetBerryAndStatusBarSprites(void) { u8 i; - for (i = 0; i < 11; i++) + for (i = 0; i < NUM_BERRY_COLUMNS; i++) { - sub_8028BF8(i, TRUE); - sub_8028C7C(i, 1); + SetBerryInvisibility(i, TRUE); + SetBerryYPos(i, 1); } - sub_80289E8(FALSE); + SetStatusBarInvisibility(FALSE); } -static void sub_8028FF8(u8 frameId) +static void LoadWindowFrameGfx(u8 frameId) { - LoadBgTiles(0, GetWindowFrameTilesPal(frameId)->tiles, 0x120, 1); + LoadBgTiles(BG_INTERFACE, GetWindowFrameTilesPal(frameId)->tiles, 0x120, 1); LoadPalette(GetWindowFrameTilesPal(frameId)->pal, 0xA0, 0x20); } -static void sub_802902C(void) +static void LoadUserWindowFrameGfx(void) { LoadUserWindowBorderGfx_(0, 0xA, 0xB0); } -static void sub_802903C(void) +static void ResetGfxState(void) { - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->unk3018 = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + sGfx->finished = FALSE; + sGfx->state = 0; + sGfx->loadState = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; } -static void sub_8029074(const struct WindowTemplate *winTempl) +static void DrawYesNoMessageWindow(const struct WindowTemplate *template) { - u8 pal = 0xA; + u8 pal = 10; - FillBgTilemapBufferRect(0, 1, winTempl->tilemapLeft - 1, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 2, winTempl->tilemapLeft, winTempl->tilemapTop - 1, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 3, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 4, winTempl->tilemapLeft - 1, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 6, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 7, winTempl->tilemapLeft - 1, winTempl->tilemapTop + winTempl->height, 1, 1, pal); - FillBgTilemapBufferRect(0, 8, winTempl->tilemapLeft, winTempl->tilemapTop + winTempl->height, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 9, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop + winTempl->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 1, template->tilemapLeft - 1, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 2, template->tilemapLeft, template->tilemapTop - 1, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 3, template->tilemapLeft + template->width, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 4, template->tilemapLeft - 1, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 6, template->tilemapLeft + template->width, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 7, template->tilemapLeft - 1, template->tilemapTop + template->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 8, template->tilemapLeft, template->tilemapTop + template->height, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 9, template->tilemapLeft + template->width, template->tilemapTop + template->height, 1, 1, pal); } -static void sub_8029174(const struct WindowTemplate *winTempl) +static void DrawMessageWindow(const struct WindowTemplate *template) { - u8 pal = 0xB; + u8 pal = 11; - FillBgTilemapBufferRect(0, 10, winTempl->tilemapLeft - 1, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 11, winTempl->tilemapLeft, winTempl->tilemapTop - 1, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 12, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop - 1, 1, 1, pal); - FillBgTilemapBufferRect(0, 13, winTempl->tilemapLeft - 1, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 15, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop, 1, winTempl->height, pal); - FillBgTilemapBufferRect(0, 16, winTempl->tilemapLeft - 1, winTempl->tilemapTop + winTempl->height, 1, 1, pal); - FillBgTilemapBufferRect(0, 17, winTempl->tilemapLeft, winTempl->tilemapTop + winTempl->height, winTempl->width, 1, pal); - FillBgTilemapBufferRect(0, 18, winTempl->tilemapLeft + winTempl->width, winTempl->tilemapTop + winTempl->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 10, template->tilemapLeft - 1, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 11, template->tilemapLeft, template->tilemapTop - 1, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 12, template->tilemapLeft + template->width, template->tilemapTop - 1, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 13, template->tilemapLeft - 1, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 15, template->tilemapLeft + template->width, template->tilemapTop, 1, template->height, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 16, template->tilemapLeft - 1, template->tilemapTop + template->height, 1, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 17, template->tilemapLeft, template->tilemapTop + template->height, template->width, 1, pal); + FillBgTilemapBufferRect(BG_INTERFACE, 18, template->tilemapLeft + template->width, template->tilemapTop + template->height, 1, 1, pal); } -static void sub_8029274(struct DodrioSubstruct_0160 *ptr) +static void InitGameGfx(struct DodrioGame_Gfx *ptr) { - gUnknown_02022CF8 = ptr; - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->unk3018 = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; - gUnknown_02022CF8->unk3004 = CreateTask(sub_8029314, 3); - sub_802A72C(sub_8029338); + sGfx = ptr; + sGfx->finished = FALSE; + sGfx->state = 0; + sGfx->loadState = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; + sGfx->taskId = CreateTask(Task_TryRunGfxFunc, 3); + SetGfxFunc(LoadGfx); } -static void sub_80292D4(void) +// Unused +static void FreeAllWindowBuffers_(void) { FreeAllWindowBuffers(); } @@ -3968,30 +4499,37 @@ struct WinCoords u8 top; }; +enum { + COLORID_GREY, + COLORID_RED, + COLORID_BLUE, + COLORID_GREEN, // Unused +}; + static const u8 sTextColorTable[][3] = { - {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, - {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, - {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, - {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, + [COLORID_GREY] = {TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY, TEXT_COLOR_LIGHT_GREY}, + [COLORID_RED] = {TEXT_COLOR_WHITE, TEXT_COLOR_RED, TEXT_COLOR_LIGHT_RED}, + [COLORID_BLUE] = {TEXT_COLOR_WHITE, TEXT_COLOR_BLUE, TEXT_COLOR_LIGHT_BLUE}, + [COLORID_GREEN] = {TEXT_COLOR_WHITE, TEXT_COLOR_GREEN, TEXT_COLOR_LIGHT_GREEN}, }; -static const struct WinCoords gUnknown_082FB38C[] = {{12, 6}}; -static const struct WinCoords gUnknown_082FB390[] = {{9, 10}, {15, 6}}; -static const struct WinCoords gUnknown_082FB398[] = {{12, 6}, {18, 10}, {6, 10}}; -static const struct WinCoords gUnknown_082FB3A4[] = {{9, 10}, {15, 6}, {21, 10}, {3, 6}}; -static const struct WinCoords gUnknown_082FB3B4[] = {{12, 6}, {18, 10}, {23, 6}, {1, 6}, {6, 10}}; +static const struct WinCoords sNameWindowCoords_1Player[] = {{12, 6}}; +static const struct WinCoords sNameWindowCoords_2Players[] = {{9, 10}, {15, 6}}; +static const struct WinCoords sNameWindowCoords_3Players[] = {{12, 6}, {18, 10}, {6, 10}}; +static const struct WinCoords sNameWindowCoords_4Players[] = {{9, 10}, {15, 6}, {21, 10}, {3, 6}}; +static const struct WinCoords sNameWindowCoords_5Players[] = {{12, 6}, {18, 10}, {23, 6}, {1, 6}, {6, 10}}; -static const struct WinCoords *const gUnknown_082FB3C8[] = +static const struct WinCoords *const sNameWindowCoords[MAX_RFU_PLAYERS] = { - gUnknown_082FB38C, - gUnknown_082FB390, - gUnknown_082FB398, - gUnknown_082FB3A4, - gUnknown_082FB3B4, + sNameWindowCoords_1Player, + sNameWindowCoords_2Players, + sNameWindowCoords_3Players, + sNameWindowCoords_4Players, + sNameWindowCoords_5Players, }; -static const u8 *const gUnknown_082FB3DC[] = +static const u8 *const sRankingTexts[MAX_RFU_PLAYERS] = { gText_1Colon, gText_2Colon, @@ -4000,625 +4538,640 @@ static const u8 *const gUnknown_082FB3DC[] = gText_5Colon, }; -static const u16 gUnknown_082FB3F0[] = {92, 132, 172, 212}; -static const u16 gUnknown_082FB3F8[] = {33, 49, 65, 81, 97}; -static const u16 gUnknown_082FB402[] = {17, 33, 49, 65, 81}; +static const u16 sResultsXCoords[] = {92, 132, 172, 212}; +static const u16 sResultsYCoords[] = {33, 49, 65, 81, 97}; +static const u16 sRankingYCoords[] = {17, 33, 49, 65, 81}; struct { u8 id; void (*func)(void); -} const gUnknown_082FB40C[] = -{ - {0, sub_8029338}, - {1, sub_8029440}, - {2, sub_802988C}, - {3, sub_802A010}, - {4, sub_802A380}, - {5, sub_802A454}, - {6, sub_802A534}, - {7, sub_802A588}, - {8, sub_802A6FC}, - {9, nullsub_16}, +} const sGfxFuncs[] = +{ + {GFXFUNC_LOAD, LoadGfx}, // Element not used, LoadGfx is passed directly to SetGfxFunc + {GFXFUNC_SHOW_NAMES, ShowNames}, + {GFXFUNC_SHOW_RESULTS, ShowResults}, + {GFXFUNC_MSG_PLAY_AGAIN, Msg_WantToPlayAgain}, + {GFXFUNC_MSG_SAVING, Msg_SavingDontTurnOff}, + {GFXFUNC_MSG_COMM_STANDBY, Msg_CommunicationStandby}, + {GFXFUNC_ERASE_MSG, EraseMessage}, + {GFXFUNC_MSG_PLAYER_DROPPED, Msg_SomeoneDroppedOut}, + {GFXFUNC_STOP, StopGfxFuncs}, + {GFXFUNC_IDLE, GfxIdle}, }; -static void sub_80292E0(u8 arg0) +static void SetGfxFuncById(u8 funcId) { u8 i; - for (i = 0; i < 10; i++) + for (i = 0; i < ARRAY_COUNT(sGfxFuncs); i++) { - if (gUnknown_082FB40C[i].id == arg0) - sub_802A72C(gUnknown_082FB40C[i].func); + if (sGfxFuncs[i].id == funcId) + SetGfxFunc(sGfxFuncs[i].func); } } -static void sub_8029314(u8 taskId) +static void Task_TryRunGfxFunc(u8 taskId) { - if (!gUnknown_02022CF8->finished) - sub_802A75C()(); + // Continue calling function until it + // has reached its finished state. + // Another will not be called until + // readied by SetGfxFunc + if (!sGfx->finished) + GetGfxFunc()(); } -static void sub_8029338(void) +static void LoadGfx(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - sub_802A7A8(); - gUnknown_02022CF8->state++; + InitBgs(); + sGfx->state++; break; case 1: - if (sub_802A8E8() == TRUE) - gUnknown_02022CF8->state++; + if (LoadBgGfx() == TRUE) + sGfx->state++; break; case 2: - CopyToBgTilemapBuffer(3, gDodrioBerryBgTilemap1, 0, 0); - CopyToBgTilemapBuffer(1, gDodrioBerryBgTilemap2Left, 0, 0); - CopyToBgTilemapBuffer(2, gDodrioBerryBgTilemap2Right, 0, 0); - CopyBgTilemapBufferToVram(3); - CopyBgTilemapBufferToVram(1); - CopyBgTilemapBufferToVram(2); - gUnknown_02022CF8->state++; + CopyToBgTilemapBuffer(BG_SCENERY, sBg_Tilemap, 0, 0); + CopyToBgTilemapBuffer(BG_TREE_LEFT, sTreeBorderLeft_Tilemap, 0, 0); + CopyToBgTilemapBuffer(BG_TREE_RIGHT, sTreeBorderRight_Tilemap, 0, 0); + CopyBgTilemapBufferToVram(BG_SCENERY); + CopyBgTilemapBufferToVram(BG_TREE_LEFT); + CopyBgTilemapBufferToVram(BG_TREE_RIGHT); + sGfx->state++; break; case 3: - ShowBg(0); - ShowBg(3); - ShowBg(1); - ShowBg(2); - gUnknown_02022CF8->state++; + ShowBg(BG_INTERFACE); + ShowBg(BG_SCENERY); + ShowBg(BG_TREE_LEFT); + ShowBg(BG_TREE_RIGHT); + sGfx->state++; break; case 4: - sub_8028FF8(gSaveBlock2Ptr->optionsWindowFrameType); - sub_802902C(); - gUnknown_02022CF8->state++; + LoadWindowFrameGfx(gSaveBlock2Ptr->optionsWindowFrameType); + LoadUserWindowFrameGfx(); + sGfx->state++; break; default: - gUnknown_02022CF8->finished = TRUE; + sGfx->finished = TRUE; break; } } -static void sub_8029440(void) +static void ShowNames(void) { - u8 i, playersCount, id, colorsId, *name; + u8 i, numPlayers, playerId, colorsId, *name; u32 left; struct WindowTemplate window; - const struct WinCoords *ptr; + const struct WinCoords *coords; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - playersCount = sub_8027650(); - ptr = gUnknown_082FB3C8[playersCount - 1]; - window.bg = 0; + numPlayers = GetNumPlayers(); + coords = sNameWindowCoords[numPlayers - 1]; + window.bg = BG_INTERFACE; window.width = 7; window.height = 2; - window.paletteNum = 0xD; + window.paletteNum = 13; window.baseBlock = 0x13; - for (i = 0; i < playersCount; ptr++, i++) + for (i = 0; i < numPlayers; coords++, i++) { - colorsId = 0; - id = sub_8027A48(i); - left = (56 - GetStringWidth(1, sub_8027660(id), -1)) / 2u; - window.tilemapLeft = ptr->left; - window.tilemapTop = ptr->top; - gUnknown_02022CF8->unk3008[i] = AddWindow(&window); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[i]); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[i], PIXEL_FILL(1)); - if (id == GetMultiplayerId()) - colorsId = 2; - name = sub_8027660(id); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[i], 1, left, 1, sTextColorTable[colorsId], -1, name); - CopyWindowToVram(gUnknown_02022CF8->unk3008[i], 2); + colorsId = COLORID_GREY; + playerId = GetPlayerIdByPos(i); + left = (56 - GetStringWidth(1, GetPlayerName(playerId), -1)) / 2u; + window.tilemapLeft = coords->left; + window.tilemapTop = coords->top; + sGfx->windowIds[i] = AddWindow(&window); + ClearWindowTilemap(sGfx->windowIds[i]); + FillWindowPixelBuffer(sGfx->windowIds[i], PIXEL_FILL(1)); + if (playerId == GetMultiplayerId()) + colorsId = COLORID_BLUE; + name = GetPlayerName(playerId); + AddTextPrinterParameterized3(sGfx->windowIds[i], 1, left, 1, sTextColorTable[colorsId], -1, name); + CopyWindowToVram(sGfx->windowIds[i], 2); window.baseBlock += 0xE; - sub_8029174(&window); + DrawMessageWindow(&window); } - gUnknown_02022CF8->state++; + sGfx->state++; break; case 1: if (!IsDma3ManagerBusyWithBgCopy()) { - playersCount = sub_8027650(); - for (i = 0; i < playersCount; i++) - PutWindowTilemap(gUnknown_02022CF8->unk3008[i]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + numPlayers = GetNumPlayers(); + for (i = 0; i < numPlayers; i++) + PutWindowTilemap(sGfx->windowIds[i]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; } break; default: - if (++gUnknown_02022CF8->state > 180) + if (++sGfx->state > 180) { - playersCount = sub_8027650(); - for (i = 0; i < playersCount; i++) + numPlayers = GetNumPlayers(); + for (i = 0; i < numPlayers; i++) { - ClearWindowTilemap(gUnknown_02022CF8->unk3008[i]); - RemoveWindow(gUnknown_02022CF8->unk3008[i]); + ClearWindowTilemap(sGfx->windowIds[i]); + RemoveWindow(sGfx->windowIds[i]); } - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; } break; } } -static void sub_80296A8(u8 playersCount_) +static void PrintRankedScores(u8 numPlayers_) { - u8 i, r8 = 0, r6 = 0; - u8 playersCount = playersCount_; // Pointless variable, I know, but it's needed to match. + u8 i, ranking = 0, rankedPlayers = 0; + u8 numPlayers = numPlayers_; // Needed to match u8 *name; u32 x, numWidth; u8 numString[32]; - u8 array[5] = {0, 1, 2, 3, 4}; - struct DodrioSubstruct_3308 temp, structArray[5]; + u8 playersByRanking[MAX_RFU_PLAYERS] = {0, 1, 2, 3, 4}; + struct DodrioGame_ScoreResults temp, scoreResults[MAX_RFU_PLAYERS]; - for (i = 0; i < playersCount; i++) + // Get all players scores and rankings + for (i = 0; i < numPlayers; i++) { - array[i] = i; - sub_802793C(&temp, i); - structArray[i] = temp; + playersByRanking[i] = i; + GetScoreResults(&temp, i); + scoreResults[i] = temp; } - if (sub_8027748() != 0) + // Sort player ids by ranking + if (GetHighestScore() != 0) { do { - for (i = 0; i < playersCount; i++) + for (i = 0; i < numPlayers; i++) { - if (structArray[i].unk0 == r8) + if (scoreResults[i].ranking == ranking) { - array[r6] = i; - r6++; + playersByRanking[rankedPlayers] = i; + rankedPlayers++; } } - r8 = r6; - } while (r6 < playersCount); + ranking = rankedPlayers; + } while (rankedPlayers < numPlayers); } - for (i = 0; i < playersCount; i++) + // Put any player with a score of 0 at lowest ranking + for (i = 0; i < numPlayers; i++) { - if (structArray[i].unk4 == 0) - structArray[i].unk0 = playersCount - 1; + if (scoreResults[i].score == 0) + scoreResults[i].ranking = numPlayers - 1; } + // Print text x = 216 - GetStringWidth(1, gText_SpacePoints, 0); - for (i = 0; i < playersCount; i++) + for (i = 0; i < numPlayers; i++) { - u8 colorsId = 0; - u8 id = array[i]; - u32 points = structArray[id].unk4; + u8 colorsId = COLORID_GREY; + u8 playerId = playersByRanking[i]; + u32 points = scoreResults[playerId].score; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gUnknown_082FB3DC[structArray[id].unk0], 8, gUnknown_082FB402[i], -1, NULL); - if (id == GetMultiplayerId()) - colorsId = 2; - name = sub_8027660(id); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, 28, gUnknown_082FB402[i], sTextColorTable[colorsId], -1, name); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, sRankingTexts[scoreResults[playerId].ranking], 8, sRankingYCoords[i], -1, NULL); + if (playerId == GetMultiplayerId()) + colorsId = COLORID_BLUE; + name = GetPlayerName(playerId); + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, 28, sRankingYCoords[i], sTextColorTable[colorsId], -1, name); ConvertIntToDecimalStringN(numString, points, STR_CONV_MODE_LEFT_ALIGN, 7); numWidth = GetStringWidth(1, numString, -1); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, numString, x - numWidth, gUnknown_082FB402[i], -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SpacePoints, x, gUnknown_082FB402[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, numString, x - numWidth, sRankingYCoords[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gText_SpacePoints, x, sRankingYCoords[i], -1, NULL); } } -static void sub_802988C(void) +static void ShowResults(void) { - u8 i, j, itemGiveRet, playersCount = sub_8027650(); + u8 i, j, prizeState, numPlayers = GetNumPlayers(); u8 *name; u32 strWidth, x; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - sub_802784C(); - gUnknown_02022CF8->unk301C = 0; - gUnknown_02022CF8->state++; + SetScoreResults(); + sGfx->timer = 0; + sGfx->state++; break; case 1: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BBC[0]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BBC[1]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BBC[0]); - sub_8029174(&gUnknown_082F7BBC[1]); - gUnknown_02022CF8->state++; + sGfx->windowIds[0] = AddWindow(&sWindowTemplates_Results[0]); + sGfx->windowIds[1] = AddWindow(&sWindowTemplates_Results[1]); + ClearWindowTilemap(sGfx->windowIds[0]); + ClearWindowTilemap(sGfx->windowIds[1]); + DrawMessageWindow(&sWindowTemplates_Results[0]); + DrawMessageWindow(&sWindowTemplates_Results[1]); + sGfx->state++; break; case 2: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_BerryPickingResults, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_BerryPickingResults, x, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_10P30P50P50P, 68, 17, -1, NULL); - for (i = 0; i < playersCount; i++) + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_BerryPickingResults, x, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gText_10P30P50P50P, 68, 17, -1, NULL); + for (i = 0; i < numPlayers; i++) { - u8 colorsId = 0; + u8 colorsId = COLORID_GREY; if (i == GetMultiplayerId()) - colorsId = 2; + colorsId = COLORID_BLUE; - name = sub_8027660(i); - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, 0, gUnknown_082FB3F8[i], sTextColorTable[colorsId], -1, name); + name = GetPlayerName(i); + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, 0, sResultsYCoords[i], sTextColorTable[colorsId], -1, name); for (j = 0; j < 4; j++) { u32 width; - u16 result1 = Min(sub_80276A0(i, j), 9999); - u16 result2 = Min(sub_802778C(j), 9999); + u16 berriesPicked = Min(GetBerryResult(i, j), MAX_BERRIES); + u16 maxBerriesPicked = Min(GetHighestBerryResult(j), MAX_BERRIES); - ConvertIntToDecimalStringN(gStringVar4, result1, STR_CONV_MODE_LEFT_ALIGN, 4); + ConvertIntToDecimalStringN(gStringVar4, berriesPicked, STR_CONV_MODE_LEFT_ALIGN, 4); width = GetStringWidth(1, gStringVar4, -1); - if (result2 == result1 && result2 != 0) - AddTextPrinterParameterized3(gUnknown_02022CF8->unk3008[1], 1, gUnknown_082FB3F0[j] - width, gUnknown_082FB3F8[i], sTextColorTable[1], -1, gStringVar4); + + // If player got the most of a berry type, highlight their number in red + if (maxBerriesPicked == berriesPicked && maxBerriesPicked != 0) + AddTextPrinterParameterized3(sGfx->windowIds[1], 1, sResultsXCoords[j] - width, sResultsYCoords[i], sTextColorTable[COLORID_RED], -1, gStringVar4); else - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, gUnknown_082FB3F0[j] - width, gUnknown_082FB3F8[i], -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, sResultsXCoords[j] - width, sResultsYCoords[i], -1, NULL); } } - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 3: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); - sub_8028C30(FALSE); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + SetBerryIconsInvisibility(FALSE); + sGfx->state++; break; case 4: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - sub_8028C30(TRUE); - gUnknown_02022CF8->state++; + SetBerryIconsInvisibility(TRUE); + sGfx->state++; } break; case 5: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_AnnouncingRankings, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_AnnouncingRankings, x, 1, -1, NULL); - gUnknown_02022CF8->state++; + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_AnnouncingRankings, x, 1, -1, NULL); + sGfx->state++; break; case 6: - sub_80296A8(playersCount); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + PrintRankedScores(numPlayers); + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 7: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 8: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - if (sub_8027748() < 3000) + if (GetHighestScore() < PRIZE_SCORE) { - gUnknown_02022CF8->state = 127; + sGfx->state = 127; // Skip to end, past giving prize } else { StopMapMusic(); - gUnknown_02022CF8->state++; + sGfx->state++; } - FillBgTilemapBufferRect_Palette0(0, 0, 0, 5, 30, 15); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BCC); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BCC); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 5, 30, 15); + RemoveWindow(sGfx->windowIds[1]); + sGfx->windowIds[1] = AddWindow(&sWindowTemplate_Prize); + ClearWindowTilemap(sGfx->windowIds[1]); + DrawMessageWindow(&sWindowTemplate_Prize); } break; case 9: PlayNewMapMusic(MUS_LEVEL_UP); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[1], PIXEL_FILL(1)); strWidth = GetStringWidth(1, gText_AnnouncingPrizes, -1); x = (224 - strWidth) / 2; - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_AnnouncingPrizes, x, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_AnnouncingPrizes, x, 1, -1, NULL); DynamicPlaceholderTextUtil_Reset(); - CopyItemName(sub_802762C(), gStringVar1); + CopyItemName(GetPrizeItemId(), gStringVar1); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1); DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_FirstPlacePrize); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, 0, 1, -1, NULL); - itemGiveRet = sub_80279C8(); - if (itemGiveRet != 0 && itemGiveRet != 3) + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, 0, 1, -1, NULL); + prizeState = TryGivePrize(); + if (prizeState != PRIZE_RECEIVED && prizeState != NO_PRIZE) { DynamicPlaceholderTextUtil_Reset(); - CopyItemName(sub_802762C(), gStringVar1); + CopyItemName(GetPrizeItemId(), gStringVar1); DynamicPlaceholderTextUtil_SetPlaceholderPtr(0, gStringVar1); - if (itemGiveRet == 2) + if (prizeState == PRIZE_NO_ROOM) DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_CantHoldAnyMore); - else if (itemGiveRet == 1) + else if (prizeState == PRIZE_FILLED_BAG) DynamicPlaceholderTextUtil_ExpandPlaceholders(gStringVar4, gText_FilledStorageSpace); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gStringVar4, 0, 41, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[1], 1, gStringVar4, 0, 41, -1, NULL); } - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + CopyWindowToVram(sGfx->windowIds[0], 2); + CopyWindowToVram(sGfx->windowIds[1], 2); + sGfx->state++; break; case 10: if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[0]); + PutWindowTilemap(sGfx->windowIds[1]); } - CopyBgTilemapBufferToVram(0); + CopyBgTilemapBufferToVram(BG_INTERFACE); FadeOutAndFadeInNewMapMusic(MUS_RG_VICTORY_WILD, 20, 10); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 11: - if (++gUnknown_02022CF8->unk301C >= 30 && JOY_NEW(A_BUTTON)) + if (++sGfx->timer >= 30 && JOY_NEW(A_BUTTON)) { - gUnknown_02022CF8->unk301C = 0; + sGfx->timer = 0; PlaySE(SE_SELECT); - gUnknown_02022CF8->state++; + sGfx->state++; } break; default: - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + ClearWindowTilemap(sGfx->windowIds[0]); + ClearWindowTilemap(sGfx->windowIds[1]); + RemoveWindow(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[1]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A010(void) +static void Msg_WantToPlayAgain(void) { u8 y; - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BD4[0]); - gUnknown_02022CF8->unk3008[1] = AddWindow(&gUnknown_082F7BD4[1]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - sub_8029174(&gUnknown_082F7BD4[0]); - sub_8029074(&gUnknown_082F7BD4[1]); - gUnknown_02022CF8->state++; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + // Create windows + sGfx->windowIds[WIN_PLAY_AGAIN] = AddWindow(&sWindowTemplates_PlayAgain[WIN_PLAY_AGAIN]); + sGfx->windowIds[WIN_YES_NO] = AddWindow(&sWindowTemplates_PlayAgain[WIN_YES_NO]); + ClearWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + ClearWindowTilemap(sGfx->windowIds[WIN_YES_NO]); + DrawMessageWindow(&sWindowTemplates_PlayAgain[WIN_PLAY_AGAIN]); + DrawYesNoMessageWindow(&sWindowTemplates_PlayAgain[WIN_YES_NO]); + sGfx->state++; + sGfx->cursorSelection = PLAY_AGAIN_NONE; + sGfx->playAgainState = PLAY_AGAIN_NONE; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_WantToPlayAgain, 0, 5, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_Yes, 8, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_No, 8, 17, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SelectorArrow2, 0, 1, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 2); - gUnknown_02022CF8->state++; + // Print text + FillWindowPixelBuffer(sGfx->windowIds[WIN_PLAY_AGAIN], PIXEL_FILL(1)); + FillWindowPixelBuffer(sGfx->windowIds[WIN_YES_NO], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[WIN_PLAY_AGAIN], 1, gText_WantToPlayAgain, 0, 5, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_Yes, 8, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_No, 8, 17, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_SelectorArrow2, 0, 1, -1, NULL); + CopyWindowToVram(sGfx->windowIds[WIN_PLAY_AGAIN], 2); + CopyWindowToVram(sGfx->windowIds[WIN_YES_NO], 2); + sGfx->state++; break; case 2: + // Draw windows if (!IsDma3ManagerBusyWithBgCopy()) { - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - PutWindowTilemap(gUnknown_02022CF8->unk3008[1]); + PutWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + PutWindowTilemap(sGfx->windowIds[WIN_YES_NO]); } - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 3: - y = gUnknown_02022CF8->unk3020; - if (y == 0) - y = 1; - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[1], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_Yes, 8, 1, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_No, 8, 17, -1, NULL); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[1], 1, gText_SelectorArrow2, 0, ((y - 1) * 16) + 1, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[1], 3); + // Handle input + y = sGfx->cursorSelection; + if (y == PLAY_AGAIN_NONE) + y = PLAY_AGAIN_YES; + FillWindowPixelBuffer(sGfx->windowIds[WIN_YES_NO], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_Yes, 8, 1, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_No, 8, 17, -1, NULL); + AddTextPrinterParameterized(sGfx->windowIds[WIN_YES_NO], 1, gText_SelectorArrow2, 0, ((y - 1) * 16) + 1, -1, NULL); + CopyWindowToVram(sGfx->windowIds[WIN_YES_NO], 3); + // Increment state only if A or B button have been pressed. if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); - if (gUnknown_02022CF8->unk3020 == 0) - gUnknown_02022CF8->unk3020 = 1; - gUnknown_02022CF8->state++; + if (sGfx->cursorSelection == PLAY_AGAIN_NONE) + sGfx->cursorSelection = PLAY_AGAIN_YES; + sGfx->state++; } else if (JOY_NEW(DPAD_UP | DPAD_DOWN)) { PlaySE(SE_SELECT); - switch (gUnknown_02022CF8->unk3020) + switch (sGfx->cursorSelection) { - case 0: - gUnknown_02022CF8->unk3020 = 2; + case PLAY_AGAIN_NONE: + sGfx->cursorSelection = PLAY_AGAIN_NO; break; - case 1: - gUnknown_02022CF8->unk3020 = 2; + case PLAY_AGAIN_YES: + sGfx->cursorSelection = PLAY_AGAIN_NO; break; - case 2: - gUnknown_02022CF8->unk3020 = 1; + case PLAY_AGAIN_NO: + sGfx->cursorSelection = PLAY_AGAIN_YES; break; } } else if (JOY_NEW(B_BUTTON)) { PlaySE(SE_SELECT); - gUnknown_02022CF8->unk3020 = 2; - gUnknown_02022CF8->state++; + sGfx->cursorSelection = PLAY_AGAIN_NO; + sGfx->state++; } break; default: - gUnknown_02022CF8->unk3024 = gUnknown_02022CF8->unk3020; - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[1]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[1]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + sGfx->playAgainState = sGfx->cursorSelection; + ClearWindowTilemap(sGfx->windowIds[WIN_PLAY_AGAIN]); + ClearWindowTilemap(sGfx->windowIds[WIN_YES_NO]); + RemoveWindow(sGfx->windowIds[WIN_PLAY_AGAIN]); + RemoveWindow(sGfx->windowIds[WIN_YES_NO]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A380(void) +static void Msg_SavingDontTurnOff(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: DrawDialogueFrame(0, FALSE); AddTextPrinterParameterized2(0, 1, gText_SavingDontTurnOffPower, 0, NULL, 2, 1, 3); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 1: CopyWindowToVram(0, 3); - gUnknown_02022CF8->state++; + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) { CreateTask(Task_LinkSave, 0); - gUnknown_02022CF8->state++; + sGfx->state++; } break; case 3: if (!FuncIsActiveTask(Task_LinkSave)) - gUnknown_02022CF8->state++; + sGfx->state++; break; default: - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A454(void) +static void Msg_CommunicationStandby(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BEC); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - sub_8029174(&gUnknown_082F7BEC); - gUnknown_02022CF8->state++; + sGfx->windowIds[0] = AddWindow(&sWindowTemplate_CommStandby); + ClearWindowTilemap(sGfx->windowIds[0]); + DrawMessageWindow(&sWindowTemplate_CommStandby); + sGfx->state++; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_CommunicationStandby3, 0, 5, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - gUnknown_02022CF8->state++; + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_CommunicationStandby3, 0, 5, -1, NULL); + CopyWindowToVram(sGfx->windowIds[0], 2); + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + PutWindowTilemap(sGfx->windowIds[0]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; default: - gUnknown_02022CF8->finished = TRUE; + sGfx->finished = TRUE; break; } } -static void sub_802A534(void) +static void EraseMessage(void) { - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + ClearWindowTilemap(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[0]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; } -static void sub_802A588(void) +static void Msg_SomeoneDroppedOut(void) { - switch (gUnknown_02022CF8->state) + switch (sGfx->state) { case 0: - gUnknown_02022CF8->unk3008[0] = AddWindow(&gUnknown_082F7BE4); - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - sub_8029174(&gUnknown_082F7BE4); - gUnknown_02022CF8->state++; - gUnknown_02022CF8->unk301C = 0; - gUnknown_02022CF8->unk3020 = 0; - gUnknown_02022CF8->unk3024 = 0; + sGfx->windowIds[0] = AddWindow(&sWindowTemplate_DroppedOut); + ClearWindowTilemap(sGfx->windowIds[0]); + DrawMessageWindow(&sWindowTemplate_DroppedOut); + sGfx->state++; + sGfx->timer = 0; + sGfx->cursorSelection = 0; + sGfx->playAgainState = PLAY_AGAIN_NONE; break; case 1: - FillWindowPixelBuffer(gUnknown_02022CF8->unk3008[0], PIXEL_FILL(1)); - AddTextPrinterParameterized(gUnknown_02022CF8->unk3008[0], 1, gText_SomeoneDroppedOut, 0, 5, -1, NULL); - CopyWindowToVram(gUnknown_02022CF8->unk3008[0], 2); - gUnknown_02022CF8->state++; + FillWindowPixelBuffer(sGfx->windowIds[0], PIXEL_FILL(1)); + AddTextPrinterParameterized(sGfx->windowIds[0], 1, gText_SomeoneDroppedOut, 0, 5, -1, NULL); + CopyWindowToVram(sGfx->windowIds[0], 2); + sGfx->state++; break; case 2: if (!IsDma3ManagerBusyWithBgCopy()) - PutWindowTilemap(gUnknown_02022CF8->unk3008[0]); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->state++; + PutWindowTilemap(sGfx->windowIds[0]); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->state++; break; case 3: - if (++gUnknown_02022CF8->unk301C >= 120) - gUnknown_02022CF8->state++; + if (++sGfx->timer >= 120) + sGfx->state++; break; default: - gUnknown_02022CF8->unk3024 = 5; - ClearWindowTilemap(gUnknown_02022CF8->unk3008[0]); - RemoveWindow(gUnknown_02022CF8->unk3008[0]); - FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); - CopyBgTilemapBufferToVram(0); - gUnknown_02022CF8->finished = TRUE; + sGfx->playAgainState = PLAY_AGAIN_DROPPED; + ClearWindowTilemap(sGfx->windowIds[0]); + RemoveWindow(sGfx->windowIds[0]); + FillBgTilemapBufferRect_Palette0(BG_INTERFACE, 0, 0, 0, 30, 20); + CopyBgTilemapBufferToVram(BG_INTERFACE); + sGfx->finished = TRUE; break; } } -static void sub_802A6FC(void) +static void StopGfxFuncs(void) { - DestroyTask(gUnknown_02022CF8->unk3004); - gUnknown_02022CF8->finished = TRUE; + DestroyTask(sGfx->taskId); + sGfx->finished = TRUE; } -static void nullsub_16(void) +static void GfxIdle(void) { } -static void sub_802A72C(void (*func)(void)) +static void SetGfxFunc(void (*func)(void)) { - gUnknown_02022CF8->state = 0; - gUnknown_02022CF8->finished = FALSE; - gUnknown_02022CF8->unk3028 = func; + sGfx->state = 0; + sGfx->finished = FALSE; + sGfx->func = func; } -static void (*sub_802A75C(void))(void) +static void (*GetGfxFunc(void))(void) { - return gUnknown_02022CF8->unk3028; + return sGfx->func; } -static bool32 sub_802A770(void) +static bool32 IsGfxFuncActive(void) { - if (gUnknown_02022CF8->finished == TRUE) + if (sGfx->finished == TRUE) return FALSE; else return TRUE; } -static u8 sub_802A794(void) +static u8 GetPlayAgainState(void) { - return gUnknown_02022CF8->unk3024; + return sGfx->playAgainState; } -static void sub_802A7A8(void) +static void InitBgs(void) { DmaClearLarge16(3, (void *)VRAM, VRAM_SIZE, 0x1000); DmaClear32(3,(void *)OAM, OAM_SIZE); DmaClear16(3, (void *)PLTT, PLTT_SIZE); SetGpuReg(REG_OFFSET_DISPCNT, 0); ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, gUnknown_082F7BA4, ARRAY_COUNT(gUnknown_082F7BA4)); + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); @@ -4630,26 +5183,26 @@ static void sub_802A7A8(void) InitStandardTextBoxWindows(); InitTextBoxGfxAndPrinters(); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); - SetBgTilemapBuffer(3, gUnknown_02022CF8->tilemapBuffers[0]); - SetBgTilemapBuffer(1, gUnknown_02022CF8->tilemapBuffers[1]); - SetBgTilemapBuffer(2, gUnknown_02022CF8->tilemapBuffers[2]); + SetBgTilemapBuffer(BG_SCENERY, sGfx->tilemapBuffers[0]); + SetBgTilemapBuffer(BG_TREE_LEFT, sGfx->tilemapBuffers[1]); + SetBgTilemapBuffer(BG_TREE_RIGHT, sGfx->tilemapBuffers[2]); } -static bool32 sub_802A8E8(void) +static bool32 LoadBgGfx(void) { - switch (gUnknown_02022CF8->unk3018) + switch (sGfx->loadState) { case 0: - LoadPalette(gDodrioBerryBgPal1, 0, sizeof(gDodrioBerryBgPal1)); + LoadPalette(sBg_Pal, 0, sizeof(sBg_Pal)); break; case 1: ResetTempTileDataBuffers(); break; case 2: - DecompressAndCopyTileDataToVram(3, gDodrioBerryBgGfx1, 0, 0, 0); + DecompressAndCopyTileDataToVram(BG_SCENERY, sBg_Gfx, 0, 0, 0); break; case 3: - DecompressAndCopyTileDataToVram(1, gDodrioBerryBgGfx2, 0, 0, 0); + DecompressAndCopyTileDataToVram(BG_TREE_LEFT, sTreeBorder_Gfx, 0, 0, 0); break; case 4: if (FreeTempTileDataBuffersIfPossible() == TRUE) @@ -4659,10 +5212,10 @@ static bool32 sub_802A8E8(void) LoadPalette(GetTextWindowPalette(3), 0xD0, 0x20); break; default: - gUnknown_02022CF8->unk3018 = 0; + sGfx->loadState = 0; return TRUE; } - gUnknown_02022CF8->unk3018++; + sGfx->loadState++; return FALSE; } diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index a811901a9..6ec280fd0 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -67,7 +67,7 @@ static bool8 TryStartCoordEventScript(struct MapPosition *); static bool8 TryStartWarpEventScript(struct MapPosition *, u16); static bool8 TryStartMiscWalkingScripts(u16); static bool8 TryStartStepCountScript(u16); -static void UpdateHappinessStepCounter(void); +static void UpdateFriendshipStepCounter(void); static bool8 UpdatePoisonStepCounter(void); void FieldClearPlayerInput(struct FieldInput *input) @@ -542,7 +542,7 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) } IncrementRematchStepCounter(); - UpdateHappinessStepCounter(); + UpdateFriendshipStepCounter(); UpdateFarawayIslandStepCounter(); if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_FORCED_MOVE) && !MetatileBehavior_IsForcedMovementTile(metatileBehavior)) @@ -607,14 +607,15 @@ static bool8 TryStartStepCountScript(u16 metatileBehavior) return FALSE; } -void Unref_ClearHappinessStepCounter(void) +// Unused +static void ClearFriendshipStepCounter(void) { - VarSet(VAR_HAPPINESS_STEP_COUNTER, 0); + VarSet(VAR_FRIENDSHIP_STEP_COUNTER, 0); } -static void UpdateHappinessStepCounter(void) +static void UpdateFriendshipStepCounter(void) { - u16 *ptr = GetVarPointer(VAR_HAPPINESS_STEP_COUNTER); + u16 *ptr = GetVarPointer(VAR_FRIENDSHIP_STEP_COUNTER); int i; (*ptr)++; diff --git a/src/field_door.c b/src/field_door.c index 4dcb07cca..8aeb1d491 100644 --- a/src/field_door.c +++ b/src/field_door.c @@ -357,40 +357,42 @@ static void DrawDoor(const struct DoorGraphics *gfx, const struct DoorAnimFrame } } -enum +#define tFramesHi data[0] +#define tFramesLo data[1] +#define tGfxHi data[2] +#define tGfxLo data[3] +#define tFrameId data[4] +#define tCounter data[5] +#define tX data[6] +#define tY data[7] + +// Draws a single frame of the door animation, or skips drawing to wait between frames. +// Returns FALSE when the final frame has been reached +static bool32 AnimateDoorFrame(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, s16 *data) { - TD_FRAMELIST = 0, - TD_GFX = 2, - TD_FRAME = 4, - TD_COUNTER, - TD_X, - TD_Y -}; + if (tCounter == 0) + DrawDoor(gfx, &frames[tFrameId], tX, tY); -static bool32 sub_808A5F0(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, s16 *taskData) -{ - if (taskData[TD_COUNTER] == 0) - DrawDoor(gfx, &frames[taskData[TD_FRAME]], taskData[TD_X], taskData[TD_Y]); - if (taskData[TD_COUNTER] == frames[taskData[TD_FRAME]].time) + if (tCounter == frames[tFrameId].time) { - taskData[TD_COUNTER] = 0; - taskData[TD_FRAME]++; - if (frames[taskData[TD_FRAME]].time == 0) + tCounter = 0; + tFrameId++; + if (frames[tFrameId].time == 0) return FALSE; else return TRUE; } - taskData[TD_COUNTER]++; + tCounter++; return TRUE; } static void Task_AnimateDoor(u8 taskId) { - u16 *taskData = gTasks[taskId].data; - struct DoorAnimFrame *frames = (struct DoorAnimFrame *)(taskData[TD_FRAMELIST] << 16 | taskData[TD_FRAMELIST + 1]); - struct DoorGraphics *gfx = (struct DoorGraphics *)(taskData[TD_GFX] << 16 | taskData[TD_GFX + 1]); + u16 *data = gTasks[taskId].data; + struct DoorAnimFrame *frames = (struct DoorAnimFrame *)(tFramesHi << 16 | tFramesLo); + struct DoorGraphics *gfx = (struct DoorGraphics *)(tGfxHi << 16 | tGfxLo); - if (sub_808A5F0(gfx, frames, taskData) == FALSE) + if (AnimateDoorFrame(gfx, frames, data) == FALSE) DestroyTask(taskId); } @@ -419,16 +421,16 @@ static s8 StartDoorAnimationTask(const struct DoorGraphics *gfx, const struct Do else { u8 taskId = CreateTask(Task_AnimateDoor, 0x50); - s16 *taskData = gTasks[taskId].data; + s16 *data = gTasks[taskId].data; - taskData[TD_X] = x; - taskData[TD_Y] = y; + tX = x; + tY = y; - taskData[TD_FRAMELIST + 1] = (u32)frames; - taskData[TD_FRAMELIST] = (u32)frames >> 16; + tFramesLo = (u32)frames; + tFramesHi = (u32)frames >> 16; - taskData[TD_GFX + 1] = (u32)gfx; - taskData[TD_GFX] = (u32)gfx >> 16; + tGfxLo = (u32)gfx; + tGfxHi = (u32)gfx >> 16; return taskId; } diff --git a/src/field_effect.c b/src/field_effect.c index 162a530ca..445827390 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -480,13 +480,13 @@ static const struct Subsprite sSubsprites_HofMonitorBig[] = static const struct SubspriteTable sSubspriteTable_HofMonitorBig = subsprite_table(sSubsprites_HofMonitorBig); -const union AnimCmd gSpriteAnim_855C2CC[] = +const union AnimCmd sAnim_Static[] = { ANIMCMD_FRAME(.imageValue = 0, .duration = 1), ANIMCMD_JUMP(0) }; -const union AnimCmd gSpriteAnim_855C2D4[] = +const union AnimCmd sAnim_Flicker[] = { ANIMCMD_FRAME(.imageValue = 0, .duration = 16), ANIMCMD_FRAME(.imageValue = 1, .duration = 16), @@ -499,15 +499,16 @@ const union AnimCmd gSpriteAnim_855C2D4[] = ANIMCMD_END }; -const union AnimCmd *const gSpriteAnimTable_855C2F8[] = +// Flicker on and off, for the Pokéballs / monitors during the PokéCenter heal effect +const union AnimCmd *const sAnims_Flicker[] = { - gSpriteAnim_855C2CC, - gSpriteAnim_855C2D4 + sAnim_Static, + sAnim_Flicker }; -static const union AnimCmd *const sAnimTable_HofMonitor[] = +static const union AnimCmd *const sAnims_HofMonitor[] = { - gSpriteAnim_855C2CC + sAnim_Static }; static const struct SpriteTemplate sSpriteTemplate_PokeballGlow = @@ -515,7 +516,7 @@ static const struct SpriteTemplate sSpriteTemplate_PokeballGlow = .tileTag = 0xFFFF, .paletteTag = FLDEFF_PAL_TAG_POKEBALL_GLOW, .oam = &sOam_8x8, - .anims = gSpriteAnimTable_855C2F8, + .anims = sAnims_Flicker, .images = sPicTable_PokeballGlow, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_PokeballGlow @@ -526,7 +527,7 @@ static const struct SpriteTemplate sSpriteTemplate_PokecenterMonitor = .tileTag = 0xFFFF, .paletteTag = FLDEFF_PAL_TAG_GENERAL_0, .oam = &sOam_16x16, - .anims = gSpriteAnimTable_855C2F8, + .anims = sAnims_Flicker, .images = sPicTable_PokecenterMonitor, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_PokecenterMonitor @@ -537,7 +538,7 @@ static const struct SpriteTemplate sSpriteTemplate_HofMonitorBig = .tileTag = 0xFFFF, .paletteTag = FLDEFF_PAL_TAG_HOF_MONITOR, .oam = &sOam_16x16, - .anims = sAnimTable_HofMonitor, + .anims = sAnims_HofMonitor, .images = sPicTable_HofMonitorBig, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_HallOfFameMonitor @@ -548,7 +549,7 @@ static const struct SpriteTemplate sSpriteTemplate_HofMonitorSmall = .tileTag = 0xFFFF, .paletteTag = FLDEFF_PAL_TAG_HOF_MONITOR, .oam = &sOam_32x16, - .anims = sAnimTable_HofMonitor, + .anims = sAnims_HofMonitor, .images = sPicTable_HofMonitorSmall, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCB_HallOfFameMonitor @@ -3853,16 +3854,8 @@ static void Task_MoveDeoxysRock(u8 taskId) case 0: data[4] = sprite->pos1.x << 4; data[5] = sprite->pos1.y << 4; - - // UB: Possible divide by zero - #ifdef UBFIX - #define DIVISOR (data[8] ? data[8] : 1); - #else - #define DIVISOR (data[8]) - #endif - - data[6] = (data[2] * 16 - data[4]) / DIVISOR; - data[7] = (data[3] * 16 - data[5]) / DIVISOR; + data[6] = SAFE_DIV(data[2] * 16 - data[4], data[8]); + data[7] = SAFE_DIV(data[3] * 16 - data[5], data[8]); data[0]++; case 1: if (data[8] != 0) diff --git a/src/fldeff_flash.c b/src/fldeff_flash.c index b2ddf3180..9c166d008 100644 --- a/src/fldeff_flash.c +++ b/src/fldeff_flash.c @@ -16,7 +16,6 @@ #include "constants/songs.h" #include "constants/map_types.h" -// structures struct FlashStruct { u8 fromType; @@ -26,7 +25,6 @@ struct FlashStruct void (*func)(void); }; -// static functions static void FieldCallback_Flash(void); static void FldEff_UseFlash(void); static bool8 TryDoMapTransition(void); @@ -42,7 +40,6 @@ static void Task_EnterCaveTransition2(u8 taskId); static void Task_EnterCaveTransition3(u8 taskId); static void Task_EnterCaveTransition4(u8 taskId); -// rodata static const struct FlashStruct sTransitionTypes[] = { {MAP_TYPE_TOWN, MAP_TYPE_UNDERGROUND, TRUE, FALSE, DoEnterCaveTransition}, @@ -64,15 +61,14 @@ static const struct FlashStruct sTransitionTypes[] = {}, }; -static const u16 gCaveTransitionPalette_White[] = INCBIN_U16("graphics/misc/cave_transition_white.gbapal"); -static const u16 gCaveTransitionPalette_Black[] = INCBIN_U16("graphics/misc/cave_transition_black.gbapal"); +static const u16 sCaveTransitionPalette_White[] = INCBIN_U16("graphics/misc/cave_transition_white.gbapal"); +static const u16 sCaveTransitionPalette_Black[] = INCBIN_U16("graphics/misc/cave_transition_black.gbapal"); -static const u16 gUnknown_085B2890[] = INCBIN_U16("graphics/misc/85B2890.gbapal"); -static const u16 gUnknown_085B28A0[] = INCBIN_U16("graphics/misc/85B28A0.gbapal"); -static const u32 gCaveTransitionTilemap[] = INCBIN_U32("graphics/misc/cave_transition_map.bin.lz"); -static const u32 gCaveTransitionTiles[] = INCBIN_U32("graphics/misc/cave_transition.4bpp.lz"); +static const u16 sCaveTransitionPalette_Enter[] = INCBIN_U16("graphics/misc/cave_transition_enter.gbapal"); +static const u16 sCaveTransitionPalette_Exit[] = INCBIN_U16("graphics/misc/cave_transition_exit.gbapal"); +static const u32 sCaveTransitionTilemap[] = INCBIN_U32("graphics/misc/cave_transition_map.bin.lz"); +static const u32 sCaveTransitionTiles[] = INCBIN_U32("graphics/misc/cave_transition.4bpp.lz"); -// text bool8 SetUpFieldMove_Flash(void) { // In Ruby and Sapphire, Registeel's tomb is opened by using Fly. In Emerald, @@ -220,10 +216,10 @@ static void Task_ExitCaveTransition1(u8 taskId) static void Task_ExitCaveTransition2(u8 taskId) { SetGpuReg(REG_OFFSET_DISPCNT, 0); - LZ77UnCompVram(gCaveTransitionTiles, (void *)(VRAM + 0xC000)); - LZ77UnCompVram(gCaveTransitionTilemap, (void *)(VRAM + 0xF800)); - LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); - LoadPalette(gUnknown_085B28A0, 0xE0, 0x10); + LZ77UnCompVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); + LZ77UnCompVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); + LoadPalette(sCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(sCaveTransitionPalette_Exit, 0xE0, 0x10); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 @@ -274,11 +270,11 @@ static void Task_ExitCaveTransition4(u8 taskId) if (count < 8) { gTasks[taskId].data[2]++; - LoadPalette(&gUnknown_085B28A0[count], 0xE0, 16 - 2 * count); + LoadPalette(&sCaveTransitionPalette_Exit[count], 0xE0, 16 - 2 * count); } else { - LoadPalette(gCaveTransitionPalette_White, 0, 0x20); + LoadPalette(sCaveTransitionPalette_White, 0, 0x20); gTasks[taskId].func = Task_ExitCaveTransition5; gTasks[taskId].data[2] = 8; } @@ -305,8 +301,8 @@ static void Task_EnterCaveTransition1(u8 taskId) static void Task_EnterCaveTransition2(u8 taskId) { SetGpuReg(REG_OFFSET_DISPCNT, 0); - LZ77UnCompVram(gCaveTransitionTiles, (void *)(VRAM + 0xC000)); - LZ77UnCompVram(gCaveTransitionTilemap, (void *)(VRAM + 0xF800)); + LZ77UnCompVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); + LZ77UnCompVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetGpuReg(REG_OFFSET_BLDY, 0); @@ -319,8 +315,8 @@ static void Task_EnterCaveTransition2(u8 taskId) | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_OBJ_ON); - LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); - LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + LoadPalette(sCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(sCaveTransitionPalette_Black, 0, 0x20); gTasks[taskId].func = Task_EnterCaveTransition3; gTasks[taskId].data[0] = 16; gTasks[taskId].data[1] = 0; @@ -335,7 +331,7 @@ static void Task_EnterCaveTransition3(u8 taskId) { gTasks[taskId].data[2]++; gTasks[taskId].data[2]++; - LoadPalette(&gUnknown_085B2890[15 - count], 0xE0, 2 * (count + 1)); + LoadPalette(&sCaveTransitionPalette_Enter[15 - count], 0xE0, 2 * (count + 1)); } else { @@ -363,7 +359,7 @@ static void Task_EnterCaveTransition4(u8 taskId) } else { - LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + LoadPalette(sCaveTransitionPalette_Black, 0, 0x20); SetMainCallback2(gMain.savedCallback); } } diff --git a/src/frontier_util.c b/src/frontier_util.c index 095c750a6..491aef936 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -2383,13 +2383,13 @@ void ClearRankingHallRecords(void) { s32 i, j, k; - // BUG: Passing 0 as a pointer instead of a pointer holding a value of 0. - #ifdef BUGFIX - u8 zero = 0; - #define ZERO (&zero) - #else + // UB: Passing 0 as a pointer instead of a pointer holding a value of 0. +#ifdef UBFIX + u8 emptyId[TRAINER_ID_LENGTH] = {0}; + #define ZERO emptyId +#else #define ZERO 0 - #endif +#endif for (i = 0; i < HALL_FACILITIES_COUNT; i++) { diff --git a/src/graphics.c b/src/graphics.c index 1a3423fb6..7a7a11b2b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1543,9 +1543,9 @@ const u16 gUnknown_08DE3350[] = INCBIN_U16("graphics/frontier_pass/tilemap1.bin" const u16 gUnknown_08DE3374[] = INCBIN_U16("graphics/frontier_pass/tilemap2.bin"); // Berry Crush -const u16 gUnknown_08DE3398[] = INCBIN_U16("graphics/berry_crusher/tiles.gbapal"); -const u32 gUnknown_08DE34B8[] = INCBIN_U32("graphics/berry_crusher/tiles.4bpp.lz"); -const u32 gUnknown_08DE3FD4[] = INCBIN_U32("graphics/berry_crusher/tiles.bin.lz"); +const u16 gBerryCrush_Crusher_Pal[] = INCBIN_U16("graphics/berry_crush/crusher.gbapal"); +const u32 gBerryCrush_Crusher_Gfx[] = INCBIN_U32("graphics/berry_crush/crusher.4bpp.lz"); +const u32 gBerryCrush_Crusher_Tilemap[] = INCBIN_U32("graphics/berry_crush/crusher.bin.lz"); // random garbage at the end. static const u8 sEmpty3[0x54BAC] = {0}; diff --git a/src/image_processing_effects.c b/src/image_processing_effects.c index 224de6fe1..4a56871a4 100644 --- a/src/image_processing_effects.c +++ b/src/image_processing_effects.c @@ -51,7 +51,9 @@ static u16 QuantizePixel_GrayscaleSmall(u16*); static u16 QuantizePixel_Grayscale(u16*); static u16 QuantizePixel_PrimaryColors(u16*); -extern const u8 gPointillismPoints[][3]; +#define MAX_DIMENSION 64 + +#include "data/pointillism_points.h" void ApplyImageProcessingEffects(struct ImageProcessingContext *context) { @@ -169,7 +171,7 @@ static void ApplyImageEffect_RedChannelGrayscaleHighlight(u8 highlight) static void ApplyImageEffect_Pointillism(void) { u32 i; - for (i = 0; i < 3200; i++) + for (i = 0; i < ARRAY_COUNT(sPointillismPoints); i++) AddPointillismPoints(i); } @@ -307,9 +309,9 @@ static void ApplyImageEffect_Shimmer(void) // First, invert all of the colors. pixel = gCanvasPixels; - for (i = 0; i < 64; i++) + for (i = 0; i < MAX_DIMENSION; i++) { - for (j = 0; j < 64; j++, pixel++) + for (j = 0; j < MAX_DIMENSION; j++, pixel++) { if (!IS_ALPHA(*pixel)) *pixel = QuantizePixel_Invert(pixel); @@ -317,16 +319,16 @@ static void ApplyImageEffect_Shimmer(void) } // Blur the pixels twice. - for (j = 0; j < 64; j++) + for (j = 0; j < MAX_DIMENSION; j++) { pixel = &gCanvasPixels[j]; prevPixel = *pixel; *pixel = RGB_ALPHA; - for (i = 1, pixel += 64; i < 63; i++, pixel += 64) + for (i = 1, pixel += MAX_DIMENSION; i < MAX_DIMENSION - 1; i++, pixel += MAX_DIMENSION) { if (!IS_ALPHA(*pixel)) { - *pixel = QuantizePixel_BlurHard(&prevPixel, pixel, pixel + 64); + *pixel = QuantizePixel_BlurHard(&prevPixel, pixel, pixel + MAX_DIMENSION); prevPixel = *pixel; } } @@ -335,11 +337,11 @@ static void ApplyImageEffect_Shimmer(void) pixel = &gCanvasPixels[j]; prevPixel = *pixel; *pixel = RGB_ALPHA; - for (i = 1, pixel += 64; i < 63; i++, pixel += 64) + for (i = 1, pixel += MAX_DIMENSION; i < MAX_DIMENSION - 1; i++, pixel += MAX_DIMENSION) { if (!IS_ALPHA(*pixel)) { - *pixel = QuantizePixel_BlurHard(&prevPixel, pixel, pixel + 64); + *pixel = QuantizePixel_BlurHard(&prevPixel, pixel, pixel + MAX_DIMENSION); prevPixel = *pixel; } } @@ -351,9 +353,9 @@ static void ApplyImageEffect_Shimmer(void) // The above blur causes the outline areas to darken, which makes // this inversion give the effect of light outlines. pixel = gCanvasPixels; - for (i = 0; i < 64; i++) + for (i = 0; i < MAX_DIMENSION; i++) { - for (j = 0; j < 64; j++, pixel++) + for (j = 0; j < MAX_DIMENSION; j++, pixel++) { if (!IS_ALPHA(*pixel)) *pixel = QuantizePixel_Invert(pixel); @@ -408,19 +410,19 @@ struct PointillismPoint u16 delta; }; -static void AddPointillismPoints(u16 arg0) +static void AddPointillismPoints(u16 point) { u8 i; bool8 offsetDownLeft; u8 colorType; struct PointillismPoint points[6]; - points[0].column = gPointillismPoints[arg0][0]; - points[0].row = gPointillismPoints[arg0][1]; - points[0].delta = (gPointillismPoints[arg0][2] >> 3) & 7; + points[0].column = sPointillismPoints[point][0]; + points[0].row = sPointillismPoints[point][1]; + points[0].delta = GET_POINT_DELTA(sPointillismPoints[point][2]); - colorType = (gPointillismPoints[arg0][2] >> 1) & 3; - offsetDownLeft = gPointillismPoints[arg0][2] & 1; + colorType = GET_POINT_COLOR_TYPE(sPointillismPoints[point][2]); + offsetDownLeft = GET_POINT_OFFSET_DL(sPointillismPoints[point][2]); for (i = 1; i < points[0].delta; i++) { if (!offsetDownLeft) @@ -434,7 +436,7 @@ static void AddPointillismPoints(u16 arg0) points[i].row = points[0].row - 1; } - if (points[i].column > 63 || points[i].row > 63) + if (points[i].column >= MAX_DIMENSION || points[i].row >= MAX_DIMENSION) { points[0].delta = i - 1; break; @@ -445,7 +447,7 @@ static void AddPointillismPoints(u16 arg0) for (i = 0; i < points[0].delta; i++) { - u16 *pixel = &gCanvasPixels[points[i].row * 64] + points[i].column; + u16 *pixel = &gCanvasPixels[points[i].row * MAX_DIMENSION] + points[i].column; if (!IS_ALPHA(*pixel)) { @@ -457,7 +459,7 @@ static void AddPointillismPoints(u16 arg0) { case 0: case 1: - switch (((gPointillismPoints[arg0][2] >> 3) & 7) % 3) + switch (GET_POINT_DELTA(sPointillismPoints[point][2]) % 3) { case 0: if (red >= points[i].delta) diff --git a/src/intro.c b/src/intro.c index a8468d518..1477b67a1 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1746,7 +1746,7 @@ static void Task_Scene3_SpinPokeball(u8 taskId) gTasks[taskId].func = Task_Scene3_WaitGroudon; } - PanFadeAndZoomScreen(0x78, 0x50, 0x10000 / gTasks[taskId].tZoomDiv, gTasks[taskId].tAlpha); + PanFadeAndZoomScreen(0x78, 0x50, SAFE_DIV(0x10000, gTasks[taskId].tZoomDiv), gTasks[taskId].tAlpha); if (gIntroFrameCounter == TIMER_POKEBALL_FADE) BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_WHITEALPHA); diff --git a/src/item.c b/src/item.c index 91d2f1a0a..892092184 100644 --- a/src/item.c +++ b/src/item.c @@ -19,9 +19,6 @@ extern u16 gUnknown_0203CF30[]; // this file's functions -#if !defined(NONMATCHING) && MODERN -#define static -#endif static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count); diff --git a/src/link.c b/src/link.c index e151bfa28..0b2f46a34 100644 --- a/src/link.c +++ b/src/link.c @@ -41,8 +41,8 @@ struct LinkTestBGInfo { u32 screenBaseBlock; u32 paletteNum; - u32 dummy_8; - u32 dummy_C; + u32 baseChar; + u32 unused; }; static struct BlockTransfer sBlockSend; @@ -97,28 +97,26 @@ struct Link gLink; u8 gLastRecvQueueCount; u16 gLinkSavedIme; -EWRAM_DATA u8 gLinkTestDebugValuesEnabled = 0; -EWRAM_DATA u8 gUnknown_020223BD = 0; +static EWRAM_DATA u8 sLinkTestDebugValuesEnabled = 0; +static EWRAM_DATA u8 sDummyFlag = FALSE; EWRAM_DATA u32 gBerryBlenderKeySendAttempts = 0; EWRAM_DATA u16 gBlockRecvBuffer[MAX_RFU_PLAYERS][BLOCK_BUFFER_SIZE / 2] = {}; EWRAM_DATA u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE] = {}; -EWRAM_DATA bool8 gLinkOpen = FALSE; +static EWRAM_DATA bool8 sLinkOpen = FALSE; EWRAM_DATA u16 gLinkType = 0; -EWRAM_DATA u16 gLinkTimeOutCounter = 0; +static EWRAM_DATA u16 sTimeOutCounter = 0; EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {}; EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {}; -EWRAM_DATA struct LinkPlayer gSavedLinkPlayers[MAX_RFU_PLAYERS] = {}; +static EWRAM_DATA struct LinkPlayer sSavedLinkPlayers[MAX_RFU_PLAYERS] = {}; EWRAM_DATA struct { u32 status; u8 lastRecvQueueCount; u8 lastSendQueueCount; - u8 unk_06; + bool8 disconnected; } sLinkErrorBuffer = {}; static EWRAM_DATA u16 sReadyCloseLinkAttempts = 0; // never read static EWRAM_DATA void *sLinkErrorBgTilemapBuffer = NULL; -// Static ROM declarations - static void InitLocalLinkPlayer(void); static void VBlankCB_LinkError(void); static void CB2_LinkTest(void); @@ -131,7 +129,7 @@ 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 LinkTest_PrintHex(u32 pos, u8 a0, u8 a1, u8 a2); static void LinkCB_RequestPlayerDataExchange(void); static void Task_PrintTestData(u8 taskId); @@ -160,15 +158,13 @@ static void DoSend(void); static void StopTimer(void); static void SendRecvDone(void); -// .rodata - static const u16 sWirelessLinkDisplayPal[] = INCBIN_U16("graphics/interface/wireless_link_display.gbapal"); static const u32 sWirelessLinkDisplayGfx[] = INCBIN_U32("graphics/interface/wireless_link_display.4bpp.lz"); static const u32 sWirelessLinkDisplayTilemap[] = INCBIN_U32("graphics/interface/wireless_link_display.bin.lz"); static const u16 sLinkTestDigitsPal[] = INCBIN_U16("graphics/interface/link_test_digits.gbapal"); static const u16 sLinkTestDigitsGfx[] = INCBIN_U16("graphics/interface/link_test_digits.4bpp"); static const u8 sUnusedTransparentWhite[] = _("{HIGHLIGHT TRANSPARENT}{COLOR WHITE}"); -static const u16 s2BlankTilesGfx[] = INCBIN_U16("graphics/interface/blank_1x2.4bpp"); +static const u16 sCommErrorBg_Gfx[] = INCBIN_U16("graphics/interface/comm_error_bg.4bpp"); static const struct BlockRequest sBlockRequests[] = { {gBlockSendBuffer, 200}, {gBlockSendBuffer, 200}, @@ -226,15 +222,13 @@ static const struct WindowTemplate sLinkErrorWindowTemplates[] = { }; static const u8 sTextColors[] = { TEXT_COLOR_TRANSPARENT, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GREY }; -static const u8 sUnused_082ED224[] = {0x00, 0xFF, 0xFE, 0xFF, 0x00}; - -// .text +static const u8 sUnusedData[] = {0x00, 0xFF, 0xFE, 0xFF, 0x00}; bool8 IsWirelessAdapterConnected(void) { SetWirelessCommType1(); InitRFUAPI(); - if (rfu_LMAN_REQBN_softReset_and_checkID() == 0x8001) + if (rfu_LMAN_REQBN_softReset_and_checkID() == RFU_ID) { rfu_REQ_stopMode(); rfu_waitREQComplete(); @@ -251,13 +245,13 @@ void Task_DestroySelf(u8 taskId) DestroyTask(taskId); } -static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock, u16 a4) +static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock, u16 baseChar) { LoadPalette(sLinkTestDigitsPal, paletteNum * 16, 0x20); - DmaCopy16(3, sLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock) + (16 * a4), sizeof sLinkTestDigitsGfx); + DmaCopy16(3, sLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock) + (16 * baseChar), sizeof sLinkTestDigitsGfx); gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; gLinkTestBGInfo.paletteNum = paletteNum; - gLinkTestBGInfo.dummy_8 = a4; + gLinkTestBGInfo.baseChar = baseChar; switch (bgNum) { case 1: @@ -274,17 +268,19 @@ static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charB SetGpuReg(REG_OFFSET_BG0VOFS + bgNum * 4, 0); } -void sub_80094EC(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock) +// Unused +static void LoadLinkTestBgGfx(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock) { LoadPalette(sLinkTestDigitsPal, paletteNum * 16, 0x20); DmaCopy16(3, sLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock), sizeof sLinkTestDigitsGfx); gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; gLinkTestBGInfo.paletteNum = paletteNum; - gLinkTestBGInfo.dummy_8 = 0; + gLinkTestBGInfo.baseChar = 0; SetGpuReg(sBGControlRegs[bgNum], BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_CHARBASE(charBaseBlock)); } -void LinkTestScreen(void) +// Unused +static void LinkTestScreen(void) { int i; @@ -346,10 +342,9 @@ static void InitLink(void) int i; for (i = 0; i < CMD_LENGTH; i++) - { - gSendCmd[i] = 0xEfff; - } - gLinkOpen = TRUE; + gSendCmd[i] = LINKCMD_NONE; + + sLinkOpen = TRUE; EnableSerial(); } @@ -402,7 +397,7 @@ void CloseLink(void) { LinkRfu_Shutdown(); } - gLinkOpen = FALSE; + sLinkOpen = FALSE; DisableSerial(); } @@ -413,14 +408,14 @@ static void TestBlockTransfer(u8 nothing, u8 is, u8 used) if (sLinkTestLastBlockSendPos != sBlockSend.pos) { - LinkTest_prnthex(sBlockSend.pos, 2, 3, 2); + LinkTest_PrintHex(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); + LinkTest_PrintHex(sBlockRecv[i].pos, 2, i + 4, 2); sLinkTestLastBlockRecvPos[i] = sBlockRecv[i].pos; } } @@ -435,8 +430,8 @@ static void TestBlockTransfer(u8 nothing, u8 is, u8 used) ResetBlockReceivedFlag(i); if (gLinkTestBlockChecksums[i] != 0x0342) { - gLinkTestDebugValuesEnabled = FALSE; - gUnknown_020223BD = FALSE; + sLinkTestDebugValuesEnabled = FALSE; + sDummyFlag = FALSE; } } } @@ -469,7 +464,7 @@ static void LinkTestProcessKeyInput(void) { SetCloseLinkCallback(); } - if (gLinkTestDebugValuesEnabled) + if (sLinkTestDebugValuesEnabled) { SetLinkDebugValues(gMain.vblankCounter2, gLinkCallback ? gLinkVSyncDisabled : gLinkVSyncDisabled | 0x10); } @@ -489,7 +484,7 @@ u16 LinkMain2(const u16 *heldKeys) { u8 i; - if (!gLinkOpen) + if (!sLinkOpen) { return 0; } @@ -555,10 +550,10 @@ static void ProcessRecvCmds(u8 unused) case LINKCMD_BLENDER_SEND_KEYS: gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; break; - case LINKCMD_0x5555: + case LINKCMD_DUMMY_1: gLinkDummy2 = TRUE; break; - case LINKCMD_0x5566: + case LINKCMD_DUMMY_2: gLinkDummy2 = TRUE; break; case LINKCMD_INIT_BLOCK: @@ -612,7 +607,7 @@ static void ProcessRecvCmds(u8 unused) linkPlayer->neverRead = 0; linkPlayer->progressFlags = 0; } - sub_800B524(linkPlayer); + ConvertLinkPlayerName(linkPlayer); if (strcmp(block->magic1, sASCIIGameFreakInc) != 0 || strcmp(block->magic2, sASCIIGameFreakInc) != 0) { @@ -664,22 +659,19 @@ static void BuildSendCmd(u16 command) gSendCmd[0] = LINKCMD_BLENDER_SEND_KEYS; gSendCmd[1] = gMain.heldKeys; break; - case LINKCMD_0x5555: - gSendCmd[0] = LINKCMD_0x5555; + case LINKCMD_DUMMY_1: + gSendCmd[0] = LINKCMD_DUMMY_1; break; - case LINKCMD_0x6666: - gSendCmd[0] = LINKCMD_0x6666; + case LINKCMD_SEND_EMPTY: + gSendCmd[0] = LINKCMD_SEND_EMPTY; gSendCmd[1] = 0; break; - case LINKCMD_0x7777: + case LINKCMD_SEND_0xEE: { u8 i; - - gSendCmd[0] = LINKCMD_0x7777; + gSendCmd[0] = LINKCMD_SEND_0xEE; for (i = 0; i < 5; i++) - { gSendCmd[i + 1] = 0xEE; - } break; } case LINKCMD_INIT_BLOCK: @@ -690,8 +682,8 @@ static void BuildSendCmd(u16 command) case LINKCMD_BLENDER_NO_PBLOCK_SPACE: gSendCmd[0] = LINKCMD_BLENDER_NO_PBLOCK_SPACE; break; - case LINKCMD_0xAAAB: - gSendCmd[0] = LINKCMD_0xAAAB; + case LINKCMD_SEND_ITEM: + gSendCmd[0] = LINKCMD_SEND_ITEM; gSendCmd[1] = gSpecialVar_ItemId; break; case LINKCMD_SEND_BLOCK_REQ: @@ -702,14 +694,13 @@ static void BuildSendCmd(u16 command) gSendCmd[0] = LINKCMD_READY_CLOSE_LINK; gSendCmd[1] = gReadyCloseLinkType; break; - case LINKCMD_0x5566: - gSendCmd[0] = LINKCMD_0x5566; + case LINKCMD_DUMMY_2: + gSendCmd[0] = LINKCMD_DUMMY_2; break; case LINKCMD_SEND_HELD_KEYS: if (gHeldKeyCodeToSend == 0 || gLinkTransferringData) - { break; - } + gSendCmd[0] = LINKCMD_SEND_HELD_KEYS; gSendCmd[1] = gHeldKeyCodeToSend; break; @@ -819,7 +810,7 @@ bool32 Link_AnyPartnersPlayingFRLG_JP(void) void OpenLinkTimed(void) { sPlayerDataExchangeStatus = EXCHANGE_NOT_STARTED; - gLinkTimeOutCounter = 0; + sTimeOutCounter = 0; OpenLink(); } @@ -892,7 +883,7 @@ u8 GetLinkPlayerDataExchangeStatusTimed(int minPlayers, int maxPlayers) } } } - else if (++gLinkTimeOutCounter > 600) + else if (++sTimeOutCounter > 600) { sPlayerDataExchangeStatus = EXCHANGE_TIMED_OUT; } @@ -909,9 +900,7 @@ bool8 IsLinkPlayerDataExchangeComplete(void) for (i = 0; i < GetLinkPlayerCount(); i++) { if (gLinkPlayers[i].linkType == gLinkPlayers[0].linkType) - { count++; - } } if (count == GetLinkPlayerCount()) { @@ -936,9 +925,7 @@ void ResetLinkPlayers(void) int i; for (i = 0; i <= MAX_LINK_PLAYERS; i++) - { gLinkPlayers[i] = (struct LinkPlayer){}; - } } static void ResetBlockSend(void) @@ -966,9 +953,8 @@ static bool32 InitBlockSend(const void *src, size_t size) else { if (src != gBlockSendBuffer) - { memcpy(gBlockSendBuffer, src, size); - } + sBlockSend.src = gBlockSendBuffer; } BuildSendCmd(LINKCMD_INIT_BLOCK); @@ -980,9 +966,7 @@ static bool32 InitBlockSend(const void *src, size_t size) static void LinkCB_BlockSendBegin(void) { if (++sBlockSendDelayCounter > 2) - { gLinkCallback = LinkCB_BlockSend; - } } static void LinkCB_BlockSend(void) @@ -1020,13 +1004,9 @@ void SetBerryBlenderLinkCallback(void) { gBerryBlenderKeySendAttempts = 0; if (gWirelessCommType) - { Rfu_SetBerryBlenderLinkCallback(); - } else - { gLinkCallback = LinkCB_BerryBlenderSendHeldKeys; - } } // Unused @@ -1044,9 +1024,8 @@ static void SendBerryBlenderNoSpaceForPokeblocks(void) u8 GetMultiplayerId(void) { if (gWirelessCommType == TRUE) - { return Rfu_GetMultiplayerId(); - } + return SIO_MULTI_CNT->id; } @@ -1061,18 +1040,16 @@ u8 bitmask_all_link_players_but_self(void) bool8 SendBlock(u8 unused, const void *src, u16 size) { if (gWirelessCommType == TRUE) - { return Rfu_InitBlockSend(src, size); - } + return InitBlockSend(src, size); } bool8 SendBlockRequest(u8 blockReqType) { if (gWirelessCommType == TRUE) - { return Rfu_SendBlockRequest(blockReqType); - } + if (gLinkCallback == NULL) { gBlockRequestType = blockReqType; @@ -1085,31 +1062,25 @@ bool8 SendBlockRequest(u8 blockReqType) bool8 IsLinkTaskFinished(void) { if (gWirelessCommType == TRUE) - { return IsLinkRfuTaskFinished(); - } + return gLinkCallback == NULL; } u8 GetBlockReceivedStatus(void) { if (gWirelessCommType == TRUE) - { return Rfu_GetBlockReceivedStatus(); - } + return (gBlockReceivedStatus[3] << 3) | (gBlockReceivedStatus[2] << 2) | (gBlockReceivedStatus[1] << 1) | (gBlockReceivedStatus[0] << 0); } static void SetBlockReceivedFlag(u8 who) { if (gWirelessCommType == TRUE) - { Rfu_SetBlockReceivedFlag(who); - } else - { gBlockReceivedStatus[who] = TRUE; - } } void ResetBlockReceivedFlags(void) @@ -1119,16 +1090,12 @@ void ResetBlockReceivedFlags(void) if (gWirelessCommType == TRUE) { for (i = 0; i < MAX_RFU_PLAYERS; i++) - { Rfu_ResetBlockReceivedFlag(i); - } } else { for (i = 0; i < MAX_LINK_PLAYERS; i++) - { gBlockReceivedStatus[i] = FALSE; - } } } @@ -1147,9 +1114,7 @@ void ResetBlockReceivedFlag(u8 who) void CheckShouldAdvanceLinkState(void) { if ((gLinkStatus & LINK_STAT_MASTER) && EXTRACT_PLAYER_COUNT(gLinkStatus) > 1) - { gShouldAdvanceLinkState = 1; - } } static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size) @@ -1159,92 +1124,90 @@ static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size) chksum = 0; for (i = 0; i < size / 2; i++) - { chksum += src[i]; - } + return chksum; } -static void LinkTest_prnthexchar(char a0, u8 a1, u8 a2) +static void LinkTest_PrintNumChar(char val, u8 x, u8 y) { u16 *vAddr; vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); - vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + 1 + gLinkTestBGInfo.dummy_8); + vAddr[y * 32 + x] = (gLinkTestBGInfo.paletteNum << 12) | (val + 1 + gLinkTestBGInfo.baseChar); } -static void LinkTest_prntchar(char a0, u8 a1, u8 a2) +static void LinkTest_PrintChar(char val, u8 x, u8 y) { u16 *vAddr; vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); - vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + gLinkTestBGInfo.dummy_8); + vAddr[y * 32 + x] = (gLinkTestBGInfo.paletteNum << 12) | (val + gLinkTestBGInfo.baseChar); } -static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2) +static void LinkTest_PrintHex(u32 num, u8 x, u8 y, u8 length) { - char sp[32 / 2]; + char buff[16]; int i; - for (i = 0; i < a2; i++) + for (i = 0; i < length; i++) { - sp[i] = pos & 0xf; - pos >>= 4; + buff[i] = num & 0xF; + num >>= 4; } - for (i = a2 - 1; i >= 0; i--) + for (i = length - 1; i >= 0; i--) { - LinkTest_prnthexchar(sp[i], a0, a1); - a0++; + LinkTest_PrintNumChar(buff[i], x, y); + x++; } } -static void LinkTest_prntint(int a0, u8 a1, u8 a2, u8 a3) +static void LinkTest_PrintInt(int num, u8 x, u8 y, u8 length) { - char sp[32 / 2]; - int sp10; + char buff[16]; + int negX; int i; - sp10 = -1; - if (a0 < 0) - { - sp10 = a1; - a0 = -a0; - } - for (i = 0; i < a3; i++) + negX = -1; + if (num < 0) { - sp[i] = a0 % 10; - a0 /= 10; + negX = x; + num = -num; } - for (i = a3 - 1; i >= 0; i--) + for (i = 0; i < length; i++) { - LinkTest_prnthexchar(sp[i], a1, a2); - a1++; + buff[i] = num % 10; + num /= 10; } - if (sp10 != -1) + for (i = length - 1; i >= 0; i--) { - LinkTest_prnthexchar(*"\n", sp10, a2); + LinkTest_PrintNumChar(buff[i], x, y); + x++; } + + if (negX != -1) + LinkTest_PrintNumChar(*"\n", negX, y); } -static void LinkTest_prntstr(const char *a0, u8 a1, u8 a2) +static void LinkTest_PrintString(const char *str, u8 x, u8 y) { - int r6; + int xOffset; int i; - int r5; + int yOffset; - r5 = 0; - r6 = 0; - for (i = 0; a0[i] != 0; a0++) + yOffset = 0; + xOffset = 0; + for (i = 0; str[i] != 0; str++) { - if (a0[i] == *"\n") + if (str[i] == *"\n") { - r5++; - r6 = 0; + yOffset++; + xOffset = 0; } else { - LinkTest_prntchar(a0[i], a1 + r6, a2 + r5); - r6++; + LinkTest_PrintChar(str[i], x + xOffset, y + yOffset); + xOffset++; } } } @@ -1260,29 +1223,28 @@ static void LinkCB_RequestPlayerDataExchange(void) static void Task_PrintTestData(u8 taskId) { - char sp[32]; + char testTitle[32]; int i; - strcpy(sp, sASCIITestPrint); - 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); + strcpy(testTitle, sASCIITestPrint); + LinkTest_PrintString(testTitle, 5, 2); + LinkTest_PrintHex(gShouldAdvanceLinkState, 2, 1, 2); + LinkTest_PrintHex(gLinkStatus, 15, 1, 8); + LinkTest_PrintHex(gLink.state, 2, 10, 2); + LinkTest_PrintHex(EXTRACT_PLAYER_COUNT(gLinkStatus), 15, 10, 2); + LinkTest_PrintHex(GetMultiplayerId(), 15, 12, 2); + LinkTest_PrintHex(gLastSendQueueCount, 25, 1, 2); + LinkTest_PrintHex(gLastRecvQueueCount, 25, 2, 2); + LinkTest_PrintHex(GetBlockReceivedStatus(), 15, 5, 2); + LinkTest_PrintHex(gLinkDebugSeed, 2, 12, 8); + LinkTest_PrintHex(gLinkDebugFlags, 2, 13, 8); + LinkTest_PrintHex(GetSioMultiSI(), 25, 5, 1); + LinkTest_PrintHex(IsSioMultiMaster(), 25, 6, 1); + LinkTest_PrintHex(IsLinkConnectionEstablished(), 25, 7, 1); + LinkTest_PrintHex(HasLinkErrorOccurred(), 25, 8, 1); + for (i = 0; i < MAX_LINK_PLAYERS; i++) - { - LinkTest_prnthex(gLinkTestBlockChecksums[i], 10, 4 + i, 4); - } + LinkTest_PrintHex(gLinkTestBlockChecksums[i], 10, 4 + i, 4); } void SetLinkDebugValues(u32 seed, u32 flags) @@ -1298,9 +1260,8 @@ u8 GetSavedLinkPlayerCountAsBitFlags(void) flags = 0; for (i = 0; i < gSavedLinkPlayerCount; i++) - { flags |= (1 << i); - } + return flags; } @@ -1311,9 +1272,8 @@ u8 GetLinkPlayerCountAsBitFlags(void) flags = 0; for (i = 0; i < GetLinkPlayerCount(); i++) - { flags |= (1 << i); - } + return flags; } @@ -1324,9 +1284,7 @@ void SaveLinkPlayers(u8 playerCount) gSavedLinkPlayerCount = playerCount; gSavedMultiplayerId = GetMultiplayerId(); for (i = 0; i < MAX_RFU_PLAYERS; i++) - { - gSavedLinkPlayers[i] = gLinkPlayers[i]; - } + sSavedLinkPlayers[i] = gLinkPlayers[i]; } // The number of players when trading began. This is frequently compared against the @@ -1349,7 +1307,7 @@ bool8 DoesLinkPlayerCountMatchSaved(void) for (i = 0; i < gSavedLinkPlayerCount; i++) { - if (gLinkPlayers[i].trainerId == gSavedLinkPlayers[i].trainerId) + if (gLinkPlayers[i].trainerId == sSavedLinkPlayers[i].trainerId) { if (gLinkType == LINKTYPE_BATTLE_TOWER) { @@ -1375,12 +1333,15 @@ bool8 DoesLinkPlayerCountMatchSaved(void) void ClearSavedLinkPlayers(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)); - } + // The CpuSet loop below is incorrectly writing to NULL + // instead of sSavedLinkPlayers. + // Additionally it's using the wrong array size. +#ifdef UBFIX + memset(sSavedLinkPlayers, 0, sizeof(sSavedLinkPlayers)); +#else + for (i = 0; i < MAX_LINK_PLAYERS; i++) + CpuSet(&sSavedLinkPlayers[i], NULL, sizeof(struct LinkPlayer)); +#endif } void CheckLinkPlayersMatchSaved(void) @@ -1389,8 +1350,8 @@ void CheckLinkPlayersMatchSaved(void) for (i = 0; i < gSavedLinkPlayerCount; i++) { - if (gSavedLinkPlayers[i].trainerId != gLinkPlayers[i].trainerId - || StringCompare(gSavedLinkPlayers[i].name, gLinkPlayers[i].name) != 0) + if (sSavedLinkPlayers[i].trainerId != gLinkPlayers[i].trainerId + || StringCompare(sSavedLinkPlayers[i].name, gLinkPlayers[i].name) != 0) { gLinkErrorOccurred = TRUE; CloseLink(); @@ -1413,9 +1374,8 @@ u8 GetLinkPlayerCount_2(void) bool8 IsLinkMaster(void) { if (gWirelessCommType) - { return Rfu_IsMaster(); - } + return EXTRACT_MASTER(gLinkStatus); } @@ -1568,9 +1528,8 @@ void SetLinkStandbyCallback(void) else { if (gLinkCallback == NULL) - { gLinkCallback = LinkCB_Standby; - } + gLinkDummy1 = FALSE; } } @@ -1606,7 +1565,7 @@ static void LinkCB_StandbyForAll(void) static void CheckErrorStatus(void) { - if (gLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus)) + if (sLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus)) { if (!gSuppressLinkErrorMessage) { @@ -1620,12 +1579,12 @@ static void CheckErrorStatus(void) } } -void BufferLinkErrorInfo(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 unk_06) +void BufferLinkErrorInfo(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, bool8 disconnected) { sLinkErrorBuffer.status = status; sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount; sLinkErrorBuffer.lastRecvQueueCount = lastRecvQueueCount; - sLinkErrorBuffer.unk_06 = unk_06; + sLinkErrorBuffer.disconnected = disconnected; } void CB2_LinkError(void) @@ -1645,16 +1604,15 @@ void CB2_LinkError(void) ScanlineEffect_Stop(); if (gWirelessCommType) { - if (!sLinkErrorBuffer.unk_06) - { + if (!sLinkErrorBuffer.disconnected) gWirelessCommType = 3; - } + ResetLinkRfuGFLayer(); } SetVBlankCallback(VBlankCB_LinkError); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sLinkErrorBgTemplates, ARRAY_COUNT(sLinkErrorBgTemplates)); - sLinkErrorBgTilemapBuffer = tilemapBuffer = malloc(0x800); + sLinkErrorBgTilemapBuffer = tilemapBuffer = malloc(BG_SCREEN_SIZE); SetBgTilemapBuffer(1, tilemapBuffer); if (InitWindows(sLinkErrorWindowTemplates)) { @@ -1680,9 +1638,9 @@ void CB2_LinkError(void) } } -static void sub_800B080(void) +static void ErrorMsg_MoveCloserToPartner(void) { - LoadBgTiles(0, s2BlankTilesGfx, 0x20, 0); + LoadBgTiles(0, sCommErrorBg_Gfx, 0x20, 0); DecompressAndLoadBgGfxUsingHeap(1, sWirelessLinkDisplayGfx, FALSE, 0, 0); CopyToBgTilemapBuffer(1, sWirelessLinkDisplayTilemap, 0, 0); CopyBgTilemapBufferToVram(1); @@ -1697,9 +1655,9 @@ static void sub_800B080(void) CopyWindowToVram(2, 3); } -static void sub_800B138(void) +static void ErrorMsg_CheckConnections(void) { - LoadBgTiles(0, s2BlankTilesGfx, 0x20, 0); + LoadBgTiles(0, sCommErrorBg_Gfx, 0x20, 0); FillWindowPixelBuffer(1, PIXEL_FILL(0)); FillWindowPixelBuffer(2, PIXEL_FILL(0)); AddTextPrinterParameterized3(1, 3, 2, 0, sTextColors, 0, gText_CommErrorCheckConnections); @@ -1714,21 +1672,17 @@ static void CB2_PrintErrorMessage(void) switch (gMain.state) { case 00: - if (sLinkErrorBuffer.unk_06) - { - sub_800B080(); - } + // Below is only true for the RFU, so the other error + // type is inferred to be from a wired connection + if (sLinkErrorBuffer.disconnected) + ErrorMsg_MoveCloserToPartner(); else - { - sub_800B138(); - } + ErrorMsg_CheckConnections(); break; case 02: ShowBg(0); - if (sLinkErrorBuffer.unk_06) - { + if (sLinkErrorBuffer.disconnected) ShowBg(1); - } break; case 30: PlaySE(SE_BOO); @@ -1741,13 +1695,9 @@ static void CB2_PrintErrorMessage(void) break; case 130: if (gWirelessCommType == 2) - { AddTextPrinterParameterized3(0, 3, 2, 20, sTextColors, 0, gText_ABtnTitleScreen); - } else if (gWirelessCommType == 1) - { AddTextPrinterParameterized3(0, 3, 2, 20, sTextColors, 0, gText_ABtnRegistrationCounter); - } break; } if (gMain.state == 160) @@ -1758,7 +1708,7 @@ static void CB2_PrintErrorMessage(void) { PlaySE(SE_PIN); gWirelessCommType = 0; - sLinkErrorBuffer.unk_06 = 0; + sLinkErrorBuffer.disconnected = FALSE; sub_81700F8(); } } @@ -1772,10 +1722,9 @@ static void CB2_PrintErrorMessage(void) } } } + if (gMain.state != 160) - { gMain.state++; - } } // TODO: there might be a file boundary here, let's name it @@ -1805,7 +1754,7 @@ bool8 HasLinkErrorOccurred(void) return gLinkErrorOccurred; } -void sub_800B348(void) +void LocalLinkPlayerToBlock(void) { struct LinkPlayerBlock *block; @@ -1826,11 +1775,11 @@ void LinkPlayerFromBlock(u32 who) block = (struct LinkPlayerBlock *)gBlockRecvBuffer[who_]; player = &gLinkPlayers[who_]; *player = block->linkPlayer; - sub_800B524(player); - if (strcmp(block->magic1, sASCIIGameFreakInc) != 0 || strcmp(block->magic2, sASCIIGameFreakInc) != 0) - { + ConvertLinkPlayerName(player); + + if (strcmp(block->magic1, sASCIIGameFreakInc) != 0 + || strcmp(block->magic2, sASCIIGameFreakInc) != 0) SetMainCallback2(CB2_LinkError); - } } bool8 HandleLinkConnection(void) @@ -1842,21 +1791,17 @@ bool8 HandleLinkConnection(void) { gLinkStatus = LinkMain1(&gShouldAdvanceLinkState, gSendCmd, gRecvCmds); LinkMain2(&gMain.heldKeys); - if ((gLinkStatus & LINK_STAT_RECEIVED_NOTHING) && sub_808766C() == TRUE) - { + if ((gLinkStatus & LINK_STAT_RECEIVED_NOTHING) && IsSendingKeysOverCable() == TRUE) return TRUE; - } } else { r4 = sub_8010EC0(); r5 = sub_8010F1C(); - if (sub_808766C() == TRUE) + if (IsSendingKeysOverCable() == TRUE) { if (r4 == TRUE || IsRfuRecvQueueEmpty() || r5) - { return TRUE; - } } } return FALSE; @@ -1865,42 +1810,34 @@ bool8 HandleLinkConnection(void) void SetWirelessCommType1(void) { if (gReceivedRemoteLinkPlayers == 0) - { gWirelessCommType = 1; - } } static void SetWirelessCommType0_Internal(void) { if (gReceivedRemoteLinkPlayers == 0) - { gWirelessCommType = 0; - } } void SetWirelessCommType0(void) { if (gReceivedRemoteLinkPlayers == 0) - { gWirelessCommType = 0; - } } u32 GetLinkRecvQueueLength(void) { if (gWirelessCommType != 0) - { return GetRfuRecvQueueLength(); - } + return gLink.recvQueue.count; } -bool32 sub_800B504(void) +bool32 IsLinkRecvQueueLengthAtLeast3(void) { if (GetLinkRecvQueueLength() > 2) - { return TRUE; - } + return FALSE; } @@ -1910,9 +1847,9 @@ u8 GetWirelessCommType(void) return gWirelessCommType; } -void sub_800B524(struct LinkPlayer *player) +void ConvertLinkPlayerName(struct LinkPlayer *player) { - player->progressFlagsCopy = player->progressFlags; + player->progressFlagsCopy = player->progressFlags; // ? Perhaps relocating for a longer name field ConvertInternationalString(player->name, player->language); } @@ -2420,9 +2357,7 @@ void ResetSendBuffer(void) for (i = 0; i < CMD_LENGTH; i++) { for (j = 0; j < QUEUE_CAPACITY; j++) - { - gLink.sendQueue.data[i][j] = 0xEFFF; - } + gLink.sendQueue.data[i][j] = LINKCMD_NONE; } } @@ -2439,9 +2374,7 @@ void ResetRecvBuffer(void) for (j = 0; j < CMD_LENGTH; j++) { for (k = 0; k < QUEUE_CAPACITY; k++) - { - gLink.recvQueue.data[i][j][k] = 0xEFFF; - } + gLink.recvQueue.data[i][j][k] = LINKCMD_NONE; } } } diff --git a/src/link_rfu_2.c b/src/link_rfu_2.c index 3b49ae4b1..6366b9704 100644 --- a/src/link_rfu_2.c +++ b/src/link_rfu_2.c @@ -1697,7 +1697,7 @@ static void sub_801084C(u8 taskId) if (AreNoPlayersReceiving()) { ResetBlockReceivedFlags(); - sub_800B348(); + LocalLinkPlayerToBlock(); gTasks[taskId].data[0]++; } break; @@ -1786,7 +1786,7 @@ static void ReceiveRfuLinkPlayers(const struct SioInfo *sioInfo) for (i = 0; i < MAX_RFU_PLAYERS; i++) { gLinkPlayers[i] = sioInfo->linkPlayers[i]; - sub_800B524(gLinkPlayers + i); + ConvertLinkPlayerName(gLinkPlayers + i); } } @@ -1831,7 +1831,7 @@ static void Task_ExchangeLinkPlayers(u8 taskId) ResetBlockReceivedFlag(r4); r2 = (struct LinkPlayerBlock *)gBlockRecvBuffer[r4]; gLinkPlayers[r4] = r2->linkPlayer; - sub_800B524(gLinkPlayers + r4); + ConvertLinkPlayerName(gLinkPlayers + r4); gTasks[taskId].data[0]++; } break; @@ -1887,7 +1887,7 @@ static void sub_8010D0C(u8 taskId) case 0: if (Rfu.playerCount) { - sub_800B348(); + LocalLinkPlayerToBlock(); SendBlock(0, gBlockSendBuffer, sizeof(struct LinkPlayerBlock)); gTasks[taskId].data[0]++; } @@ -2472,7 +2472,7 @@ void RfuVSync(void) rfu_LMAN_syncVBlank(); } -void sub_8011AC8(void) +void ClearRecvCommands(void) { CpuFill32(0, gRecvCmds, sizeof(gRecvCmds)); } @@ -1616,6 +1616,9 @@ void ply_xcmd_0C(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *tra void ply_xcmd_0D(struct MusicPlayerInfo *mplayInfo, struct MusicPlayerTrack *track) { u32 unk; +#ifdef UBFIX + unk = 0; +#endif READ_XCMD_BYTE(unk, 0) // UB: uninitialized variable READ_XCMD_BYTE(unk, 1) @@ -1657,18 +1660,12 @@ start_song: mplayInfo = &gPokemonCryMusicPlayers[i]; mplayInfo->ident++; -#define CRY ((s32)&gPokemonCrySongs + i * sizeof(struct PokemonCrySong)) -#define CRY_OFS(field) offsetof(struct PokemonCrySong, field) + gPokemonCrySongs[i] = gPokemonCrySong; - memcpy((void *)CRY, &gPokemonCrySong, sizeof(struct PokemonCrySong)); - - *(u32 *)(CRY + CRY_OFS(tone)) = (u32)tone; - *(u32 *)(CRY + CRY_OFS(part)) = CRY + CRY_OFS(part0); - *(u32 *)(CRY + CRY_OFS(part) + 4) = CRY + CRY_OFS(part1); - *(u32 *)(CRY + CRY_OFS(gotoTarget)) = CRY + CRY_OFS(cont); - -#undef CRY_OFS -#undef CRY + gPokemonCrySongs[i].tone = tone; + gPokemonCrySongs[i].part[0] = &gPokemonCrySongs[i].part0; + gPokemonCrySongs[i].part[1] = &gPokemonCrySongs[i].part1; + gPokemonCrySongs[i].gotoTarget = (u32)&gPokemonCrySongs[i].cont; mplayInfo->ident = ID_NUMBER; diff --git a/src/mail.c b/src/mail.c index db8451395..0ee294787 100644 --- a/src/mail.c +++ b/src/mail.c @@ -593,7 +593,7 @@ static bool8 MailReadBuildGraphics(void) } break; case 15: - if (sub_8087598() == TRUE) + if (Overworld_LinkRecvQueueLengthMoreThan2() == TRUE) { return FALSE; } diff --git a/src/main.c b/src/main.c index 278b93542..3125716e2 100644 --- a/src/main.c +++ b/src/main.c @@ -132,7 +132,7 @@ void AgbMain() DoSoftReset(); } - if (sub_8087634() == 1) + if (Overworld_SendKeysToLinkIsRunning() == TRUE) { gLinkTransferringData = TRUE; UpdateLinkAndCallCallbacks(); @@ -143,7 +143,7 @@ void AgbMain() gLinkTransferringData = FALSE; UpdateLinkAndCallCallbacks(); - if (sub_80875C8() == 1) + if (Overworld_RecvKeysFromLinkIsRunning() == TRUE) { gMain.newKeys = 0; ClearSpriteCopyRequests(); diff --git a/src/map_name_popup.c b/src/map_name_popup.c index 8939edd90..65192fa33 100644 --- a/src/map_name_popup.c +++ b/src/map_name_popup.c @@ -197,8 +197,8 @@ static const u8 * const gBattlePyramid_MapHeaderStrings[] = gText_Pyramid, }; -// text -bool8 sub_80D47D4(void) +// Unused +static bool8 StartMenu_ShowMapNamePopup(void) { HideStartMenu(); ShowMapNamePopup(); @@ -333,24 +333,36 @@ static void ShowMapNamePopUpWindow(void) CopyWindowToVram(GetMapNamePopUpWindowId(), 3); } -static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) +#define TILE_TOP_EDGE_START 0x21D +#define TILE_TOP_EDGE_END 0x228 +#define TILE_LEFT_EDGE_TOP 0x229 +#define TILE_RIGHT_EDGE_TOP 0x22A +#define TILE_LEFT_EDGE_MID 0x22B +#define TILE_RIGHT_EDGE_MID 0x22C +#define TILE_LEFT_EDGE_BOT 0x22D +#define TILE_RIGHT_EDGE_BOT 0x22E +#define TILE_BOT_EDGE_START 0x22F +#define TILE_BOT_EDGE_END 0x23A + +static void DrawMapNamePopUpFrame(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) { s32 i; - for (i = 0; i < 12; i++) - { - FillBgTilemapBufferRect(bg, 0x21D + i, i - 1 + x, y - 1, 1, 1, 0xE); - } - FillBgTilemapBufferRect(bg, 0x229, x - 1, y, 1, 1, 0xE); - FillBgTilemapBufferRect(bg, 0x22A, deltaX + x, y, 1, 1, 0xE); - FillBgTilemapBufferRect(bg, 0x22B, x - 1, y + 1 , 1, 1, 0xE); - FillBgTilemapBufferRect(bg, 0x22C, deltaX + x, y + 1, 1, 1, 0xE); - FillBgTilemapBufferRect(bg, 0x22D, x - 1, y + 2, 1, 1, 0xE); - FillBgTilemapBufferRect(bg, 0x22E, deltaX + x, y + 2, 1, 1, 0xE); - for (i = 0; i < 12; i++) - { - FillBgTilemapBufferRect(bg, 0x22F + i, i - 1 + x, y + deltaY, 1, 1, 0xE); - } + // Draw top edge + for (i = 0; i < 1 + TILE_TOP_EDGE_END - TILE_TOP_EDGE_START; i++) + FillBgTilemapBufferRect(bg, TILE_TOP_EDGE_START + i, i - 1 + x, y - 1, 1, 1, 14); + + // Draw sides + FillBgTilemapBufferRect(bg, TILE_LEFT_EDGE_TOP, x - 1, y, 1, 1, 14); + FillBgTilemapBufferRect(bg, TILE_RIGHT_EDGE_TOP, deltaX + x, y, 1, 1, 14); + FillBgTilemapBufferRect(bg, TILE_LEFT_EDGE_MID, x - 1, y + 1, 1, 1, 14); + FillBgTilemapBufferRect(bg, TILE_RIGHT_EDGE_MID, deltaX + x, y + 1, 1, 1, 14); + FillBgTilemapBufferRect(bg, TILE_LEFT_EDGE_BOT, x - 1, y + 2, 1, 1, 14); + FillBgTilemapBufferRect(bg, TILE_RIGHT_EDGE_BOT, deltaX + x, y + 2, 1, 1, 14); + + // Draw bottom edge + for (i = 0; i < 1 + TILE_BOT_EDGE_END - TILE_BOT_EDGE_START; i++) + FillBgTilemapBufferRect(bg, TILE_BOT_EDGE_START + i, i - 1 + x, y + deltaY, 1, 1, 14); } static void LoadMapNamePopUpWindowBg(void) @@ -369,7 +381,7 @@ static void LoadMapNamePopUpWindowBg(void) popUpThemeId = gRegionMapSectionId_To_PopUpThemeIdMapping[regionMapSectionId]; LoadBgTiles(GetWindowAttribute(popupWindowId, WINDOW_BG), gMapPopUp_Outline_Table[popUpThemeId], 0x400, 0x21D); - CallWindowFunction(popupWindowId, sub_80D4A78); + CallWindowFunction(popupWindowId, DrawMapNamePopUpFrame); PutWindowTilemap(popupWindowId); if (gMapHeader.weather == WEATHER_UNDERWATER_BUBBLES) LoadPalette(&gUnknown_0857F444, 0xE0, 0x20); diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index cdcde9b06..228415628 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -425,21 +425,21 @@ static void StartBardSong(bool8 useTemporaryLyrics) gTasks[taskId].tUseTemporaryLyrics = useTemporaryLyrics; } -static void sub_81206F0(void) +static void EnableTextPrinters(void) { - gUnknown_03002F84 = FALSE; + gDisableTextPrinters = FALSE; } -static void BardSong_TextSubPrinter(struct TextPrinterTemplate * printer, u16 a1) +static void BardSong_DisableTextPrinters(struct TextPrinterTemplate * printer, u16 a1) { - gUnknown_03002F84 = TRUE; + gDisableTextPrinters = TRUE; } static void sub_8120708(const u8 * src) { DrawDialogueFrame(0, 0); - AddTextPrinterParameterized(0, 1, src, 0, 1, 1, BardSong_TextSubPrinter); - gUnknown_03002F84 = TRUE; + AddTextPrinterParameterized(0, 1, src, 0, 1, 1, BardSong_DisableTextPrinters); + gDisableTextPrinters = TRUE; CopyWindowToVram(0, 3); } @@ -620,7 +620,7 @@ static void Task_BardSong(u8 taskId) else if (gStringVar4[task->tCharIndex] == CHAR_SPACE) { - sub_81206F0(); + EnableTextPrinters(); task->tCharIndex++; task->tState = 2; task->data[2] = 0; @@ -640,7 +640,7 @@ static void Task_BardSong(u8 taskId) else if (gStringVar4[task->tCharIndex] == CHAR_SONG_WORD_SEPARATOR) { gStringVar4[task->tCharIndex] = CHAR_SPACE; // restore it back to a space - sub_81206F0(); + EnableTextPrinters(); task->tCharIndex++; task->data[2] = 0; } @@ -649,7 +649,7 @@ static void Task_BardSong(u8 taskId) switch (task->data[1]) { case 0: - sub_81206F0(); + EnableTextPrinters(); task->data[1]++; break; case 1: diff --git a/src/menu_helpers.c b/src/menu_helpers.c index b31d84a1e..e7385a5ed 100644 --- a/src/menu_helpers.c +++ b/src/menu_helpers.c @@ -312,14 +312,14 @@ static bool8 sub_81221D0(void) if (!MenuHelpers_LinkSomething()) return FALSE; else - return sub_8087598(); + return Overworld_LinkRecvQueueLengthMoreThan2(); } bool8 MenuHelpers_CallLinkSomething(void) { if (sub_81221D0() == TRUE) return TRUE; - else if (sub_800B504() != TRUE) + else if (IsLinkRecvQueueLengthAtLeast3() != TRUE) return FALSE; else return TRUE; diff --git a/src/minigame_countdown.c b/src/minigame_countdown.c index 01fb05fd8..2d4d98138 100644 --- a/src/minigame_countdown.c +++ b/src/minigame_countdown.c @@ -5,279 +5,378 @@ #include "sound.h" #include "task.h" #include "trig.h" +#include "minigame_countdown.h" #include "constants/songs.h" +/* + This file contains two types of '3-2-1 Start' countdowns intended for use by the wireless minigames. + + One is static, where the numbers simply appear and disappear without moving. This version is unused. + The other (used) version has the numbers squish and bounce up as they appear. +*/ + +#define TAG_STATIC_COUNTDOWN 0x2000 + +enum { + STATE_IDLE = 1, + STATE_START, + STATE_RUN, + STATE_END, +}; + +enum { + FUNC_INIT, + FUNC_FREE, + FUNC_START, + FUNC_RUN, +}; + +enum { + ANIM_THREE, + ANIM_TWO, + ANIM_ONE, + ANIM_START_LEFT, + ANIM_START_MID, + ANIM_START_RIGHT, +}; + extern const struct OamData gOamData_AffineOff_ObjNormal_32x32; -static void sub_802E6D0(u8 taskId); -static void sub_802E83C(u8 taskId); -static void sub_802E8C8(u8 taskId); -static void sub_802EA50(u8 taskId); -static void sub_802EAB0(u8 taskId); -static void Task_MinigameCountdown(u8 taskId); -static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId); -static bool32 IsStartGraphicAnimRunning(u8 spriteId); -static void Load321StartGfx(u16 tileTag, u16 palTag); -static u8 CreateNumberSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority); -static void CreateStartSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority, s16 *spriteId1, s16 *spriteId2); -static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3); -static void SpriteCB_Start(struct Sprite *sprite); +static void Task_StaticCountdown(u8 taskId); +static void Task_StaticCountdown_Init(u8 taskId); +static void Task_StaticCountdown_Free(u8 taskId); +static void Task_StaticCountdown_Start(u8 taskId); +static void Task_StaticCountdown_Run(u8 taskId); -static const u16 sSpritePal_321Start_2[] = INCBIN_U16("graphics/link_games/321start_2.gbapal"); -static const u32 sSpriteSheet_321Start_2[] = INCBIN_U32("graphics/link_games/321start_2.4bpp.lz"); +static const u16 s321Start_Static_Pal[] = INCBIN_U16("graphics/minigame_countdown/321start_static.gbapal"); +static const u32 s321Start_Static_Gfx[] = INCBIN_U32("graphics/minigame_countdown/321start_static.4bpp.lz"); -static const struct CompressedSpriteSheet gUnknown_082FE6C8[] = +static const struct CompressedSpriteSheet sSpriteSheet_321Start_Static[] = { - {sSpriteSheet_321Start_2, 0xC00, 0x2000}, + {s321Start_Static_Gfx, 0xC00, TAG_STATIC_COUNTDOWN}, {}, }; -static const struct SpritePalette gUnknown_082FE6D8[] = +static const struct SpritePalette sSpritePalette_321Start_Static[] = { - {sSpritePal_321Start_2, 0x2000}, + {s321Start_Static_Pal, TAG_STATIC_COUNTDOWN}, {}, }; -static const union AnimCmd sSpriteAnim_82FE6E8[] = +static const union AnimCmd sAnim_StaticCountdown_Three[] = { ANIMCMD_FRAME(0, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FE6F0[] = +static const union AnimCmd sAnim_StaticCountdown_Two[] = { ANIMCMD_FRAME(16, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FE6F8[] = +static const union AnimCmd sAnim_StaticCountdown_One[] = { ANIMCMD_FRAME(32, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FE700[] = +static const union AnimCmd sAnim_StaticCountdown_StartLeft[] = { ANIMCMD_FRAME(64, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FE708[] = +static const union AnimCmd sAnim_StaticCountdown_StartMid[] = { ANIMCMD_FRAME(48, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FE710[] = +static const union AnimCmd sAnim_StaticCountdown_StartRight[] = { ANIMCMD_FRAME(80, 0), ANIMCMD_END }; -static const union AnimCmd *const sSpriteAnimTable_82FE718[] = +static const union AnimCmd *const sAnims_StaticCountdown[] = { - sSpriteAnim_82FE6E8, - sSpriteAnim_82FE6F0, - sSpriteAnim_82FE6F8, - sSpriteAnim_82FE700, - sSpriteAnim_82FE708, - sSpriteAnim_82FE710 + [ANIM_THREE] = sAnim_StaticCountdown_Three, + [ANIM_TWO] = sAnim_StaticCountdown_Two, + [ANIM_ONE] = sAnim_StaticCountdown_One, + [ANIM_START_LEFT] = sAnim_StaticCountdown_StartLeft, + [ANIM_START_MID] = sAnim_StaticCountdown_StartMid, + [ANIM_START_RIGHT] = sAnim_StaticCountdown_StartRight }; -static const struct SpriteTemplate gUnknown_082FE730[] = +static const struct SpriteTemplate sSpriteTemplate_StaticCountdown[] = { { - .tileTag = 0x2000, - .paletteTag = 0x2000, + .tileTag = TAG_STATIC_COUNTDOWN, + .paletteTag = TAG_STATIC_COUNTDOWN, .oam = &gOamData_AffineOff_ObjNormal_32x32, - .anims = sSpriteAnimTable_82FE718, + .anims = sAnims_StaticCountdown, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }, }; -static const TaskFunc gUnknown_082FE748[][4] = +static const TaskFunc sStaticCountdownFuncs[][4] = { { - sub_802E83C, - sub_802E8C8, - sub_802EA50, - sub_802EAB0 + [FUNC_INIT] = Task_StaticCountdown_Init, + [FUNC_FREE] = Task_StaticCountdown_Free, + [FUNC_START] = Task_StaticCountdown_Start, + [FUNC_RUN] = Task_StaticCountdown_Run }, }; -static const u16 sSpritePal_321Start[] = INCBIN_U16("graphics/link_games/321start.gbapal"); -static const u32 sSpriteSheet_321Start[] = INCBIN_U32("graphics/link_games/321start.4bpp.lz"); +#define tState data[0] +#define tFuncSetId data[1] // These 4 data elements are indexes into +#define tSpriteTemplateId data[2] // arrays that only have 1 element with +#define tSpriteSheetId data[3] // data. As such their only legal value +#define tSpritePalId data[4] // is 0. Unclear why they were used. +#define tInterval data[5] +#define tPriority data[6] +#define tSubpriority data[7] +#define tNumSprites data[8] +#define tX data[9] +#define tY data[10] +#define tPrevTime data[10] // Re-used +#define tTimer data[11] +#define tLinkTimer data[12] +// 13-15 hold sprite ids +// tSpriteIds(0) is used for the number sprites, and the leftmost part of 'Start' +// tSpriteIds(1) is used for the middle part of 'Start' +// tSpriteIds(2) is used for for the rightmost part of 'Start' +#define tSpriteIds(i) data[13 + i] + +#define sInterval data[1] // Never read +#define sAnimNum data[2] +#define sTaskId data[3] +#define sId data[4] // Never read +#define sNumberSpriteId data[5] // Never read // Unused -static u32 sub_802E63C(u8 funcSetId, u8 taskPriority) +static u32 CreateStaticCountdownTask(u8 funcSetId, u8 taskPriority) { - u8 taskId = CreateTask(sub_802E6D0, taskPriority); + u8 taskId = CreateTask(Task_StaticCountdown, taskPriority); struct Task *task = &gTasks[taskId]; - task->data[0] = 1; - task->data[1] = funcSetId; - gUnknown_082FE748[funcSetId][0](taskId); + task->tState = STATE_IDLE; + task->tFuncSetId = funcSetId; + sStaticCountdownFuncs[funcSetId][FUNC_INIT](taskId); return taskId; } -static bool32 sub_802E688(void) +static bool32 StartStaticCountdown(void) { - u8 taskId = FindTaskIdByFunc(sub_802E6D0); + u8 taskId = FindTaskIdByFunc(Task_StaticCountdown); if (taskId == TASK_NONE) return FALSE; - gTasks[taskId].data[0] = 2; + gTasks[taskId].tState = STATE_START; return TRUE; } -static bool32 sub_802E6BC(void) +static bool32 IsStaticCountdownRunning(void) { - return FuncIsActiveTask(sub_802E6D0); + return FuncIsActiveTask(Task_StaticCountdown); } -static void sub_802E6D0(u8 taskId) +static void Task_StaticCountdown(u8 taskId) { s16 *data = gTasks[taskId].data; - switch (data[0]) + switch (tState) { - case 2: - gUnknown_082FE748[data[1]][2](taskId); - data[0] = 3; + // STATE_IDLE does nothing; wait until started + case STATE_START: + sStaticCountdownFuncs[tFuncSetId][FUNC_START](taskId); + tState = STATE_RUN; break; - case 3: - gUnknown_082FE748[data[1]][3](taskId); + case STATE_RUN: + sStaticCountdownFuncs[tFuncSetId][FUNC_RUN](taskId); break; - case 4: - gUnknown_082FE748[data[1]][1](taskId); + case STATE_END: + sStaticCountdownFuncs[tFuncSetId][FUNC_FREE](taskId); DestroyTask(taskId); break; } } -static void sub_802E75C(u8 taskId, s16 *data) +static void StaticCountdown_CreateSprites(u8 taskId, s16 *data) { u8 i; struct Sprite *sprite; - LoadCompressedSpriteSheet(&gUnknown_082FE6C8[data[3]]); - LoadSpritePalette(&gUnknown_082FE6D8[data[4]]); - for (i = 0; i < data[8]; i++) - data[13 + i] = CreateSprite(&gUnknown_082FE730[data[2]], data[9], data[10], data[7]); - for (i = 0; i < data[8]; i++) + LoadCompressedSpriteSheet(&sSpriteSheet_321Start_Static[tSpriteSheetId]); + LoadSpritePalette(&sSpritePalette_321Start_Static[tSpritePalId]); + for (i = 0; i < tNumSprites; i++) + tSpriteIds(i) = CreateSprite(&sSpriteTemplate_StaticCountdown[tSpriteTemplateId], tX, tY, tSubpriority); + for (i = 0; i < tNumSprites; i++) { - sprite = &gSprites[data[13 + i]]; - sprite->oam.priority = data[6]; + sprite = &gSprites[tSpriteIds(i)]; + sprite->oam.priority = tPriority; sprite->invisible = TRUE; - sprite->data[1] = data[5]; - sprite->data[3] = taskId; - sprite->data[4] = i; - sprite->data[5] = data[13]; + sprite->sInterval = tInterval; + sprite->sTaskId = taskId; + sprite->sId = i; + sprite->sNumberSpriteId = tSpriteIds(0); } } -static void sub_802E83C(u8 taskId) +static void Task_StaticCountdown_Init(u8 taskId) { s16 *data = gTasks[taskId].data; - data[2] = 0; - data[3] = 0; - data[4] = 0; - data[5] = 60; - data[6] = 0; - data[7] = 0; - data[8] = 3; - data[9] = 120; - data[10] = 88; - sub_802E75C(taskId, data); - - StartSpriteAnim(&gSprites[data[14]], 4); - gSprites[data[14]].pos2.x = -32; - - StartSpriteAnim(&gSprites[data[15]], 5); - gSprites[data[15]].pos2.x = 32; + tSpriteTemplateId = 0; + tSpriteSheetId = 0; + tSpritePalId = 0; + tInterval = 60; + tPriority = 0; + tSubpriority = 0; + tNumSprites = 3; + tX = 120; + tY = 88; + StaticCountdown_CreateSprites(taskId, data); + + StartSpriteAnim(&gSprites[tSpriteIds(1)], ANIM_START_MID); + gSprites[tSpriteIds(1)].pos2.x = -32; + + StartSpriteAnim(&gSprites[tSpriteIds(2)], ANIM_START_RIGHT); + gSprites[tSpriteIds(2)].pos2.x = 32; } -static void sub_802E8C8(u8 taskId) +static void Task_StaticCountdown_Free(u8 taskId) { u8 i = 0; s16 *data = gTasks[taskId].data; - for (i = 0; i < data[8]; i++) - DestroySprite(&gSprites[data[13 + i]]); - FreeSpriteTilesByTag(gUnknown_082FE6C8[data[3]].tag); - FreeSpritePaletteByTag(gUnknown_082FE6D8[data[4]].tag); + for (i = 0; i < tNumSprites; i++) + DestroySprite(&gSprites[tSpriteIds(i)]); + FreeSpriteTilesByTag(sSpriteSheet_321Start_Static[tSpriteSheetId].tag); + FreeSpritePaletteByTag(sSpritePalette_321Start_Static[tSpritePalId].tag); } -static void sub_802E938(struct Sprite *sprite) +static void SpriteCB_StaticCountdown(struct Sprite *sprite) { - s16 *data = gTasks[sprite->data[3]].data; + s16 *data = gTasks[sprite->sTaskId].data; - if (data[11] % data[5] != 0) + if (tTimer % tInterval != 0) return; - if (data[11] == data[10]) + if (tTimer == tPrevTime) return; - data[10] = data[11]; - switch (sprite->data[2]) + tPrevTime = tTimer; + switch (sprite->sAnimNum) { - case 0: + case ANIM_THREE: sprite->invisible = FALSE; - case 1: - case 2: + case ANIM_TWO: + case ANIM_ONE: + // Set sprite to a number PlaySE(SE_BALL_BOUNCE_1); - StartSpriteAnim(sprite, sprite->data[2]); + StartSpriteAnim(sprite, sprite->sAnimNum); break; - case 3: + case ANIM_START_LEFT: + // Set sprite to 'Start' PlaySE(SE_PIN); - StartSpriteAnim(sprite, sprite->data[2]); - gSprites[data[14]].invisible = FALSE; - gSprites[data[15]].invisible = FALSE; + StartSpriteAnim(sprite, sprite->sAnimNum); + gSprites[tSpriteIds(1)].invisible = FALSE; + gSprites[tSpriteIds(2)].invisible = FALSE; break; - case 4: + case ANIM_START_LEFT + 1: // End + // Hide countdown sprite->invisible = TRUE; - gSprites[data[14]].invisible = TRUE; - gSprites[data[15]].invisible = TRUE; - data[0] = 4; + gSprites[tSpriteIds(1)].invisible = TRUE; + gSprites[tSpriteIds(2)].invisible = TRUE; + tState = STATE_END; return; } - sprite->data[2]++; + sprite->sAnimNum++; } -static void sub_802EA50(u8 taskId) +static void Task_StaticCountdown_Start(u8 taskId) { s16 *data = gTasks[taskId].data; PlaySE(SE_BALL_BOUNCE_1); - gSprites[data[13]].callback = sub_802E938; - gSprites[data[13]].invisible = FALSE; - gTasks[taskId].data[0] = 3; + gSprites[tSpriteIds(0)].callback = SpriteCB_StaticCountdown; + gSprites[tSpriteIds(0)].invisible = FALSE; + gTasks[taskId].tState = STATE_RUN; } -static void sub_802EAB0(u8 taskId) +// Increment timer for progressing the countdown. +// If the player is the link leader, increment a +// separate timer and send it to group members for +// them to read and use. +static void Task_StaticCountdown_Run(u8 taskId) { - u16 packet[6]; + u16 packet[RFU_PACKET_SIZE]; s16 *data = gTasks[taskId].data; if (gReceivedRemoteLinkPlayers != 0) { - if (gRecvCmds[0][1] == LINKCMD_0x7FFF) - data[11] = gRecvCmds[0][2]; + // Read link timer + if (gRecvCmds[0][1] == LINKCMD_COUNTDOWN) + tTimer = gRecvCmds[0][2]; + if (GetMultiplayerId() == 0) { - data[12]++; + // Player is link leader. + // Send timer to group members + tLinkTimer++; memset(packet, 0, sizeof(packet)); - packet[0] = LINKCMD_0x7FFF; - packet[1] = data[12]; + packet[0] = LINKCMD_COUNTDOWN; + packet[1] = tLinkTimer; Rfu_SendPacket(packet); } } else { - data[11]++; + // Local, just increment own timer + tTimer++; } } +#undef tState +#undef tFuncSetId +#undef tSpriteTemplateId +#undef tSpriteSheetId +#undef tSpritePalId +#undef tInterval +#undef tPriority +#undef tSubpriority +#undef tNumSprites +#undef tX +#undef tY +#undef tPrevTime +#undef tTimer +#undef tLinkTimer +#undef tSpriteIds +#undef sInterval +#undef sAnimNum +#undef sTaskId +#undef sId +#undef sNumberSpriteId + +/* + The countdown that actually gets used by + the wireless minigames starts here +*/ + +static void Task_MinigameCountdown(u8 taskId); +static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId); +static bool32 IsStartGraphicAnimRunning(u8 spriteId); +static void Load321StartGfx(u16 tileTag, u16 palTag); +static u8 CreateNumberSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority); +static void CreateStartSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority, s16 *spriteId1, s16 *spriteId2); +static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3); +static void SpriteCB_Start(struct Sprite *sprite); + +static const u16 s321Start_Pal[] = INCBIN_U16("graphics/minigame_countdown/321start.gbapal"); +static const u32 s321Start_Gfx[] = INCBIN_U32("graphics/minigame_countdown/321start.4bpp.lz"); + #define tState data[0] #define tTilesTag data[2] #define tPalTag data[3] @@ -288,7 +387,7 @@ static void sub_802EAB0(u8 taskId) #define tSpriteId2 data[8] #define tSpriteId3 data[9] -void StartMinigameCountdown(s16 tilesTag, s16 palTag, s16 x, s16 y, u8 subpriority) +void StartMinigameCountdown(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority) { u8 taskId = CreateTask(Task_MinigameCountdown, 80); gTasks[taskId].tTilesTag = tilesTag; @@ -337,69 +436,82 @@ static void Task_MinigameCountdown(u8 taskId) } } +#define sState data[0] +#define sTimer data[2] +#define sAnimNum data[4] + static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId) { struct Sprite *sprite = &gSprites[spriteId]; - switch (sprite->data[0]) + switch (sprite->sState) { case 0: sub_8007E18(sprite, 0x800, 0x1A); - sprite->data[0]++; + sprite->sState++; // fallthrough case 1: - if (sprite->data[2] == 0) + if (sprite->sTimer == 0) PlaySE(SE_BALL_BOUNCE_2); - if (++sprite->data[2] >= 20) + + if (++sprite->sTimer >= 20) { - sprite->data[2] = 0; + // Ready for jump + sprite->sTimer = 0; StartSpriteAffineAnim(sprite, 1); - sprite->data[0]++; + sprite->sState++; } break; case 2: if (sprite->affineAnimEnded) - sprite->data[0]++; + sprite->sState++; break; case 3: - if (++sprite->data[2] >= 4) + if (++sprite->sTimer >= 4) { - sprite->data[2] = 0; - sprite->data[0]++; + // Start jump + sprite->sTimer = 0; + sprite->sState++; StartSpriteAffineAnim(sprite, 2); } break; case 4: + // Moving up from jump sprite->pos1.y -= 4; - if (++sprite->data[2] >= 8) + if (++sprite->sTimer >= 8) { - if (sprite->data[4] <= 1) + if (sprite->sAnimNum < 2) { - StartSpriteAnim(sprite, sprite->data[4] + 1); - sprite->data[2] = 0; - sprite->data[0]++; + // Swap to the next number + StartSpriteAnim(sprite, sprite->sAnimNum + 1); + sprite->sTimer = 0; + sprite->sState++; } else { - sprite->data[0] = 7; + // End + sprite->sState = 7; return FALSE; } } break; case 5: + // Falling after jump sprite->pos1.y += 4; - if (++sprite->data[2] >= 8) + if (++sprite->sTimer >= 8) { - sprite->data[2] = 0; + // Land from jump + sprite->sTimer = 0; StartSpriteAffineAnim(sprite, 3); - sprite->data[0]++; + sprite->sState++; } break; case 6: if (sprite->affineAnimEnded) { - sprite->data[4]++; - sprite->data[0] = 1; + // Restart for next number + sprite->sAnimNum++; + sprite->sState = 1; } break; case 7: @@ -409,6 +521,10 @@ static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId) return TRUE; } +#undef sState +#undef sTimer +#undef sAnimNum + // First argument is unused. static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3) { @@ -425,60 +541,70 @@ static bool32 IsStartGraphicAnimRunning(u8 spriteId) return gSprites[spriteId].callback == SpriteCB_Start; } +#define sState data[0] +#define sTimer data[1] +#define sYSpeed data[4] +#define sY data[5] + static void SpriteCB_Start(struct Sprite *sprite) { int y; s16 *data = sprite->data; - switch (data[0]) + switch (sState) { case 0: - data[4] = 64; - data[5] = sprite->pos2.y << 4; - data[0]++; + sYSpeed = 64; + sY = sprite->pos2.y << 4; + sState++; case 1: - data[5] += data[4]; - data[4]++; - sprite->pos2.y = data[5] >> 4; + sY += sYSpeed; + sYSpeed++; + sprite->pos2.y = sY >> 4; if (sprite->pos2.y >= 0) { PlaySE(SE_BALL_BOUNCE_2); sprite->pos2.y = 0; - data[0]++; + sState++; } break; case 2: - data[1] += 12; - if (data[1] >= 128) + sTimer += 12; + if (sTimer >= 128) { PlaySE(SE_BALL_BOUNCE_2); - data[1] = 0; - data[0]++; + sTimer = 0; + sState++; } - y = gSineTable[data[1]]; + y = gSineTable[sTimer]; sprite->pos2.y = -(y >> 4); break; case 3: - data[1] += 16; - if (data[1] >= 128) + sTimer += 16; + if (sTimer >= 128) { PlaySE(SE_BALL_BOUNCE_2); - data[1] = 0; - data[0]++; + sTimer = 0; + sState++; } - sprite->pos2.y = -(gSineTable[data[1]] >> 5); + sprite->pos2.y = -(gSineTable[sTimer] >> 5); break; case 4: - if (++data[1] > 40) + if (++sTimer > 40) sprite->callback = SpriteCallbackDummy; break; } } +#undef sState +#undef sTimer +#undef sYSpeed +#undef sY + static void Load321StartGfx(u16 tileTag, u16 palTag) { - struct CompressedSpriteSheet spriteSheet = {sSpriteSheet_321Start, 0xE00, 0}; - struct SpritePalette spritePalette = {sSpritePal_321Start, 0}; + struct CompressedSpriteSheet spriteSheet = {s321Start_Gfx, 0xE00, 0}; + struct SpritePalette spritePalette = {s321Start_Pal, 0}; spriteSheet.tag = tileTag; spritePalette.tag = palTag; @@ -564,26 +690,26 @@ static const union AnimCmd *const sAnimTable_Start[] = sAnim_StartRight }; -static const union AffineAnimCmd sAffineAnim_Numbers_0[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Normal[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_1[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Squash[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_FRAME(16, -16, 0, 8), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_2[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Stretch[] = { AFFINEANIMCMD_FRAME(-18, 18, 0, 8), AFFINEANIMCMD_END }; -static const union AffineAnimCmd sAffineAnim_Numbers_3[] = +static const union AffineAnimCmd sAffineAnim_Numbers_Land[] = { AFFINEANIMCMD_FRAME( 6, -6, 0, 8), AFFINEANIMCMD_FRAME( -4, 4, 0, 8), @@ -593,10 +719,10 @@ static const union AffineAnimCmd sAffineAnim_Numbers_3[] = static const union AffineAnimCmd *const sAffineAnimTable_Numbers[] = { - sAffineAnim_Numbers_0, - sAffineAnim_Numbers_1, - sAffineAnim_Numbers_2, - sAffineAnim_Numbers_3 + sAffineAnim_Numbers_Normal, + sAffineAnim_Numbers_Squash, // Push down before the jump + sAffineAnim_Numbers_Stretch, // Stretch up for the jump + sAffineAnim_Numbers_Land // Land after the jump }; static u8 CreateNumberSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority) diff --git a/src/option_menu.c b/src/option_menu.c index 64e9b6576..936aff923 100644 --- a/src/option_menu.c +++ b/src/option_menu.c @@ -75,7 +75,7 @@ static u8 ButtonMode_ProcessInput(u8 selection); static void ButtonMode_DrawChoices(u8 selection); static void DrawTextOption(void); static void DrawOptionMenuTexts(void); -static void sub_80BB154(void); +static void DrawBgWindowFrames(void); EWRAM_DATA static bool8 sArrowPressed = FALSE; @@ -228,7 +228,7 @@ void CB2_InitOptionMenu(void) DrawOptionMenuTexts(); gMain.state++; case 9: - sub_80BB154(); + DrawBgWindowFrames(); gMain.state++; break; case 10: @@ -642,25 +642,37 @@ static void DrawOptionMenuTexts(void) CopyWindowToVram(WIN_OPTIONS, 3); } -static void sub_80BB154(void) +#define TILE_TOP_CORNER_L 0x1A2 +#define TILE_TOP_EDGE 0x1A3 +#define TILE_TOP_CORNER_R 0x1A4 +#define TILE_LEFT_EDGE 0x1A5 +#define TILE_RIGHT_EDGE 0x1A7 +#define TILE_BOT_CORNER_L 0x1A8 +#define TILE_BOT_EDGE 0x1A9 +#define TILE_BOT_CORNER_R 0x1AA + +static void DrawBgWindowFrames(void) { - // bg, tileNum, x, y, width, height, pal - FillBgTilemapBufferRect(1, 0x1A2, 1, 0, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A3, 2, 0, 0x1B, 1, 7); - FillBgTilemapBufferRect(1, 0x1A4, 28, 0, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A5, 1, 1, 1, 2, 7); - FillBgTilemapBufferRect(1, 0x1A7, 28, 1, 1, 2, 7); - FillBgTilemapBufferRect(1, 0x1A8, 1, 3, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A9, 2, 3, 0x1B, 1, 7); - FillBgTilemapBufferRect(1, 0x1AA, 28, 3, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A2, 1, 4, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A3, 2, 4, 0x1A, 1, 7); - FillBgTilemapBufferRect(1, 0x1A4, 28, 4, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A5, 1, 5, 1, 0x12, 7); - FillBgTilemapBufferRect(1, 0x1A7, 28, 5, 1, 0x12, 7); - FillBgTilemapBufferRect(1, 0x1A8, 1, 19, 1, 1, 7); - FillBgTilemapBufferRect(1, 0x1A9, 2, 19, 0x1A, 1, 7); - FillBgTilemapBufferRect(1, 0x1AA, 28, 19, 1, 1, 7); + // bg, tile, x, y, width, height, palNum + // Draw title window frame + FillBgTilemapBufferRect(1, TILE_TOP_CORNER_L, 1, 0, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_TOP_EDGE, 2, 0, 27, 1, 7); + FillBgTilemapBufferRect(1, TILE_TOP_CORNER_R, 28, 0, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_LEFT_EDGE, 1, 1, 1, 2, 7); + FillBgTilemapBufferRect(1, TILE_RIGHT_EDGE, 28, 1, 1, 2, 7); + FillBgTilemapBufferRect(1, TILE_BOT_CORNER_L, 1, 3, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_BOT_EDGE, 2, 3, 27, 1, 7); + FillBgTilemapBufferRect(1, TILE_BOT_CORNER_R, 28, 3, 1, 1, 7); + + // Draw options list window frame + FillBgTilemapBufferRect(1, TILE_TOP_CORNER_L, 1, 4, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_TOP_EDGE, 2, 4, 26, 1, 7); + FillBgTilemapBufferRect(1, TILE_TOP_CORNER_R, 28, 4, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_LEFT_EDGE, 1, 5, 1, 18, 7); + FillBgTilemapBufferRect(1, TILE_RIGHT_EDGE, 28, 5, 1, 18, 7); + FillBgTilemapBufferRect(1, TILE_BOT_CORNER_L, 1, 19, 1, 1, 7); + FillBgTilemapBufferRect(1, TILE_BOT_EDGE, 2, 19, 26, 1, 7); + FillBgTilemapBufferRect(1, TILE_BOT_CORNER_R, 28, 19, 1, 1, 7); CopyBgTilemapBufferToVram(1); } diff --git a/src/overworld.c b/src/overworld.c index 5aa5bb73d..e7c86b0a4 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -125,14 +125,14 @@ static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion); static void GetLinkPlayerCoords(u8 linkPlayerId, u16 *x, u16 *y); static u8 GetLinkPlayerFacingDirection(u8 linkPlayerId); static u8 GetLinkPlayerElevation(u8 linkPlayerId); -static s32 sub_80878E4(u8 linkPlayerId); +static s32 GetLinkPlayerObjectStepTimer(u8 linkPlayerId); static u8 GetLinkPlayerIdAt(s16 x, s16 y); static void SetPlayerFacingDirection(u8 linkPlayerId, u8 a2); static void ZeroObjectEvent(struct ObjectEvent *objEvent); static void SpawnLinkPlayerObjectEvent(u8 linkPlayerId, s16 x, s16 y, u8 a4); static void InitLinkPlayerObjectEventPos(struct ObjectEvent *objEvent, s16 x, s16 y); -static void sub_80877DC(u8 linkPlayerId, u8 a2); -static void sub_808780C(u8 linkPlayerId); +static void SetLinkPlayerObjectRange(u8 linkPlayerId, u8 a2); +static void DestroyLinkPlayerObject(u8 linkPlayerId); static u8 GetSpriteForLinkedPlayer(u8 linkPlayerId); static void RunTerminateLinkScript(void); static u32 GetLinkSendQueueLength(void); @@ -172,7 +172,7 @@ static u8 sPlayerTradingStates[MAX_LINK_PLAYERS]; // adjusted key code, effectively intercepting the input before anything // can process it. static u16 (*sPlayerKeyInterceptCallback)(u32); -static bool8 sUnknown_03000E18; +static bool8 sReceivingFromLink; static u8 sRfuKeepAliveTimer; // IWRAM common @@ -1626,7 +1626,7 @@ static void CB2_ReturnToFieldLocal(void) static void CB2_ReturnToFieldLink(void) { - if (!sub_8087598() && ReturnToFieldLink(&gMain.state)) + if (!Overworld_LinkRecvQueueLengthMoreThan2() && ReturnToFieldLink(&gMain.state)) SetMainCallback2(CB2_Overworld); } @@ -2823,18 +2823,18 @@ static void RunTerminateLinkScript(void) ScriptContext2_Enable(); } -bool32 sub_8087598(void) +bool32 Overworld_LinkRecvQueueLengthMoreThan2(void) { if (!IsUpdateLinkStateCBActive()) return FALSE; if (GetLinkRecvQueueLength() >= 3) - sUnknown_03000E18 = TRUE; + sReceivingFromLink = TRUE; else - sUnknown_03000E18 = FALSE; - return sUnknown_03000E18; + sReceivingFromLink = FALSE; + return sReceivingFromLink; } -bool32 sub_80875C8(void) +bool32 Overworld_RecvKeysFromLinkIsRunning(void) { u8 temp; @@ -2849,8 +2849,8 @@ bool32 sub_80875C8(void) else if (sPlayerKeyInterceptCallback != KeyInterCB_DeferToEventScript) return FALSE; - temp = sUnknown_03000E18; - sUnknown_03000E18 = FALSE; + temp = sReceivingFromLink; + sReceivingFromLink = FALSE; if (temp == TRUE) return TRUE; @@ -2860,7 +2860,7 @@ bool32 sub_80875C8(void) return FALSE; } -bool32 sub_8087634(void) +bool32 Overworld_SendKeysToLinkIsRunning(void) { if (GetLinkSendQueueLength() < 2) return FALSE; @@ -2874,7 +2874,7 @@ bool32 sub_8087634(void) return FALSE; } -bool32 sub_808766C(void) +bool32 IsSendingKeysOverCable(void) { if (gWirelessCommType != 0) return FALSE; @@ -2923,15 +2923,15 @@ static void SpawnLinkPlayerObjectEvent(u8 linkPlayerId, s16 x, s16 y, u8 gender) ZeroLinkPlayerObjectEvent(linkPlayerObjEvent); ZeroObjectEvent(objEvent); - linkPlayerObjEvent->active = 1; + linkPlayerObjEvent->active = TRUE; linkPlayerObjEvent->linkPlayerId = linkPlayerId; linkPlayerObjEvent->objEventId = objEventId; linkPlayerObjEvent->movementMode = MOVEMENT_MODE_FREE; - objEvent->active = 1; + objEvent->active = TRUE; linkGender(objEvent) = gender; linkDirection(objEvent) = DIR_NORTH; - objEvent->spriteId = 64; + objEvent->spriteId = MAX_SPRITES; InitLinkPlayerObjectEventPos(objEvent, x, y); } @@ -2947,7 +2947,7 @@ static void InitLinkPlayerObjectEventPos(struct ObjectEvent *objEvent, s16 x, s1 ObjectEventUpdateZCoord(objEvent); } -static void sub_80877DC(u8 linkPlayerId, u8 dir) +static void SetLinkPlayerObjectRange(u8 linkPlayerId, u8 dir) { if (gLinkPlayerObjectEvents[linkPlayerId].active) { @@ -2957,7 +2957,7 @@ static void sub_80877DC(u8 linkPlayerId, u8 dir) } } -static void sub_808780C(u8 linkPlayerId) +static void DestroyLinkPlayerObject(u8 linkPlayerId) { struct LinkPlayerObjectEvent *linkPlayerObjEvent = &gLinkPlayerObjectEvents[linkPlayerId]; u8 objEventId = linkPlayerObjEvent->objEventId; @@ -2998,7 +2998,7 @@ static u8 GetLinkPlayerElevation(u8 linkPlayerId) return objEvent->currentElevation; } -static s32 sub_80878E4(u8 linkPlayerId) +static s32 GetLinkPlayerObjectStepTimer(u8 linkPlayerId) { u8 objEventId = gLinkPlayerObjectEvents[linkPlayerId].objEventId; struct ObjectEvent *objEvent = &gObjectEvents[objEventId]; @@ -3048,32 +3048,32 @@ static void SetPlayerFacingDirection(u8 linkPlayerId, u8 facing) } -static u8 MovementEventModeCB_Normal(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static u8 MovementEventModeCB_Normal(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { - return gLinkPlayerFacingHandlers[a3](linkPlayerObjEvent, objEvent, a3); + return gLinkPlayerFacingHandlers[dir](linkPlayerObjEvent, objEvent, dir); } -static u8 MovementEventModeCB_Ignored(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static u8 MovementEventModeCB_Ignored(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { return FACING_UP; } // Duplicate Function -static u8 MovementEventModeCB_Normal_2(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static u8 MovementEventModeCB_Normal_2(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { - return gLinkPlayerFacingHandlers[a3](linkPlayerObjEvent, objEvent, a3); + return gLinkPlayerFacingHandlers[dir](linkPlayerObjEvent, objEvent, dir); } -static bool8 FacingHandler_DoNothing(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static bool8 FacingHandler_DoNothing(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { return FALSE; } -static bool8 FacingHandler_DpadMovement(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static bool8 FacingHandler_DpadMovement(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { s16 x, y; - linkDirection(objEvent) = FlipVerticalAndClearForced(a3, linkDirection(objEvent)); + linkDirection(objEvent) = FlipVerticalAndClearForced(dir, linkDirection(objEvent)); ObjectEventMoveDestCoords(objEvent, linkDirection(objEvent), &x, &y); if (LinkPlayerDetectCollision(linkPlayerObjEvent->objEventId, linkDirection(objEvent), x, y)) @@ -3089,9 +3089,9 @@ static bool8 FacingHandler_DpadMovement(struct LinkPlayerObjectEvent *linkPlayer } } -static bool8 FacingHandler_ForcedFacingChange(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 a3) +static bool8 FacingHandler_ForcedFacingChange(struct LinkPlayerObjectEvent *linkPlayerObjEvent, struct ObjectEvent *objEvent, u8 dir) { - linkDirection(objEvent) = FlipVerticalAndClearForced(a3, linkDirection(objEvent)); + linkDirection(objEvent) = FlipVerticalAndClearForced(dir, linkDirection(objEvent)); return FALSE; } diff --git a/src/party_menu.c b/src/party_menu.c index fc547e96d..7b77a1067 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4904,7 +4904,7 @@ void ItemUseCB_RareCandy(u8 taskId, TaskFunc task) else { gPartyMenuUseExitCallback = TRUE; - PlayFanfareByFanfareNum(0); + PlayFanfareByFanfareNum(FANFARE_LEVEL_UP); UpdateMonDisplayInfoAfterRareCandy(gPartyMenu.slotId, mon); RemoveBagItem(gSpecialVar_ItemId, 1); GetMonNickname(mon, gStringVar1); diff --git a/src/pokedex.c b/src/pokedex.c index 645d8e6c8..558c27083 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -3032,17 +3032,8 @@ static void SpriteCB_PokedexListMonSprite(struct Sprite *sprite) else { u32 var; - sprite->pos2.y = gSineTable[(u8)sprite->data[5]] * 76 / 256; - // UB: possible division by zero -#ifdef UBFIX - if (gSineTable[sprite->data[5] + 64] != 0) - var = 0x10000 / gSineTable[sprite->data[5] + 64]; - else - var = 0; -#else - var = 0x10000 / gSineTable[sprite->data[5] + 64]; -#endif //UBFIX + var = SAFE_DIV(0x10000, gSineTable[sprite->data[5] + 64]); if (var > 0xFFFF) var = 0xFFFF; SetOamMatrix(sprite->data[1] + 1, 0x100, 0, 0, var); diff --git a/src/pokemon.c b/src/pokemon.c index 2abf9cb56..5b683584b 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4649,7 +4649,7 @@ bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, { \ friendshipChange = itemEffect[itemEffectParam]; \ friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); \ - if (friendshipChange > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) \ + if (friendshipChange > 0 && holdEffect == HOLD_EFFECT_FRIENDSHIP_UP) \ friendship += 150 * friendshipChange / 100; \ else \ friendship += friendshipChange; \ @@ -5828,7 +5828,7 @@ void AdjustFriendship(struct Pokemon *mon, u8 event) && (event != FRIENDSHIP_EVENT_LEAGUE_BATTLE || IS_LEAGUE_BATTLE)) { s8 mod = sFriendshipEventModifiers[event][friendshipLevel]; - if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) + if (mod > 0 && holdEffect == HOLD_EFFECT_FRIENDSHIP_UP) mod = (150 * mod) / 100; friendship += mod; if (mod > 0) diff --git a/src/pokemon_jump.c b/src/pokemon_jump.c index f50a2d042..a1b7d36aa 100755 --- a/src/pokemon_jump.c +++ b/src/pokemon_jump.c @@ -131,14 +131,16 @@ enum { #define TAG_MON4 3 #define TAG_MON5 4 -#define GFXTAG_VINE1 5 -#define GFXTAG_VINE2 6 -#define GFXTAG_VINE3 7 -#define GFXTAG_VINE4 8 -#define GFXTAG_STAR 10 +#define GFXTAG_VINE1 5 +#define GFXTAG_VINE2 6 +#define GFXTAG_VINE3 7 +#define GFXTAG_VINE4 8 +#define GFXTAG_COUNTDOWN 9 +#define GFXTAG_STAR 10 -#define PALTAG_1 5 -#define PALTAG_2 6 +#define PALTAG_1 5 +#define PALTAG_2 6 +#define PALTAG_COUNTDOWN 7 #define TAG_DIGITS 800 @@ -2646,13 +2648,13 @@ static const struct OamData sOamData_Star = .affineParam = 0 }; -static const union AnimCmd sSpriteAnim_82FBFE0[] = +static const union AnimCmd sAnim_Star_Still[] = { ANIMCMD_FRAME(0, 0), ANIMCMD_END }; -static const union AnimCmd sSpriteAnim_82FBFE8[] = +static const union AnimCmd sAnim_Star_Spinning[] = { ANIMCMD_FRAME(0, 4), ANIMCMD_FRAME(4, 4), @@ -2665,8 +2667,8 @@ static const union AnimCmd sSpriteAnim_82FBFE8[] = static const union AnimCmd *const sAnims_Star[] = { - sSpriteAnim_82FBFE0, - sSpriteAnim_82FBFE8 + sAnim_Star_Still, + sAnim_Star_Spinning }; static const struct SpriteTemplate sSpriteTemplate_Star = @@ -3007,7 +3009,7 @@ static void UpdateVineAnim(struct PokemonJumpGfx *jumpGfx, int vineState) static void StartPokeJumpCountdown(struct PokemonJumpGfx *jumpGfx) { - StartMinigameCountdown(9, 7, 120, 80, 0); + StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0); Gfx_ResetMonSpriteSubpriorities(jumpGfx); } diff --git a/src/pokenav.c b/src/pokenav.c index eac0c85b4..881411b9e 100644 --- a/src/pokenav.c +++ b/src/pokenav.c @@ -288,7 +288,7 @@ static void Task_RunLoopedTask_LinkMode(u8 taskId) s16 *state; u32 action; - if (sub_8087598()) + if (Overworld_LinkRecvQueueLengthMoreThan2()) return; task = (LoopedTask)GetWordTaskArg(taskId, 1); diff --git a/src/recorded_battle.c b/src/recorded_battle.c index 5db4f82c5..e29792766 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -84,7 +84,7 @@ EWRAM_DATA static u8 sFrontierFacility = 0; EWRAM_DATA static u8 sFrontierBrainSymbol = 0; EWRAM_DATA static MainCallback sCallback2_AfterRecordedBattle = NULL; EWRAM_DATA u8 gRecordedBattleMultiplayerId = 0; -EWRAM_DATA static u8 sUnknown_0203C7B5 = 0; +EWRAM_DATA static u8 sFrontierPassFlag = 0; EWRAM_DATA static u8 sBattleScene = 0; EWRAM_DATA static u8 sTextSpeed = 0; EWRAM_DATA static u32 sBattleFlags = 0; @@ -687,19 +687,20 @@ u8 GetActiveBattlerLinkPlayerGender(void) return 0; } -void sub_8185F84(void) +void RecordedBattle_ClearFrontierPassFlag(void) { - sUnknown_0203C7B5 = 0; + sFrontierPassFlag = 0; } -void sub_8185F90(u16 arg0) +// Set sFrontierPassFlag to received state of FLAG_SYS_FRONTIER_PASS +void RecordedBattle_SetFrontierPassFlagFromHword(u16 arg0) { - sUnknown_0203C7B5 |= (arg0 & 0x8000) >> 0xF; + sFrontierPassFlag |= (arg0 & 0x8000) >> 15; } -u8 sub_8185FAC(void) +u8 RecordedBattle_GetFrontierPassFlag(void) { - return sUnknown_0203C7B5; + return sFrontierPassFlag; } u8 GetBattleSceneInRecordedBattle(void) diff --git a/src/shop.c b/src/shop.c index 26bd964c5..dac43c96d 100755 --- a/src/shop.c +++ b/src/shop.c @@ -40,11 +40,14 @@ #include "constants/songs.h" #include "constants/tv.h" -EWRAM_DATA struct MartInfo gMartInfo = {0}; -EWRAM_DATA struct ShopData *gShopDataPtr = NULL; -EWRAM_DATA struct ListMenuItem *gUnknown_02039F74 = NULL; -EWRAM_DATA u8 (*gUnknown_02039F78)[16] = {0}; -EWRAM_DATA u8 gMartPurchaseHistoryId = 0; +#define TAG_SCROLL_ARROW 2100 +#define TAG_ITEM_ICON_BASE 2110 + +static EWRAM_DATA struct MartInfo sMartInfo = {0}; +static EWRAM_DATA struct ShopData *sShopData = NULL; +static EWRAM_DATA struct ListMenuItem *sListMenuItems = NULL; +static EWRAM_DATA u8 (*sItemNames)[16] = {0}; +static EWRAM_DATA u8 sPurchaseHistoryId = 0; EWRAM_DATA struct ItemSlot gMartPurchaseHistory[3] = {0}; static void Task_ShopMenu(u8 taskId); @@ -276,15 +279,15 @@ static u8 CreateShopMenu(u8 martType) int numMenuItems; ScriptContext2_Enable(); - gMartInfo.martType = martType; + sMartInfo.martType = martType; if (martType == MART_TYPE_NORMAL) { struct WindowTemplate winTemplate; winTemplate = sShopMenuWindowTemplates[0]; winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuySellQuit, ARRAY_COUNT(sShopMenuActions_BuySellQuit)); - gMartInfo.windowId = AddWindow(&winTemplate); - gMartInfo.menuActions = sShopMenuActions_BuySellQuit; + sMartInfo.windowId = AddWindow(&winTemplate); + sMartInfo.menuActions = sShopMenuActions_BuySellQuit; numMenuItems = ARRAY_COUNT(sShopMenuActions_BuySellQuit); } else @@ -292,35 +295,35 @@ static u8 CreateShopMenu(u8 martType) struct WindowTemplate winTemplate; winTemplate = sShopMenuWindowTemplates[1]; winTemplate.width = GetMaxWidthInMenuTable(sShopMenuActions_BuyQuit, ARRAY_COUNT(sShopMenuActions_BuyQuit)); - gMartInfo.windowId = AddWindow(&winTemplate); - gMartInfo.menuActions = sShopMenuActions_BuyQuit; + sMartInfo.windowId = AddWindow(&winTemplate); + sMartInfo.menuActions = sShopMenuActions_BuyQuit; numMenuItems = ARRAY_COUNT(sShopMenuActions_BuyQuit); } - SetStandardWindowBorderStyle(gMartInfo.windowId, 0); - PrintMenuTable(gMartInfo.windowId, numMenuItems, gMartInfo.menuActions); - InitMenuInUpperLeftCornerPlaySoundWhenAPressed(gMartInfo.windowId, numMenuItems, 0); - PutWindowTilemap(gMartInfo.windowId); - CopyWindowToVram(gMartInfo.windowId, 1); + SetStandardWindowBorderStyle(sMartInfo.windowId, 0); + PrintMenuTable(sMartInfo.windowId, numMenuItems, sMartInfo.menuActions); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(sMartInfo.windowId, numMenuItems, 0); + PutWindowTilemap(sMartInfo.windowId); + CopyWindowToVram(sMartInfo.windowId, 1); return CreateTask(Task_ShopMenu, 8); } static void SetShopMenuCallback(void (* callback)(void)) { - gMartInfo.callback = callback; + sMartInfo.callback = callback; } static void SetShopItemsForSale(const u16 *items) { u16 i = 0; - gMartInfo.itemList = items; - gMartInfo.itemCount = 0; + sMartInfo.itemList = items; + sMartInfo.itemCount = 0; - while (gMartInfo.itemList[i]) + while (sMartInfo.itemList[i]) { - gMartInfo.itemCount++; + sMartInfo.itemCount++; i++; } } @@ -337,7 +340,7 @@ static void Task_ShopMenu(u8 taskId) Task_HandleShopMenuQuit(taskId); break; default: - gMartInfo.menuActions[inputCode].func.void_u8(taskId); + sMartInfo.menuActions[inputCode].func.void_u8(taskId); break; } } @@ -368,14 +371,14 @@ void CB2_ExitSellMenu(void) static void Task_HandleShopMenuQuit(u8 taskId) { - ClearStdWindowAndFrameToTransparent(gMartInfo.windowId, 2); - RemoveWindow(gMartInfo.windowId); + ClearStdWindowAndFrameToTransparent(sMartInfo.windowId, 2); + RemoveWindow(sMartInfo.windowId); SaveRecordedItemPurchasesForTVShow(); ScriptContext2_Disable(); DestroyTask(taskId); - if (gMartInfo.callback) - gMartInfo.callback(); + if (sMartInfo.callback) + sMartInfo.callback(); } static void Task_GoToBuyOrSellMenu(u8 taskId) @@ -398,7 +401,7 @@ static void Task_ReturnToShopMenu(u8 taskId) { if (IsWeatherNotFadingIn() == TRUE) { - if (gMartInfo.martType == MART_TYPE_DECOR2) + if (sMartInfo.martType == MART_TYPE_DECOR2) DisplayItemMessageOnField(taskId, gText_CanIHelpWithAnythingElse, ShowShopMenuAfterExitingBuyOrSellMenu); else DisplayItemMessageOnField(taskId, gText_AnythingElseICanHelp, ShowShopMenuAfterExitingBuyOrSellMenu); @@ -407,7 +410,7 @@ static void Task_ReturnToShopMenu(u8 taskId) static void ShowShopMenuAfterExitingBuyOrSellMenu(u8 taskId) { - CreateShopMenu(gMartInfo.martType); + CreateShopMenu(sMartInfo.martType); DestroyTask(taskId); } @@ -447,10 +450,10 @@ static void CB2_InitBuyMenu(void) ResetSpriteData(); ResetTasks(); ClearScheduledBgCopiesToVram(); - gShopDataPtr = AllocZeroed(sizeof(struct ShopData)); - gShopDataPtr->scrollIndicatorsTaskId = TASK_NONE; - gShopDataPtr->itemSpriteIds[0] = SPRITE_NONE; - gShopDataPtr->itemSpriteIds[1] = SPRITE_NONE; + sShopData = AllocZeroed(sizeof(struct ShopData)); + sShopData->scrollIndicatorsTaskId = TASK_NONE; + sShopData->itemSpriteIds[0] = SPRITE_NONE; + sShopData->itemSpriteIds[1] = SPRITE_NONE; BuyMenuBuildListMenuTemplate(); BuyMenuInitBgs(); FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x20, 0x20); @@ -480,9 +483,9 @@ static void CB2_InitBuyMenu(void) static void BuyMenuFreeMemory(void) { - Free(gShopDataPtr); - Free(gUnknown_02039F74); - Free(gUnknown_02039F78); + Free(sShopData); + Free(sListMenuItems); + Free(sItemNames); FreeAllWindowBuffers(); } @@ -490,29 +493,29 @@ static void BuyMenuBuildListMenuTemplate(void) { u16 i; - gUnknown_02039F74 = Alloc((gMartInfo.itemCount + 1) * sizeof(*gUnknown_02039F74)); - gUnknown_02039F78 = Alloc((gMartInfo.itemCount + 1) * sizeof(*gUnknown_02039F78)); - for (i = 0; i < gMartInfo.itemCount; i++) - BuyMenuSetListEntry(&gUnknown_02039F74[i], gMartInfo.itemList[i], gUnknown_02039F78[i]); + sListMenuItems = Alloc((sMartInfo.itemCount + 1) * sizeof(*sListMenuItems)); + sItemNames = Alloc((sMartInfo.itemCount + 1) * sizeof(*sItemNames)); + for (i = 0; i < sMartInfo.itemCount; i++) + BuyMenuSetListEntry(&sListMenuItems[i], sMartInfo.itemList[i], sItemNames[i]); - StringCopy(gUnknown_02039F78[i], gText_Cancel2); - gUnknown_02039F74[i].name = gUnknown_02039F78[i]; - gUnknown_02039F74[i].id = -2; + StringCopy(sItemNames[i], gText_Cancel2); + sListMenuItems[i].name = sItemNames[i]; + sListMenuItems[i].id = LIST_CANCEL; gMultiuseListMenuTemplate = sShopBuyMenuListTemplate; - gMultiuseListMenuTemplate.items = gUnknown_02039F74; - gMultiuseListMenuTemplate.totalItems = gMartInfo.itemCount + 1; + gMultiuseListMenuTemplate.items = sListMenuItems; + gMultiuseListMenuTemplate.totalItems = sMartInfo.itemCount + 1; if (gMultiuseListMenuTemplate.totalItems > 8) gMultiuseListMenuTemplate.maxShowed = 8; else gMultiuseListMenuTemplate.maxShowed = gMultiuseListMenuTemplate.totalItems; - gShopDataPtr->itemsShowed = gMultiuseListMenuTemplate.maxShowed; + sShopData->itemsShowed = gMultiuseListMenuTemplate.maxShowed; } static void BuyMenuSetListEntry(struct ListMenuItem *menuItem, u16 item, u8 *name) { - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) CopyItemName(item, name); else StringCopy(name, gDecorations[item].name); @@ -527,16 +530,16 @@ static void BuyMenuPrintItemDescriptionAndShowItemIcon(s32 item, bool8 onInit, s if (onInit != TRUE) PlaySE(SE_SELECT); - if (item != -2) - BuyMenuAddItemIcon(item, gShopDataPtr->iconSlot); + if (item != LIST_CANCEL) + BuyMenuAddItemIcon(item, sShopData->iconSlot); else - BuyMenuAddItemIcon(-1, gShopDataPtr->iconSlot); + BuyMenuAddItemIcon(-1, sShopData->iconSlot); - BuyMenuRemoveItemIcon(item, gShopDataPtr->iconSlot ^ 1); - gShopDataPtr->iconSlot ^= 1; - if (item != -2) + BuyMenuRemoveItemIcon(item, sShopData->iconSlot ^ 1); + sShopData->iconSlot ^= 1; + if (item != LIST_CANCEL) { - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) description = ItemId_GetDescription(item); else description = gDecorations[item].description; @@ -554,9 +557,9 @@ static void BuyMenuPrintPriceInList(u8 windowId, s32 item, u8 y) { u8 x; - if (item != -2) + if (item != LIST_CANCEL) { - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) { ConvertIntToDecimalStringN( gStringVar1, @@ -581,26 +584,26 @@ static void BuyMenuPrintPriceInList(u8 windowId, s32 item, u8 y) static void BuyMenuAddScrollIndicatorArrows(void) { - if (gShopDataPtr->scrollIndicatorsTaskId == TASK_NONE && gMartInfo.itemCount + 1 > 8) + if (sShopData->scrollIndicatorsTaskId == TASK_NONE && sMartInfo.itemCount + 1 > 8) { - gShopDataPtr->scrollIndicatorsTaskId = AddScrollIndicatorArrowPairParameterized( + sShopData->scrollIndicatorsTaskId = AddScrollIndicatorArrowPairParameterized( SCROLL_ARROW_UP, - 0xAC, - 0xC, - 0x94, - gMartInfo.itemCount - 7, - 2100, - 2100, - &gShopDataPtr->scrollOffset); + 172, + 12, + 148, + sMartInfo.itemCount - 7, + TAG_SCROLL_ARROW, + TAG_SCROLL_ARROW, + &sShopData->scrollOffset); } } static void BuyMenuRemoveScrollIndicatorArrows(void) { - if (gShopDataPtr->scrollIndicatorsTaskId != TASK_NONE) + if (sShopData->scrollIndicatorsTaskId != TASK_NONE) { - RemoveScrollIndicatorArrowPair(gShopDataPtr->scrollIndicatorsTaskId); - gShopDataPtr->scrollIndicatorsTaskId = TASK_NONE; + RemoveScrollIndicatorArrowPair(sShopData->scrollIndicatorsTaskId); + sShopData->scrollIndicatorsTaskId = TASK_NONE; } } @@ -613,13 +616,13 @@ static void BuyMenuPrintCursor(u8 scrollIndicatorsTaskId, u8 colorSet) static void BuyMenuAddItemIcon(u16 item, u8 iconSlot) { u8 spriteId; - u8 *spriteIdPtr = &gShopDataPtr->itemSpriteIds[iconSlot]; + u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot]; if (*spriteIdPtr != SPRITE_NONE) return; - if (gMartInfo.martType == MART_TYPE_NORMAL || item == 0xFFFF) + if (sMartInfo.martType == MART_TYPE_NORMAL || item == 0xFFFF) { - spriteId = AddItemIconSprite(iconSlot + 2110, iconSlot + 2110, item); + spriteId = AddItemIconSprite(iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE, item); if (spriteId != MAX_SPRITES) { *spriteIdPtr = spriteId; @@ -629,7 +632,7 @@ static void BuyMenuAddItemIcon(u16 item, u8 iconSlot) } else { - spriteId = AddDecorationIconObject(item, 20, 84, 1, iconSlot + 2110, iconSlot + 2110); + spriteId = AddDecorationIconObject(item, 20, 84, 1, iconSlot + TAG_ITEM_ICON_BASE, iconSlot + TAG_ITEM_ICON_BASE); if (spriteId != MAX_SPRITES) *spriteIdPtr = spriteId; } @@ -637,12 +640,12 @@ static void BuyMenuAddItemIcon(u16 item, u8 iconSlot) static void BuyMenuRemoveItemIcon(u16 item, u8 iconSlot) { - u8 *spriteIdPtr = &gShopDataPtr->itemSpriteIds[iconSlot]; + u8 *spriteIdPtr = &sShopData->itemSpriteIds[iconSlot]; if (*spriteIdPtr == SPRITE_NONE) return; - FreeSpriteTilesByTag(iconSlot + 2110); - FreeSpritePaletteByTag(iconSlot + 2110); + FreeSpriteTilesByTag(iconSlot + TAG_ITEM_ICON_BASE); + FreeSpritePaletteByTag(iconSlot + TAG_ITEM_ICON_BASE); DestroySprite(&gSprites[*spriteIdPtr]); *spriteIdPtr = SPRITE_NONE; } @@ -651,9 +654,9 @@ static void BuyMenuInitBgs(void) { ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sShopBuyMenuBgTemplates, ARRAY_COUNT(sShopBuyMenuBgTemplates)); - SetBgTilemapBuffer(1, gShopDataPtr->tilemapBuffers[1]); - SetBgTilemapBuffer(2, gShopDataPtr->tilemapBuffers[3]); - SetBgTilemapBuffer(3, gShopDataPtr->tilemapBuffers[2]); + SetBgTilemapBuffer(1, sShopData->tilemapBuffers[1]); + SetBgTilemapBuffer(2, sShopData->tilemapBuffers[3]); + SetBgTilemapBuffer(3, sShopData->tilemapBuffers[2]); SetGpuReg(REG_OFFSET_BG0HOFS, 0); SetGpuReg(REG_OFFSET_BG0VOFS, 0); SetGpuReg(REG_OFFSET_BG1HOFS, 0); @@ -673,7 +676,7 @@ static void BuyMenuInitBgs(void) static void BuyMenuDecompressBgGraphics(void) { DecompressAndCopyTileDataToVram(1, gBuyMenuFrame_Gfx, 0x3A0, 0x3E3, 0); - LZDecompressWram(gBuyMenuFrame_Tilemap, gShopDataPtr->tilemapBuffers[0]); + LZDecompressWram(gBuyMenuFrame_Tilemap, sShopData->tilemapBuffers[0]); LoadCompressedPalette(gMenuMoneyPal, 0xC0, 0x20); } @@ -763,16 +766,16 @@ static void BuyMenuDrawMapMetatile(s16 x, s16 y, const u16 *src, u8 metatileLaye switch (metatileLayerType) { case 0: - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[3], offset1, offset2, src); - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[1], offset1, offset2, src + 4); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4); break; case 1: - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[2], offset1, offset2, src); - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[3], offset1, offset2, src + 4); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[3], offset1, offset2, src + 4); break; case 2: - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[2], offset1, offset2, src); - BuyMenuDrawMapMetatileLayer(gShopDataPtr->tilemapBuffers[1], offset1, offset2, src + 4); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[2], offset1, offset2, src); + BuyMenuDrawMapMetatileLayer(sShopData->tilemapBuffers[1], offset1, offset2, src + 4); break; } } @@ -796,7 +799,7 @@ static void BuyMenuCollectObjectEventData(void) GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY); for (y = 0; y < OBJECT_EVENTS_COUNT; y++) - gShopDataPtr->viewportObjects[y][OBJ_EVENT_ID] = OBJECT_EVENTS_COUNT; + sShopData->viewportObjects[y][OBJ_EVENT_ID] = OBJECT_EVENTS_COUNT; for (y = 0; y < 5; y++) { for (x = 0; x < 7; x++) @@ -805,25 +808,25 @@ static void BuyMenuCollectObjectEventData(void) if (objEventId != OBJECT_EVENTS_COUNT) { - gShopDataPtr->viewportObjects[r8][OBJ_EVENT_ID] = objEventId; - gShopDataPtr->viewportObjects[r8][X_COORD] = x; - gShopDataPtr->viewportObjects[r8][Y_COORD] = y; - gShopDataPtr->viewportObjects[r8][LAYER_TYPE] = MapGridGetMetatileLayerTypeAt(facingX - 4 + x, facingY - 2 + y); + sShopData->viewportObjects[r8][OBJ_EVENT_ID] = objEventId; + sShopData->viewportObjects[r8][X_COORD] = x; + sShopData->viewportObjects[r8][Y_COORD] = y; + sShopData->viewportObjects[r8][LAYER_TYPE] = MapGridGetMetatileLayerTypeAt(facingX - 4 + x, facingY - 2 + y); switch (gObjectEvents[objEventId].facingDirection) { case DIR_SOUTH: - gShopDataPtr->viewportObjects[r8][ANIM_NUM] = 0; + sShopData->viewportObjects[r8][ANIM_NUM] = 0; break; case DIR_NORTH: - gShopDataPtr->viewportObjects[r8][ANIM_NUM] = 1; + sShopData->viewportObjects[r8][ANIM_NUM] = 1; break; case DIR_WEST: - gShopDataPtr->viewportObjects[r8][ANIM_NUM] = 2; + sShopData->viewportObjects[r8][ANIM_NUM] = 2; break; case DIR_EAST: default: - gShopDataPtr->viewportObjects[r8][ANIM_NUM] = 3; + sShopData->viewportObjects[r8][ANIM_NUM] = 3; break; } r8++; @@ -840,25 +843,25 @@ static void BuyMenuDrawObjectEvents(void) for (i = 0; i < OBJECT_EVENTS_COUNT; i++) { - if (gShopDataPtr->viewportObjects[i][OBJ_EVENT_ID] == OBJECT_EVENTS_COUNT) + if (sShopData->viewportObjects[i][OBJ_EVENT_ID] == OBJECT_EVENTS_COUNT) continue; - graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[gShopDataPtr->viewportObjects[i][OBJ_EVENT_ID]].graphicsId); + graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId); spriteId = AddPseudoObjectEvent( - gObjectEvents[gShopDataPtr->viewportObjects[i][OBJ_EVENT_ID]].graphicsId, + gObjectEvents[sShopData->viewportObjects[i][OBJ_EVENT_ID]].graphicsId, SpriteCallbackDummy, - (u16)gShopDataPtr->viewportObjects[i][X_COORD] * 16 + 8, - (u16)gShopDataPtr->viewportObjects[i][Y_COORD] * 16 + 48 - graphicsInfo->height / 2, + (u16)sShopData->viewportObjects[i][X_COORD] * 16 + 8, + (u16)sShopData->viewportObjects[i][Y_COORD] * 16 + 48 - graphicsInfo->height / 2, 2); - if (BuyMenuCheckIfObjectEventOverlapsMenuBg(gShopDataPtr->viewportObjects[i]) == TRUE) + if (BuyMenuCheckIfObjectEventOverlapsMenuBg(sShopData->viewportObjects[i]) == TRUE) { gSprites[spriteId].subspriteTableNum = 4; gSprites[spriteId].subspriteMode = SUBSPRITES_ON; } - StartSpriteAnim(&gSprites[spriteId], gShopDataPtr->viewportObjects[i][ANIM_NUM]); + StartSpriteAnim(&gSprites[spriteId], sShopData->viewportObjects[i][ANIM_NUM]); } } @@ -877,8 +880,8 @@ static bool8 BuyMenuCheckIfObjectEventOverlapsMenuBg(s16 *object) static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void) { s16 i; - u16 *dest = gShopDataPtr->tilemapBuffers[1]; - const u16 *src = gShopDataPtr->tilemapBuffers[0]; + u16 *dest = sShopData->tilemapBuffers[1]; + const u16 *src = sShopData->tilemapBuffers[0]; for (i = 0; i < 1024; i++) { @@ -891,7 +894,7 @@ static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void) static bool8 BuyMenuCheckForOverlapWithMenuBg(int x, int y) { - const u16 *metatile = gShopDataPtr->tilemapBuffers[0]; + const u16 *metatile = sShopData->tilemapBuffers[0]; int offset1 = x * 2; int offset2 = y * 64; @@ -913,7 +916,7 @@ static void Task_BuyMenu(u8 taskId) if (!gPaletteFade.active) { s32 itemId = ListMenu_ProcessInput(tListTaskId); - ListMenuGetScrollAndRow(tListTaskId, &gShopDataPtr->scrollOffset, &gShopDataPtr->selectedRow); + ListMenuGetScrollAndRow(tListTaskId, &sShopData->scrollOffset, &sShopData->selectedRow); switch (itemId) { @@ -930,22 +933,22 @@ static void Task_BuyMenu(u8 taskId) BuyMenuRemoveScrollIndicatorArrows(); BuyMenuPrintCursor(tListTaskId, 2); - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) { - gShopDataPtr->totalCost = (ItemId_GetPrice(itemId) >> GetPriceReduction(POKENEWS_SLATEPORT)); + sShopData->totalCost = (ItemId_GetPrice(itemId) >> GetPriceReduction(POKENEWS_SLATEPORT)); } else { - gShopDataPtr->totalCost = gDecorations[itemId].price; + sShopData->totalCost = gDecorations[itemId].price; } - if (!IsEnoughMoney(&gSaveBlock1Ptr->money, gShopDataPtr->totalCost)) + if (!IsEnoughMoney(&gSaveBlock1Ptr->money, sShopData->totalCost)) { BuyMenuDisplayMessage(taskId, gText_YouDontHaveMoney, BuyMenuReturnToItemList); } else { - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) { CopyItemName(itemId, gStringVar1); if (ItemId_GetPocket(itemId) == POCKET_TM_HM) @@ -961,9 +964,9 @@ static void Task_BuyMenu(u8 taskId) else { StringCopy(gStringVar1, gDecorations[itemId].name); - ConvertIntToDecimalStringN(gStringVar2, gShopDataPtr->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar2, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6); - if (gMartInfo.martType == MART_TYPE_DECOR) + if (sMartInfo.martType == MART_TYPE_DECOR) StringExpandPlaceholders(gStringVar4, gText_Var1IsItThatllBeVar2); else // MART_TYPE_DECOR2 StringExpandPlaceholders(gStringVar4, gText_YouWantedVar1ThatllBeVar2); @@ -992,15 +995,15 @@ static void Task_BuyHowManyDialogueInit(u8 taskId) BuyMenuPrintItemQuantityAndPrice(taskId); ScheduleBgCopyTilemapToVram(0); - maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / gShopDataPtr->totalCost; + maxQuantity = GetMoney(&gSaveBlock1Ptr->money) / sShopData->totalCost; if (maxQuantity > MAX_BAG_ITEM_CAPACITY) { - gShopDataPtr->maxQuantity = MAX_BAG_ITEM_CAPACITY; + sShopData->maxQuantity = MAX_BAG_ITEM_CAPACITY; } else { - gShopDataPtr->maxQuantity = maxQuantity; + sShopData->maxQuantity = maxQuantity; } gTasks[taskId].func = Task_BuyHowManyDialogueHandleInput; @@ -1010,9 +1013,9 @@ static void Task_BuyHowManyDialogueHandleInput(u8 taskId) { s16 *data = gTasks[taskId].data; - if (AdjustQuantityAccordingToDPadInput(&tItemCount, gShopDataPtr->maxQuantity) == TRUE) + if (AdjustQuantityAccordingToDPadInput(&tItemCount, sShopData->maxQuantity) == TRUE) { - gShopDataPtr->totalCost = (ItemId_GetPrice(tItemId) >> GetPriceReduction(POKENEWS_SLATEPORT)) * tItemCount; + sShopData->totalCost = (ItemId_GetPrice(tItemId) >> GetPriceReduction(POKENEWS_SLATEPORT)) * tItemCount; BuyMenuPrintItemQuantityAndPrice(taskId); } else @@ -1027,7 +1030,7 @@ static void Task_BuyHowManyDialogueHandleInput(u8 taskId) PutWindowTilemap(1); CopyItemName(tItemId, gStringVar1); ConvertIntToDecimalStringN(gStringVar2, tItemCount, STR_CONV_MODE_LEFT_ALIGN, BAG_ITEM_CAPACITY_DIGITS); - ConvertIntToDecimalStringN(gStringVar3, gShopDataPtr->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6); + ConvertIntToDecimalStringN(gStringVar3, sShopData->totalCost, STR_CONV_MODE_LEFT_ALIGN, 6); BuyMenuDisplayMessage(taskId, gText_Var1AndYouWantedVar2, BuyMenuConfirmPurchase); } else if (JOY_NEW(B_BUTTON)) @@ -1053,7 +1056,7 @@ static void BuyMenuTryMakePurchase(u8 taskId) PutWindowTilemap(1); - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) { if (AddBagItem(tItemId, tItemCount) == TRUE) { @@ -1069,7 +1072,7 @@ static void BuyMenuTryMakePurchase(u8 taskId) { if (DecorationAdd(tItemId)) { - if (gMartInfo.martType == MART_TYPE_DECOR) + if (sMartInfo.martType == MART_TYPE_DECOR) BuyMenuDisplayMessage(taskId, gText_ThankYouIllSendItHome, BuyMenuSubtractMoney); else // MART_TYPE_DECOR2 BuyMenuDisplayMessage(taskId, gText_ThanksIllSendItHome, BuyMenuSubtractMoney); @@ -1084,11 +1087,11 @@ static void BuyMenuTryMakePurchase(u8 taskId) static void BuyMenuSubtractMoney(u8 taskId) { IncrementGameStat(GAME_STAT_SHOPPED); - RemoveMoney(&gSaveBlock1Ptr->money, gShopDataPtr->totalCost); + RemoveMoney(&gSaveBlock1Ptr->money, sShopData->totalCost); PlaySE(SE_SHOP); PrintMoneyAmountInMoneyBox(0, GetMoney(&gSaveBlock1Ptr->money), 0); - if (gMartInfo.martType == MART_TYPE_NORMAL) + if (sMartInfo.martType == MART_TYPE_NORMAL) { gTasks[taskId].func = Task_ReturnToItemListAfterItemPurchase; } @@ -1143,7 +1146,7 @@ static void BuyMenuPrintItemQuantityAndPrice(u8 taskId) s16 *data = gTasks[taskId].data; FillWindowPixelBuffer(4, PIXEL_FILL(1)); - PrintMoneyAmount(4, 38, 1, gShopDataPtr->totalCost, TEXT_SPEED_FF); + PrintMoneyAmount(4, 38, 1, sShopData->totalCost, TEXT_SPEED_FF); ConvertIntToDecimalStringN(gStringVar1, tItemCount, STR_CONV_MODE_LEADING_ZEROS, BAG_ITEM_CAPACITY_DIGITS); StringExpandPlaceholders(gStringVar4, gText_xVar1); BuyMenuPrint(4, gStringVar4, 0, 1, 0, 0); @@ -1169,7 +1172,7 @@ static void Task_ExitBuyMenu(u8 taskId) static void ClearItemPurchases(void) { - gMartPurchaseHistoryId = 0; + sPurchaseHistoryId = 0; memset(gMartPurchaseHistory, 0, sizeof(gMartPurchaseHistory)); } @@ -1179,27 +1182,23 @@ static void RecordItemPurchase(u8 taskId) u16 i; - for (i = 0; i < 3; i++) + for (i = 0; i < ARRAY_COUNT(gMartPurchaseHistory); i++) { if (gMartPurchaseHistory[i].itemId == tItemId && gMartPurchaseHistory[i].quantity != 0) { if (gMartPurchaseHistory[i].quantity + tItemCount > 255) - { gMartPurchaseHistory[i].quantity = 255; - } else - { gMartPurchaseHistory[i].quantity += tItemCount; - } return; } } - if (gMartPurchaseHistoryId < 3) + if (sPurchaseHistoryId < ARRAY_COUNT(gMartPurchaseHistory)) { - gMartPurchaseHistory[gMartPurchaseHistoryId].itemId = tItemId; - gMartPurchaseHistory[gMartPurchaseHistoryId].quantity = tItemCount; - gMartPurchaseHistoryId++; + gMartPurchaseHistory[sPurchaseHistoryId].itemId = tItemId; + gMartPurchaseHistory[sPurchaseHistoryId].quantity = tItemCount; + sPurchaseHistoryId++; } } diff --git a/src/sound.c b/src/sound.c index ee1753bb3..42f507b7c 100644 --- a/src/sound.c +++ b/src/sound.c @@ -41,24 +41,24 @@ static void Task_DuckBGMForPokemonCry(u8 taskId); static void RestoreBGMVolumeAfterPokemonCry(void); static const struct Fanfare sFanfares[] = { - { MUS_LEVEL_UP, 80 }, - { MUS_OBTAIN_ITEM, 160 }, - { MUS_EVOLVED, 220 }, - { MUS_OBTAIN_TMHM, 220 }, - { MUS_HEAL, 160 }, - { MUS_OBTAIN_BADGE, 340 }, - { MUS_MOVE_DELETED, 180 }, - { MUS_OBTAIN_BERRY, 120 }, - { MUS_AWAKEN_LEGEND, 710 }, - { MUS_SLOTS_JACKPOT, 250 }, - { MUS_SLOTS_WIN, 150 }, - { MUS_TOO_BAD, 160 }, - { MUS_RG_POKE_FLUTE, 450 }, - { MUS_RG_OBTAIN_KEY_ITEM, 170 }, - { MUS_RG_DEX_RATING, 196 }, - { MUS_OBTAIN_B_POINTS, 313 }, - { MUS_OBTAIN_SYMBOL, 318 }, - { MUS_REGISTER_MATCH_CALL, 135 }, + [FANFARE_LEVEL_UP] = { MUS_LEVEL_UP, 80 }, + [FANFARE_OBTAIN_ITEM] = { MUS_OBTAIN_ITEM, 160 }, + [FANFARE_EVOLVED] = { MUS_EVOLVED, 220 }, + [FANFARE_OBTAIN_TMHM] = { MUS_OBTAIN_TMHM, 220 }, + [FANFARE_HEAL] = { MUS_HEAL, 160 }, + [FANFARE_OBTAIN_BADGE] = { MUS_OBTAIN_BADGE, 340 }, + [FANFARE_MOVE_DELETED] = { MUS_MOVE_DELETED, 180 }, + [FANFARE_OBTAIN_BERRY] = { MUS_OBTAIN_BERRY, 120 }, + [FANFARE_AWAKEN_LEGEND] = { MUS_AWAKEN_LEGEND, 710 }, + [FANFARE_SLOTS_JACKPOT] = { MUS_SLOTS_JACKPOT, 250 }, + [FANFARE_SLOTS_WIN] = { MUS_SLOTS_WIN, 150 }, + [FANFARE_TOO_BAD] = { MUS_TOO_BAD, 160 }, + [FANFARE_RG_POKE_FLUTE] = { MUS_RG_POKE_FLUTE, 450 }, + [FANFARE_RG_OBTAIN_KEY_ITEM] = { MUS_RG_OBTAIN_KEY_ITEM, 170 }, + [FANFARE_RG_DEX_RATING] = { MUS_RG_DEX_RATING, 196 }, + [FANFARE_OBTAIN_B_POINTS] = { MUS_OBTAIN_B_POINTS, 313 }, + [FANFARE_OBTAIN_SYMBOL] = { MUS_OBTAIN_SYMBOL, 318 }, + [FANFARE_REGISTER_MATCH_CALL] = { MUS_REGISTER_MATCH_CALL, 135 }, }; #define CRY_VOLUME 120 // was 125 in R/S @@ -212,6 +212,7 @@ bool8 WaitFanfare(bool8 stop) } } +// Unused void StopFanfareByFanfareNum(u8 fanfareNum) { m4aSongNumStop(sFanfares[fanfareNum].songNum); @@ -220,7 +221,7 @@ void StopFanfareByFanfareNum(u8 fanfareNum) void PlayFanfare(u16 songNum) { s32 i; - for (i = 0; (u32)i < 18; i++) + for (i = 0; (u32)i < ARRAY_COUNT(sFanfares); i++) { if (sFanfares[i].songNum == songNum) { @@ -230,6 +231,8 @@ void PlayFanfare(u16 songNum) } } + // songNum is not in sFanfares + // Play first fanfare in table instead PlayFanfareByFanfareNum(0); CreateFanfareTask(); } diff --git a/src/start_menu.c b/src/start_menu.c index 26a5097a6..2316b85b6 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -170,7 +170,7 @@ static const struct MenuAction sStartMenuItems[] = {gText_MenuBag, {.u8_void = StartMenuBattlePyramidBagCallback}} }; -static const struct BgTemplate sUnknown_085105A8[] = +static const struct BgTemplate sBgTemplates_LinkBattleSave[] = { { .bg = 0, @@ -183,13 +183,29 @@ static const struct BgTemplate sUnknown_085105A8[] = } }; -static const struct WindowTemplate sUnknown_085105AC[] = +static const struct WindowTemplate sWindowTemplates_LinkBattleSave[] = { - {0, 2, 0xF, 0x1A, 4, 0xF, 0x194}, + { + .bg = 0, + .tilemapLeft = 2, + .tilemapTop = 15, + .width = 26, + .height = 4, + .paletteNum = 15, + .baseBlock = 0x194 + }, DUMMY_WIN_TEMPLATE }; -static const struct WindowTemplate sSaveInfoWindowTemplate = {0, 1, 1, 0xE, 0xA, 0xF, 8}; +static const struct WindowTemplate sSaveInfoWindowTemplate = { + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 14, + .height = 10, + .paletteNum = 15, + .baseBlock = 8 +}; // Local functions static void BuildStartMenuActions(void); @@ -211,13 +227,13 @@ static void CreateStartMenuTask(TaskFunc followupFunc); static void InitSave(void); static u8 RunSaveCallback(void); static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)); -static void sub_80A0014(void); +static void HideSaveMessageWindow(void); static void HideSaveInfoWindow(void); static void SaveStartTimer(void); static bool8 SaveSuccesTimer(void); static bool8 SaveErrorTimer(void); static void InitBattlePyramidRetire(void); -static void sub_80A03D8(void); +static void VBlankCB_LinkBattleSave(void); static bool32 InitSaveWindowAfterLinkBattle(u8 *par1); static void CB2_SaveAfterLinkBattle(void); static void ShowSaveInfoWindow(void); @@ -887,7 +903,7 @@ static void SaveGameTask(u8 taskId) EnableBothScriptContexts(); } -static void sub_80A0014(void) +static void HideSaveMessageWindow(void) { ClearDialogWindowAndFrame(0, TRUE); } @@ -982,7 +998,7 @@ static u8 SaveConfirmInputCallback(void) case -1: // B Button case 1: // No HideSaveInfoWindow(); - sub_80A0014(); + HideSaveMessageWindow(); return SAVE_CANCELED; } @@ -1028,7 +1044,7 @@ static u8 SaveOverwriteInputCallback(void) case -1: // B Button case 1: // No HideSaveInfoWindow(); - sub_80A0014(); + HideSaveMessageWindow(); return SAVE_CANCELED; } @@ -1146,14 +1162,14 @@ static u8 BattlePyramidRetireInputCallback(void) return SAVE_CANCELED; case -1: // B Button case 1: // No - sub_80A0014(); + HideSaveMessageWindow(); return SAVE_SUCCESS; } return SAVE_IN_PROGRESS; } -static void sub_80A03D8(void) +static void VBlankCB_LinkBattleSave(void) { TransferPlttBuffer(); } @@ -1167,7 +1183,7 @@ static bool32 InitSaveWindowAfterLinkBattle(u8 *state) SetVBlankCallback(NULL); ScanlineEffect_Stop(); DmaClear16(3, PLTT, PLTT_SIZE); - DmaFillLarge16(3, 0, (void *)(VRAM + 0x0), 0x18000, 0x1000); + DmaFillLarge16(3, 0, (void *)VRAM, VRAM_SIZE, 0x1000); break; case 1: ResetSpriteData(); @@ -1177,15 +1193,15 @@ static bool32 InitSaveWindowAfterLinkBattle(u8 *state) break; case 2: ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, sUnknown_085105A8, ARRAY_COUNT(sUnknown_085105A8)); - InitWindows(sUnknown_085105AC); + InitBgsFromTemplates(0, sBgTemplates_LinkBattleSave, ARRAY_COUNT(sBgTemplates_LinkBattleSave)); + InitWindows(sWindowTemplates_LinkBattleSave); LoadUserWindowBorderGfx_(0, 8, 224); Menu_LoadStdPalAt(240); break; case 3: ShowBg(0); BlendPalettes(-1, 16, 0); - SetVBlankCallback(sub_80A03D8); + SetVBlankCallback(VBlankCB_LinkBattleSave); EnableInterrupts(1); break; case 4: diff --git a/src/strings.c b/src/strings.c index fe5051d71..19d0e3cca 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1292,7 +1292,7 @@ const u8 gText_MatchCallMay_Intro1[] = _("My POKéMON and I help"); const u8 gText_MatchCallMay_Intro2[] = _("my father's research."); const u8 gText_HatchedFromEgg[] = _("{STR_VAR_1} hatched from the EGG!"); const u8 gText_NicknameHatchPrompt[] = _("Would you like to nickname the newly\nhatched {STR_VAR_1}?"); -ALIGNED(4) const u8 gText_ReadyToBerryCrush[] = _("Are you ready to BERRY-CRUSH?\nPlease pick a BERRY for use.\p"); +ALIGNED(4) const u8 gText_ReadyPickBerry[] = _("Are you ready to BERRY-CRUSH?\nPlease pick a BERRY for use.\p"); ALIGNED(4) const u8 gText_WaitForAllChooseBerry[] = _("Please wait while each member\nchooses a BERRY."); ALIGNED(4) const u8 gText_EndedWithXUnitsPowder[] = _("{PAUSE_MUSIC}{PLAY_BGM MUS_LEVEL_UP}You ended up with {STR_VAR_1} units of\nsilky-smooth BERRY POWDER.{RESUME_MUSIC}\pYour total amount of BERRY POWDER\nis {STR_VAR_2}.\p"); ALIGNED(4) const u8 gText_RecordingGameResults[] = _("Recording your game results in the\nsave file.\lPlease wait."); diff --git a/src/trade.c b/src/trade.c index b6646378d..f423b20af 100644 --- a/src/trade.c +++ b/src/trade.c @@ -165,9 +165,6 @@ static EWRAM_DATA struct { /*0xFE*/ u8 wirelessWinBottom; } *sTradeData = {NULL}; -#if !defined(NONMATCHING) && MODERN -#define static -#endif static bool32 IsWirelessTrade(void); static void CB2_CreateTradeMenu(void); static void VBlankCB_TradeMenu(void); @@ -1163,12 +1160,12 @@ static void ReactToLinkTradeData(u8 mpId, u8 status) { switch (gBlockRecvBuffer[0][0]) { - case LINKCMD_CANCEL_TRADE: + case LINKCMD_BOTH_CANCEL_TRADE: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); PrintTradeMessage(TRADE_MSG_WAITING_FOR_FRIEND); sTradeMenuData->tradeMenuFunc = TRADEMENUFUNC_CANCEL_TRADE_1; break; - case LINKCMD_0xEECC: + case LINKCMD_PARTNER_CANCEL_TRADE: PrintTradeMessage(TRADE_MSG_FRIEND_WANTS_TO_TRADE); sTradeMenuData->tradeMenuFunc = TRADEMENUFUNC_REDRAW_MAIN_MENU; break; @@ -1183,7 +1180,7 @@ static void ReactToLinkTradeData(u8 mpId, u8 status) BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); sTradeMenuData->tradeMenuFunc = TRADEMENUFUNC_LINK_TRADE_WAIT_FADE; break; - case LINKCMD_0xDDEE: + case LINKCMD_PLAYER_CANCEL_TRADE: PrintTradeMessage(TRADE_MSG_CANCELED); sTradeMenuData->tradeMenuFunc = TRADEMENUFUNC_REDRAW_MAIN_MENU; } @@ -1211,7 +1208,7 @@ static void QueueLinkTradeData(void) && sTradeMenuData->partnerLinkFlagChoseAction == WANTS_TO_CANCEL) { PrintTradeMessage(TRADE_MSG_CANCELED); - sTradeMenuData->linkData[0] = LINKCMD_0xEECC; + sTradeMenuData->linkData[0] = LINKCMD_PARTNER_CANCEL_TRADE; sTradeMenuData->linkData[1] = 0; QueueAction(QUEUE_DELAY_DATA, QUEUE_SEND_DATA); sTradeMenuData->playerLinkFlagStatus = sTradeMenuData->partnerLinkFlagStatus = 0; @@ -1222,7 +1219,7 @@ static void QueueLinkTradeData(void) && sTradeMenuData->partnerLinkFlagChoseAction == WANTS_TO_TRADE) { PrintTradeMessage(TRADE_MSG_FRIEND_WANTS_TO_TRADE); - sTradeMenuData->linkData[0] = LINKCMD_0xDDEE; + sTradeMenuData->linkData[0] = LINKCMD_PLAYER_CANCEL_TRADE; sTradeMenuData->linkData[1] = 0; QueueAction(QUEUE_DELAY_DATA, QUEUE_SEND_DATA); sTradeMenuData->playerLinkFlagStatus = sTradeMenuData->partnerLinkFlagStatus = 0; @@ -1232,7 +1229,7 @@ static void QueueLinkTradeData(void) else if (sTradeMenuData->playerLinkFlagChoseAction == WANTS_TO_CANCEL && sTradeMenuData->partnerLinkFlagChoseAction == WANTS_TO_CANCEL) { - sTradeMenuData->linkData[0] = LINKCMD_CANCEL_TRADE; + sTradeMenuData->linkData[0] = LINKCMD_BOTH_CANCEL_TRADE; sTradeMenuData->linkData[1] = 0; QueueAction(QUEUE_DELAY_DATA, QUEUE_SEND_DATA); BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); @@ -1258,7 +1255,7 @@ static void QueueLinkTradeData(void) || sTradeMenuData->partnerLinkFlagStatus == CANCEL_TRADE) { PrintTradeMessage(TRADE_MSG_CANCELED); - sTradeMenuData->linkData[0] = LINKCMD_0xDDEE; + sTradeMenuData->linkData[0] = LINKCMD_PLAYER_CANCEL_TRADE; sTradeMenuData->linkData[1] = 0; QueueAction(QUEUE_DELAY_DATA, QUEUE_SEND_DATA); sTradeMenuData->playerLinkFlagStatus = 0; diff --git a/src/trainer_card.c b/src/trainer_card.c index c42c16845..d4bcf4299 100755 --- a/src/trainer_card.c +++ b/src/trainer_card.c @@ -80,7 +80,7 @@ struct TrainerCardData u8 cardTiles[0x2300]; u16 cardTilemapBuffer[0x1000]; u16 bgTilemapBuffer[0x1000]; - u16 var_7CA8; + u16 cardTop; u8 language; }; @@ -113,7 +113,7 @@ static void SetPlayerCardData(struct TrainerCard*, u8); static void TrainerCard_GenerateCardForLinkPlayer(struct TrainerCard*); static u8 VersionToCardType(u8); static void SetDataFromTrainerCard(void); -static void HandleGpuRegs(void); +static void InitGpuRegs(void); static void ResetGpuRegs(void); static void InitBgsAndWindows(void); static void SetTrainerCardCb2(void); @@ -158,31 +158,30 @@ static bool8 Task_DrawFlippedCardSide(struct Task* task); static bool8 Task_SetCardFlipped(struct Task* task); static bool8 Task_AnimateCardFlipUp(struct Task* task); static bool8 Task_EndCardFlip(struct Task* task); -static void sub_80C32EC(u16); +static void UpdateCardFlipRegs(u16); static void LoadMonIconGfx(void); -// const rom data -static const u32 sTrainerCardStickers_Gfx[] = INCBIN_U32("graphics/trainer_card/stickers_fr.4bpp.lz"); -static const u16 sUnused_0856F18C[] = INCBIN_U16("graphics/trainer_card/unknown_56F18C.gbapal"); -static const u16 sHoennTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star.gbapal"); -static const u16 sKantoTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star_fr.gbapal"); -static const u16 sHoennTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars.gbapal"); -static const u16 sKantoTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars_fr.gbapal"); -static const u16 sHoennTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars.gbapal"); -static const u16 sKantoTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars_fr.gbapal"); -static const u16 sHoennTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars.gbapal"); -static const u16 sKantoTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars_fr.gbapal"); +static const u32 sTrainerCardStickers_Gfx[] = INCBIN_U32("graphics/trainer_card/stickers_fr.4bpp.lz"); +static const u16 sUnused_Pal[] = INCBIN_U16("graphics/trainer_card/unused.gbapal"); +static const u16 sHoennTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star.gbapal"); +static const u16 sKantoTrainerCard1Star_Pal[] = INCBIN_U16("graphics/trainer_card/one_star_fr.gbapal"); +static const u16 sHoennTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars.gbapal"); +static const u16 sKantoTrainerCard2Star_Pal[] = INCBIN_U16("graphics/trainer_card/two_stars_fr.gbapal"); +static const u16 sHoennTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars.gbapal"); +static const u16 sKantoTrainerCard3Star_Pal[] = INCBIN_U16("graphics/trainer_card/three_stars_fr.gbapal"); +static const u16 sHoennTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars.gbapal"); +static const u16 sKantoTrainerCard4Star_Pal[] = INCBIN_U16("graphics/trainer_card/four_stars_fr.gbapal"); static const u16 sHoennTrainerCardFemaleBg_Pal[] = INCBIN_U16("graphics/trainer_card/female_bg.gbapal"); static const u16 sKantoTrainerCardFemaleBg_Pal[] = INCBIN_U16("graphics/trainer_card/female_bg_fr.gbapal"); -static const u16 sHoennTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges.gbapal"); -static const u16 sKantoTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges_fr.gbapal"); -static const u16 sTrainerCardGold_Pal[] = INCBIN_U16("graphics/trainer_card/gold.gbapal"); -static const u16 sTrainerCardSticker1_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr1.gbapal"); -static const u16 sTrainerCardSticker2_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr2.gbapal"); -static const u16 sTrainerCardSticker3_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr3.gbapal"); -static const u16 sTrainerCardSticker4_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr4.gbapal"); -static const u32 sHoennTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges.4bpp.lz"); -static const u32 sKantoTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges_fr.4bpp.lz"); +static const u16 sHoennTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges.gbapal"); +static const u16 sKantoTrainerCardBadges_Pal[] = INCBIN_U16("graphics/trainer_card/badges_fr.gbapal"); +static const u16 sTrainerCardGold_Pal[] = INCBIN_U16("graphics/trainer_card/gold.gbapal"); +static const u16 sTrainerCardSticker1_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr1.gbapal"); +static const u16 sTrainerCardSticker2_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr2.gbapal"); +static const u16 sTrainerCardSticker3_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr3.gbapal"); +static const u16 sTrainerCardSticker4_Pal[] = INCBIN_U16("graphics/trainer_card/stickers_fr4.gbapal"); +static const u32 sHoennTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges.4bpp.lz"); +static const u32 sKantoTrainerCardBadges_Gfx[] = INCBIN_U32("graphics/trainer_card/badges_fr.4bpp.lz"); static const struct BgTemplate sTrainerCardBgTemplates[4] = { @@ -321,7 +320,6 @@ static bool8 (*const sTrainerCardFlipTasks[])(struct Task *) = Task_EndCardFlip, }; -// code static void VblankCb_TrainerCard(void) { LoadOam(); @@ -458,7 +456,7 @@ static void Task_TrainerCard(u8 taskId) } break; case STATE_WAIT_FLIP_TO_BACK: - if (IsCardFlipTaskActive() && sub_8087598() != TRUE) + if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE) { PlaySE(SE_RG_CARD_OPEN); sData->mainState = STATE_HANDLE_INPUT_BACK; @@ -515,7 +513,7 @@ static void Task_TrainerCard(u8 taskId) CloseTrainerCard(taskId); break; case STATE_WAIT_FLIP_TO_FRONT: - if (IsCardFlipTaskActive() && sub_8087598() != TRUE) + if (IsCardFlipTaskActive() && Overworld_LinkRecvQueueLengthMoreThan2() != TRUE) { sData->mainState = STATE_HANDLE_INPUT_FRONT; PlaySE(SE_RG_CARD_OPEN); @@ -620,7 +618,7 @@ static void CB2_InitTrainerCard(void) gMain.state++; break; case 8: - HandleGpuRegs(); + InitGpuRegs(); gMain.state++; break; case 9: @@ -841,7 +839,7 @@ static void SetDataFromTrainerCard(void) } } -static void HandleGpuRegs(void) +static void InitGpuRegs(void) { SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); ShowBg(0); @@ -852,24 +850,23 @@ static void HandleGpuRegs(void) SetGpuReg(REG_OFFSET_BLDY, 0); SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR); SetGpuReg(REG_OFFSET_WINOUT, WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_BG3 | WINOUT_WIN01_OBJ); - SetGpuReg(REG_OFFSET_WIN0V, 160); - SetGpuReg(REG_OFFSET_WIN0H, 240); + SetGpuReg(REG_OFFSET_WIN0V, DISPLAY_HEIGHT); + SetGpuReg(REG_OFFSET_WIN0H, DISPLAY_WIDTH); if (gReceivedRemoteLinkPlayers) EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); else EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK); } -// Part of animating card flip -static void sub_80C32EC(u16 arg0) +static void UpdateCardFlipRegs(u16 cardTop) { - s8 quotient = (arg0 + 40) / 10; + s8 blendY = (cardTop + 40) / 10; - if (quotient <= 4) - quotient = 0; - sData->flipBlendY = quotient; + if (blendY <= 4) + blendY = 0; + sData->flipBlendY = blendY; SetGpuReg(REG_OFFSET_BLDY, sData->flipBlendY); - SetGpuReg(REG_OFFSET_WIN0V, (sData->var_7CA8 * 256) | (160 - sData->var_7CA8)); + SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(sData->cardTop, DISPLAY_HEIGHT - sData->cardTop)); } static void ResetGpuRegs(void) @@ -1578,6 +1575,7 @@ u8 GetTrainerCardStars(u8 cardId) } #define tFlipState data[0] +#define tCardTop data[1] static void FlipTrainerCard(void) { @@ -1608,41 +1606,43 @@ static bool8 Task_BeginCardFlip(struct Task* task) HideBg(3); ScanlineEffect_Stop(); ScanlineEffect_Clear(); - for (i = 0; i < 160; i++) + for (i = 0; i < DISPLAY_HEIGHT; i++) gScanlineEffectRegBuffers[1][i] = 0; task->tFlipState++; return FALSE; } +// Note: Cannot be DISPLAY_HEIGHT / 2, or cardHeight will be 0 +#define CARD_FLIP_Y ((DISPLAY_HEIGHT / 2) - 3) + static bool8 Task_AnimateCardFlipDown(struct Task* task) { - u32 r4, r5, r10, r7, r6, var_24, r9, var; + u32 cardHeight, r5, r10, cardTop, r6, var_24, cardBottom, var; s16 i; sData->allowDMACopy = FALSE; - if (task->data[1] >= 77) - task->data[1] = 77; + if (task->tCardTop >= CARD_FLIP_Y) + task->tCardTop = CARD_FLIP_Y; else - task->data[1] += 7; - - sData->var_7CA8 = task->data[1]; - sub_80C32EC(task->data[1]); - - // ??? - r7 = task->data[1]; - r9 = 160 - r7; - r4 = r9 - r7; - r6 = -r7 << 16; - r5 = 0xA00000 / r4; - r5 += 0xFFFF0000; + task->tCardTop += 7; + + sData->cardTop = task->tCardTop; + UpdateCardFlipRegs(task->tCardTop); + + cardTop = task->tCardTop; + cardBottom = DISPLAY_HEIGHT - cardTop; + cardHeight = cardBottom - cardTop; + r6 = -cardTop << 16; + r5 = (DISPLAY_HEIGHT << 16) / cardHeight; + r5 -= 1 << 16; var_24 = r6; - var_24 += r5 * r4; - r10 = r5 / r4; + var_24 += r5 * cardHeight; + r10 = r5 / cardHeight; r5 *= 2; - for (i = 0; i < r7; i++) + for (i = 0; i < cardTop; i++) gScanlineEffectRegBuffers[0][i] = -i; - for (; i < (s16)(r9); i++) + for (; i < (s16)cardBottom; i++) { var = r6 >> 16; r6 += r5; @@ -1650,11 +1650,11 @@ static bool8 Task_AnimateCardFlipDown(struct Task* task) gScanlineEffectRegBuffers[0][i] = var; } var = var_24 >> 16; - for (; i < 160; i++) + for (; i < DISPLAY_HEIGHT; i++) gScanlineEffectRegBuffers[0][i] = var; sData->allowDMACopy = TRUE; - if (task->data[1] >= 77) + if (task->tCardTop >= CARD_FLIP_Y) task->tFlipState++; return FALSE; @@ -1663,7 +1663,7 @@ static bool8 Task_AnimateCardFlipDown(struct Task* task) static bool8 Task_DrawFlippedCardSide(struct Task* task) { sData->allowDMACopy = FALSE; - if (sub_8087598() == TRUE) + if (Overworld_LinkRecvQueueLengthMoreThan2() == TRUE) return FALSE; do @@ -1736,33 +1736,32 @@ static bool8 Task_SetCardFlipped(struct Task* task) static bool8 Task_AnimateCardFlipUp(struct Task* task) { - u32 r4, r5, r10, r7, r6, var_24, r9, var; + u32 cardHeight, r5, r10, cardTop, r6, var_24, cardBottom, var; s16 i; sData->allowDMACopy = FALSE; - if (task->data[1] <= 5) - task->data[1] = 0; + if (task->tCardTop <= 5) + task->tCardTop = 0; else - task->data[1] -= 5; - - sData->var_7CA8 = task->data[1]; - sub_80C32EC(task->data[1]); - - // ??? - r7 = task->data[1]; - r9 = 160 - r7; - r4 = r9 - r7; - r6 = -r7 << 16; - r5 = 0xA00000 / r4; - r5 += 0xFFFF0000; + task->tCardTop -= 5; + + sData->cardTop = task->tCardTop; + UpdateCardFlipRegs(task->tCardTop); + + cardTop = task->tCardTop; + cardBottom = DISPLAY_HEIGHT - cardTop; + cardHeight = cardBottom - cardTop; + r6 = -cardTop << 16; + r5 = (DISPLAY_HEIGHT << 16) / cardHeight; + r5 -= 1 << 16; var_24 = r6; - var_24 += r5 * r4; - r10 = r5 / r4; + var_24 += r5 * cardHeight; + r10 = r5 / cardHeight; r5 /= 2; - for (i = 0; i < r7; i++) + for (i = 0; i < cardTop; i++) gScanlineEffectRegBuffers[0][i] = -i; - for (; i < (s16)(r9); i++) + for (; i < (s16)cardBottom; i++) { var = r6 >> 16; r6 += r5; @@ -1770,11 +1769,11 @@ static bool8 Task_AnimateCardFlipUp(struct Task* task) gScanlineEffectRegBuffers[0][i] = var; } var = var_24 >> 16; - for (; i < 160; i++) + for (; i < DISPLAY_HEIGHT; i++) gScanlineEffectRegBuffers[0][i] = var; sData->allowDMACopy = TRUE; - if (task->data[1] <= 0) + if (task->tCardTop <= 0) task->tFlipState++; return FALSE; diff --git a/src/trainer_hill.c b/src/trainer_hill.c index 18d56723c..3bc6c970b 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -74,7 +74,7 @@ static void GetChallengeWon(void); static void TrainerHillSetTag(void); static void SetUpDataStruct(void); static void FreeDataStruct(void); -static void nullsub_2(void); +static void TrainerHillDummy(void); static void SetTimerValue(u32 *dst, u32 val); static u32 GetTimerValue(u32 *src); static void SetTrainerHillMonLevel(struct Pokemon *mon, u8 level); @@ -358,7 +358,7 @@ static void SetUpDataStruct(void) sHillData = AllocZeroed(sizeof(*sHillData)); sHillData->floorId = gMapHeader.mapLayoutId - LAYOUT_TRAINER_HILL_1F; CpuCopy32(sDataPerTag[gSaveBlock1Ptr->trainerHill.tag], &sHillData->tag, sizeof(sHillData->tag) + 4 * sizeof(struct TrHillFloor)); - nullsub_2(); + TrainerHillDummy(); } } @@ -397,7 +397,7 @@ void CopyTrainerHillTrainerText(u8 which, u16 trainerId) static void TrainerHillStartChallenge(void) { - nullsub_2(); + TrainerHillDummy(); if (!ReadTrainerHillAndValidate()) gSaveBlock1Ptr->trainerHill.field_3D6E_0f = 1; else @@ -573,12 +573,12 @@ static void IsTrainerHillChallengeActive(void) gSpecialVar_Result = TRUE; } -void nullsub_129(void) +static void TrainerHillDummy_Unused(void) { } -static void nullsub_2(void) +static void TrainerHillDummy(void) { } @@ -75,9 +75,6 @@ EWRAM_DATA ALIGNED(4) u8 sTVShowState = 0; EWRAM_DATA u8 sTVSecretBaseSecretsRandomValues[3] = {}; // Static ROM declarations -#if !defined(NONMATCHING) && MODERN -#define static -#endif void ClearPokemonNews(void); u8 GetTVChannelByShowType(u8 kind); u8 FindFirstActiveTVShowThatIsNotAMassOutbreak(void); diff --git a/src/unk_text_util_2.c b/src/unk_text_util_2.c index b92b34fbd..3459dde85 100644 --- a/src/unk_text_util_2.c +++ b/src/unk_text_util_2.c @@ -5,7 +5,7 @@ #include "sound.h" ALIGNED(4) -static const u8 sUnknown_08616124[] = {1, 2, 4}; +static const u8 sScrollDistances[] = {1, 2, 4}; static const u16 sFont6BrailleGlyphs[] = INCBIN_U16("graphics/fonts/font6.fwjpnfont"); static void DecompressGlyphFont6(u16); @@ -135,7 +135,7 @@ u16 Font6Func(struct TextPrinter *textPrinter) } DecompressGlyphFont6(char_); CopyGlyphToWindow(textPrinter); - textPrinter->printerTemplate.currentX += gUnknown_03002F90.width + textPrinter->printerTemplate.letterSpacing; + textPrinter->printerTemplate.currentX += gCurGlyph.width + textPrinter->printerTemplate.letterSpacing; return 0; case 1: if (TextPrinterWait(textPrinter)) @@ -164,15 +164,15 @@ u16 Font6Func(struct TextPrinter *textPrinter) case 4: if (textPrinter->scrollDistance) { - if (textPrinter->scrollDistance < sUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed]) + if (textPrinter->scrollDistance < sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed]) { ScrollWindow(textPrinter->printerTemplate.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->printerTemplate.bgColor)); textPrinter->scrollDistance = 0; } else { - ScrollWindow(textPrinter->printerTemplate.windowId, 0, sUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->printerTemplate.bgColor)); - textPrinter->scrollDistance -= sUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed]; + ScrollWindow(textPrinter->printerTemplate.windowId, 0, sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->printerTemplate.bgColor)); + textPrinter->scrollDistance -= sScrollDistances[gSaveBlock2Ptr->optionsTextSpeed]; } CopyWindowToVram(textPrinter->printerTemplate.windowId, 2); } @@ -206,12 +206,12 @@ static void DecompressGlyphFont6(u16 glyph) const u16 *glyphs; glyphs = sFont6BrailleGlyphs + 0x100 * (glyph / 8) + 0x10 * (glyph % 8); - DecompressGlyphTile(glyphs, (u16 *)gUnknown_03002F90.unk0); - DecompressGlyphTile(glyphs + 0x8, (u16 *)(gUnknown_03002F90.unk20)); - DecompressGlyphTile(glyphs + 0x80, (u16 *)(gUnknown_03002F90.unk40)); - DecompressGlyphTile(glyphs + 0x88, (u16 *)(gUnknown_03002F90.unk60)); - gUnknown_03002F90.width = 0x10; - gUnknown_03002F90.height = 0x10; + DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop); + DecompressGlyphTile(glyphs + 0x8, gCurGlyph.gfxBufferTop + 8); + DecompressGlyphTile(glyphs + 0x80, gCurGlyph.gfxBufferBottom); + DecompressGlyphTile(glyphs + 0x88, gCurGlyph.gfxBufferBottom + 8); + gCurGlyph.width = 0x10; + gCurGlyph.height = 0x10; } u32 GetGlyphWidthFont6(u16 glyphId, bool32 isJapanese) |