diff options
Diffstat (limited to 'src')
127 files changed, 52310 insertions, 9046 deletions
diff --git a/src/bard_music.c b/src/bard_music.c index 6fb1496e5..6c2578071 100644 --- a/src/bard_music.c +++ b/src/bard_music.c @@ -2,6 +2,7 @@ // Includes #include "global.h" #include "bard_music.h" +#include "constants/easy_chat.h" #include "easy_chat.h" #include "data/bard_music/bard_sounds.h" diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c index d6ccf9305..e1a9168a9 100644 --- a/src/battle_ai_script_commands.c +++ b/src/battle_ai_script_commands.c @@ -12,10 +12,6 @@ #include "util.h" #include "constants/battle_ai.h" -#define AIScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) -#define AIScriptRead16(ptr) ((ptr)[0] | (ptr)[1] << 8) -#define AIScriptReadPtr(ptr) (const u8*) AIScriptRead32(ptr) - #define AI_ACTION_DONE 0x0001 #define AI_ACTION_FLEE 0x0002 #define AI_ACTION_WATCH 0x0004 @@ -45,7 +41,6 @@ in order to read the next command correctly. refer to battle_ai_scripts.s for th AI scripts. */ -extern const struct BattleMove gBattleMoves[]; extern const u8 * const gBattleAI_ScriptsTable[]; extern u32 GetAiScriptsInRecordedBattle(); @@ -346,7 +341,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves) } gBattleResources->AI_ScriptsStack->size = 0; sBattler_AI = gActiveBattler; - // decide a random target bank in doubles + // decide a random target battlerId in doubles if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { gBattlerTarget = (Random() & BIT_FLANK) + (GetBattlerSide(gActiveBattler) ^ BIT_SIDE); @@ -620,32 +615,32 @@ static void RecordLastUsedMoveByTarget(void) } } -void ClearBattlerMoveHistory(u8 bank) +void ClearBattlerMoveHistory(u8 battlerId) { s32 i; for (i = 0; i < 4; i++) - gBattleResources->battleHistory->usedMoves[bank].moves[i] = 0; + gBattleResources->battleHistory->usedMoves[battlerId].moves[i] = 0; } -void RecordAbilityBattle(u8 bank, u8 abilityId) +void RecordAbilityBattle(u8 battlerId, u8 abilityId) { - gBattleResources->battleHistory->abilities[bank] = abilityId; + gBattleResources->battleHistory->abilities[battlerId] = abilityId; } -void ClearBattlerAbilityHistory(u8 bank) +void ClearBattlerAbilityHistory(u8 battlerId) { - gBattleResources->battleHistory->abilities[bank] = 0; + gBattleResources->battleHistory->abilities[battlerId] = 0; } -void RecordItemEffectBattle(u8 bank, u8 itemEffect) +void RecordItemEffectBattle(u8 battlerId, u8 itemEffect) { - gBattleResources->battleHistory->itemEffects[bank] = itemEffect; + gBattleResources->battleHistory->itemEffects[battlerId] = itemEffect; } -void ClearBankItemEffectHistory(u8 bank) +void ClearBankItemEffectHistory(u8 battlerId) { - gBattleResources->battleHistory->itemEffects[bank] = 0; + gBattleResources->battleHistory->itemEffects[battlerId] = 0; } static void BattleAICmd_if_random_less_than(void) @@ -653,7 +648,7 @@ static void BattleAICmd_if_random_less_than(void) u16 random = Random(); if (random % 256 < gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -663,7 +658,7 @@ static void BattleAICmd_if_random_greater_than(void) u16 random = Random(); if (random % 256 > gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -673,7 +668,7 @@ static void BattleAICmd_if_random_equal(void) u16 random = Random(); if (random % 256 == gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -683,7 +678,7 @@ static void BattleAICmd_if_random_not_equal(void) u16 random = Random(); if (random % 256 != gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -700,206 +695,206 @@ static void BattleAICmd_score(void) static void BattleAICmd_if_hp_less_than(void) { - u16 bank; + u16 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if ((u32)(100 * gBattleMons[bank].hp / gBattleMons[bank].maxHP) < gAIScriptPtr[2]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + if ((u32)(100 * gBattleMons[battlerId].hp / gBattleMons[battlerId].maxHP) < gAIScriptPtr[2]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_hp_more_than(void) { - u16 bank; + u16 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if ((u32)(100 * gBattleMons[bank].hp / gBattleMons[bank].maxHP) > gAIScriptPtr[2]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + if ((u32)(100 * gBattleMons[battlerId].hp / gBattleMons[battlerId].maxHP) > gAIScriptPtr[2]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_hp_equal(void) { - u16 bank; + u16 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if ((u32)(100 * gBattleMons[bank].hp / gBattleMons[bank].maxHP) == gAIScriptPtr[2]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + if ((u32)(100 * gBattleMons[battlerId].hp / gBattleMons[battlerId].maxHP) == gAIScriptPtr[2]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_hp_not_equal(void) { - u16 bank; + u16 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if ((u32)(100 * gBattleMons[bank].hp / gBattleMons[bank].maxHP) != gAIScriptPtr[2]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + if ((u32)(100 * gBattleMons[battlerId].hp / gBattleMons[battlerId].maxHP) != gAIScriptPtr[2]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_status(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gBattleMons[bank].status1 & status) != 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gBattleMons[battlerId].status1 & status) != 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_not_status(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gBattleMons[bank].status1 & status) == 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gBattleMons[battlerId].status1 & status) == 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_status2(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gBattleMons[bank].status2 & status) != 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gBattleMons[battlerId].status2 & status) != 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_not_status2(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gBattleMons[bank].status2 & status) == 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gBattleMons[battlerId].status2 & status) == 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_status3(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gStatuses3[bank] & status) != 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gStatuses3[battlerId] & status) != 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_not_status3(void) { - u16 bank; + u16 battlerId; u32 status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - status = AIScriptRead32(gAIScriptPtr + 2); + status = T1_READ_32(gAIScriptPtr + 2); - if ((gStatuses3[bank] & status) == 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + if ((gStatuses3[battlerId] & status) == 0) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_side_affecting(void) { - u16 bank; + u16 battlerId; u32 side, status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - side = GET_BATTLER_SIDE(bank); - status = AIScriptRead32(gAIScriptPtr + 2); + side = GET_BATTLER_SIDE(battlerId); + status = T1_READ_32(gAIScriptPtr + 2); if ((gSideStatuses[side] & status) != 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } static void BattleAICmd_if_not_side_affecting(void) { - u16 bank; + u16 battlerId; u32 side, status; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - side = GET_BATTLER_SIDE(bank); - status = AIScriptRead32(gAIScriptPtr + 2); + side = GET_BATTLER_SIDE(battlerId); + status = T1_READ_32(gAIScriptPtr + 2); if ((gSideStatuses[side] & status) == 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); else gAIScriptPtr += 10; } @@ -907,7 +902,7 @@ static void BattleAICmd_if_not_side_affecting(void) static void BattleAICmd_if_less_than(void) { if (AI_THINKING_STRUCT->funcResult < gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -915,7 +910,7 @@ static void BattleAICmd_if_less_than(void) static void BattleAICmd_if_more_than(void) { if (AI_THINKING_STRUCT->funcResult > gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -923,7 +918,7 @@ static void BattleAICmd_if_more_than(void) static void BattleAICmd_if_equal(void) { if (AI_THINKING_STRUCT->funcResult == gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -931,80 +926,80 @@ static void BattleAICmd_if_equal(void) static void BattleAICmd_if_not_equal(void) { if (AI_THINKING_STRUCT->funcResult != gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } static void BattleAICmd_if_less_than_ptr(void) { - const u8 *value = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *value = T1_READ_PTR(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->funcResult < *value) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); else gAIScriptPtr += 9; } static void BattleAICmd_if_more_than_ptr(void) { - const u8 *value = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *value = T1_READ_PTR(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->funcResult > *value) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); else gAIScriptPtr += 9; } static void BattleAICmd_if_equal_ptr(void) { - const u8 *value = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *value = T1_READ_PTR(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->funcResult == *value) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); else gAIScriptPtr += 9; } static void BattleAICmd_if_not_equal_ptr(void) { - const u8 *value = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *value = T1_READ_PTR(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->funcResult != *value) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); else gAIScriptPtr += 9; } static void BattleAICmd_if_move(void) { - u16 move = AIScriptRead16(gAIScriptPtr + 1); + u16 move = T1_READ_16(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->moveConsidered == move) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_not_move(void) { - u16 move = AIScriptRead16(gAIScriptPtr + 1); + u16 move = T1_READ_16(gAIScriptPtr + 1); if (AI_THINKING_STRUCT->moveConsidered != move) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); else gAIScriptPtr += 7; } static void BattleAICmd_if_in_bytes(void) { - const u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *ptr = T1_READ_PTR(gAIScriptPtr + 1); while (*ptr != 0xFF) { if (AI_THINKING_STRUCT->funcResult == *ptr) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); return; } ptr++; @@ -1014,7 +1009,7 @@ static void BattleAICmd_if_in_bytes(void) static void BattleAICmd_if_not_in_bytes(void) { - const u8 *ptr = AIScriptReadPtr(gAIScriptPtr + 1); + const u8 *ptr = T1_READ_PTR(gAIScriptPtr + 1); while (*ptr != 0xFF) { @@ -1025,18 +1020,18 @@ static void BattleAICmd_if_not_in_bytes(void) } ptr++; } - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); } static void BattleAICmd_if_in_hwords(void) { - const u16 *ptr = (const u16 *)AIScriptReadPtr(gAIScriptPtr + 1); + const u16 *ptr = (const u16 *)T1_READ_PTR(gAIScriptPtr + 1); while (*ptr != 0xFFFF) { if (AI_THINKING_STRUCT->funcResult == *ptr) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); return; } ptr++; @@ -1046,7 +1041,7 @@ static void BattleAICmd_if_in_hwords(void) static void BattleAICmd_if_not_in_hwords(void) { - const u16 *ptr = (u16 *)AIScriptReadPtr(gAIScriptPtr + 1); + const u16 *ptr = (u16 *)T1_READ_PTR(gAIScriptPtr + 1); while (*ptr != 0xFFFF) { @@ -1057,7 +1052,7 @@ static void BattleAICmd_if_not_in_hwords(void) } ptr++; } - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 5); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 5); } static void BattleAICmd_if_user_has_attacking_move(void) @@ -1073,7 +1068,7 @@ static void BattleAICmd_if_user_has_attacking_move(void) if (i == 4) gAIScriptPtr += 5; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); } static void BattleAICmd_if_user_has_no_attacking_moves(void) @@ -1089,7 +1084,7 @@ static void BattleAICmd_if_user_has_no_attacking_moves(void) if (i != 4) gAIScriptPtr += 5; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); } static void BattleAICmd_get_turn_count(void) @@ -1123,9 +1118,9 @@ static void BattleAICmd_get_type(void) gAIScriptPtr += 2; } -static u8 BattleAI_GetWantedBank(u8 bank) +static u8 BattleAI_GetWantedBank(u8 battlerId) { - switch (bank) + switch (battlerId) { case AI_USER: return sBattler_AI; @@ -1141,9 +1136,9 @@ static u8 BattleAI_GetWantedBank(u8 bank) static void BattleAICmd_is_of_type(void) { - u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + u8 battlerId = BattleAI_GetWantedBank(gAIScriptPtr[1]); - if(gBattleMons[bank].type1 == gAIScriptPtr[2] || gBattleMons[bank].type2 == gAIScriptPtr[2]) + if(gBattleMons[battlerId].type1 == gAIScriptPtr[2] || gBattleMons[battlerId].type2 == gAIScriptPtr[2]) { AI_THINKING_STRUCT->funcResult = TRUE; } @@ -1238,7 +1233,7 @@ static void BattleAICmd_get_last_used_bank_move(void) static void BattleAICmd_if_equal_(void) // same as if_equal { if (gAIScriptPtr[1] == AI_THINKING_STRUCT->funcResult) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1246,7 +1241,7 @@ static void BattleAICmd_if_equal_(void) // same as if_equal static void BattleAICmd_if_not_equal_(void) // same as if_not_equal { if (gAIScriptPtr[1] != AI_THINKING_STRUCT->funcResult) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1254,7 +1249,7 @@ static void BattleAICmd_if_not_equal_(void) // same as if_not_equal static void BattleAICmd_if_user_goes(void) { if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) == gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1262,7 +1257,7 @@ static void BattleAICmd_if_user_goes(void) static void BattleAICmd_if_user_doesnt_go(void) { if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) != gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1277,7 +1272,7 @@ static void BattleAICmd_nullsub_2B(void) static void BattleAICmd_count_usable_party_mons(void) { - u8 bank; + u8 battlerId; u8 bankOnField1, bankOnField2; struct Pokemon *party; int i; @@ -1285,11 +1280,11 @@ static void BattleAICmd_count_usable_party_mons(void) AI_THINKING_STRUCT->funcResult = 0; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (GetBattlerSide(bank) == B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) party = gPlayerParty; else party = gEnemyParty; @@ -1297,14 +1292,14 @@ static void BattleAICmd_count_usable_party_mons(void) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { u32 position; - bankOnField1 = gBattlerPartyIndexes[bank]; - position = GetBattlerPosition(bank) ^ BIT_FLANK; + bankOnField1 = gBattlerPartyIndexes[battlerId]; + position = GetBattlerPosition(battlerId) ^ BIT_FLANK; bankOnField2 = gBattlerPartyIndexes[GetBattlerAtPosition(position)]; } - else // in singles there's only one bank by side + else // in singles there's only one battlerId by side { - bankOnField1 = gBattlerPartyIndexes[bank]; - bankOnField2 = gBattlerPartyIndexes[bank]; + bankOnField1 = gBattlerPartyIndexes[battlerId]; + bankOnField2 = gBattlerPartyIndexes[battlerId]; } for (i = 0; i < PARTY_SIZE; i++) @@ -1335,110 +1330,110 @@ static void BattleAICmd_get_considered_move_effect(void) static void BattleAICmd_get_ability(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gActiveBattler != bank) + if (gActiveBattler != battlerId) { - if (BATTLE_HISTORY->abilities[bank] != 0) + if (BATTLE_HISTORY->abilities[battlerId] != 0) { - AI_THINKING_STRUCT->funcResult = BATTLE_HISTORY->abilities[bank]; + AI_THINKING_STRUCT->funcResult = BATTLE_HISTORY->abilities[battlerId]; gAIScriptPtr += 2; return; } // abilities that prevent fleeing. - if (gBattleMons[bank].ability == ABILITY_SHADOW_TAG - || gBattleMons[bank].ability == ABILITY_MAGNET_PULL - || gBattleMons[bank].ability == ABILITY_ARENA_TRAP) + if (gBattleMons[battlerId].ability == ABILITY_SHADOW_TAG + || gBattleMons[battlerId].ability == ABILITY_MAGNET_PULL + || gBattleMons[battlerId].ability == ABILITY_ARENA_TRAP) { - AI_THINKING_STRUCT->funcResult = gBattleMons[bank].ability; + AI_THINKING_STRUCT->funcResult = gBattleMons[battlerId].ability; gAIScriptPtr += 2; return; } - if (gBaseStats[gBattleMons[bank].species].ability1 != ABILITY_NONE) + if (gBaseStats[gBattleMons[battlerId].species].ability1 != ABILITY_NONE) { - if (gBaseStats[gBattleMons[bank].species].ability2 != ABILITY_NONE) + if (gBaseStats[gBattleMons[battlerId].species].ability2 != ABILITY_NONE) { // AI has no knowledge of opponent, so it guesses which ability. if (Random() & 1) { - AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[bank].species].ability1; + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[battlerId].species].ability1; } else { - AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[bank].species].ability2; + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[battlerId].species].ability2; } } else { - AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[bank].species].ability1; // it's definitely ability 1. + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[battlerId].species].ability1; // it's definitely ability 1. } } else { - AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[bank].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. + AI_THINKING_STRUCT->funcResult = gBaseStats[gBattleMons[battlerId].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. } } else { // The AI knows its own ability. - AI_THINKING_STRUCT->funcResult = gBattleMons[bank].ability; + AI_THINKING_STRUCT->funcResult = gBattleMons[battlerId].ability; } gAIScriptPtr += 2; } static void BattleAICmd_check_ability(void) { - u32 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + u32 battlerId = BattleAI_GetWantedBank(gAIScriptPtr[1]); u32 ability = gAIScriptPtr[2]; if (gAIScriptPtr[1] == AI_TARGET || gAIScriptPtr[1] == AI_TARGET_PARTNER) { - if (BATTLE_HISTORY->abilities[bank] != 0) + if (BATTLE_HISTORY->abilities[battlerId] != 0) { - ability = BATTLE_HISTORY->abilities[bank]; + ability = BATTLE_HISTORY->abilities[battlerId]; AI_THINKING_STRUCT->funcResult = ability; } // abilities that prevent fleeing. - else if (gBattleMons[bank].ability == ABILITY_SHADOW_TAG - || gBattleMons[bank].ability == ABILITY_MAGNET_PULL - || gBattleMons[bank].ability == ABILITY_ARENA_TRAP) + else if (gBattleMons[battlerId].ability == ABILITY_SHADOW_TAG + || gBattleMons[battlerId].ability == ABILITY_MAGNET_PULL + || gBattleMons[battlerId].ability == ABILITY_ARENA_TRAP) { - ability = gBattleMons[bank].ability; + ability = gBattleMons[battlerId].ability; } - else if (gBaseStats[gBattleMons[bank].species].ability1 != ABILITY_NONE) + else if (gBaseStats[gBattleMons[battlerId].species].ability1 != ABILITY_NONE) { - if (gBaseStats[gBattleMons[bank].species].ability2 != ABILITY_NONE) + if (gBaseStats[gBattleMons[battlerId].species].ability2 != ABILITY_NONE) { u8 abilityDummyVariable = ability; // needed to match - if (gBaseStats[gBattleMons[bank].species].ability1 != abilityDummyVariable - && gBaseStats[gBattleMons[bank].species].ability2 != abilityDummyVariable) + if (gBaseStats[gBattleMons[battlerId].species].ability1 != abilityDummyVariable + && gBaseStats[gBattleMons[battlerId].species].ability2 != abilityDummyVariable) { - ability = gBaseStats[gBattleMons[bank].species].ability1; + ability = gBaseStats[gBattleMons[battlerId].species].ability1; } else ability = 0; } else { - ability = gBaseStats[gBattleMons[bank].species].ability1; + ability = gBaseStats[gBattleMons[battlerId].species].ability1; } } else { - ability = gBaseStats[gBattleMons[bank].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. + ability = gBaseStats[gBattleMons[battlerId].species].ability2; // AI cant actually reach this part since every mon has at least 1 ability. } } else { // The AI knows its own or partner's ability. - ability = gBattleMons[bank].ability; + ability = gBattleMons[battlerId].ability; } if (ability == 0) { @@ -1528,7 +1523,7 @@ static void BattleAICmd_if_type_effectiveness(void) damageVar = gBattleMoveDamage; if (damageVar == gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1546,21 +1541,21 @@ static void BattleAICmd_if_status_in_party(void) struct Pokemon *party; int i; u32 statusToCompareTo; - u8 bank; + u8 battlerId; switch(gAIScriptPtr[1]) { case AI_USER: - bank = sBattler_AI; + battlerId = sBattler_AI; break; default: - bank = gBattlerTarget; + battlerId = gBattlerTarget; break; } - party = (GetBattlerSide(bank) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + party = (GetBattlerSide(battlerId) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - statusToCompareTo = AIScriptRead32(gAIScriptPtr + 2); + statusToCompareTo = T1_READ_32(gAIScriptPtr + 2); for (i = 0; i < PARTY_SIZE; i++) { @@ -1570,7 +1565,7 @@ static void BattleAICmd_if_status_in_party(void) if (species != SPECIES_NONE && species != SPECIES_EGG && hp != 0 && status == statusToCompareTo) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); return; } } @@ -1583,21 +1578,21 @@ static void BattleAICmd_if_status_not_in_party(void) struct Pokemon *party; int i; u32 statusToCompareTo; - u8 bank; + u8 battlerId; switch(gAIScriptPtr[1]) { case 1: - bank = sBattler_AI; + battlerId = sBattler_AI; break; default: - bank = gBattlerTarget; + battlerId = gBattlerTarget; break; } - party = (GetBattlerSide(bank) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; + party = (GetBattlerSide(battlerId) == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - statusToCompareTo = AIScriptRead32(gAIScriptPtr + 2); + statusToCompareTo = T1_READ_32(gAIScriptPtr + 2); for (i = 0; i < PARTY_SIZE; i++) { @@ -1611,7 +1606,7 @@ static void BattleAICmd_if_status_not_in_party(void) } } - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 6); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6); } static void BattleAICmd_get_weather(void) @@ -1631,7 +1626,7 @@ static void BattleAICmd_get_weather(void) static void BattleAICmd_if_effect(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect == gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } @@ -1639,67 +1634,67 @@ static void BattleAICmd_if_effect(void) static void BattleAICmd_if_not_effect(void) { if (gBattleMoves[AI_THINKING_STRUCT->moveConsidered].effect != gAIScriptPtr[1]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } static void BattleAICmd_if_stat_level_less_than(void) { - u32 bank; + u32 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gBattleMons[bank].statStages[gAIScriptPtr[2]] < gAIScriptPtr[3]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + if (gBattleMons[battlerId].statStages[gAIScriptPtr[2]] < gAIScriptPtr[3]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; } static void BattleAICmd_if_stat_level_more_than(void) { - u32 bank; + u32 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gBattleMons[bank].statStages[gAIScriptPtr[2]] > gAIScriptPtr[3]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + if (gBattleMons[battlerId].statStages[gAIScriptPtr[2]] > gAIScriptPtr[3]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; } static void BattleAICmd_if_stat_level_equal(void) { - u32 bank; + u32 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gBattleMons[bank].statStages[gAIScriptPtr[2]] == gAIScriptPtr[3]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + if (gBattleMons[battlerId].statStages[gAIScriptPtr[2]] == gAIScriptPtr[3]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; } static void BattleAICmd_if_stat_level_not_equal(void) { - u32 bank; + u32 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gBattleMons[bank].statStages[gAIScriptPtr[2]] != gAIScriptPtr[3]) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + if (gBattleMons[battlerId].statStages[gAIScriptPtr[2]] != gAIScriptPtr[3]) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; } @@ -1728,7 +1723,7 @@ static void BattleAICmd_if_can_faint(void) gBattleMoveDamage = 1; if (gBattleMons[gBattlerTarget].hp <= gBattleMoveDamage) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } @@ -1755,7 +1750,7 @@ static void BattleAICmd_if_cant_faint(void) // this macro is missing the damage 0 = 1 assumption. if (gBattleMons[gBattlerTarget].hp > gBattleMoveDamage) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } @@ -1780,7 +1775,7 @@ static void BattleAICmd_if_has_move(void) } else { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); return; } case AI_USER_PARTNER: @@ -1804,7 +1799,7 @@ static void BattleAICmd_if_has_move(void) } else { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); return; } case AI_TARGET: @@ -1821,7 +1816,7 @@ static void BattleAICmd_if_has_move(void) } else { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); return; } } @@ -1848,7 +1843,7 @@ static void BattleAICmd_if_doesnt_have_move(void) } else { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); return; } case AI_TARGET: @@ -1865,7 +1860,7 @@ static void BattleAICmd_if_doesnt_have_move(void) } else { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); return; } } @@ -1887,7 +1882,7 @@ static void BattleAICmd_if_has_move_with_effect(void) if (i == 4) gAIScriptPtr += 7; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); break; case AI_TARGET: case AI_TARGET_PARTNER: @@ -1900,7 +1895,7 @@ static void BattleAICmd_if_has_move_with_effect(void) if (i == 4) gAIScriptPtr += 7; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); break; } } @@ -1921,7 +1916,7 @@ static void BattleAICmd_if_doesnt_have_move_with_effect(void) if (i != 4) gAIScriptPtr += 7; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); break; case AI_TARGET: case AI_TARGET_PARTNER: @@ -1933,28 +1928,28 @@ static void BattleAICmd_if_doesnt_have_move_with_effect(void) if (i != 4) gAIScriptPtr += 7; else - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); break; } } static void BattleAICmd_if_any_move_disabled_or_encored(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; if (gAIScriptPtr[2] == 0) { - if (gDisableStructs[bank].disabledMove == 0) + if (gDisableStructs[battlerId].disabledMove == 0) { gAIScriptPtr += 7; return; } - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); return; } else if (gAIScriptPtr[2] != 1) // ignore the macro if its not 0 or 1. @@ -1962,9 +1957,9 @@ static void BattleAICmd_if_any_move_disabled_or_encored(void) gAIScriptPtr += 7; return; } - else if (gDisableStructs[bank].encoredMove != 0) + else if (gDisableStructs[battlerId].encoredMove != 0) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 3); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3); return; } gAIScriptPtr += 7; @@ -1977,7 +1972,7 @@ static void BattleAICmd_if_curr_move_disabled_or_encored(void) case 0: if (gDisableStructs[gActiveBattler].disabledMove == AI_THINKING_STRUCT->moveConsidered) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; @@ -1985,7 +1980,7 @@ static void BattleAICmd_if_curr_move_disabled_or_encored(void) case 1: if (gDisableStructs[gActiveBattler].encoredMove == AI_THINKING_STRUCT->moveConsidered) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; @@ -2006,7 +2001,7 @@ static void BattleAICmd_if_random_safari_flee(void) u8 safariFleeRate = gBattleStruct->field_7B * 5; // safari flee rate, from 0-20 if ((u8)(Random() % 100) < safariFleeRate) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } @@ -2018,80 +2013,80 @@ static void BattleAICmd_watch(void) static void BattleAICmd_get_hold_effect(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - if (gActiveBattler != bank) - AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(BATTLE_HISTORY->itemEffects[bank]); + if (gActiveBattler != battlerId) + AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(BATTLE_HISTORY->itemEffects[battlerId]); else - AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(gBattleMons[bank].item); + AI_THINKING_STRUCT->funcResult = ItemId_GetHoldEffect(gBattleMons[battlerId].item); gAIScriptPtr += 2; } static void BattleAICmd_if_holds_item(void) { - u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + u8 battlerId = BattleAI_GetWantedBank(gAIScriptPtr[1]); u16 item; u8 var1, var2; - if ((bank & BIT_SIDE) == (sBattler_AI & BIT_SIDE)) - item = gBattleMons[bank].item; + if ((battlerId & BIT_SIDE) == (sBattler_AI & BIT_SIDE)) + item = gBattleMons[battlerId].item; else - item = BATTLE_HISTORY->itemEffects[bank]; + item = BATTLE_HISTORY->itemEffects[battlerId]; // UB: doesn't properly read an unaligned u16 var2 = gAIScriptPtr[2]; var1 = gAIScriptPtr[3]; if ((var1 | var2) == item) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 4); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 4); else gAIScriptPtr += 8; } static void BattleAICmd_get_gender(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - AI_THINKING_STRUCT->funcResult = GetGenderFromSpeciesAndPersonality(gBattleMons[bank].species, gBattleMons[bank].personality); + AI_THINKING_STRUCT->funcResult = GetGenderFromSpeciesAndPersonality(gBattleMons[battlerId].species, gBattleMons[battlerId].personality); gAIScriptPtr += 2; } static void BattleAICmd_is_first_turn_for(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].isFirstTurn; + AI_THINKING_STRUCT->funcResult = gDisableStructs[battlerId].isFirstTurn; gAIScriptPtr += 2; } static void BattleAICmd_get_stockpile_count(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].stockpileCounter; + AI_THINKING_STRUCT->funcResult = gDisableStructs[battlerId].stockpileCounter; gAIScriptPtr += 2; } @@ -2105,18 +2100,18 @@ static void BattleAICmd_is_double_battle(void) static void BattleAICmd_get_used_held_item(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; // This is likely a leftover from Ruby's code and its ugly ewram access #ifdef NONMATCHING - AI_THINKING_STRUCT->funcResult = gBattleStruct->usedHeldItems[bank]; + AI_THINKING_STRUCT->funcResult = gBattleStruct->usedHeldItems[battlerId]; #else - AI_THINKING_STRUCT->funcResult = *(u8*)((u8*)(gBattleStruct) + offsetof(struct BattleStruct, usedHeldItems) + (bank * 2)); + AI_THINKING_STRUCT->funcResult = *(u8*)((u8*)(gBattleStruct) + offsetof(struct BattleStruct, usedHeldItems) + (battlerId * 2)); #endif // NONMATCHING gAIScriptPtr += 2; @@ -2145,14 +2140,14 @@ static void BattleAICmd_get_move_effect_from_result(void) static void BattleAICmd_get_protect_count(void) { - u8 bank; + u8 battlerId; if (gAIScriptPtr[1] == AI_USER) - bank = sBattler_AI; + battlerId = sBattler_AI; else - bank = gBattlerTarget; + battlerId = gBattlerTarget; - AI_THINKING_STRUCT->funcResult = gDisableStructs[bank].protectUses; + AI_THINKING_STRUCT->funcResult = gDisableStructs[battlerId].protectUses; gAIScriptPtr += 2; } @@ -2184,12 +2179,12 @@ static void BattleAICmd_nullsub_57(void) static void BattleAICmd_call(void) { AIStackPushVar(gAIScriptPtr + 5); - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); } static void BattleAICmd_goto(void) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); } static void BattleAICmd_end(void) @@ -2205,7 +2200,7 @@ static void BattleAICmd_if_level_cond(void) case 0: // greater than if (gBattleMons[sBattler_AI].level > gBattleMons[gBattlerTarget].level) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; @@ -2213,7 +2208,7 @@ static void BattleAICmd_if_level_cond(void) case 1: // less than if (gBattleMons[sBattler_AI].level < gBattleMons[gBattlerTarget].level) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; @@ -2221,7 +2216,7 @@ static void BattleAICmd_if_level_cond(void) case 2: // equal if (gBattleMons[sBattler_AI].level == gBattleMons[gBattlerTarget].level) { - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); return; } gAIScriptPtr += 6; @@ -2232,7 +2227,7 @@ static void BattleAICmd_if_level_cond(void) static void BattleAICmd_if_target_taunted(void) { if (gDisableStructs[gBattlerTarget].tauntTimer1 != 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } @@ -2240,7 +2235,7 @@ static void BattleAICmd_if_target_taunted(void) static void BattleAICmd_if_target_not_taunted(void) { if (gDisableStructs[gBattlerTarget].tauntTimer1 == 0) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } @@ -2248,17 +2243,17 @@ static void BattleAICmd_if_target_not_taunted(void) static void BattleAICmd_if_target_is_ally(void) { if ((sBattler_AI & BIT_SIDE) == (gBattlerTarget & BIT_SIDE)) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 1); + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1); else gAIScriptPtr += 5; } static void BattleAICmd_if_flash_fired(void) { - u8 bank = BattleAI_GetWantedBank(gAIScriptPtr[1]); + u8 battlerId = BattleAI_GetWantedBank(gAIScriptPtr[1]); - if (gBattleResources->flags->flags[bank] & UNKNOWN_FLAG_FLASH_FIRE) - gAIScriptPtr = AIScriptReadPtr(gAIScriptPtr + 2); + if (gBattleResources->flags->flags[battlerId] & UNKNOWN_FLAG_FLASH_FIRE) + gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2); else gAIScriptPtr += 6; } diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index b0fcc2e29..83ad2b4fd 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -8,11 +8,6 @@ #include "random.h" #include "util.h" #include "constants/items.h" -#include "pokemon_item_effects.h" - -extern const struct BattleMove gBattleMoves[]; -extern const u8 gTypeEffectiveness[]; -extern const u8 * const gItemEffectTable[]; // todo: fix once struct is declared // this file's functions static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng); diff --git a/src/battle_anim.c b/src/battle_anim.c index 7606f701d..8071736e6 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -19,10 +19,6 @@ // sprites start at 10000 and thus must be subtracted of 10000 to account for the true index. #define GET_TRUE_SPRITE_INDEX(i) ((i - 10000)) -#define SCRIPT_READ_16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) -#define SCRIPT_READ_32(ptr) (((ptr)[0]) + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) -#define SCRIPT_READ_PTR(ptr) ((const u8*)(SCRIPT_READ_32(ptr))) - #define ANIM_SPRITE_INDEX_COUNT 8 extern u16 gBattle_WIN0H; @@ -127,7 +123,7 @@ EWRAM_DATA static u8 sAnimBackgroundFadeState = 0; EWRAM_DATA static u16 sAnimMoveIndex = 0; // set but unused. EWRAM_DATA u8 gBattleAnimAttacker = 0; EWRAM_DATA u8 gBattleAnimTarget = 0; -EWRAM_DATA u16 gAnimSpeciesByBanks[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gUnknown_02038440 = 0; // const rom data @@ -232,15 +228,15 @@ void LaunchBattleAnimation(const u8 *const animsTable[], u16 tableId, bool8 isMo for (i = 0; i < MAX_BATTLERS_COUNT; i++) { if (GetBattlerSide(i) != 0) - gAnimSpeciesByBanks[i] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + gAnimBattlerSpecies[i] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); else - gAnimSpeciesByBanks[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); + gAnimBattlerSpecies[i] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[i]], MON_DATA_SPECIES); } } else { for (i = 0; i < 4; i++) - gAnimSpeciesByBanks[i] = gContestResources->field_18->field_0; + gAnimBattlerSpecies[i] = gContestResources->field_18->field_0; } if (!isMoveAnim) @@ -352,7 +348,7 @@ static void ScriptCmd_loadspritegfx(void) u16 index; sBattleAnimScriptPtr++; - index = SCRIPT_READ_16(sBattleAnimScriptPtr); + index = T1_READ_16(sBattleAnimScriptPtr); LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)]); LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(index)]); sBattleAnimScriptPtr += 2; @@ -366,7 +362,7 @@ static void ScriptCmd_unloadspritegfx(void) u16 index; sBattleAnimScriptPtr++; - index = SCRIPT_READ_16(sBattleAnimScriptPtr); + index = T1_READ_16(sBattleAnimScriptPtr); FreeSpriteTilesByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); FreeSpritePaletteByTag(gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(index)].tag); sBattleAnimScriptPtr += 2; @@ -382,7 +378,7 @@ static void ScriptCmd_createsprite(void) s16 subpriority; sBattleAnimScriptPtr++; - template = (const struct SpriteTemplate *)(SCRIPT_READ_32(sBattleAnimScriptPtr)); + template = (const struct SpriteTemplate *)(T2_READ_32(sBattleAnimScriptPtr)); sBattleAnimScriptPtr += 4; argVar = sBattleAnimScriptPtr[0]; @@ -392,7 +388,7 @@ static void ScriptCmd_createsprite(void) sBattleAnimScriptPtr++; for (i = 0; i < argsCount; i++) { - gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } @@ -433,7 +429,7 @@ static void ScriptCmd_createvisualtask(void) sBattleAnimScriptPtr++; - taskFunc = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); + taskFunc = (TaskFunc)T2_READ_32(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 4; taskPriority = sBattleAnimScriptPtr[0]; @@ -444,7 +440,7 @@ static void ScriptCmd_createvisualtask(void) for (i = 0; i < numArgs; i++) { - gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } @@ -542,26 +538,26 @@ static void ScriptCmd_end(void) static void ScriptCmd_playse(void) { sBattleAnimScriptPtr++; - PlaySE(SCRIPT_READ_16(sBattleAnimScriptPtr)); + PlaySE(T1_READ_16(sBattleAnimScriptPtr)); sBattleAnimScriptPtr += 2; } -#define t1_MONBG_BANK 0 +#define t1_MONBG_BATTLER 0 #define t1_MON_IN_BG2 1 #define t1_CREATE_ANOTHER_TASK 2 #define t1_IS_SECONDMON_BG 3 -#define t2_BANK_SPRITE_ID 0 +#define t2_BATTLER_SPRITE_ID 0 #define t2_MON_IN_BG2 5 -#define t2_MONBG_BANK 6 +#define t2_MONBG_BATTLER 6 static void sub_80A40F4(u8 taskId) { u8 newTaskId; s16 *selfData = gTasks[taskId].data; - u8 bankSpriteId = gBattlerSpriteIds[selfData[t1_MONBG_BANK]]; - gSprites[bankSpriteId].invisible = 1; + u8 battlerSpriteId = gBattlerSpriteIds[selfData[t1_MONBG_BATTLER]]; + gSprites[battlerSpriteId].invisible = 1; if (!selfData[t1_CREATE_ANOTHER_TASK]) { @@ -570,9 +566,9 @@ static void sub_80A40F4(u8 taskId) } newTaskId = CreateTask(task_pA_ma0A_obj_to_bg_pal, 10); - gTasks[newTaskId].data[t2_BANK_SPRITE_ID] = bankSpriteId; - gTasks[newTaskId].data[1] = gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x; - gTasks[newTaskId].data[2] = gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y; + gTasks[newTaskId].data[t2_BATTLER_SPRITE_ID] = battlerSpriteId; + gTasks[newTaskId].data[1] = gSprites[battlerSpriteId].pos1.x + gSprites[battlerSpriteId].pos2.x; + gTasks[newTaskId].data[2] = gSprites[battlerSpriteId].pos1.y + gSprites[battlerSpriteId].pos2.y; if (!selfData[t1_MON_IN_BG2]) { @@ -586,7 +582,7 @@ static void sub_80A40F4(u8 taskId) } gTasks[newTaskId].data[t2_MON_IN_BG2] = selfData[t1_MON_IN_BG2]; - gTasks[newTaskId].data[t2_MONBG_BANK] = selfData[t1_MONBG_BANK]; + gTasks[newTaskId].data[t2_MONBG_BATTLER] = selfData[t1_MONBG_BATTLER]; sMonAnimTaskIdArray[selfData[t1_IS_SECONDMON_BG]] = newTaskId; DestroyAnimVisualTask(taskId); } @@ -595,48 +591,48 @@ static void ScriptCmd_monbg(void) { bool8 toBG_2; u8 taskId; - u8 bank; + u8 battlerId; u8 animBank; sBattleAnimScriptPtr++; animBank = sBattleAnimScriptPtr[0]; if (animBank & ANIM_TARGET) - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; else - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; - if (IsBattlerSpriteVisible(bank)) + if (IsBattlerSpriteVisible(battlerId)) { - u8 position = GetBattlerPosition(bank); + u8 position = GetBattlerPosition(battlerId); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; - sub_80A438C(bank, toBG_2, FALSE); + sub_80A438C(battlerId, toBG_2, FALSE); taskId = CreateTask(sub_80A40F4, 10); gAnimVisualTaskCount++; - gTasks[taskId].data[t1_MONBG_BANK] = bank; + gTasks[taskId].data[t1_MONBG_BATTLER] = battlerId; gTasks[taskId].data[t1_MON_IN_BG2] = toBG_2; gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; gTasks[taskId].data[t1_IS_SECONDMON_BG] = 0; } - bank ^= BIT_FLANK; - if (IsBattlerSpriteVisible(bank)) + battlerId ^= BIT_FLANK; + if (IsBattlerSpriteVisible(battlerId)) { - u8 position = GetBattlerPosition(bank); + u8 position = GetBattlerPosition(battlerId); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; - sub_80A438C(bank, toBG_2, FALSE); + sub_80A438C(battlerId, toBG_2, FALSE); taskId = CreateTask(sub_80A40F4, 10); gAnimVisualTaskCount++; - gTasks[taskId].data[0] = bank; + gTasks[taskId].data[0] = battlerId; gTasks[taskId].data[1] = toBG_2; gTasks[taskId].data[t1_CREATE_ANOTHER_TASK] = TRUE; gTasks[taskId].data[t1_IS_SECONDMON_BG] = 1; @@ -647,33 +643,33 @@ static void ScriptCmd_monbg(void) gAnimScriptCallback = WaitAnimFrameCount; } -bool8 IsBattlerSpriteVisible(u8 bank) +bool8 IsBattlerSpriteVisible(u8 battlerId) { if (IsContest()) { - if (bank == gBattleAnimAttacker) + if (battlerId == gBattleAnimAttacker) return TRUE; else return FALSE; } - if (!IsBattlerSpritePresent(bank)) + if (!IsBattlerSpritePresent(battlerId)) return FALSE; if (IsContest()) return TRUE; // this line wont ever be reached. - if (!gBattleSpritesDataPtr->battlerData[bank].invisible || !gSprites[gBattlerSpriteIds[bank]].invisible) + if (!gBattleSpritesDataPtr->battlerData[battlerId].invisible || !gSprites[gBattlerSpriteIds[battlerId]].invisible) return TRUE; return FALSE; } -void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) +void sub_80A438C(u8 battlerId, bool8 toBG_2, bool8 setSpriteInvisible) { struct UnknownAnimStruct2 unknownStruct; - u8 bankSpriteId; + u8 battlerSpriteId; if (!toBG_2) { - u8 bankIdentity; + u8 battlerPosition; if (IsContest() == TRUE) { @@ -694,28 +690,28 @@ void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 1); SetAnimBgAttribute(1, BG_ANIM_AREA_OVERFLOW_MODE, 0); - bankSpriteId = gBattlerSpriteIds[bank]; + battlerSpriteId = gBattlerSpriteIds[battlerId]; - gBattle_BG1_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; + gBattle_BG1_X = -(gSprites[battlerSpriteId].pos1.x + gSprites[battlerSpriteId].pos2.x) + 0x20; if (IsContest() && IsSpeciesNotUnown(gContestResources->field_18->field_0)) gBattle_BG1_X--; - gBattle_BG1_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; + gBattle_BG1_Y = -(gSprites[battlerSpriteId].pos1.y + gSprites[battlerSpriteId].pos2.y) + 0x20; if (setSpriteInvisible) - gSprites[gBattlerSpriteIds[bank]].invisible = 1; + gSprites[gBattlerSpriteIds[battlerId]].invisible = 1; SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); - LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], unknownStruct.unk8 * 16, 0x20); - CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + unknownStruct.unk8 * 32), 0x20); + LoadPalette(&gPlttBufferUnfaded[0x100 + battlerId * 16], unknownStruct.unk8 * 16, 0x20); + CpuCopy32(&gPlttBufferUnfaded[0x100 + battlerId * 16], (void*)(BG_PLTT + unknownStruct.unk8 * 32), 0x20); if (IsContest()) - bankIdentity = 0; + battlerPosition = 0; else - bankIdentity = GetBattlerPosition(bank); + battlerPosition = GetBattlerPosition(battlerId); - sub_8118FBC(1, 0, 0, bankIdentity, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA); + sub_8118FBC(1, 0, 0, battlerPosition, unknownStruct.unk8, unknownStruct.unk0, unknownStruct.unk4, unknownStruct.unkA); if (IsContest()) sub_80A46A0(); @@ -731,21 +727,21 @@ void sub_80A438C(u8 bank, bool8 toBG_2, bool8 setSpriteInvisible) SetAnimBgAttribute(2, BG_ANIM_SCREEN_SIZE, 1); SetAnimBgAttribute(2, BG_ANIM_AREA_OVERFLOW_MODE, 0); - bankSpriteId = gBattlerSpriteIds[bank]; + battlerSpriteId = gBattlerSpriteIds[battlerId]; - gBattle_BG2_X = -(gSprites[bankSpriteId].pos1.x + gSprites[bankSpriteId].pos2.x) + 0x20; - gBattle_BG2_Y = -(gSprites[bankSpriteId].pos1.y + gSprites[bankSpriteId].pos2.y) + 0x20; + gBattle_BG2_X = -(gSprites[battlerSpriteId].pos1.x + gSprites[battlerSpriteId].pos2.x) + 0x20; + gBattle_BG2_Y = -(gSprites[battlerSpriteId].pos1.y + gSprites[battlerSpriteId].pos2.y) + 0x20; if (setSpriteInvisible) - gSprites[gBattlerSpriteIds[bank]].invisible = 1; + gSprites[gBattlerSpriteIds[battlerId]].invisible = 1; SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X); SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y); - LoadPalette(&gPlttBufferUnfaded[0x100 + bank * 16], 0x90, 0x20); - CpuCopy32(&gPlttBufferUnfaded[0x100 + bank * 16], (void*)(BG_PLTT + 0x120), 0x20); + LoadPalette(&gPlttBufferUnfaded[0x100 + battlerId * 16], 0x90, 0x20); + CpuCopy32(&gPlttBufferUnfaded[0x100 + battlerId * 16], (void*)(BG_PLTT + 0x120), 0x20); - sub_8118FBC(2, 0, 0, GetBattlerPosition(bank), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA); + sub_8118FBC(2, 0, 0, GetBattlerPosition(battlerId), unknownStruct.unk8, unknownStruct.unk0 + 0x1000, unknownStruct.unk4 + 0x400, unknownStruct.unkA); } } @@ -852,7 +848,7 @@ static void task_pA_ma0A_obj_to_bg_pal(u8 taskId) static void ScriptCmd_clearmonbg(void) { u8 animBankId; - u8 bank; + u8 battlerId; u8 taskId; sBattleAnimScriptPtr++; @@ -864,20 +860,20 @@ static void ScriptCmd_clearmonbg(void) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; else - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; if (sMonAnimTaskIdArray[0] != 0xFF) - gSprites[gBattlerSpriteIds[bank]].invisible = 0; + gSprites[gBattlerSpriteIds[battlerId]].invisible = 0; if (animBankId > 1 && sMonAnimTaskIdArray[1] != 0xFF) - gSprites[gBattlerSpriteIds[bank ^ BIT_FLANK]].invisible = 0; + gSprites[gBattlerSpriteIds[battlerId ^ BIT_FLANK]].invisible = 0; else animBankId = 0; taskId = CreateTask(sub_80A4980, 5); gTasks[taskId].data[0] = animBankId; - gTasks[taskId].data[2] = bank; + gTasks[taskId].data[2] = battlerId; sBattleAnimScriptPtr++; } @@ -913,7 +909,7 @@ static void sub_80A4980(u8 taskId) static void ScriptCmd_monbg_22(void) { bool8 toBG_2; - u8 bank; + u8 battlerId; u8 animBankId; sBattleAnimScriptPtr++; @@ -926,31 +922,31 @@ static void ScriptCmd_monbg_22(void) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; else - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; - if (IsBattlerSpriteVisible(bank)) + if (IsBattlerSpriteVisible(battlerId)) { - u8 position = GetBattlerPosition(bank); + u8 position = GetBattlerPosition(battlerId); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; - sub_80A438C(bank, toBG_2, FALSE); + sub_80A438C(battlerId, toBG_2, FALSE); } - bank ^= BIT_FLANK; - if (animBankId > 1 && IsBattlerSpriteVisible(bank)) + battlerId ^= BIT_FLANK; + if (animBankId > 1 && IsBattlerSpriteVisible(battlerId)) { - u8 position = GetBattlerPosition(bank); + u8 position = GetBattlerPosition(battlerId); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; - sub_80A438C(bank, toBG_2, FALSE); + sub_80A438C(battlerId, toBG_2, FALSE); } sBattleAnimScriptPtr++; @@ -959,7 +955,7 @@ static void ScriptCmd_monbg_22(void) static void ScriptCmd_clearmonbg_23(void) { u8 animBankId; - u8 bank; + u8 battlerId; u8 taskId; sBattleAnimScriptPtr++; @@ -971,20 +967,20 @@ static void ScriptCmd_clearmonbg_23(void) animBankId = ANIM_DEF_PARTNER; if (animBankId == ANIM_ATTACKER || animBankId == ANIM_ATK_PARTNER) - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; else - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; - if (IsBattlerSpriteVisible(bank)) - gSprites[gBattlerSpriteIds[bank]].invisible = 0; - if (animBankId > 1 && IsBattlerSpriteVisible(bank ^ BIT_FLANK)) - gSprites[gBattlerSpriteIds[bank ^ BIT_FLANK]].invisible = 0; + if (IsBattlerSpriteVisible(battlerId)) + gSprites[gBattlerSpriteIds[battlerId]].invisible = 0; + if (animBankId > 1 && IsBattlerSpriteVisible(battlerId ^ BIT_FLANK)) + gSprites[gBattlerSpriteIds[battlerId ^ BIT_FLANK]].invisible = 0; else animBankId = 0; taskId = CreateTask(sub_80A4BB0, 5); gTasks[taskId].data[0] = animBankId; - gTasks[taskId].data[2] = bank; + gTasks[taskId].data[2] = battlerId; sBattleAnimScriptPtr++; } @@ -995,30 +991,30 @@ static void sub_80A4BB0(u8 taskId) if (gTasks[taskId].data[1] != 1) { bool8 toBG_2; - u8 bank = gTasks[taskId].data[2]; - u8 position = GetBattlerPosition(bank); + u8 battlerId = gTasks[taskId].data[2]; + u8 position = GetBattlerPosition(battlerId); if (position == B_POSITION_OPPONENT_LEFT || position == B_POSITION_PLAYER_RIGHT || IsContest()) toBG_2 = FALSE; else toBG_2 = TRUE; - if (IsBattlerSpriteVisible(bank)) + if (IsBattlerSpriteVisible(battlerId)) sub_80A477C(toBG_2); - if (gTasks[taskId].data[0] > 1 && IsBattlerSpriteVisible(bank ^ BIT_FLANK)) + if (gTasks[taskId].data[0] > 1 && IsBattlerSpriteVisible(battlerId ^ BIT_FLANK)) sub_80A477C(toBG_2 ^ 1); DestroyTask(taskId); } } -#undef t1_MONBG_BANK +#undef t1_MONBG_BATTLER #undef t1_MON_IN_BG2 #undef t1_CREATE_ANOTHER_TASK #undef t1_IS_SECONDMON_BG -#undef t2_BANK_SPRITE_ID +#undef t2_BATTLER_SPRITE_ID #undef t2_MON_IN_BG2 -#undef t2_MONBG_BANK +#undef t2_MONBG_BATTLER static void ScriptCmd_setalpha(void) { @@ -1052,7 +1048,7 @@ static void ScriptCmd_call(void) { sBattleAnimScriptPtr++; sBattleAnimScriptRetAddr = sBattleAnimScriptPtr + 4; - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr); } static void ScriptCmd_return(void) @@ -1069,7 +1065,7 @@ static void ScriptCmd_setarg(void) sBattleAnimScriptPtr++; argId = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; - value = SCRIPT_READ_16(sBattleAnimScriptPtr); + value = T1_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr = addr + 4; gBattleAnimArgs[argId] = value; } @@ -1079,7 +1075,7 @@ static void ScriptCmd_choosetwoturnanim(void) sBattleAnimScriptPtr++; if (gAnimMoveTurn & 1) sBattleAnimScriptPtr += 4; - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr); } static void ScriptCmd_jumpifmoveturn(void) @@ -1090,7 +1086,7 @@ static void ScriptCmd_jumpifmoveturn(void) sBattleAnimScriptPtr++; if (toCheck == gAnimMoveTurn) - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr); else sBattleAnimScriptPtr += 4; } @@ -1098,7 +1094,7 @@ static void ScriptCmd_jumpifmoveturn(void) static void ScriptCmd_goto(void) { sBattleAnimScriptPtr++; - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr); } // Uses of this function that rely on a TRUE return are expecting inBattle to not be ticked as defined in contest behavior. As a result, if misused, this function cannot reliably discern between field and contest status and could result in undefined behavior. @@ -1322,16 +1318,16 @@ s8 BattleAnimAdjustPanning2(s8 pan) return pan; } -s16 sub_80A52EC(s16 a) +s16 KeepPanInRange(s16 panArg) { - s16 var = a; + s16 pan = panArg; - if (var > 63) - var = 63; - else if (var < -64) - var = -64; + if (pan > PAN_SIDE_OPPONENT) + pan = PAN_SIDE_OPPONENT; + else if (pan < PAN_SIDE_PLAYER) + pan = PAN_SIDE_PLAYER; - return var; + return pan; } s16 CalculatePanIncrement(s16 sourcePan, s16 targetPan, s16 incrementPan) @@ -1354,7 +1350,7 @@ static void ScriptCmd_playsewithpan(void) s8 pan; sBattleAnimScriptPtr++; - songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + songId = T1_READ_16(sBattleAnimScriptPtr); pan = sBattleAnimScriptPtr[2]; PlaySE12WithPanning(songId, BattleAnimAdjustPanning(pan)); sBattleAnimScriptPtr += 3; @@ -1385,7 +1381,7 @@ static void ScriptCmd_panse_1B(void) u8 taskId; sBattleAnimScriptPtr++; - songNum = SCRIPT_READ_16(sBattleAnimScriptPtr); + songNum = T1_READ_16(sBattleAnimScriptPtr); currentPanArg = sBattleAnimScriptPtr[2]; incrementPan = sBattleAnimScriptPtr[3]; incrementPanArg = sBattleAnimScriptPtr[4]; @@ -1457,7 +1453,7 @@ static void ScriptCmd_panse_26(void) u8 taskId; sBattleAnimScriptPtr++; - songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + songId = T1_READ_16(sBattleAnimScriptPtr); currentPan = sBattleAnimScriptPtr[2]; targetPan = sBattleAnimScriptPtr[3]; incrementPan = sBattleAnimScriptPtr[4]; @@ -1484,7 +1480,7 @@ static void ScriptCmd_panse_27(void) u8 taskId; sBattleAnimScriptPtr++; - songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + songId = T1_READ_16(sBattleAnimScriptPtr); currentPanArg = sBattleAnimScriptPtr[2]; targetPanArg = sBattleAnimScriptPtr[3]; incrementPanArg = sBattleAnimScriptPtr[4]; @@ -1528,7 +1524,7 @@ static void ScriptCmd_loopsewithpan(void) u8 taskId; sBattleAnimScriptPtr++; - songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + songId = T1_READ_16(sBattleAnimScriptPtr); panningArg = sBattleAnimScriptPtr[2]; framesToWait = sBattleAnimScriptPtr[3]; numberOfPlays = sBattleAnimScriptPtr[4]; @@ -1585,7 +1581,7 @@ static void ScriptCmd_waitplaysewithpan(void) u8 taskId; sBattleAnimScriptPtr++; - songId = SCRIPT_READ_16(sBattleAnimScriptPtr); + songId = T1_READ_16(sBattleAnimScriptPtr); panningArg = sBattleAnimScriptPtr[2]; framesToWait = sBattleAnimScriptPtr[3]; panning = BattleAnimAdjustPanning(panningArg); @@ -1620,13 +1616,13 @@ static void ScriptCmd_createsoundtask(void) s32 i; sBattleAnimScriptPtr++; - func = (TaskFunc)SCRIPT_READ_32(sBattleAnimScriptPtr); + func = (TaskFunc)T2_READ_32(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 4; numArgs = sBattleAnimScriptPtr[0]; sBattleAnimScriptPtr++; for (i = 0; i < numArgs; i++) { - gBattleAnimArgs[i] = SCRIPT_READ_16(sBattleAnimScriptPtr); + gBattleAnimArgs[i] = T1_READ_16(sBattleAnimScriptPtr); sBattleAnimScriptPtr += 2; } taskId = CreateTask(func, 1); @@ -1669,10 +1665,10 @@ static void ScriptCmd_jumpargeq(void) sBattleAnimScriptPtr++; argId = sBattleAnimScriptPtr[0]; - valueToCheck = SCRIPT_READ_16(sBattleAnimScriptPtr + 1); + valueToCheck = T1_READ_16(sBattleAnimScriptPtr + 1); if (valueToCheck == gBattleAnimArgs[argId]) - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr + 3); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr + 3); else sBattleAnimScriptPtr += 7; } @@ -1681,7 +1677,7 @@ static void ScriptCmd_jumpifcontest(void) { sBattleAnimScriptPtr++; if (IsContest()) - sBattleAnimScriptPtr = SCRIPT_READ_PTR(sBattleAnimScriptPtr); + sBattleAnimScriptPtr = T2_READ_PTR(sBattleAnimScriptPtr); else sBattleAnimScriptPtr += 4; } @@ -1689,19 +1685,19 @@ static void ScriptCmd_jumpifcontest(void) static void ScriptCmd_monbgprio_28(void) { u8 wantedBank; - u8 bank; - u8 bankIdentity; + u8 battlerId; + u8 battlerPosition; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (wantedBank != ANIM_ATTACKER) - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; else - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; - bankIdentity = GetBattlerPosition(bank); - if (!IsContest() && (bankIdentity == B_POSITION_PLAYER_LEFT || bankIdentity == B_POSITION_OPPONENT_RIGHT)) + battlerPosition = GetBattlerPosition(battlerId); + if (!IsContest() && (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_OPPONENT_RIGHT)) { SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); @@ -1721,20 +1717,20 @@ static void ScriptCmd_monbgprio_29(void) static void ScriptCmd_monbgprio_2A(void) { u8 wantedBank; - u8 bankIdentity; - u8 bank; + u8 battlerPosition; + u8 battlerId; wantedBank = sBattleAnimScriptPtr[1]; sBattleAnimScriptPtr += 2; if (GetBattlerSide(gBattleAnimAttacker) != GetBattlerSide(gBattleAnimTarget)) { if (wantedBank != ANIM_ATTACKER) - bank = gBattleAnimTarget; + battlerId = gBattleAnimTarget; else - bank = gBattleAnimAttacker; + battlerId = gBattleAnimAttacker; - bankIdentity = GetBattlerPosition(bank); - if (!IsContest() && (bankIdentity == B_POSITION_PLAYER_LEFT || bankIdentity == B_POSITION_OPPONENT_RIGHT)) + battlerPosition = GetBattlerPosition(battlerId); + if (!IsContest() && (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_OPPONENT_RIGHT)) { SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); SetAnimBgAttribute(2, BG_ANIM_PRIORITY, 2); diff --git a/src/battle_anim_sound_tasks.c b/src/battle_anim_sound_tasks.c new file mode 100644 index 000000000..2316b9759 --- /dev/null +++ b/src/battle_anim_sound_tasks.c @@ -0,0 +1,438 @@ +#include "global.h" +#include "battle.h" +#include "constants/battle_anim.h" +#include "constants/species.h" +#include "battle_anim.h" +#include "task.h" +#include "sound.h" +#include "contest.h" + +// this file's functions +static void sub_8158B98(u8 taskId); +static void sub_8158C04(u8 taskId); +static void sub_8158D08(u8 taskId); +static void sub_8158FF4(u8 taskId); +static void sub_815913C(u8 taskId); +static void sub_8159308(u8 taskId); + +// task start +void sub_8158B30(u8 taskId) +{ + s8 pan1, pan2, panIncrement; + + gTasks[taskId].data[0] = gBattleAnimArgs[0]; + gTasks[taskId].data[1] = gBattleAnimArgs[1]; + + pan1 = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + pan2 = BattleAnimAdjustPanning(PAN_SIDE_OPPONENT); + panIncrement = CalculatePanIncrement(pan1, pan2, 2); + + gTasks[taskId].data[2] = pan1; + gTasks[taskId].data[3] = pan2; + gTasks[taskId].data[4] = panIncrement; + gTasks[taskId].data[10] = 10; + + gTasks[taskId].func = sub_8158B98; +} + +static void sub_8158B98(u8 taskId) +{ + s16 pan = gTasks[taskId].data[2]; + s8 panIncrement = gTasks[taskId].data[4]; + if (++gTasks[taskId].data[11] == 111) + { + gTasks[taskId].data[10] = 5; + gTasks[taskId].data[11] = 0; + gTasks[taskId].func = sub_8158C04; + } + else + { + if (++gTasks[taskId].data[10] == 11) + { + gTasks[taskId].data[10] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], pan); + } + pan += panIncrement; + gTasks[taskId].data[2] = KeepPanInRange(pan); + } +} + +static void sub_8158C04(u8 taskId) +{ + if (++gTasks[taskId].data[10] == 6) + { + s8 pan; + + gTasks[taskId].data[10] = 0; + pan = BattleAnimAdjustPanning(PAN_SIDE_OPPONENT); + PlaySE12WithPanning(gTasks[taskId].data[1], pan); + if (++gTasks[taskId].data[11] == 2) + DestroyAnimSoundTask(taskId); + } +} +// task end + +// task start +void sub_8158C58(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 targetPan = gBattleAnimArgs[2]; + s8 panIncrement = gBattleAnimArgs[3]; + u8 r10 = gBattleAnimArgs[4]; + u8 r7 = gBattleAnimArgs[5]; + u8 r9 = gBattleAnimArgs[6]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + + gTasks[taskId].data[0] = songId; + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[4] = r10; + gTasks[taskId].data[5] = r7; + gTasks[taskId].data[6] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + gTasks[taskId].data[12] = r9; + + gTasks[taskId].func = sub_8158D08; + sub_8158D08(taskId); +} + +static void sub_8158D08(u8 taskId) +{ + if (gTasks[taskId].data[12]++ == gTasks[taskId].data[6]) + { + gTasks[taskId].data[12] = 0; + PlaySE12WithPanning(gTasks[taskId].data[0], gTasks[taskId].data[11]); + if (--gTasks[taskId].data[4] == 0) + { + DestroyAnimSoundTask(taskId); + return; + } + } + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] += gTasks[taskId].data[3]; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11]); + } +} +// task end + +// task start +void sub_8158D8C(u8 taskId) +{ + u16 species = 0; + s8 pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + if (IsContest()) + { + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + species = gContestResources->field_18->field_0; + else + DestroyAnimVisualTask(taskId); // UB: function should return upon destroying task + } + else + { + u8 battlerId; + + // get wanted battler + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + + // check if battler is visible + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + } + + if (species != SPECIES_NONE) + PlayCry3(species, pan, 3); + + DestroyAnimVisualTask(taskId); +} +// task end + +// task start +void sub_8158E9C(u8 taskId) +{ + u16 species = 0; + s8 pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + if (IsContest()) + { + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + species = gContestResources->field_18->field_0; + else + DestroyAnimVisualTask(taskId); // UB: function should return upon destroying task + } + else + { + u8 battlerId; + + // get wanted battler + if (gBattleAnimArgs[0] == ANIM_ATTACKER) + battlerId = gBattleAnimAttacker; + else if (gBattleAnimArgs[0] == ANIM_TARGET) + battlerId = gBattleAnimTarget; + else if (gBattleAnimArgs[0] == ANIM_ATK_PARTNER) + battlerId = BATTLE_PARTNER(gBattleAnimAttacker); + else + battlerId = BATTLE_PARTNER(gBattleAnimTarget); + + // check if battler is visible + if ((gBattleAnimArgs[0] == ANIM_TARGET || gBattleAnimArgs[0] == ANIM_DEF_PARTNER) && !IsBattlerSpriteVisible(battlerId)) + { + DestroyAnimVisualTask(taskId); + return; + } + + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + else + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + } + + gTasks[taskId].data[0] = gBattleAnimArgs[1]; + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + + if (species != SPECIES_NONE) + { + if (gBattleAnimArgs[1] == 0xFF) + PlayCry3(species, pan, 9); + else + PlayCry3(species, pan, 7); + + gTasks[taskId].func = sub_8158FF4; + } + else + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_8158FF4(u8 taskId) +{ + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + if (gTasks[taskId].data[9] < 2) + { + gTasks[taskId].data[9]++; + } + else + { + if (gTasks[taskId].data[0] == 0xFF) + { + if (!IsCryPlaying()) + { + PlayCry3(species, pan, 10); + DestroyAnimVisualTask(taskId); + } + } + else + { + if (!IsCryPlaying()) + { + PlayCry3(species, pan, 8); + DestroyAnimVisualTask(taskId); + } + } + } +} +// task end + +void sub_8159078(u8 taskId) +{ + if (gTasks[taskId].data[9] < 2) + { + gTasks[taskId].data[9]++; + } + else + { + if (!IsCryPlaying()) + DestroyAnimVisualTask(taskId); + } +} + +// task start +void sub_81590B8(u8 taskId) +{ + u16 species; + s8 pan; + + gTasks[taskId].data[10] = gBattleAnimArgs[0]; + pan = BattleAnimAdjustPanning(PAN_SIDE_PLAYER); + + if (IsContest()) + species = gContestResources->field_18->field_0; + else + species = gAnimBattlerSpecies[gBattleAnimAttacker]; + + gTasks[taskId].data[1] = species; + gTasks[taskId].data[2] = pan; + + if (species != SPECIES_NONE) + gTasks[taskId].func = sub_815913C; + else + DestroyAnimVisualTask(taskId); +} + +static void sub_815913C(u8 taskId) +{ + u16 species = gTasks[taskId].data[1]; + s8 pan = gTasks[taskId].data[2]; + + switch (gTasks[taskId].data[9]) + { + case 2: + PlayCry6(species, pan, 4); + gTasks[taskId].data[9]++; + break; + case 1: + case 3: + case 4: + gTasks[taskId].data[9]++; + break; + case 5: + if (IsCryPlaying()) + break; + case 0: + StopCryAndClearCrySongs(); + gTasks[taskId].data[9]++; + break; + default: + if (gTasks[taskId].data[10] == 0) + PlayCry6(species, pan, 6); + else + PlayCry3(species, pan, 6); + + DestroyAnimVisualTask(taskId); + break; + } +} +// task end + +void sub_8159210(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE1WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_8159244(u8 taskId) +{ + u16 songId = gBattleAnimArgs[0]; + s8 pan = BattleAnimAdjustPanning(gBattleAnimArgs[1]); + + PlaySE2WithPanning(songId, pan); + DestroyAnimVisualTask(taskId); +} + +void sub_8159278(u8 taskId) +{ + s8 targetPan = gBattleAnimArgs[1]; + s8 panIncrement = gBattleAnimArgs[2]; + u16 r9 = gBattleAnimArgs[3]; + s8 sourcePan = BattleAnimAdjustPanning(gBattleAnimArgs[0]); + + targetPan = BattleAnimAdjustPanning(targetPan); + panIncrement = CalculatePanIncrement(sourcePan, targetPan, panIncrement); + + gTasks[taskId].data[1] = sourcePan; + gTasks[taskId].data[2] = targetPan; + gTasks[taskId].data[3] = panIncrement; + gTasks[taskId].data[5] = r9; + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] = sourcePan; + + gTasks[taskId].func = sub_8159308; + sub_8159308(taskId); +} + +#ifdef NONMATCHING +void sub_8159308(u8 taskId) +{ + s16 panIncrement = gTasks[taskId].data[3]; + + if (gTasks[taskId].data[10]++ == gTasks[taskId].data[5]) + { + gTasks[taskId].data[10] = 0; + + gTasks[taskId].data[11] += panIncrement; + gTasks[taskId].data[11] = KeepPanInRange(gTasks[taskId].data[11]); + } + + gUnknown_02038440 = gTasks[taskId].data[11]; + if (gTasks[taskId].data[11] == gTasks[taskId].data[2]) + DestroyAnimVisualTask(taskId); +} +#else +NAKED +void sub_8159308(u8 taskId) +{ + asm_unified(" push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + adds r5, r0, 0\n\ + ldr r1, =gTasks\n\ + lsls r0, r5, 2\n\ + adds r0, r5\n\ + lsls r0, 3\n\ + adds r4, r0, r1\n\ + ldrh r2, [r4, 0xE]\n\ + ldrh r0, [r4, 0x1C]\n\ + adds r1, r0, 0x1\n\ + strh r1, [r4, 0x1C]\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + movs r3, 0x12\n\ + ldrsh r1, [r4, r3]\n\ + cmp r0, r1\n\ + bne _08159342\n\ + movs r0, 0\n\ + strh r0, [r4, 0x1C]\n\ + ldrh r1, [r4, 0x1E]\n\ + adds r0, r2, r1\n\ + strh r0, [r4, 0x1E]\n\ + movs r2, 0x1E\n\ + ldrsh r0, [r4, r2]\n\ + bl KeepPanInRange\n\ + strh r0, [r4, 0x1E]\n\ +_08159342:\n\ + ldr r1, =gUnknown_02038440\n\ + ldrh r0, [r4, 0x1E]\n\ + strb r0, [r1]\n\ + movs r3, 0x1E\n\ + ldrsh r1, [r4, r3]\n\ + movs r2, 0xC\n\ + ldrsh r0, [r4, r2]\n\ + cmp r1, r0\n\ + bne _0815935A\n\ + adds r0, r5, 0\n\ + bl DestroyAnimVisualTask\n\ +_0815935A:\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} +#endif diff --git a/src/battle_bg.c b/src/battle_bg.c index f493bafea..d4bfd297a 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -14,7 +14,6 @@ #include "trig.h" #include "sound.h" #include "constants/songs.h" -#include "strings.h" #include "window.h" #include "text_window.h" #include "menu.h" diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 290236f4a..a4aac55e2 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -6,7 +6,7 @@ #include "battle_anim.h" #include "constants/battle_anim.h" #include "battle_ai_script_commands.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "pokemon.h" #include "link.h" #include "util.h" @@ -26,17 +26,14 @@ #include "data2.h" #include "battle_setup.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern struct MusicPlayerInfo gMPlayInfo_BGM; extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; -extern const struct BattleMove gBattleMoves[]; -extern const u8 gFacilityClassToPicIndex[]; -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); extern void sub_81851A8(u8 *); extern u16 sub_8068B48(void); @@ -106,7 +103,7 @@ static void LinkOpponentBufferExecCompleted(void); static void sub_8064DD0(void); static u32 CopyLinkOpponentMonData(u8 monId, u8 *dst); static void SetLinkOpponentMonData(u8 monId); -static void sub_8066494(u8 bank, bool8 dontClearSubstituteBit); +static void sub_8066494(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void LinkOpponentDoMoveAnimation(void); static void sub_8067618(u8 taskId); @@ -1162,36 +1159,36 @@ static void LinkOpponentHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_8064F40; } -static void sub_8066494(u8 bank, bool8 dontClearSubstituteBit) +static void sub_8066494(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[bank]], bank); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite( + gBattlerSpriteIds[battlerId] = CreateSprite( &gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); } static void LinkOpponentHandleReturnMonToBall(void) @@ -1246,7 +1243,7 @@ static void LinkOpponentHandleDrawTrainerPic(void) if (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER) { - if (gActiveBattler == 1) + if (gActiveBattler == B_POSITION_OPPONENT_LEFT) trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_A); else trainerPicId = GetFrontierTrainerFrontSpriteId(gTrainerBattleOpponent_B); @@ -1256,18 +1253,18 @@ static void LinkOpponentHandleDrawTrainerPic(void) if ((gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_FIRE_RED || (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_LEAF_GREEN) { - if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != 0) - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_10]; + if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != MALE) + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_LEAF]; else - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_9]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RED]; } else if ((gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_RUBY || (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].version & 0xFF) == VERSION_SAPPHIRE) { - if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != 0) - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_12]; + if (gLinkPlayers[GetBattlerMultiplayerId(gActiveBattler)].gender != MALE) + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_MAY]; else - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_11]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_BRENDAN]; } else { @@ -1286,17 +1283,17 @@ static void LinkOpponentHandleDrawTrainerPic(void) || (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_LEAF_GREEN) { if (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].gender != 0) - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_10]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_LEAF]; else - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_9]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RED]; } else if ((gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_RUBY || (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].version & 0xFF) == VERSION_SAPPHIRE) { if (gLinkPlayers[GetMultiplayerId() ^ BIT_SIDE].gender != 0) - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_12]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_MAY]; else - trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_11]; + trainerPicId = gFacilityClassToPicIndex[FACILITY_CLASS_PKMN_TRAINER_RS_BRENDAN]; } else { @@ -1340,7 +1337,7 @@ static void LinkOpponentHandleTrainerSlide(void) gSprites[gBattlerSpriteIds[gActiveBattler]].oam.affineParam = trainerPicId; gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_805D7AC; - gBattlerControllerFuncs[gActiveBattler] = CompleteOnBankSpriteCallbackDummy2; // this line is redundant, because LinkOpponentBufferExecCompleted changes the battle bank function + gBattlerControllerFuncs[gActiveBattler] = CompleteOnBankSpriteCallbackDummy2; // this line is redundant, because LinkOpponentBufferExecCompleted changes the battle battlerId function LinkOpponentBufferExecCompleted(); } @@ -1416,7 +1413,7 @@ static void LinkOpponentHandleMoveAnimation(void) { gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkOpponentDoMoveAnimation; - sub_817E0FC(move, gWeatherMoveAnim, gAnimDisableStructPtr); + BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); } } } @@ -1480,7 +1477,7 @@ static void LinkOpponentHandlePrintString(void) BufferStringBattle(*stringId); BattleHandleAddTextPrinter(gDisplayedStringBattle, 0); gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter; - sub_817C95C(*stringId); + BattleTv_SetDataBasedOnString(*stringId); } static void LinkOpponentHandlePrintSelectionString(void) @@ -1551,11 +1548,11 @@ static void LinkOpponentHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } @@ -1833,7 +1830,7 @@ static void LinkOpponentHandleBattleAnimation(void) else gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation; - sub_817E32C(animationId); + BattleTv_SetDataBasedOnAnimation(animationId); } } diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 9d2c79922..d742d5df2 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -6,7 +6,7 @@ #include "battle_anim.h" #include "constants/battle_anim.h" #include "battle_ai_script_commands.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "pokemon.h" #include "link.h" #include "util.h" @@ -25,16 +25,14 @@ #include "data2.h" #include "battle_setup.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const struct BattleMove gBattleMoves[]; -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); extern void sub_81851A8(u8 *); extern u8 GetFrontierTrainerFrontSpriteId(u16 trainerId); @@ -103,7 +101,7 @@ static void LinkPartnerBufferExecCompleted(void); static void sub_814B554(void); static u32 CopyLinkPartnerMonData(u8 monId, u8 *dst); static void SetLinkPartnerMonData(u8 monId); -static void sub_814CC98(u8 bank, bool8 dontClearSubstituteBit); +static void sub_814CC98(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void LinkPartnerDoMoveAnimation(void); static void sub_814DCCC(u8 taskId); @@ -1047,35 +1045,35 @@ static void LinkPartnerHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_814B69C; } -static void sub_814CC98(u8 bank, bool8 dontClearSubstituteBit) +static void sub_814CC98(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite( + gBattlerSpriteIds[battlerId] = CreateSprite( &gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); } static void LinkPartnerHandleReturnMonToBall(void) @@ -1239,7 +1237,7 @@ static void LinkPartnerHandleMoveAnimation(void) { gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = LinkPartnerDoMoveAnimation; - sub_817E0FC(move, gWeatherMoveAnim, gAnimDisableStructPtr); + BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); } } } @@ -1303,7 +1301,7 @@ static void LinkPartnerHandlePrintString(void) BufferStringBattle(*stringId); BattleHandleAddTextPrinter(gDisplayedStringBattle, 0); gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter; - sub_817C95C(*stringId); + BattleTv_SetDataBasedOnString(*stringId); } static void LinkPartnerHandlePrintSelectionString(void) @@ -1374,11 +1372,11 @@ static void LinkPartnerHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } @@ -1667,7 +1665,7 @@ static void LinkPartnerHandleBattleAnimation(void) else gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation; - sub_817E32C(animationId); + BattleTv_SetDataBasedOnAnimation(animationId); } } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 5a3732f8b..64cf16b86 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -5,7 +5,7 @@ #include "battle_interface.h" #include "battle_anim.h" #include "constants/battle_anim.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "battle_ai_script_commands.h" #include "pokemon.h" #include "link.h" @@ -29,18 +29,16 @@ #include "data2.h" #include "battle_setup.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern struct MusicPlayerInfo gMPlayInfo_BGM; extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; -extern const struct BattleMove gBattleMoves[]; -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); -extern void sub_81A57E4(u8 bank, u16 stringId); +extern void sub_81A57E4(u8 battlerId, u16 stringId); extern u8 sub_81A4CB0(void); extern u8 sub_81D5588(u16 trainerId); extern u8 GetFrontierTrainerFrontSpriteId(u16 trainerId); @@ -110,7 +108,7 @@ static void OpponentBufferExecCompleted(void); static void sub_805FC80(void); static u32 GetOpponentMonData(u8 monId, u8 *dst); static void SetOpponentMonData(u8 monId); -static void sub_80613DC(u8 bank, bool8 dontClearSubstituteBit); +static void sub_80613DC(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void OpponentDoMoveAnimation(void); static void sub_806280C(struct Sprite *sprite); @@ -1155,36 +1153,36 @@ static void OpponentHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_805FDF0; } -static void sub_80613DC(u8 bank, bool8 dontClearSubstituteBit) +static void sub_80613DC(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[bank]], bank); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite(&gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + gBattlerSpriteIds[battlerId] = CreateSprite(&gUnknown_0202499C, + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); } static void OpponentHandleReturnMonToBall(void) @@ -1564,7 +1562,7 @@ static void OpponentHandleChooseMove(void) BtlController_EmitTwoReturnValues(1, 15, gBattlerTarget); break; default: - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_x10)) + if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) gBattlerTarget = gActiveBattler; if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) { @@ -1586,7 +1584,7 @@ static void OpponentHandleChooseMove(void) move = moveInfo->moves[chosenMoveId]; } while (move == MOVE_NONE); - if (gBattleMoves[move].target & (MOVE_TARGET_USER | MOVE_TARGET_x10)) + if (gBattleMoves[move].target & (MOVE_TARGET_USER_OR_SELECTED | MOVE_TARGET_USER)) BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (gActiveBattler << 8)); else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) BtlController_EmitTwoReturnValues(1, 10, (chosenMoveId) | (GetBattlerAtPosition(Random() & 2) << 8)); @@ -1699,11 +1697,11 @@ static void OpponentHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 897122ddd..e0694029a 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -5,7 +5,7 @@ #include "battle_interface.h" #include "battle_anim.h" #include "constants/battle_anim.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "pokemon.h" #include "link.h" #include "util.h" @@ -42,22 +42,12 @@ extern struct SpriteTemplate gUnknown_0202499C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const u8 gTypeNames[][7]; -extern const struct BattleMove gBattleMoves[]; - -extern const u8 gText_BattleSwitchWhich[]; -extern const u8 gText_MoveInterfacePP[]; -extern const u8 gText_MoveInterfaceType[]; -extern const u8 gText_LinkStandby[]; -extern const u8 gText_BattleMenu[]; -extern const u8 gText_WhatWillPkmnDo[]; -extern const u8 gText_BattleYesNoChoice[]; - -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); + +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_81B89AC(u8 arg0); extern void sub_81AABB0(void); extern void sub_806A068(u16, u8); -extern void sub_81A57E4(u8 bank, u16 stringId); +extern void sub_81A57E4(u8 battlerId, u16 stringId); extern void sub_81851A8(u8 *); // this file's functions @@ -140,7 +130,7 @@ static void sub_80595A4(u8 taskId); static void PrintLinkStandbyMsg(void); static u32 CopyPlayerMonData(u8 monId, u8 *dst); static void SetPlayerMonData(u8 monId); -static void sub_805B258(u8 bank, bool8 dontClearSubstituteBit); +static void sub_805B258(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void PlayerDoMoveAnimation(void); static void task05_08033660(u8 taskId); @@ -432,7 +422,7 @@ static void HandleInputChooseTarget(void) case B_POSITION_PLAYER_RIGHT: if (gActiveBattler != gMultiUsePlayerCursor) i++; - else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler])].target & MOVE_TARGET_USER) + else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler])].target & MOVE_TARGET_USER_OR_SELECTED) i++; break; case B_POSITION_OPPONENT_LEFT: @@ -474,7 +464,7 @@ static void HandleInputChooseTarget(void) case B_POSITION_PLAYER_RIGHT: if (gActiveBattler != gMultiUsePlayerCursor) i++; - else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler])].target & MOVE_TARGET_USER) + else if (gBattleMoves[GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MOVE1 + gMoveSelectionCursor[gActiveBattler])].target & MOVE_TARGET_USER_OR_SELECTED) i++; break; case B_POSITION_OPPONENT_LEFT: @@ -508,7 +498,7 @@ static void HandleInputChooseMove(void) if (moveInfo->moves[gMoveSelectionCursor[gActiveBattler]] == MOVE_CURSE) { if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST) - moveTarget = MOVE_TARGET_x10; + moveTarget = MOVE_TARGET_USER; else moveTarget = MOVE_TARGET_SELECTED; } @@ -517,26 +507,26 @@ static void HandleInputChooseMove(void) moveTarget = gBattleMoves[moveInfo->moves[gMoveSelectionCursor[gActiveBattler]]].target; } - if (moveTarget & MOVE_TARGET_x10) + if (moveTarget & MOVE_TARGET_USER) gMultiUsePlayerCursor = gActiveBattler; else gMultiUsePlayerCursor = GetBattlerAtPosition((GetBattlerPosition(gActiveBattler) & BIT_SIDE) ^ BIT_SIDE); if (!gBattleBufferA[gActiveBattler][1]) // not a double battle { - if (moveTarget & MOVE_TARGET_USER && !gBattleBufferA[gActiveBattler][2]) + if (moveTarget & MOVE_TARGET_USER_OR_SELECTED && !gBattleBufferA[gActiveBattler][2]) canSelectTarget++; } else // double battle { - if (!(moveTarget & (MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH | MOVE_TARGET_DEPENDS | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_x10))) + if (!(moveTarget & (MOVE_TARGET_RANDOM | MOVE_TARGET_BOTH | MOVE_TARGET_DEPENDS | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) canSelectTarget++; // either selected or user if (moveInfo->currentPp[gMoveSelectionCursor[gActiveBattler]] == 0) { canSelectTarget = FALSE; } - else if (!(moveTarget & (MOVE_TARGET_x10 | MOVE_TARGET_USER)) && CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) <= 1) + else if (!(moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) && CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) <= 1) { gMultiUsePlayerCursor = GetDefaultMoveTarget(gActiveBattler); canSelectTarget = FALSE; @@ -552,7 +542,7 @@ static void HandleInputChooseMove(void) { gBattlerControllerFuncs[gActiveBattler] = HandleInputChooseTarget; - if (moveTarget & (MOVE_TARGET_x10 | MOVE_TARGET_USER)) + if (moveTarget & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) gMultiUsePlayerCursor = gActiveBattler; else if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)]) gMultiUsePlayerCursor = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); @@ -872,7 +862,7 @@ static void HandleMoveSwitchting(void) static void sub_80586F8(void) { - if (gLinkVSyncDisabled == 0) + if (gWirelessCommType == 0) { if (gReceivedRemoteLinkPlayers == 0) { @@ -881,7 +871,7 @@ static void sub_80586F8(void) gMain.callback1 = gPreBattleCallback1; SetMainCallback2(sub_8038D64); if (gBattleOutcome == B_OUTCOME_WON) - sub_817E3F4(); + TryPutLinkBattleTvShowOnAir(); FreeAllWindowBuffers(); } } @@ -894,7 +884,7 @@ static void sub_80586F8(void) gMain.callback1 = gPreBattleCallback1; SetMainCallback2(sub_8038D64); if (gBattleOutcome == B_OUTCOME_WON) - sub_817E3F4(); + TryPutLinkBattleTvShowOnAir(); FreeAllWindowBuffers(); } } @@ -908,7 +898,7 @@ void sub_80587B0(void) { if (sub_800A520()) { - if (gLinkVSyncDisabled == 0) + if (gWirelessCommType == 0) sub_800AC34(); else sub_800ADF8(); @@ -1159,10 +1149,10 @@ static void CompleteOnInactiveTextPrinter(void) static void Task_GiveExpToMon(u8 taskId) { u32 monId = (u8)(gTasks[taskId].tExpTask_monId); - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; - if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[bank]) // give exp without the expbar + if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[battlerId]) // give exp without the expbar { struct Pokemon *mon = &gPlayerParty[monId]; u16 species = GetMonData(mon, MON_DATA_SPECIES); @@ -1178,12 +1168,12 @@ static void Task_GiveExpToMon(u8 taskId) CalculateMonStats(mon); gainedExp -= nextLvlExp - currExp; savedActiveBank = gActiveBattler; - gActiveBattler = bank; + gActiveBattler = battlerId; BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELLED_UP, gainedExp); gActiveBattler = savedActiveBank; if (IsDoubleBattle() == TRUE - && ((u16)(monId) == gBattlerPartyIndexes[bank] || (u16)(monId) == gBattlerPartyIndexes[bank ^ BIT_FLANK])) + && ((u16)(monId) == gBattlerPartyIndexes[battlerId] || (u16)(monId) == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])) gTasks[taskId].func = sub_8059544; else gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; @@ -1192,7 +1182,7 @@ static void Task_GiveExpToMon(u8 taskId) { currExp += gainedExp; SetMonData(mon, MON_DATA_EXP, &currExp); - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } } @@ -1206,7 +1196,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId) { u8 monIndex = gTasks[taskId].tExpTask_monId; s32 gainedExp = gTasks[taskId].tExpTask_gainedExp; - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; struct Pokemon *mon = &gPlayerParty[monIndex]; u8 level = GetMonData(mon, MON_DATA_LEVEL); u16 species = GetMonData(mon, MON_DATA_SPECIES); @@ -1216,7 +1206,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId) exp -= currLvlExp; expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp; - SetBattleBarStruct(bank, gHealthboxSpriteIds[bank], expToNextLvl, exp, -gainedExp); + SetBattleBarStruct(battlerId, gHealthboxSpriteIds[battlerId], expToNextLvl, exp, -gainedExp); PlaySE(SE_EXP); gTasks[taskId].func = sub_8059400; } @@ -1231,11 +1221,11 @@ static void sub_8059400(u8 taskId) { u8 monId = gTasks[taskId].tExpTask_monId; s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; s16 r4; - r4 = sub_8074AA0(bank, gHealthboxSpriteIds[bank], EXP_BAR, 0); - SetHealthboxSpriteVisible(gHealthboxSpriteIds[bank]); + r4 = sub_8074AA0(battlerId, gHealthboxSpriteIds[battlerId], EXP_BAR, 0); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[battlerId]); if (r4 == -1) { u8 level; @@ -1257,7 +1247,7 @@ static void sub_8059400(u8 taskId) CalculateMonStats(&gPlayerParty[monId]); gainedExp -= expOnNextLvl - currExp; savedActiveBank = gActiveBattler; - gActiveBattler = bank; + gActiveBattler = battlerId; BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELLED_UP, gainedExp); gActiveBattler = savedActiveBank; gTasks[taskId].func = sub_8059544; @@ -1266,7 +1256,7 @@ static void sub_8059400(u8 taskId) { currExp += gainedExp; SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp); - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } } @@ -1275,30 +1265,30 @@ static void sub_8059400(u8 taskId) static void sub_8059544(u8 taskId) { - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; u8 monIndex = gTasks[taskId].tExpTask_monId; - if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[bank ^ BIT_FLANK]) - bank ^= BIT_FLANK; + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + battlerId ^= BIT_FLANK; - InitAndLaunchSpecialAnimation(bank, bank, bank, B_ANIM_LVL_UP); + InitAndLaunchSpecialAnimation(battlerId, battlerId, battlerId, B_ANIM_LVL_UP); gTasks[taskId].func = sub_80595A4; } static void sub_80595A4(u8 taskId) { - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; - if (!gBattleSpritesDataPtr->healthBoxesData[bank].specialAnimActive) + if (!gBattleSpritesDataPtr->healthBoxesData[battlerId].specialAnimActive) { u8 monIndex = gTasks[taskId].tExpTask_monId; GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value - if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[bank ^ BIT_FLANK]) - UpdateHealthboxAttribute(gHealthboxSpriteIds[bank ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL); + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL); else - UpdateHealthboxAttribute(gHealthboxSpriteIds[bank], &gPlayerParty[monIndex], HEALTHBOX_ALL); + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], &gPlayerParty[monIndex], HEALTHBOX_ALL); gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; } @@ -1307,12 +1297,12 @@ static void sub_80595A4(u8 taskId) static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId) { u8 monIndex; - u8 bank; + u8 battlerId; monIndex = gTasks[taskId].tExpTask_monId; GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value - bank = gTasks[taskId].tExpTask_bank; - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + battlerId = gTasks[taskId].tExpTask_bank; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } @@ -2201,35 +2191,35 @@ static void PlayerHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_805902C; } -static void sub_805B258(u8 bank, bool8 dontClearSubstituteBit) +static void sub_805B258(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite( + gBattlerSpriteIds[battlerId] = CreateSprite( &gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); } static void PlayerHandleReturnMonToBall(void) @@ -2484,7 +2474,7 @@ static void PlayerHandleMoveAnimation(void) { gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; gBattlerControllerFuncs[gActiveBattler] = PlayerDoMoveAnimation; - sub_817E0FC(move, gWeatherMoveAnim, gAnimDisableStructPtr); + BattleTv_SetDataBasedOnMove(move, gWeatherMoveAnim, gAnimDisableStructPtr); } } } @@ -2548,7 +2538,7 @@ static void PlayerHandlePrintString(void) BufferStringBattle(*stringId); BattleHandleAddTextPrinter(gDisplayedStringBattle, 0); gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter2; - sub_817C95C(*stringId); + BattleTv_SetDataBasedOnString(*stringId); sub_81A57E4(gActiveBattler, *stringId); } @@ -2575,7 +2565,7 @@ static void PlayerHandleChooseAction(void) s32 i; gBattlerControllerFuncs[gActiveBattler] = HandleChooseActionAfterDma3; - sub_817F2A8(); + BattleTv_ClearExplosionFaintCause(); BattleHandleAddTextPrinter(gText_BattleMenu, 2); for (i = 0; i < 4; i++) @@ -2751,11 +2741,11 @@ static void PlayerHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } @@ -2964,13 +2954,13 @@ static void PlayerHandleIntroTrainerBallThrow(void) void sub_805CC00(struct Sprite *sprite) { - u8 bank = sprite->data[5]; + u8 battlerId = sprite->data[5]; FreeSpriteOamMatrix(sprite); FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum)); DestroySprite(sprite); - BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[bank]], bank); - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], 0); + BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerId]], battlerId); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], 0); } static void task05_08033660(u8 taskId) @@ -3069,7 +3059,7 @@ static void PlayerHandleBattleAnimation(void) else gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation; - sub_817E32C(animationId); + BattleTv_SetDataBasedOnAnimation(animationId); } } diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 159fdb2ff..f18f582f7 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -25,17 +25,15 @@ #include "battle_setup.h" #include "item_use.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const struct BattleMove gBattleMoves[]; extern void sub_81358F4(void); -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); extern u8 GetFrontierTrainerFrontSpriteId(u16 trainerId); @@ -109,7 +107,7 @@ static void sub_81BB688(u8 taskId); static void sub_81BB9A0(void); static u32 CopyPlayerPartnerMonData(u8 monId, u8 *dst); static void SetPlayerPartnerMonData(u8 monId); -static void sub_81BD0E4(u8 bank, bool8 dontClearSubstituteBit); +static void sub_81BD0E4(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void PlayerPartnerDoMoveAnimation(void); static void sub_81BE2C8(u8 taskId); @@ -326,10 +324,10 @@ static void CompleteOnInactiveTextPrinter(void) static void Task_GiveExpToMon(u8 taskId) { u32 monId = (u8)(gTasks[taskId].tExpTask_monId); - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; - if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[bank]) // give exp without the expbar + if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[battlerId]) // give exp without the expbar { struct Pokemon *mon = &gPlayerParty[monId]; u16 species = GetMonData(mon, MON_DATA_SPECIES); @@ -345,12 +343,12 @@ static void Task_GiveExpToMon(u8 taskId) CalculateMonStats(mon); gainedExp -= nextLvlExp - currExp; savedActiveBank = gActiveBattler; - gActiveBattler = bank; + gActiveBattler = battlerId; BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELLED_UP, gainedExp); gActiveBattler = savedActiveBank; if (IsDoubleBattle() == TRUE - && ((u16)(monId) == gBattlerPartyIndexes[bank] || (u16)(monId) == gBattlerPartyIndexes[bank ^ BIT_FLANK])) + && ((u16)(monId) == gBattlerPartyIndexes[battlerId] || (u16)(monId) == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])) gTasks[taskId].func = sub_81BB628; else gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; @@ -359,7 +357,7 @@ static void Task_GiveExpToMon(u8 taskId) { currExp += gainedExp; SetMonData(mon, MON_DATA_EXP, &currExp); - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } } @@ -373,7 +371,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId) { u8 monIndex = gTasks[taskId].tExpTask_monId; s32 gainedExp = gTasks[taskId].tExpTask_gainedExp; - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; struct Pokemon *mon = &gPlayerParty[monIndex]; u8 level = GetMonData(mon, MON_DATA_LEVEL); u16 species = GetMonData(mon, MON_DATA_SPECIES); @@ -383,7 +381,7 @@ static void Task_PrepareToGiveExpWithExpBar(u8 taskId) exp -= currLvlExp; expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp; - SetBattleBarStruct(bank, gHealthboxSpriteIds[bank], expToNextLvl, exp, -gainedExp); + SetBattleBarStruct(battlerId, gHealthboxSpriteIds[battlerId], expToNextLvl, exp, -gainedExp); PlaySE(SE_EXP); gTasks[taskId].func = sub_81BB4E4; } @@ -398,11 +396,11 @@ static void sub_81BB4E4(u8 taskId) { u8 monId = gTasks[taskId].tExpTask_monId; s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; s16 r4; - r4 = sub_8074AA0(bank, gHealthboxSpriteIds[bank], EXP_BAR, 0); - SetHealthboxSpriteVisible(gHealthboxSpriteIds[bank]); + r4 = sub_8074AA0(battlerId, gHealthboxSpriteIds[battlerId], EXP_BAR, 0); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[battlerId]); if (r4 == -1) { u8 level; @@ -424,7 +422,7 @@ static void sub_81BB4E4(u8 taskId) CalculateMonStats(&gPlayerParty[monId]); gainedExp -= expOnNextLvl - currExp; savedActiveBank = gActiveBattler; - gActiveBattler = bank; + gActiveBattler = battlerId; BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELLED_UP, gainedExp); gActiveBattler = savedActiveBank; gTasks[taskId].func = sub_81BB628; @@ -433,7 +431,7 @@ static void sub_81BB4E4(u8 taskId) { currExp += gainedExp; SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp); - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } } @@ -442,30 +440,30 @@ static void sub_81BB4E4(u8 taskId) static void sub_81BB628(u8 taskId) { - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; u8 monIndex = gTasks[taskId].tExpTask_monId; - if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[bank ^ BIT_FLANK]) - bank ^= BIT_FLANK; + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + battlerId ^= BIT_FLANK; - InitAndLaunchSpecialAnimation(bank, bank, bank, B_ANIM_LVL_UP); + InitAndLaunchSpecialAnimation(battlerId, battlerId, battlerId, B_ANIM_LVL_UP); gTasks[taskId].func = sub_81BB688; } static void sub_81BB688(u8 taskId) { - u8 bank = gTasks[taskId].tExpTask_bank; + u8 battlerId = gTasks[taskId].tExpTask_bank; - if (!gBattleSpritesDataPtr->healthBoxesData[bank].specialAnimActive) + if (!gBattleSpritesDataPtr->healthBoxesData[battlerId].specialAnimActive) { u8 monIndex = gTasks[taskId].tExpTask_monId; GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value - if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[bank ^ BIT_FLANK]) - UpdateHealthboxAttribute(gHealthboxSpriteIds[bank ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL); + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL); else - UpdateHealthboxAttribute(gHealthboxSpriteIds[bank], &gPlayerParty[monIndex], HEALTHBOX_ALL); + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], &gPlayerParty[monIndex], HEALTHBOX_ALL); gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; } @@ -474,12 +472,12 @@ static void sub_81BB688(u8 taskId) static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId) { u8 monIndex; - u8 bank; + u8 battlerId; monIndex = gTasks[taskId].tExpTask_monId; GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value - bank = gTasks[taskId].tExpTask_bank; - gBattlerControllerFuncs[bank] = CompleteOnInactiveTextPrinter; + battlerId = gTasks[taskId].tExpTask_bank; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter; DestroyTask(taskId); } @@ -1234,35 +1232,35 @@ static void PlayerPartnerHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_81BBAE8; } -static void sub_81BD0E4(u8 bank, bool8 dontClearSubstituteBit) +static void sub_81BD0E4(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite( + gBattlerSpriteIds[battlerId] = CreateSprite( &gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); } static void PlayerPartnerHandleReturnMonToBall(void) @@ -1522,7 +1520,7 @@ static void PlayerPartnerHandleChooseMove(void) BattleAI_SetupAIData(0xF); chosenMoveId = BattleAI_ChooseMoveOrAction(); - if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_x10 | MOVE_TARGET_USER)) + if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & (MOVE_TARGET_USER | MOVE_TARGET_USER_OR_SELECTED)) gBattlerTarget = gActiveBattler; if (gBattleMoves[moveInfo->moves[chosenMoveId]].target & MOVE_TARGET_BOTH) { @@ -1627,11 +1625,11 @@ static void PlayerPartnerHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 855dfc554..4d1ccbaca 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -6,7 +6,7 @@ #include "battle_anim.h" #include "constants/battle_anim.h" #include "battle_ai_script_commands.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "recorded_battle.h" #include "pokemon.h" #include "link.h" @@ -27,7 +27,6 @@ #include "item_use.h" #include "battle_setup.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern struct MusicPlayerInfo gMPlayInfo_BGM; @@ -36,7 +35,7 @@ extern u8 gUnknown_0203C7B4; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); extern u16 sub_8068B48(void); extern u8 GetFrontierTrainerFrontSpriteId(u16 trainerId); @@ -105,7 +104,7 @@ static void RecordedOpponentBufferExecCompleted(void); static void sub_8186F14(void); static u32 CopyRecordedOpponentMonData(u8 monId, u8 *dst); static void SetRecordedOpponentMonData(u8 monId); -static void sub_81885D8(u8 bank, bool8 dontClearSubstituteBit); +static void sub_81885D8(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void RecordedOpponentDoMoveAnimation(void); static void sub_8189548(u8 taskId); @@ -1145,35 +1144,35 @@ static void RecordedOpponentHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_8187084; } -static void sub_81885D8(u8 bank, bool8 dontClearSubstituteBit) +static void sub_81885D8(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[bank]], bank); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite(&gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + gBattlerSpriteIds[battlerId] = CreateSprite(&gUnknown_0202499C, + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_OPPONENT_SENDOUT); } static void RecordedOpponentHandleReturnMonToBall(void) @@ -1491,11 +1490,11 @@ static void RecordedOpponentHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 4efe5babf..b16c3f307 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -25,7 +25,6 @@ #include "data2.h" #include "item_use.h" -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern u32 gTransformedPersonalities[MAX_BATTLERS_COUNT]; @@ -35,9 +34,8 @@ extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const struct BattleMove gBattleMoves[]; -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); extern u8 GetFrontierTrainerFrontSpriteId(u16 trainerId); @@ -105,7 +103,7 @@ static void RecordedPlayerBufferExecCompleted(void); static void sub_818A328(void); static u32 CopyRecordedPlayerMonData(u8 monId, u8 *dst); static void SetRecordedPlayerMonData(u8 monId); -static void sub_818BA6C(u8 bank, bool8 dontClearSubstituteBit); +static void sub_818BA6C(u8 battlerId, bool8 dontClearSubstituteBit); static void DoSwitchOutAnimation(void); static void RecordedPlayerDoMoveAnimation(void); static void sub_818CC24(u8 taskId); @@ -1131,35 +1129,35 @@ static void RecordedPlayerHandleSwitchInAnim(void) gBattlerControllerFuncs[gActiveBattler] = sub_818A470; } -static void sub_818BA6C(u8 bank, bool8 dontClearSubstituteBit) +static void sub_818BA6C(u8 battlerId, bool8 dontClearSubstituteBit) { u16 species; - ClearTemporarySpeciesSpriteData(bank, dontClearSubstituteBit); - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - sub_806A068(species, GetBattlerPosition(bank)); + ClearTemporarySpeciesSpriteData(battlerId, dontClearSubstituteBit); + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + sub_806A068(species, GetBattlerPosition(battlerId)); - gBattlerSpriteIds[bank] = CreateSprite( + gBattlerSpriteIds[battlerId] = CreateSprite( &gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); } static void RecordedPlayerHandleReturnMonToBall(void) @@ -1514,11 +1512,11 @@ static void RecordedPlayerHandleStatusIconUpdate(void) { if (!mplay_80342A4(gActiveBattler)) { - u8 bank; + u8 battlerId; UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); - bank = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[bank].statusAnimActive = 0; + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index f65d11a84..09776f150 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -23,16 +23,11 @@ #include "pokeblock.h" #include "item_use.h" -extern struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT]; -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const u8 gText_SafariZoneMenu[]; -extern const u8 gText_WhatWillPkmnDo2[]; - extern void sub_81358F4(void); // this file's functions diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index ad028b719..ca7b2fd44 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -5,7 +5,7 @@ #include "battle_interface.h" #include "battle_anim.h" #include "constants/battle_anim.h" -#include "battle_link_817C95C.h" +#include "battle_tv.h" #include "pokemon.h" #include "link.h" #include "util.h" @@ -30,8 +30,6 @@ #include "battle_setup.h" #include "item_use.h" -extern struct MusicPlayerInfo gMPlayInfo_BGM; -extern struct SpriteTemplate gUnknown_0202499C; extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; extern s32 gUnknown_0203CD70; @@ -39,10 +37,7 @@ extern struct UnusedControllerStruct gUnknown_02022D0C; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; -extern const u8 gText_WhatWillWallyDo[]; -extern const u8 gText_BattleMenu[]; - -extern void sub_8172EF0(u8 bank, struct Pokemon *mon); +extern void sub_8172EF0(u8 battlerId, struct Pokemon *mon); extern void sub_806A068(u16, u8); // this file's functions @@ -1462,31 +1457,31 @@ static void WallyHandleIntroTrainerBallThrow(void) gBattlerControllerFuncs[gActiveBattler] = nullsub_21; } -static void sub_816AA80(u8 bank) +static void sub_816AA80(u8 battlerId) { u16 species; - gBattleSpritesDataPtr->battlerData[bank].transformSpecies = 0; - gBattlerPartyIndexes[bank] = gBattleBufferA[bank][1]; - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES); - gUnknown_03005D7C[bank] = CreateInvisibleSpriteWithCallback(sub_805D714); - sub_806A068(species, GetBattlerPosition(bank)); - gBattlerSpriteIds[bank] = CreateSprite(&gUnknown_0202499C, - GetBattlerSpriteCoord(bank, 2), - GetBattlerSpriteDefault_Y(bank), - sub_80A82E4(bank)); - - gSprites[gUnknown_03005D7C[bank]].data[1] = gBattlerSpriteIds[bank]; - gSprites[gUnknown_03005D7C[bank]].data[2] = bank; - - gSprites[gBattlerSpriteIds[bank]].data[0] = bank; - gSprites[gBattlerSpriteIds[bank]].data[2] = species; - gSprites[gBattlerSpriteIds[bank]].oam.paletteNum = bank; - - StartSpriteAnim(&gSprites[gBattlerSpriteIds[bank]], gBattleMonForms[bank]); - gSprites[gBattlerSpriteIds[bank]].invisible = TRUE; - gSprites[gBattlerSpriteIds[bank]].callback = SpriteCallbackDummy; - gSprites[gUnknown_03005D7C[bank]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); + gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies = 0; + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_03005D7C[battlerId] = CreateInvisibleSpriteWithCallback(sub_805D714); + sub_806A068(species, GetBattlerPosition(battlerId)); + gBattlerSpriteIds[battlerId] = CreateSprite(&gUnknown_0202499C, + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + sub_80A82E4(battlerId)); + + gSprites[gUnknown_03005D7C[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gUnknown_03005D7C[battlerId]].data[2] = battlerId; + + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; + + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; + gSprites[gUnknown_03005D7C[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); } static void sub_816AC04(u8 taskId) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index cbb4fff69..2b918d018 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -12,18 +12,14 @@ #include "constants/abilities.h" #include "battle_message.h" -extern u8 gBattleBuffersTransferData[0x100]; -extern u8 gUnknown_0202428C; -extern u32 gUnknown_02022FF4; -extern u8 gUnknown_0203C7B4; extern u8 gUnknown_02022D08; extern u8 gUnknown_02022D09; extern u8 gUnknown_02022D0A; -extern const struct BattleMove gBattleMoves[]; +static EWRAM_DATA u8 sBattleBuffersTransferData[0x100] = {}; extern void task00_08081A90(u8 taskId); // cable_club -extern void sub_81B8D64(u8 bank, u8 arg1); // party_menu +extern void sub_81B8D64(u8 battlerId, u8 arg1); // party_menu // this file's funcionts static void CreateTasksForSendRecvLinkBuffers(void); @@ -37,7 +33,7 @@ void HandleLinkBattleSetup(void) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800B488(); if (!gReceivedRemoteLinkPlayers) OpenLink(); @@ -81,7 +77,6 @@ void SetUpBattleVarsAndBirchZigzagoon(void) void sub_8032768(void) { s32 i; - u8 *data; if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED)) sub_8184DA4(1); @@ -104,11 +99,11 @@ void sub_8032768(void) sub_81B8D64(i, 0); } - for (i = 0; i < sizeof(gBattleStruct->field_1A4); i++) - *(gBattleStruct->field_1A4 + i) = 0; + for (i = 0; i < sizeof(gBattleStruct->tvMovePoints); i++) + *((u8*)(&gBattleStruct->tvMovePoints) + i) = 0; - for (i = 0; i < sizeof(gBattleStruct->field_204); i++) - *(gBattleStruct->field_204 + i) = 0; + for (i = 0; i < sizeof(gBattleStruct->tv); i++) + *((u8*)(&gBattleStruct->tv) + i) = 0; } static void InitSinglePlayerBtlControllers(void) @@ -758,7 +753,7 @@ static void Task_HandleSendLinkBuffersData(u8 taskId) gTasks[taskId].data[11]++; break; case 2: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { gTasks[taskId].data[11]++; } @@ -871,7 +866,7 @@ void sub_8033648(void) static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) { u16 blockSize; - u8 bank; + u8 battlerId; u8 var; if (gTasks[taskId].data[15] != gTasks[taskId].data[14]) @@ -882,17 +877,17 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) gTasks[taskId].data[12] = 0; gTasks[taskId].data[15] = 0; } - bank = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BANK]; + battlerId = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_ACTIVE_BANK]; blockSize = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_LO] | (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_SIZE_HI] << 8); switch (gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 0]) { case 0: - if (gBattleControllerExecFlags & gBitTable[bank]) + if (gBattleControllerExecFlags & gBitTable[battlerId]) return; - memcpy(gBattleBufferA[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); - sub_803F850(bank); + memcpy(gBattleBufferA[battlerId], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); + sub_803F850(battlerId); if (!(gBattleTypeFlags & BATTLE_TYPE_WILD)) { @@ -903,11 +898,11 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) } break; case 1: - memcpy(gBattleBufferB[bank], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); + memcpy(gBattleBufferB[battlerId], &gLinkBattleRecvBuffer[gTasks[taskId].data[15] + 8], blockSize); break; case 2: var = gLinkBattleRecvBuffer[gTasks[taskId].data[15] + LINK_BUFF_DATA]; - gBattleControllerExecFlags &= ~(gBitTable[bank] << (var * 4)); + gBattleControllerExecFlags &= ~(gBitTable[battlerId] << (var * 4)); break; } @@ -917,171 +912,171 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) void BtlController_EmitGetMonData(u8 bufferId, u8 requestId, u8 monToCheck) { - gBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA; - gBattleBuffersTransferData[1] = requestId; - gBattleBuffersTransferData[2] = monToCheck; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_GETMONDATA; + sBattleBuffersTransferData[1] = requestId; + sBattleBuffersTransferData[2] = monToCheck; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitGetRawMonData(u8 bufferId, u8 monId, u8 bytes) { - gBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA; - gBattleBuffersTransferData[1] = monId; - gBattleBuffersTransferData[2] = bytes; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_GETRAWMONDATA; + sBattleBuffersTransferData[1] = monId; + sBattleBuffersTransferData[2] = bytes; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitSetMonData(u8 bufferId, u8 requestId, u8 monToCheck, u8 bytes, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA; - gBattleBuffersTransferData[1] = requestId; - gBattleBuffersTransferData[2] = monToCheck; + sBattleBuffersTransferData[0] = CONTROLLER_SETMONDATA; + sBattleBuffersTransferData[1] = requestId; + sBattleBuffersTransferData[2] = monToCheck; for (i = 0; i < bytes; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 3 + bytes); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 3 + bytes); } void BtlController_EmitSetRawMonData(u8 bufferId, u8 monId, u8 bytes, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA; - gBattleBuffersTransferData[1] = monId; - gBattleBuffersTransferData[2] = bytes; + sBattleBuffersTransferData[0] = CONTROLLER_SETRAWMONDATA; + sBattleBuffersTransferData[1] = monId; + sBattleBuffersTransferData[2] = bytes; for (i = 0; i < bytes; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, bytes + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, bytes + 3); } void BtlController_EmitLoadMonSprite(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE; - gBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[1] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[2] = CONTROLLER_LOADMONSPRITE; + sBattleBuffersTransferData[3] = CONTROLLER_LOADMONSPRITE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitSwitchInAnim(u8 bufferId, u8 partyId, bool8 dontClearSubstituteBit) { - gBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM; - gBattleBuffersTransferData[1] = partyId; - gBattleBuffersTransferData[2] = dontClearSubstituteBit; - gBattleBuffersTransferData[3] = 5; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SWITCHINANIM; + sBattleBuffersTransferData[1] = partyId; + sBattleBuffersTransferData[2] = dontClearSubstituteBit; + sBattleBuffersTransferData[3] = 5; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitReturnMonToBall(u8 bufferId, u8 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL; - gBattleBuffersTransferData[1] = arg1; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_RETURNMONTOBALL; + sBattleBuffersTransferData[1] = arg1; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitDrawTrainerPic(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC; - gBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[1] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[2] = CONTROLLER_DRAWTRAINERPIC; + sBattleBuffersTransferData[3] = CONTROLLER_DRAWTRAINERPIC; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitTrainerSlide(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE; - gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDE; + sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitTrainerSlideBack(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK; - gBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[1] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[2] = CONTROLLER_TRAINERSLIDEBACK; + sBattleBuffersTransferData[3] = CONTROLLER_TRAINERSLIDEBACK; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitFaintAnimation(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION; - gBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[1] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[2] = CONTROLLER_FAINTANIMATION; + sBattleBuffersTransferData[3] = CONTROLLER_FAINTANIMATION; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitPaletteFade(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE; - gBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[1] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[2] = CONTROLLER_PALETTEFADE; + sBattleBuffersTransferData[3] = CONTROLLER_PALETTEFADE; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitSuccessBallThrowAnim(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM; - gBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[1] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[2] = CONTROLLER_SUCCESSBALLTHROWANIM; + sBattleBuffersTransferData[3] = CONTROLLER_SUCCESSBALLTHROWANIM; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitBallThrowAnim(u8 bufferId, u8 caseId) { - gBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM; - gBattleBuffersTransferData[1] = caseId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_BALLTHROWANIM; + sBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitPause(u8 bufferId, u8 toWait, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_PAUSE; - gBattleBuffersTransferData[1] = toWait; + sBattleBuffersTransferData[0] = CONTROLLER_PAUSE; + sBattleBuffersTransferData[1] = toWait; for (i = 0; i < toWait * 3; i++) - gBattleBuffersTransferData[2 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, toWait * 3 + 2); + sBattleBuffersTransferData[2 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, toWait * 3 + 2); } void BtlController_EmitMoveAnimation(u8 bufferId, u16 move, u8 turnOfMove, u16 movePower, s32 dmg, u8 friendship, struct DisableStruct *disableStructPtr, u8 multihit) { - gBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION; - gBattleBuffersTransferData[1] = move; - gBattleBuffersTransferData[2] = (move & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = turnOfMove; - gBattleBuffersTransferData[4] = movePower; - gBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8; - gBattleBuffersTransferData[6] = dmg; - gBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8; - gBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16; - gBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24; - gBattleBuffersTransferData[10] = friendship; - gBattleBuffersTransferData[11] = multihit; + sBattleBuffersTransferData[0] = CONTROLLER_MOVEANIMATION; + sBattleBuffersTransferData[1] = move; + sBattleBuffersTransferData[2] = (move & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = turnOfMove; + sBattleBuffersTransferData[4] = movePower; + sBattleBuffersTransferData[5] = (movePower & 0xFF00) >> 8; + sBattleBuffersTransferData[6] = dmg; + sBattleBuffersTransferData[7] = (dmg & 0x0000FF00) >> 8; + sBattleBuffersTransferData[8] = (dmg & 0x00FF0000) >> 16; + sBattleBuffersTransferData[9] = (dmg & 0xFF000000) >> 24; + sBattleBuffersTransferData[10] = friendship; + sBattleBuffersTransferData[11] = multihit; if (WEATHER_HAS_EFFECT2) { - gBattleBuffersTransferData[12] = gBattleWeather; - gBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8; + sBattleBuffersTransferData[12] = gBattleWeather; + sBattleBuffersTransferData[13] = (gBattleWeather & 0xFF00) >> 8; } else { - gBattleBuffersTransferData[12] = 0; - gBattleBuffersTransferData[13] = 0; + sBattleBuffersTransferData[12] = 0; + sBattleBuffersTransferData[13] = 0; } - gBattleBuffersTransferData[14] = 0; - gBattleBuffersTransferData[15] = 0; - memcpy(&gBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 16 + sizeof(struct DisableStruct)); + sBattleBuffersTransferData[14] = 0; + sBattleBuffersTransferData[15] = 0; + memcpy(&sBattleBuffersTransferData[16], disableStructPtr, sizeof(struct DisableStruct)); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 16 + sizeof(struct DisableStruct)); } void BtlController_EmitPrintString(u8 bufferId, u16 stringID) @@ -1089,12 +1084,12 @@ void BtlController_EmitPrintString(u8 bufferId, u16 stringID) s32 i; struct StringInfoBattle* stringInfo; - gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING; - gBattleBuffersTransferData[1] = gBattleOutcome; - gBattleBuffersTransferData[2] = stringID; - gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRING; + sBattleBuffersTransferData[1] = gBattleOutcome; + sBattleBuffersTransferData[2] = stringID; + sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; - stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]); stringInfo->currentMove = gCurrentMove; stringInfo->originallyUsedMove = gChosenMove; stringInfo->lastItem = gLastUsedItem; @@ -1113,7 +1108,7 @@ void BtlController_EmitPrintString(u8 bufferId, u16 stringID) stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; } - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); } void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID) @@ -1121,12 +1116,12 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID) s32 i; struct StringInfoBattle *stringInfo; - gBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY; - gBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY; - gBattleBuffersTransferData[2] = stringID; - gBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_PRINTSTRINGPLAYERONLY; + sBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY; + sBattleBuffersTransferData[2] = stringID; + sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8; - stringInfo = (struct StringInfoBattle*)(&gBattleBuffersTransferData[4]); + stringInfo = (struct StringInfoBattle*)(&sBattleBuffersTransferData[4]); stringInfo->currentMove = gCurrentMove; stringInfo->originallyUsedMove = gChosenMove; stringInfo->lastItem = gLastUsedItem; @@ -1142,386 +1137,386 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID) stringInfo->textBuffs[1][i] = gBattleTextBuff2[i]; stringInfo->textBuffs[2][i] = gBattleTextBuff3[i]; } - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct StringInfoBattle) + 4); } void BtlController_EmitChooseAction(u8 bufferId, u8 arg1, u16 arg2) { - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEACTION; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitUnknownYesNoBox(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX; - gBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[1] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[2] = CONTROLLER_UNKNOWNYESNOBOX; + sBattleBuffersTransferData[3] = CONTROLLER_UNKNOWNYESNOBOX; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitChooseMove(u8 bufferId, bool8 isDoubleBattle, bool8 NoPpNumber, struct ChooseMoveStruct *movePpData) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE; - gBattleBuffersTransferData[1] = isDoubleBattle; - gBattleBuffersTransferData[2] = NoPpNumber; - gBattleBuffersTransferData[3] = 0; + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEMOVE; + sBattleBuffersTransferData[1] = isDoubleBattle; + sBattleBuffersTransferData[2] = NoPpNumber; + sBattleBuffersTransferData[3] = 0; for (i = 0; i < sizeof(*movePpData); i++) - gBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(*movePpData) + 4); + sBattleBuffersTransferData[4 + i] = *((u8*)(movePpData) + i); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(*movePpData) + 4); } void BtlController_EmitChooseItem(u8 bufferId, u8 *arg1) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_OPENBAG; + sBattleBuffersTransferData[0] = CONTROLLER_OPENBAG; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[1 + i] = arg1[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[1 + i] = arg1[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitChoosePokemon(u8 bufferId, u8 caseId, u8 arg2, u8 abilityId, u8* arg4) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON; - gBattleBuffersTransferData[1] = caseId; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = abilityId; + sBattleBuffersTransferData[0] = CONTROLLER_CHOOSEPOKEMON; + sBattleBuffersTransferData[1] = caseId; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = abilityId; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[4 + i] = arg4[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 8); // but only 7 bytes were written + sBattleBuffersTransferData[4 + i] = arg4[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 8); // but only 7 bytes were written } void BtlController_EmitCmd23(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_23; - gBattleBuffersTransferData[1] = CONTROLLER_23; - gBattleBuffersTransferData[2] = CONTROLLER_23; - gBattleBuffersTransferData[3] = CONTROLLER_23; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_23; + sBattleBuffersTransferData[1] = CONTROLLER_23; + sBattleBuffersTransferData[2] = CONTROLLER_23; + sBattleBuffersTransferData[3] = CONTROLLER_23; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } // why is the argument u16 if it's being cast to s16 anyway? void BtlController_EmitHealthBarUpdate(u8 bufferId, u16 hpValue) { - gBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE; - gBattleBuffersTransferData[1] = 0; - gBattleBuffersTransferData[2] = (s16)hpValue; - gBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_HEALTHBARUPDATE; + sBattleBuffersTransferData[1] = 0; + sBattleBuffersTransferData[2] = (s16)hpValue; + sBattleBuffersTransferData[3] = ((s16)hpValue & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } // why is the argument u16 if it's being cast to s16 anyway? void BtlController_EmitExpUpdate(u8 bufferId, u8 partyId, u16 expPoints) { - gBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE; - gBattleBuffersTransferData[1] = partyId; - gBattleBuffersTransferData[2] = (s16)expPoints; - gBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_EXPUPDATE; + sBattleBuffersTransferData[1] = partyId; + sBattleBuffersTransferData[2] = (s16)expPoints; + sBattleBuffersTransferData[3] = ((s16)expPoints & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitStatusIconUpdate(u8 bufferId, u32 status1, u32 status2) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE; - gBattleBuffersTransferData[1] = status1; - gBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8; - gBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16; - gBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24; - gBattleBuffersTransferData[5] = status2; - gBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8; - gBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16; - gBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 9); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSICONUPDATE; + sBattleBuffersTransferData[1] = status1; + sBattleBuffersTransferData[2] = (status1 & 0x0000FF00) >> 8; + sBattleBuffersTransferData[3] = (status1 & 0x00FF0000) >> 16; + sBattleBuffersTransferData[4] = (status1 & 0xFF000000) >> 24; + sBattleBuffersTransferData[5] = status2; + sBattleBuffersTransferData[6] = (status2 & 0x0000FF00) >> 8; + sBattleBuffersTransferData[7] = (status2 & 0x00FF0000) >> 16; + sBattleBuffersTransferData[8] = (status2 & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 9); } void BtlController_EmitStatusAnimation(u8 bufferId, bool8 status2, u32 status) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION; - gBattleBuffersTransferData[1] = status2; - gBattleBuffersTransferData[2] = status; - gBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8; - gBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16; - gBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 6); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSANIMATION; + sBattleBuffersTransferData[1] = status2; + sBattleBuffersTransferData[2] = status; + sBattleBuffersTransferData[3] = (status & 0x0000FF00) >> 8; + sBattleBuffersTransferData[4] = (status & 0x00FF0000) >> 16; + sBattleBuffersTransferData[5] = (status & 0xFF000000) >> 24; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 6); } void BtlController_EmitStatusXor(u8 bufferId, u8 b) { - gBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR; - gBattleBuffersTransferData[1] = b; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_STATUSXOR; + sBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitDataTransfer(u8 bufferId, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER; - gBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER; - gBattleBuffersTransferData[2] = size; - gBattleBuffersTransferData[3] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_DATATRANSFER; + sBattleBuffersTransferData[1] = CONTROLLER_DATATRANSFER; + sBattleBuffersTransferData[2] = size; + sBattleBuffersTransferData[3] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[4 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 4); + sBattleBuffersTransferData[4 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 4); } void BtlController_EmitDMA3Transfer(u8 bufferId, void *dst, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER; - gBattleBuffersTransferData[1] = (u32)(dst); - gBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8; - gBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16; - gBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24; - gBattleBuffersTransferData[5] = size; - gBattleBuffersTransferData[6] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_DMA3TRANSFER; + sBattleBuffersTransferData[1] = (u32)(dst); + sBattleBuffersTransferData[2] = ((u32)(dst) & 0x0000FF00) >> 8; + sBattleBuffersTransferData[3] = ((u32)(dst) & 0x00FF0000) >> 16; + sBattleBuffersTransferData[4] = ((u32)(dst) & 0xFF000000) >> 24; + sBattleBuffersTransferData[5] = size; + sBattleBuffersTransferData[6] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[7 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 7); + sBattleBuffersTransferData[7 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 7); } void BtlController_EmitPlayBGM(u8 bufferId, u16 songId, void *unusedDumbDataParameter) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_31; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_31; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; for (i = 0; i < songId; i++) // ???? - gBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, songId + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(unusedDumbDataParameter++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, songId + 3); } void BtlController_EmitCmd32(u8 bufferId, u16 size, void *data) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_32; - gBattleBuffersTransferData[1] = size; - gBattleBuffersTransferData[2] = (size & 0xFF00) >> 8; + sBattleBuffersTransferData[0] = CONTROLLER_32; + sBattleBuffersTransferData[1] = size; + sBattleBuffersTransferData[2] = (size & 0xFF00) >> 8; for (i = 0; i < size; i++) - gBattleBuffersTransferData[3 + i] = *(u8*)(data++); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, size + 3); + sBattleBuffersTransferData[3 + i] = *(u8*)(data++); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, size + 3); } void BtlController_EmitTwoReturnValues(u8 bufferId, u8 arg1, u16 arg2) { - gBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = arg2; - gBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_TWORETURNVALUES; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = arg2; + sBattleBuffersTransferData[3] = (arg2 & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitChosenMonReturnValue(u8 bufferId, u8 b, u8 *c) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE; - gBattleBuffersTransferData[1] = b; + sBattleBuffersTransferData[0] = CONTROLLER_CHOSENMONRETURNVALUE; + sBattleBuffersTransferData[1] = b; for (i = 0; i < 3; i++) - gBattleBuffersTransferData[2 + i] = c[i]; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 5); + sBattleBuffersTransferData[2 + i] = c[i]; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 5); } void BtlController_EmitOneReturnValue(u8 bufferId, u16 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = (arg1 & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitOneReturnValue_Duplicate(u8 bufferId, u16 b) { - gBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE; - gBattleBuffersTransferData[1] = b; - gBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_ONERETURNVALUE_DUPLICATE; + sBattleBuffersTransferData[1] = b; + sBattleBuffersTransferData[2] = (b & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitCmd37(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_37; - gBattleBuffersTransferData[1] = CONTROLLER_37; - gBattleBuffersTransferData[2] = CONTROLLER_37; - gBattleBuffersTransferData[3] = CONTROLLER_37; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_37; + sBattleBuffersTransferData[1] = CONTROLLER_37; + sBattleBuffersTransferData[2] = CONTROLLER_37; + sBattleBuffersTransferData[3] = CONTROLLER_37; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitCmd38(u8 bufferId, u8 b) { - gBattleBuffersTransferData[0] = CONTROLLER_38; - gBattleBuffersTransferData[1] = b; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_38; + sBattleBuffersTransferData[1] = b; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitCmd39(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_39; - gBattleBuffersTransferData[1] = CONTROLLER_39; - gBattleBuffersTransferData[2] = CONTROLLER_39; - gBattleBuffersTransferData[3] = CONTROLLER_39; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_39; + sBattleBuffersTransferData[1] = CONTROLLER_39; + sBattleBuffersTransferData[2] = CONTROLLER_39; + sBattleBuffersTransferData[3] = CONTROLLER_39; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitCmd40(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_40; - gBattleBuffersTransferData[1] = CONTROLLER_40; - gBattleBuffersTransferData[2] = CONTROLLER_40; - gBattleBuffersTransferData[3] = CONTROLLER_40; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_40; + sBattleBuffersTransferData[1] = CONTROLLER_40; + sBattleBuffersTransferData[2] = CONTROLLER_40; + sBattleBuffersTransferData[3] = CONTROLLER_40; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitHitAnimation(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION; - gBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[1] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[2] = CONTROLLER_HITANIMATION; + sBattleBuffersTransferData[3] = CONTROLLER_HITANIMATION; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitCmd42(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_42; - gBattleBuffersTransferData[1] = CONTROLLER_42; - gBattleBuffersTransferData[2] = CONTROLLER_42; - gBattleBuffersTransferData[3] = CONTROLLER_42; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_42; + sBattleBuffersTransferData[1] = CONTROLLER_42; + sBattleBuffersTransferData[2] = CONTROLLER_42; + sBattleBuffersTransferData[3] = CONTROLLER_42; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitPlaySE(u8 bufferId, u16 songId) { - gBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_EFFECTIVENESSSOUND; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = 0; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitPlayFanfareOrBGM(u8 bufferId, u16 songId, bool8 playBGM) { - gBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM; - gBattleBuffersTransferData[1] = songId; - gBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; - gBattleBuffersTransferData[3] = playBGM; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_PLAYFANFAREORBGM; + sBattleBuffersTransferData[1] = songId; + sBattleBuffersTransferData[2] = (songId & 0xFF00) >> 8; + sBattleBuffersTransferData[3] = playBGM; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitFaintingCry(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY; - gBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[1] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[2] = CONTROLLER_FAINTINGCRY; + sBattleBuffersTransferData[3] = CONTROLLER_FAINTINGCRY; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitIntroSlide(u8 bufferId, u8 terrainId) { - gBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE; - gBattleBuffersTransferData[1] = terrainId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_INTROSLIDE; + sBattleBuffersTransferData[1] = terrainId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitIntroTrainerBallThrow(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW; - gBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[1] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[2] = CONTROLLER_INTROTRAINERBALLTHROW; + sBattleBuffersTransferData[3] = CONTROLLER_INTROTRAINERBALLTHROW; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitDrawPartyStatusSummary(u8 bufferId, struct HpAndStatus* hpAndStatus, u8 arg2) { s32 i; - gBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; - gBattleBuffersTransferData[1] = arg2 & 0x7F; - gBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7; - gBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; + sBattleBuffersTransferData[0] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; + sBattleBuffersTransferData[1] = arg2 & 0x7F; + sBattleBuffersTransferData[2] = (arg2 & 0x80) >> 7; + sBattleBuffersTransferData[3] = CONTROLLER_DRAWPARTYSTATUSSUMMARY; for (i = 0; i < (s32)(sizeof(struct HpAndStatus) * 6); i++) - gBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus)); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4); + sBattleBuffersTransferData[4 + i] = *(i + (u8*)(hpAndStatus)); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sizeof(struct HpAndStatus) * 6 + 4); } void BtlController_EmitCmd49(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_49; - gBattleBuffersTransferData[1] = CONTROLLER_49; - gBattleBuffersTransferData[2] = CONTROLLER_49; - gBattleBuffersTransferData[3] = CONTROLLER_49; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_49; + sBattleBuffersTransferData[1] = CONTROLLER_49; + sBattleBuffersTransferData[2] = CONTROLLER_49; + sBattleBuffersTransferData[3] = CONTROLLER_49; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitCmd50(u8 bufferId) { - gBattleBuffersTransferData[0] = CONTROLLER_50; - gBattleBuffersTransferData[1] = CONTROLLER_50; - gBattleBuffersTransferData[2] = CONTROLLER_50; - gBattleBuffersTransferData[3] = CONTROLLER_50; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_50; + sBattleBuffersTransferData[1] = CONTROLLER_50; + sBattleBuffersTransferData[2] = CONTROLLER_50; + sBattleBuffersTransferData[3] = CONTROLLER_50; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitSpriteInvisibility(u8 bufferId, bool8 isInvisible) { - gBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY; - gBattleBuffersTransferData[1] = isInvisible; - gBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY; - gBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_SPRITEINVISIBILITY; + sBattleBuffersTransferData[1] = isInvisible; + sBattleBuffersTransferData[2] = CONTROLLER_SPRITEINVISIBILITY; + sBattleBuffersTransferData[3] = CONTROLLER_SPRITEINVISIBILITY; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitBattleAnimation(u8 bufferId, u8 animationId, u16 argument) { - gBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION; - gBattleBuffersTransferData[1] = animationId; - gBattleBuffersTransferData[2] = argument; - gBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 4); + sBattleBuffersTransferData[0] = CONTROLLER_BATTLEANIMATION; + sBattleBuffersTransferData[1] = animationId; + sBattleBuffersTransferData[2] = argument; + sBattleBuffersTransferData[3] = (argument & 0xFF00) >> 8; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 4); } void BtlController_EmitLinkStandbyMsg(u8 bufferId, u8 arg1, bool32 arg2) { bool8 arg2_ = arg2; - gBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG; - gBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[0] = CONTROLLER_LINKSTANDBYMSG; + sBattleBuffersTransferData[1] = arg1; if (arg2_) - gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = sub_81850DC(&gBattleBuffersTransferData[4]); + sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = sub_81850DC(&sBattleBuffersTransferData[4]); else - gBattleBuffersTransferData[3] = gBattleBuffersTransferData[2] = 0; + sBattleBuffersTransferData[3] = sBattleBuffersTransferData[2] = 0; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[2] + 4); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[2] + 4); } void BtlController_EmitResetActionMoveSelection(u8 bufferId, u8 caseId) { - gBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION; - gBattleBuffersTransferData[1] = caseId; - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, 2); + sBattleBuffersTransferData[0] = CONTROLLER_RESETACTIONMOVESELECTION; + sBattleBuffersTransferData[1] = caseId; + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, 2); } void BtlController_EmitCmd55(u8 bufferId, u8 arg1) { - gBattleBuffersTransferData[0] = CONTROLLER_55; - gBattleBuffersTransferData[1] = arg1; - gBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b; - gBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b; - gBattleBuffersTransferData[5] = gBattleBuffersTransferData[4] = sub_81850DC(&gBattleBuffersTransferData[6]); - PrepareBufferDataTransfer(bufferId, gBattleBuffersTransferData, gBattleBuffersTransferData[4] + 6); + sBattleBuffersTransferData[0] = CONTROLLER_55; + sBattleBuffersTransferData[1] = arg1; + sBattleBuffersTransferData[2] = gSaveBlock2Ptr->field_CA9_b; + sBattleBuffersTransferData[3] = gSaveBlock2Ptr->field_CA9_b; + sBattleBuffersTransferData[5] = sBattleBuffersTransferData[4] = sub_81850DC(&sBattleBuffersTransferData[6]); + PrepareBufferDataTransfer(bufferId, sBattleBuffersTransferData, sBattleBuffersTransferData[4] + 6); } diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 803b3eeab..d2c242553 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -28,7 +28,6 @@ extern struct MusicPlayerInfo gMPlayInfo_SE1; extern struct MusicPlayerInfo gMPlayInfo_SE2; extern struct MusicPlayerInfo gMPlayInfo_BGM; -extern const struct BattleMove gBattleMoves[]; extern const u8 gUnknown_0831C604[]; extern const u8 * const gBattleAnims_VariousTable[]; extern const u8 * const gBattleAnims_Special[]; @@ -39,7 +38,6 @@ extern const struct CompressedSpriteSheet gTrainerBackPicTable[]; extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[]; extern const struct CompressedSpritePalette gTrainerBackPicPaletteTable[]; extern const union AnimCmd* const * const gMonAnimationsSpriteAnimsPtrTable[]; -extern const struct SpriteTemplate gUnknown_08329D98[4]; extern const struct CompressedSpriteSheet gSpriteSheet_EnemyShadow; extern const struct SpriteTemplate gSpriteTemplate_EnemyShadow; extern const u8 gEnemyMonElevation[]; @@ -238,7 +236,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) if (moveInfo->moves[chosenMoveId] == MOVE_CURSE) { if (moveInfo->monType1 != TYPE_GHOST && moveInfo->monType2 != TYPE_GHOST) - var1 = MOVE_TARGET_x10; + var1 = MOVE_TARGET_USER; else var1 = MOVE_TARGET_SELECTED; } @@ -247,7 +245,7 @@ u16 ChooseMoveAndTargetInBattlePalace(void) var1 = gBattleMoves[moveInfo->moves[chosenMoveId]].target; } - if (var1 & MOVE_TARGET_x10) + if (var1 & MOVE_TARGET_USER) chosenMoveId |= (gActiveBattler << 8); else if (var1 == MOVE_TARGET_SELECTED) chosenMoveId |= (BattlePalaceGetTargetRetValue()); @@ -262,7 +260,7 @@ static u8 sub_805D4A8(u16 move) switch (gBattleMoves[move].target) { case MOVE_TARGET_SELECTED: - case MOVE_TARGET_USER: + case MOVE_TARGET_USER_OR_SELECTED: case MOVE_TARGET_RANDOM: case MOVE_TARGET_BOTH: case MOVE_TARGET_FOES_AND_ALLY: @@ -274,7 +272,7 @@ static u8 sub_805D4A8(u16 move) case MOVE_TARGET_DEPENDS: case MOVE_TARGET_OPPONENTS_FIELD: return 2; - case MOVE_TARGET_x10: + case MOVE_TARGET_USER: return 1; default: return 0; diff --git a/src/battle_interface.c b/src/battle_interface.c index bc6ff1122..9ef45020d 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -21,6 +21,7 @@ #include "safari_zone.h" #include "battle_anim.h" #include "constants/rgb.h" +#include "data2.h" struct TestingBar { @@ -154,7 +155,6 @@ enum }; extern const u8 * const gNatureNamePointers[]; -extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1]; // strings extern const u8 gText_Slash[]; @@ -162,8 +162,6 @@ extern const u8 gText_HighlightDarkGrey[]; extern const u8 gText_DynColor2[]; extern const u8 gText_DynColor2Male[]; extern const u8 gText_DynColor1Female[]; -extern const u8 gText_SafariBalls[]; -extern const u8 gText_SafariBallLeft[]; // graphics extern const u8 gBattleInterface_BallStatusBarGfx[]; @@ -198,10 +196,10 @@ static void SpriteCB_StatusSummaryBar(struct Sprite *sprite); static void SpriteCB_StatusSummaryBallsOnBattleStart(struct Sprite *sprite); static void SpriteCB_StatusSummaryBallsOnSwitchout(struct Sprite *sprite); -static u8 GetStatusIconForBankId(u8 statusElementId, u8 bank); +static u8 GetStatusIconForBankId(u8 statusElementId, u8 battlerId); static s32 sub_8074DB8(s32 maxValue, s32 currValue, s32 receivedValue, s32 *arg3, u8 arg4, u16 arg5); static u8 GetScaledExpFraction(s32 currValue, s32 receivedValue, s32 maxValue, u8 scale); -static void sub_8074B9C(u8 bank, u8 whichBar); +static void sub_8074B9C(u8 battlerId, u8 whichBar); static u8 sub_8074E8C(s32 maxValue, s32 currValue, s32 receivedValue, s32 *arg3, u8 *arg4, u8 arg5); static void sub_8074F88(struct TestingBar *barInfo, s32 *arg1, u16 *arg2); @@ -650,7 +648,7 @@ static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2) } #else -__attribute__((naked)) +NAKED static void sub_8072308(s16 arg0, u16 *arg1, u8 arg2) { asm(".syntax unified\n\ @@ -1034,13 +1032,13 @@ static void sub_8072924(struct Sprite *sprite) sprite->pos2.y = gSprites[otherSpriteId].pos2.y; } -void SetBattleBarStruct(u8 bank, u8 healthboxSpriteId, s32 maxVal, s32 currVal, s32 receivedValue) +void SetBattleBarStruct(u8 battlerId, u8 healthboxSpriteId, s32 maxVal, s32 currVal, s32 receivedValue) { - gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId = healthboxSpriteId; - gBattleSpritesDataPtr->battleBars[bank].maxValue = maxVal; - gBattleSpritesDataPtr->battleBars[bank].currentValue = currVal; - gBattleSpritesDataPtr->battleBars[bank].receivedValue = receivedValue; - gBattleSpritesDataPtr->battleBars[bank].field_10 = -32768; + gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId = healthboxSpriteId; + gBattleSpritesDataPtr->battleBars[battlerId].maxValue = maxVal; + gBattleSpritesDataPtr->battleBars[battlerId].currentValue = currVal; + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue = receivedValue; + gBattleSpritesDataPtr->battleBars[battlerId].field_10 = -32768; } void SetHealthboxSpriteInvisible(u8 healthboxSpriteId) @@ -1281,12 +1279,12 @@ static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 } else { - u8 bank; + u8 battlerId; memcpy(text, sUnknown_0832C3D8, sizeof(sUnknown_0832C3D8)); - bank = gSprites[healthboxSpriteId].data[6]; + battlerId = gSprites[healthboxSpriteId].data[6]; - if (gBattleSpritesDataPtr->battlerData[bank].hpNumbersNoBars) // don't print text if only bars are visible + if (gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) // don't print text if only bars are visible { u8 var = 4; u8 r7; @@ -1327,7 +1325,7 @@ static void UpdateHpTextInHealthboxInDoubles(u8 healthboxSpriteId, s16 value, u8 } else { - if (GetBattlerSide(bank) == B_SIDE_PLAYER) // impossible to reach part, because the bank is from the opponent's side + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) // impossible to reach part, because the battlerId is from the opponent's side { CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_116), (void*)(OBJ_VRAM0) + ((gSprites[healthboxSpriteId].oam.tileNum + 52) * 32), @@ -1469,7 +1467,7 @@ void SwapHpBarsWithHpText(void) } } -u8 CreatePartyStatusSummarySprites(u8 bank, struct HpAndStatus *partyInfo, u8 arg2, bool8 isBattleStart) +u8 CreatePartyStatusSummarySprites(u8 battlerId, struct HpAndStatus *partyInfo, u8 arg2, bool8 isBattleStart) { bool8 isOpponent; s16 bar_X, bar_Y, bar_pos2_X, bar_data0; @@ -1478,9 +1476,9 @@ u8 CreatePartyStatusSummarySprites(u8 bank, struct HpAndStatus *partyInfo, u8 ar u8 ballIconSpritesIds[6]; u8 taskId; - if (!arg2 || GetBattlerPosition(bank) != B_POSITION_OPPONENT_RIGHT) + if (!arg2 || GetBattlerPosition(battlerId) != B_POSITION_OPPONENT_RIGHT) { - if (GetBattlerSide(bank) == B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) { isOpponent = FALSE; bar_X = 136, bar_Y = 96; @@ -1559,7 +1557,7 @@ u8 CreatePartyStatusSummarySprites(u8 bank, struct HpAndStatus *partyInfo, u8 ar gSprites[ballIconSpritesIds[i]].data[2] = isOpponent; } - if (GetBattlerSide(bank) == B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { @@ -1658,7 +1656,7 @@ u8 CreatePartyStatusSummarySprites(u8 bank, struct HpAndStatus *partyInfo, u8 ar } taskId = CreateTask(TaskDummy, 5); - gTasks[taskId].data[0] = bank; + gTasks[taskId].data[0] = battlerId; gTasks[taskId].data[1] = barSpriteId; for (i = 0; i < 6; i++) @@ -1680,12 +1678,12 @@ void sub_8073C30(u8 taskId) u8 sp[6]; u8 r7; u8 r10; - u8 bank; + u8 battlerId; s32 i; r7 = gTasks[taskId].data[10]; r10 = gTasks[taskId].data[1]; - bank = gTasks[taskId].data[0]; + battlerId = gTasks[taskId].data[0]; for (i = 0; i < 6; i++) sp[i] = gTasks[taskId].data[3 + i]; @@ -1704,7 +1702,7 @@ void sub_8073C30(u8 taskId) { for (i = 0; i < 6; i++) { - if (GetBattlerSide(bank) != B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) { gSprites[sp[5 - i]].data[1] = 7 * i; gSprites[sp[5 - i]].data[3] = 0; @@ -1752,7 +1750,7 @@ static void sub_8073E64(u8 taskId) u8 sp[6]; s32 i; - u8 bank = gTasks[taskId].data[0]; + u8 battlerId = gTasks[taskId].data[0]; gTasks[taskId].data[15]--; if (gTasks[taskId].data[15] == -1) { @@ -1780,7 +1778,7 @@ static void sub_8073E64(u8 taskId) } else if (gTasks[taskId].data[15] == -3) { - gBattleSpritesDataPtr->healthBoxesData[bank].flag_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].flag_x1 = 0; SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); DestroyTask(taskId); @@ -1792,7 +1790,7 @@ static void sub_8073F98(u8 taskId) u8 sp[6]; s32 i; - u8 bank = gTasks[taskId].data[0]; + u8 battlerId = gTasks[taskId].data[0]; gTasks[taskId].data[15]--; if (gTasks[taskId].data[15] >= 0) { @@ -1813,7 +1811,7 @@ static void sub_8073F98(u8 taskId) } else if (gTasks[taskId].data[15] == -3) { - gBattleSpritesDataPtr->healthBoxesData[bank].flag_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].flag_x1 = 0; SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); DestroyTask(taskId); @@ -1976,17 +1974,17 @@ static void UpdateNickInHealthbox(u8 healthboxSpriteId, struct Pokemon *mon) static void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus) { - u8 bank, healthboxSpriteId_2; + u8 battlerId, healthboxSpriteId_2; if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) return; if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) return; - bank = gSprites[healthboxSpriteId].data[6]; - if (GetBattlerSide(bank) == B_SIDE_PLAYER) + battlerId = gSprites[healthboxSpriteId].data[6]; + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) return; - if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_SPECIES)), FLAG_GET_CAUGHT)) + if (!GetSetPokedexFlag(SpeciesToNationalPokedexNum(GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES)), FLAG_GET_CAUGHT)) return; healthboxSpriteId_2 = gSprites[healthboxSpriteId].data[5]; @@ -2000,17 +1998,17 @@ static void TryAddPokeballIconToHealthbox(u8 healthboxSpriteId, bool8 noStatus) static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) { s32 i; - u8 bank, healthboxSpriteId_2; + u8 battlerId, healthboxSpriteId_2; u32 status, pltAdder; const u8 *statusGfxPtr; s16 tileNumAdder; u8 statusPalId; - bank = gSprites[healthboxSpriteId].data[6]; + battlerId = gSprites[healthboxSpriteId].data[6]; healthboxSpriteId_2 = gSprites[healthboxSpriteId].data[5]; - if (GetBattlerSide(bank) == B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) { - status = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_STATUS); + status = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS); if (!IsDoubleBattle()) tileNumAdder = 0x1A; else @@ -2018,33 +2016,33 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) } else { - status = GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_STATUS); + status = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_STATUS); tileNumAdder = 0x11; } if (status & STATUS1_SLEEP) { - statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_SLP_BANK0, bank)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_SLP_BANK0, battlerId)); statusPalId = PAL_STATUS_SLP; } else if (status & STATUS1_PSN_ANY) { - statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PSN_BANK0, bank)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PSN_BANK0, battlerId)); statusPalId = PAL_STATUS_PSN; } else if (status & STATUS1_BURN) { - statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_BRN_BANK0, bank)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_BRN_BANK0, battlerId)); statusPalId = PAL_STATUS_BRN; } else if (status & STATUS1_FREEZE) { - statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_FRZ_BANK0, bank)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_FRZ_BANK0, battlerId)); statusPalId = PAL_STATUS_FRZ; } else if (status & STATUS1_PARALYSIS) { - statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PRZ_BANK0, bank)); + statusGfxPtr = GetHealthboxElementGfxPtr(GetStatusIconForBankId(HEALTHBOX_GFX_STATUS_PRZ_BANK0, battlerId)); statusPalId = PAL_STATUS_PAR; } else @@ -2054,7 +2052,7 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) for (i = 0; i < 3; i++) CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder + i) * 32), 32); - if (!gBattleSpritesDataPtr->battlerData[bank].hpNumbersNoBars) + if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_1), (void *)(OBJ_VRAM0 + gSprites[healthboxSpriteId_2].oam.tileNum * 32), 64); TryAddPokeballIconToHealthbox(healthboxSpriteId, TRUE); @@ -2062,14 +2060,14 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) } pltAdder = gSprites[healthboxSpriteId].oam.paletteNum * 16; - pltAdder += bank + 12; + pltAdder += battlerId + 12; FillPalette(sStatusIconColors[statusPalId], pltAdder + 0x100, 2); CpuCopy16(gPlttBufferUnfaded + 0x100 + pltAdder, (void*)(OBJ_PLTT + pltAdder * 2), 2); CpuCopy32(statusGfxPtr, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId].oam.tileNum + tileNumAdder) * 32), 96); - if (IsDoubleBattle() == TRUE || GetBattlerSide(bank) == B_SIDE_OPPONENT) + if (IsDoubleBattle() == TRUE || GetBattlerSide(battlerId) == B_SIDE_OPPONENT) { - if (!gBattleSpritesDataPtr->battlerData[bank].hpNumbersNoBars) + if (!gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars) { CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_0), (void*)(OBJ_VRAM0 + gSprites[healthboxSpriteId_2].oam.tileNum * 32), 32); CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_65), (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 1) * 32), 32); @@ -2078,58 +2076,58 @@ static void UpdateStatusIconInHealthbox(u8 healthboxSpriteId) TryAddPokeballIconToHealthbox(healthboxSpriteId, FALSE); } -static u8 GetStatusIconForBankId(u8 statusElementId, u8 bank) +static u8 GetStatusIconForBankId(u8 statusElementId, u8 battlerId) { u8 ret = statusElementId; switch (statusElementId) { case HEALTHBOX_GFX_STATUS_PSN_BANK0: - if (bank == 0) + if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_PSN_BANK0; - else if (bank == 1) + else if (battlerId == 1) ret = HEALTHBOX_GFX_STATUS_PSN_BANK1; - else if (bank == 2) + else if (battlerId == 2) ret = HEALTHBOX_GFX_STATUS_PSN_BANK2; else ret = HEALTHBOX_GFX_STATUS_PSN_BANK3; break; case HEALTHBOX_GFX_STATUS_PRZ_BANK0: - if (bank == 0) + if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_PRZ_BANK0; - else if (bank == 1) + else if (battlerId == 1) ret = HEALTHBOX_GFX_STATUS_PRZ_BANK1; - else if (bank == 2) + else if (battlerId == 2) ret = HEALTHBOX_GFX_STATUS_PRZ_BANK2; else ret = HEALTHBOX_GFX_STATUS_PRZ_BANK3; break; case HEALTHBOX_GFX_STATUS_SLP_BANK0: - if (bank == 0) + if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_SLP_BANK0; - else if (bank == 1) + else if (battlerId == 1) ret = HEALTHBOX_GFX_STATUS_SLP_BANK1; - else if (bank == 2) + else if (battlerId == 2) ret = HEALTHBOX_GFX_STATUS_SLP_BANK2; else ret = HEALTHBOX_GFX_STATUS_SLP_BANK3; break; case HEALTHBOX_GFX_STATUS_FRZ_BANK0: - if (bank == 0) + if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_FRZ_BANK0; - else if (bank == 1) + else if (battlerId == 1) ret = HEALTHBOX_GFX_STATUS_FRZ_BANK1; - else if (bank == 2) + else if (battlerId == 2) ret = HEALTHBOX_GFX_STATUS_FRZ_BANK2; else ret = HEALTHBOX_GFX_STATUS_FRZ_BANK3; break; case HEALTHBOX_GFX_STATUS_BRN_BANK0: - if (bank == 0) + if (battlerId == 0) ret = HEALTHBOX_GFX_STATUS_BRN_BANK0; - else if (bank == 1) + else if (battlerId == 1) ret = HEALTHBOX_GFX_STATUS_BRN_BANK1; - else if (bank == 2) + else if (battlerId == 2) ret = HEALTHBOX_GFX_STATUS_BRN_BANK2; else ret = HEALTHBOX_GFX_STATUS_BRN_BANK3; @@ -2170,10 +2168,10 @@ static void UpdateLeftNoOfBallsTextOnHealthbox(u8 healthboxSpriteId) void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elementId) { s32 maxHp, currHp; - u8 bank = gSprites[healthboxSpriteId].data[6]; + u8 battlerId = gSprites[healthboxSpriteId].data[6]; if (elementId == HEALTHBOX_ALL && !IsDoubleBattle()) - GetBattlerSide(bank); // pointless function call + GetBattlerSide(battlerId); // pointless function call if (GetBattlerSide(gSprites[healthboxSpriteId].data[6]) == B_SIDE_PLAYER) { @@ -2190,8 +2188,8 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem LoadBattleBarGfx(0); maxHp = GetMonData(mon, MON_DATA_MAX_HP); currHp = GetMonData(mon, MON_DATA_HP); - SetBattleBarStruct(bank, healthboxSpriteId, maxHp, currHp, 0); - sub_8074AA0(bank, healthboxSpriteId, HEALTH_BAR, 0); + SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0); + sub_8074AA0(battlerId, healthboxSpriteId, HEALTH_BAR, 0); } isDoubles = IsDoubleBattle(); if (!isDoubles && (elementId == HEALTHBOX_EXP_BAR || elementId == HEALTHBOX_ALL)) @@ -2208,8 +2206,8 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem currLevelExp = gExperienceTables[gBaseStats[species].growthRate][level]; currExpBarValue = exp - currLevelExp; maxExpBarValue = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLevelExp; - SetBattleBarStruct(bank, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles); - sub_8074AA0(bank, healthboxSpriteId, EXP_BAR, 0); + SetBattleBarStruct(battlerId, healthboxSpriteId, maxExpBarValue, currExpBarValue, isDoubles); + sub_8074AA0(battlerId, healthboxSpriteId, EXP_BAR, 0); } if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL) UpdateNickInHealthbox(healthboxSpriteId, mon); @@ -2229,8 +2227,8 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem LoadBattleBarGfx(0); maxHp = GetMonData(mon, MON_DATA_MAX_HP); currHp = GetMonData(mon, MON_DATA_HP); - SetBattleBarStruct(bank, healthboxSpriteId, maxHp, currHp, 0); - sub_8074AA0(bank, healthboxSpriteId, HEALTH_BAR, 0); + SetBattleBarStruct(battlerId, healthboxSpriteId, maxHp, currHp, 0); + sub_8074AA0(battlerId, healthboxSpriteId, HEALTH_BAR, 0); } if (elementId == HEALTHBOX_NICK || elementId == HEALTHBOX_ALL) UpdateNickInHealthbox(healthboxSpriteId, mon); @@ -2239,44 +2237,44 @@ void UpdateHealthboxAttribute(u8 healthboxSpriteId, struct Pokemon *mon, u8 elem } } -s32 sub_8074AA0(u8 bank, u8 healthboxSpriteId, u8 whichBar, u8 arg3) +s32 sub_8074AA0(u8 battlerId, u8 healthboxSpriteId, u8 whichBar, u8 arg3) { s32 var; if (whichBar == HEALTH_BAR) // health bar { - var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[bank].maxValue, - gBattleSpritesDataPtr->battleBars[bank].currentValue, - gBattleSpritesDataPtr->battleBars[bank].receivedValue, - &gBattleSpritesDataPtr->battleBars[bank].field_10, + var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, + gBattleSpritesDataPtr->battleBars[battlerId].currentValue, + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, + &gBattleSpritesDataPtr->battleBars[battlerId].field_10, 6, 1); } else // exp bar { - u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[bank].currentValue, - gBattleSpritesDataPtr->battleBars[bank].receivedValue, - gBattleSpritesDataPtr->battleBars[bank].maxValue, 8); + u16 expFraction = GetScaledExpFraction(gBattleSpritesDataPtr->battleBars[battlerId].currentValue, + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, + gBattleSpritesDataPtr->battleBars[battlerId].maxValue, 8); if (expFraction == 0) expFraction = 1; - expFraction = abs(gBattleSpritesDataPtr->battleBars[bank].receivedValue / expFraction); + expFraction = abs(gBattleSpritesDataPtr->battleBars[battlerId].receivedValue / expFraction); - var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[bank].maxValue, - gBattleSpritesDataPtr->battleBars[bank].currentValue, - gBattleSpritesDataPtr->battleBars[bank].receivedValue, - &gBattleSpritesDataPtr->battleBars[bank].field_10, + var = sub_8074DB8(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, + gBattleSpritesDataPtr->battleBars[battlerId].currentValue, + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, + &gBattleSpritesDataPtr->battleBars[battlerId].field_10, 8, expFraction); } - if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->battlerData[bank].hpNumbersNoBars)) - sub_8074B9C(bank, whichBar); + if (whichBar == EXP_BAR || (whichBar == HEALTH_BAR && !gBattleSpritesDataPtr->battlerData[battlerId].hpNumbersNoBars)) + sub_8074B9C(battlerId, whichBar); if (var == -1) - gBattleSpritesDataPtr->battleBars[bank].field_10 = 0; + gBattleSpritesDataPtr->battleBars[battlerId].field_10 = 0; return var; } -static void sub_8074B9C(u8 bank, u8 whichBar) +static void sub_8074B9C(u8 battlerId, u8 whichBar) { u8 array[8]; u8 subRet, level; @@ -2286,10 +2284,10 @@ static void sub_8074B9C(u8 bank, u8 whichBar) switch (whichBar) { case HEALTH_BAR: - subRet = sub_8074E8C(gBattleSpritesDataPtr->battleBars[bank].maxValue, - gBattleSpritesDataPtr->battleBars[bank].currentValue, - gBattleSpritesDataPtr->battleBars[bank].receivedValue, - &gBattleSpritesDataPtr->battleBars[bank].field_10, + subRet = sub_8074E8C(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, + gBattleSpritesDataPtr->battleBars[battlerId].currentValue, + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, + &gBattleSpritesDataPtr->battleBars[battlerId].field_10, array, 6); barElementId = 3; if (subRet <= 0x18) @@ -2300,7 +2298,7 @@ static void sub_8074B9C(u8 bank, u8 whichBar) } for (i = 0; i < 6; i++) { - u8 healthboxSpriteId_2 = gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].data[5]; + u8 healthboxSpriteId_2 = gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].data[5]; if (i < 2) CpuCopy32(GetHealthboxElementGfxPtr(barElementId) + array[i] * 32, (void*)(OBJ_VRAM0 + (gSprites[healthboxSpriteId_2].oam.tileNum + 2 + i) * 32), 32); @@ -2310,12 +2308,12 @@ static void sub_8074B9C(u8 bank, u8 whichBar) } break; case EXP_BAR: - sub_8074E8C(gBattleSpritesDataPtr->battleBars[bank].maxValue, - gBattleSpritesDataPtr->battleBars[bank].currentValue, - gBattleSpritesDataPtr->battleBars[bank].receivedValue, - &gBattleSpritesDataPtr->battleBars[bank].field_10, + sub_8074E8C(gBattleSpritesDataPtr->battleBars[battlerId].maxValue, + gBattleSpritesDataPtr->battleBars[battlerId].currentValue, + gBattleSpritesDataPtr->battleBars[battlerId].receivedValue, + &gBattleSpritesDataPtr->battleBars[battlerId].field_10, array, 8); - level = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_LEVEL); + level = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_LEVEL); if (level == MAX_MON_LEVEL) { for (i = 0; i < 8; i++) @@ -2325,10 +2323,10 @@ static void sub_8074B9C(u8 bank, u8 whichBar) { if (i < 4) CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32, - (void*)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].oam.tileNum + 0x24 + i) * 32), 32); + (void*)(OBJ_VRAM0 + (gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum + 0x24 + i) * 32), 32); else CpuCopy32(GetHealthboxElementGfxPtr(HEALTHBOX_GFX_12) + array[i] * 32, - (void*)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[bank].healthboxSpriteId].oam.tileNum) * 32), 32); + (void*)(OBJ_VRAM0 + 0xB80 + (i + gSprites[gBattleSpritesDataPtr->battleBars[battlerId].healthboxSpriteId].oam.tileNum) * 32), 32); } break; } diff --git a/src/battle_main.c b/src/battle_main.c index 3c4a61600..8649209c0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -20,6 +20,7 @@ #include "constants/hold_effects.h" #include "constants/trainers.h" #include "link.h" +#include "link_rfu.h" #include "bg.h" #include "dma3.h" #include "string_util.h" @@ -50,7 +51,7 @@ #include "international_string_util.h" #include "pokeball.h" -struct UnknownPokemonStruct2 +struct UnknownPokemonStruct4 { /*0x00*/ u16 species; /*0x02*/ u16 heldItem; @@ -80,12 +81,10 @@ extern struct MusicPlayerInfo gMPlayInfo_SE1; extern struct MusicPlayerInfo gMPlayInfo_SE2; extern u8 gUnknown_0203CF00[]; -extern const struct BattleMove gBattleMoves[]; extern const u16 gBattleTextboxPalette[]; // battle textbox palette extern const struct BgTemplate gUnknown_0831AA08[]; extern const struct WindowTemplate * const gUnknown_0831ABA0[]; extern const u8 gUnknown_0831ACE0[]; -extern const u8 gStatStageRatios[][2]; extern const u8 * const gBattleScriptsForMoveEffects[]; extern const u8 * const gBattlescriptsForBallThrow[]; extern const u8 * const gBattlescriptsForRunningByItem[]; @@ -95,12 +94,8 @@ extern const struct ScanlineEffectParams gUnknown_0831AC70; // strings extern const u8 gText_LinkStandby3[]; -extern const u8 gText_RecordBattleToPass[]; -extern const u8 gText_BattleYesNoChoice[]; extern const u8 gText_BattleRecordCouldntBeSaved[]; -extern const u8 gText_BattleRecordedOnPass[]; extern const u8 gText_ShedinjaJapaneseName[]; -extern const u8 gText_EmptyString3[]; extern const u8 gText_Poison[]; extern const u8 gText_Sleep[]; extern const u8 gText_Paralysis[]; @@ -198,8 +193,8 @@ EWRAM_DATA static u32 sUnusedUnknownArray[25] = {0}; EWRAM_DATA u32 gBattleTypeFlags = 0; EWRAM_DATA u8 gBattleTerrain = 0; EWRAM_DATA u32 gUnknown_02022FF4 = 0; -EWRAM_DATA struct UnknownPokemonStruct2 gUnknown_02022FF8[3] = {0}; // what is it used for? -EWRAM_DATA struct UnknownPokemonStruct2* gUnknown_02023058 = NULL; // what is it used for? +EWRAM_DATA struct UnknownPokemonStruct4 gUnknown_02022FF8[3] = {0}; // what is it used for? +EWRAM_DATA struct UnknownPokemonStruct4* gUnknown_02023058 = NULL; // what is it used for? EWRAM_DATA u8 *gUnknown_0202305C = NULL; EWRAM_DATA u8 *gUnknown_02023060 = NULL; EWRAM_DATA u8 gBattleBufferA[MAX_BATTLERS_COUNT][0x200] = {0}; @@ -301,6 +296,214 @@ u8 gNumberOfMovesToChoose; u8 gUnknown_03005D7C[MAX_BATTLERS_COUNT]; // rom const data + +// format: attacking type, defending type, damage multiplier +// the multiplier is a (decimal) fixed-point number: +// 20 is ×2.0 TYPE_MUL_SUPER_EFFECTIVE +// 10 is ×1.0 TYPE_MUL_NORMAL +// 05 is ×0.5 TYPE_MUL_NOT_EFFECTIVE +// 00 is ×0.0 TYPE_MUL_NO_EFFECT +const u8 gTypeEffectiveness[336] = +{ + TYPE_NORMAL, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_NORMAL, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIRE, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIRE, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIRE, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIRE, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIRE, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIRE, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIRE, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIRE, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_WATER, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_WATER, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE, + TYPE_WATER, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE, + TYPE_WATER, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_WATER, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_WATER, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ELECTRIC, TYPE_WATER, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ELECTRIC, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ELECTRIC, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ELECTRIC, TYPE_GROUND, TYPE_MUL_NO_EFFECT, + TYPE_ELECTRIC, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ELECTRIC, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_WATER, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GRASS, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GRASS, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GRASS, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GRASS, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ICE, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ICE, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ICE, TYPE_ICE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ICE, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ICE, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ICE, TYPE_DRAGON, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ICE, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ICE, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIGHTING, TYPE_NORMAL, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIGHTING, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIGHTING, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIGHTING, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIGHTING, TYPE_PSYCHIC, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIGHTING, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FIGHTING, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIGHTING, TYPE_DARK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FIGHTING, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_POISON, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_POISON, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_POISON, TYPE_GROUND, TYPE_MUL_NOT_EFFECTIVE, + TYPE_POISON, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_POISON, TYPE_GHOST, TYPE_MUL_NOT_EFFECTIVE, + TYPE_POISON, TYPE_STEEL, TYPE_MUL_NO_EFFECT, + TYPE_GROUND, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GROUND, TYPE_ELECTRIC, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GROUND, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GROUND, TYPE_POISON, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GROUND, TYPE_FLYING, TYPE_MUL_NO_EFFECT, + TYPE_GROUND, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GROUND, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GROUND, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FLYING, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FLYING, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FLYING, TYPE_FIGHTING, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FLYING, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_FLYING, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FLYING, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_PSYCHIC, TYPE_FIGHTING, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_PSYCHIC, TYPE_POISON, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_PSYCHIC, TYPE_PSYCHIC, TYPE_MUL_NOT_EFFECTIVE, + TYPE_PSYCHIC, TYPE_DARK, TYPE_MUL_NO_EFFECT, + TYPE_PSYCHIC, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_BUG, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_BUG, TYPE_GHOST, TYPE_MUL_NOT_EFFECTIVE, + TYPE_BUG, TYPE_DARK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_BUG, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ROCK, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ROCK, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ROCK, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ROCK, TYPE_GROUND, TYPE_MUL_NOT_EFFECTIVE, + TYPE_ROCK, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ROCK, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_ROCK, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GHOST, TYPE_NORMAL, TYPE_MUL_NO_EFFECT, + TYPE_GHOST, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_GHOST, TYPE_DARK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GHOST, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_GHOST, TYPE_GHOST, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_DRAGON, TYPE_DRAGON, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_DRAGON, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_DARK, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE, + TYPE_DARK, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_DARK, TYPE_GHOST, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_DARK, TYPE_DARK, TYPE_MUL_NOT_EFFECTIVE, + TYPE_DARK, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_STEEL, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE, + TYPE_STEEL, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE, + TYPE_STEEL, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE, + TYPE_STEEL, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_STEEL, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE, + TYPE_STEEL, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE, + TYPE_FORESIGHT, TYPE_FORESIGHT, TYPE_MUL_NO_EFFECT, + TYPE_NORMAL, TYPE_GHOST, TYPE_MUL_NO_EFFECT, + TYPE_FIGHTING, TYPE_GHOST, TYPE_MUL_NO_EFFECT, + TYPE_ENDTABLE, TYPE_ENDTABLE, TYPE_MUL_NO_EFFECT +}; + +const u8 gTypeNames[][TYPE_NAME_LENGTH + 1] = +{ + _("NORMAL"), + _("FIGHT"), + _("FLYING"), + _("POISON"), + _("GROUND"), + _("ROCK"), + _("BUG"), + _("GHOST"), + _("STEEL"), + _("???"), + _("FIRE"), + _("WATER"), + _("GRASS"), + _("ELECTR"), + _("PSYCHC"), + _("ICE"), + _("DRAGON"), + _("DARK"), +}; + +// This is a factor in how much money you get for beating a trainer. +const struct TrainerMoney gTrainerMoneyTable[] = +{ + {TRAINER_CLASS_TEAM_AQUA, 5}, + {TRAINER_CLASS_AQUA_ADMIN, 10}, + {TRAINER_CLASS_AQUA_LEADER, 20}, + {TRAINER_CLASS_AROMA_LADY, 10}, + {TRAINER_CLASS_RUIN_MANIAC, 15}, + {TRAINER_CLASS_INTERVIEWER, 12}, + {TRAINER_CLASS_TUBER_1, 1}, + {TRAINER_CLASS_TUBER_2, 1}, + {TRAINER_CLASS_SIS_AND_BRO, 3}, + {TRAINER_CLASS_COOLTRAINER_1, 12}, + {TRAINER_CLASS_HEX_MANIAC, 6}, + {TRAINER_CLASS_LADY, 50}, + {TRAINER_CLASS_BEAUTY, 20}, + {TRAINER_CLASS_RICH_BOY, 50}, + {TRAINER_CLASS_POKEMANIAC, 15}, + {TRAINER_CLASS_SWIMMER_M, 2}, + {TRAINER_CLASS_BLACK_BELT, 8}, + {TRAINER_CLASS_GUITARIST, 8}, + {TRAINER_CLASS_KINDLER, 8}, + {TRAINER_CLASS_CAMPER, 4}, + {TRAINER_CLASS_OLD_COUPLE, 10}, + {TRAINER_CLASS_BUG_MANIAC, 15}, + {TRAINER_CLASS_PSYCHIC, 6}, + {TRAINER_CLASS_GENTLEMAN, 20}, + {TRAINER_CLASS_ELITE_FOUR, 25}, + {TRAINER_CLASS_LEADER, 25}, + {TRAINER_CLASS_SCHOOL_KID, 5}, + {TRAINER_CLASS_SR_AND_JR, 4}, + {TRAINER_CLASS_POKEFAN, 20}, + {TRAINER_CLASS_EXPERT, 10}, + {TRAINER_CLASS_YOUNGSTER, 4}, + {TRAINER_CLASS_CHAMPION, 50}, + {TRAINER_CLASS_FISHERMAN, 10}, + {TRAINER_CLASS_TRIATHLETE, 10}, + {TRAINER_CLASS_DRAGON_TAMER, 12}, + {TRAINER_CLASS_BIRD_KEEPER, 8}, + {TRAINER_CLASS_NINJA_BOY, 3}, + {TRAINER_CLASS_BATTLE_GIRL, 6}, + {TRAINER_CLASS_PARASOL_LADY, 10}, + {TRAINER_CLASS_SWIMMER_F, 2}, + {TRAINER_CLASS_PICNICKER, 4}, + {TRAINER_CLASS_TWINS, 3}, + {TRAINER_CLASS_SAILOR, 8}, + {TRAINER_CLASS_COLLECTOR, 15}, + {TRAINER_CLASS_PKMN_TRAINER_3, 15}, + {TRAINER_CLASS_PKMN_BREEDER, 10}, + {TRAINER_CLASS_PKMN_RANGER, 12}, + {TRAINER_CLASS_TEAM_MAGMA, 5}, + {TRAINER_CLASS_MAGMA_ADMIN, 10}, + {TRAINER_CLASS_MAGMA_LEADER, 20}, + {TRAINER_CLASS_LASS, 4}, + {TRAINER_CLASS_BUG_CATCHER, 4}, + {TRAINER_CLASS_HIKER, 10}, + {TRAINER_CLASS_YOUNG_COUPLE, 8}, + {TRAINER_CLASS_WINSTRATE, 10}, + {0xFF, 5}, +}; + +#include "data/text/abilities.h" + static void (* const sTurnActionsFuncsTable[])(void) = { HandleAction_UseMove, // B_ACTION_USE_MOVE @@ -738,7 +941,7 @@ static void CB2_HandleStartBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); break; case 1: @@ -762,8 +965,8 @@ static void CB2_HandleStartBattle(void) SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); gBattleCommunication[MULTIUSE_STATE] = 2; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -790,7 +993,7 @@ static void CB2_HandleStartBattle(void) gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1]; sub_8185F90(gBlockRecvBuffer[playerMultiplayerId][1]); sub_8185F90(gBlockRecvBuffer[enemyMultiplayerId][1]); - sub_8068AA4(); + SetDeoxysStats(); gBattleCommunication[MULTIUSE_STATE]++; } break; @@ -933,7 +1136,7 @@ static void CB2_HandleStartMultiPartnerBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); // fall through case 1: @@ -964,8 +1167,8 @@ static void CB2_HandleStartMultiPartnerBattle(void) gBattleCommunication[MULTIUSE_STATE] = 2; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -1202,9 +1405,9 @@ static void CB2_PreInitMultiBattle(void) case 0: if (gReceivedRemoteLinkPlayers != 0 && sub_800A520()) { - gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3); + gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct4) * 3); sub_80379F8(0); - SendBlock(bitmask_all_link_players_but_self(), gUnknown_02023058, sizeof(struct UnknownPokemonStruct2) * 3); + SendBlock(bitmask_all_link_players_but_self(), gUnknown_02023058, sizeof(struct UnknownPokemonStruct4) * 3); gBattleCommunication[MULTIUSE_STATE]++; } break; @@ -1222,12 +1425,12 @@ static void CB2_PreInitMultiBattle(void) if ((!(gLinkPlayers[i].lp_field_18 & 1) && !(gLinkPlayers[playerMultiplierId].lp_field_18 & 1)) || (gLinkPlayers[i].lp_field_18 & 1 && gLinkPlayers[playerMultiplierId].lp_field_18 & 1)) { - memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3); + memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct4) * 3); } } else { - memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct2) * 3); + memcpy(gUnknown_02022FF8, gBlockRecvBuffer[i], sizeof(struct UnknownPokemonStruct4) * 3); } } gBattleCommunication[MULTIUSE_STATE]++; @@ -1241,14 +1444,14 @@ static void CB2_PreInitMultiBattle(void) if (sub_800A520() && !gPaletteFade.active) { gBattleCommunication[MULTIUSE_STATE]++; - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800ADF8(); else sub_800AC34(); } break; case 3: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { if (sub_8010500()) { @@ -1286,7 +1489,7 @@ static void CB2_PreInitIngamePlayerPartnerBattle(void) switch (gBattleCommunication[MULTIUSE_STATE]) { case 0: - gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct2) * 3); + gUnknown_02023058 = Alloc(sizeof(struct UnknownPokemonStruct4) * 3); sub_80379F8(3); gBattleCommunication[MULTIUSE_STATE]++; *savedCallback = gMain.savedCallback; @@ -1333,7 +1536,7 @@ static void CB2_HandleStartMultiBattle(void) sub_805EF14(); gBattleCommunication[MULTIUSE_STATE] = 1; } - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E0E8(); break; case 1: @@ -1351,8 +1554,8 @@ static void CB2_HandleStartMultiBattle(void) SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_180, 32); gBattleCommunication[MULTIUSE_STATE]++; } - if (gLinkVSyncDisabled) - sub_800DFB4(0, 0); + if (gWirelessCommType) + CreateWirelessStatusIndicatorSprite(0, 0); } } else @@ -1369,7 +1572,7 @@ static void CB2_HandleStartMultiBattle(void) ResetBlockReceivedFlags(); sub_8036EB8(4, playerMultiplayerId); SetAllPlayersBerryData(); - sub_8068AA4(); + SetDeoxysStats(); var = CreateTask(sub_8035D74, 0); gTasks[var].data[1] = 0x10E; gTasks[var].data[2] = 0x5A; @@ -1627,7 +1830,7 @@ static void FreeRestoreBattleData(void) gScanlineEffect.state = 3; gMain.inBattle = 0; ZeroEnemyPartyMons(); - m4aSongNumStop(0x5A); + m4aSongNumStop(SE_HINSI); FreeMonSpritesGfx(); FreeBattleSpritesData(); FreeBattleResources(); @@ -2136,12 +2339,12 @@ static void sub_8038F34(void) } break; case 8: - if (!gLinkVSyncDisabled) + if (!gWirelessCommType) sub_800AC34(); gBattleCommunication[MULTIUSE_STATE]++; break; case 9: - if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1) + if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { gMain.field_439_x4 = 0; SetMainCallback2(gMain.savedCallback); @@ -2320,13 +2523,13 @@ static void sub_803939C(void) case 8: if (--gBattleCommunication[1] == 0) { - if (gMain.field_439_x4 && !gLinkVSyncDisabled) + if (gMain.field_439_x4 && !gWirelessCommType) sub_800AC34(); gBattleCommunication[MULTIUSE_STATE]++; } break; case 9: - if (!gMain.field_439_x4 || gLinkVSyncDisabled || gReceivedRemoteLinkPlayers != 1) + if (!gMain.field_439_x4 || gWirelessCommType || gReceivedRemoteLinkPlayers != 1) { gMain.field_439_x4 = 0; if (!gPaletteFade.active) @@ -3387,9 +3590,8 @@ static void BattleIntroOpponent1SendsOutMonAnimation(void) gBattleMainFunc = BattleIntroRecordMonsToDex; } - #else -__attribute__((naked)) +NAKED static void BattleIntroOpponent1SendsOutMonAnimation(void) { asm(".syntax unified\n\ @@ -3474,7 +3676,6 @@ _0803B2F2:\n\ .pool\n\ .syntax divided"); } - #endif // NONMATCHING static void BattleIntroRecordMonsToDex(void) @@ -3835,8 +4036,7 @@ u8 IsRunningFromBattleImpossible(void) } if (side != GetBattlerSide(i) && gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE - && gBattleMons[gActiveBattler].type1 != TYPE_FLYING - && gBattleMons[gActiveBattler].type2 != TYPE_FLYING + && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING) && gBattleMons[i].ability == ABILITY_ARENA_TRAP) { gBattleScripting.battler = i; @@ -3846,7 +4046,7 @@ u8 IsRunningFromBattleImpossible(void) } } i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0); - if (i != 0 && (gBattleMons[gActiveBattler].type1 == TYPE_STEEL || gBattleMons[gActiveBattler].type2 == TYPE_STEEL)) + if (i != 0 && IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)) { gBattleScripting.battler = i - 1; gLastUsedAbility = gBattleMons[i - 1].ability; @@ -4033,12 +4233,10 @@ static void HandleTurnActionSelectionState(void) } else if ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_SHADOW_TAG, 0, 0)) || ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_ARENA_TRAP, 0, 0)) - && gBattleMons[gActiveBattler].type1 != TYPE_FLYING - && gBattleMons[gActiveBattler].type2 != TYPE_FLYING + && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING) && gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE) || ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0)) - && (gBattleMons[gActiveBattler].type1 == TYPE_STEEL - || gBattleMons[gActiveBattler].type2 == TYPE_STEEL))) + && IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL))) { BtlController_EmitChoosePokemon(0, ((i - 1) << 4) | 4, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBattler]); } @@ -5026,7 +5224,7 @@ static void ReturnFromBattleToOverworld(void) SetRoamerInactive(); } - m4aSongNumStop(0x5A); + m4aSongNumStop(SE_HINSI); SetMainCallback2(gMain.savedCallback); } @@ -5133,7 +5331,7 @@ static void HandleAction_UseMove(void) else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gSideTimers[side].followmeTimer == 0 && (gBattleMoves[gCurrentMove].power != 0 - || gBattleMoves[gCurrentMove].target != MOVE_TARGET_x10) + || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER) && gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC) { diff --git a/src/battle_message.c b/src/battle_message.c index 2b9783f1a..1f338db92 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -22,9 +22,7 @@ extern u8 gUnknown_0203C7B4; extern struct StringInfoBattle *gStringInfo; extern const u8 gMoveNames[LAST_MOVE_INDEX + 1][13]; -extern const u8 gAbilityNames[][13]; extern const u8 gTrainerClassNames[][13]; -extern const u8 gTypeNames[][7]; extern const u16 gUnknown_08D85620[]; // strings @@ -59,832 +57,832 @@ EWRAM_DATA u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT] = {0}; // const rom data // todo: make some of those names less vague: attacker/target vs pkmn, etc. -const u8 gText_Trainer1LoseText[] = _("{B_TRAINER1_LOSE_TEXT}"); -const u8 gText_PkmnGainedEXP[] = _("{B_BUFF1} gained{B_BUFF2}\n{B_BUFF3} EXP. Points!\p"); -const u8 gText_EmptyString4[] = _(""); -const u8 gText_ABoosted[] = _(" a boosted"); -const u8 gText_PkmnGrewToLv[] = _("{B_BUFF1} grew to\nLV. {B_BUFF2}!{UNKNOWN_A}\p"); -const u8 gText_PkmnLearnedMove[] = _("{B_BUFF1} learned\n{B_BUFF2}!{UNKNOWN_A}\p"); -const u8 gText_TryToLearnMove1[] = _("{B_BUFF1} is trying to\nlearn {B_BUFF2}.\p"); -const u8 gText_TryToLearnMove2[] = _("But, {B_BUFF1} can’t learn\nmore than four moves.\p"); -const u8 gText_TryToLearnMove3[] = _("Delete a move to make\nroom for {B_BUFF2}?"); -const u8 gText_PkmnForgotMove[] = _("{B_BUFF1} forgot\n{B_BUFF2}.\p"); -const u8 gText_StopLearningMove[] = _("{PAUSE 32}Stop learning\n{B_BUFF2}?"); -const u8 gText_DidNotLearnMove[] = _("{B_BUFF1} did not learn\n{B_BUFF2}.\p"); -const u8 gText_UseNextPkmn[] = _("Use next POKéMON?"); -const u8 gText_AttackMissed[] = _("{B_ATK_NAME_WITH_PREFIX}’s\nattack missed!"); -const u8 gText_PkmnProtectedItself[] = _("{B_DEF_NAME_WITH_PREFIX}\nprotected itself!"); -const u8 gText_AvoidedDamage[] = _("{B_DEF_NAME_WITH_PREFIX} avoided\ndamage with {B_DEF_ABILITY}!"); -const u8 gText_PkmnMakesGroundMiss[] = _("{B_DEF_NAME_WITH_PREFIX} makes GROUND\nmoves miss with {B_DEF_ABILITY}!"); -const u8 gText_PkmnAvoidedAttack[] = _("{B_DEF_NAME_WITH_PREFIX} avoided\nthe attack!"); -const u8 gText_ItDoesntAffect[] = _("It doesn’t affect\n{B_DEF_NAME_WITH_PREFIX}…"); -const u8 gText_AttackerFainted[] = _("{B_ATK_NAME_WITH_PREFIX}\nfainted!\p"); -const u8 gText_TargetFainted[] = _("{B_DEF_NAME_WITH_PREFIX}\nfainted!\p"); -const u8 gText_PlayerGotMoney[] = _("{B_PLAYER_NAME} got ¥{B_BUFF1}\nfor winning!\p"); -const u8 gText_PlayerWhiteout[] = _("{B_PLAYER_NAME} is out of\nusable POKéMON!\p"); -const u8 gText_PlayerWhiteout2[] = _("{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}"); -const u8 gText_PreventsEscape[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} prevents\nescape with {B_SCR_ACTIVE_ABILITY}!\p"); -const u8 gText_CantEscape2[] = _("Can’t escape!\p"); -const u8 gText_AttackerCantEscape[] = _("{B_ATK_NAME_WITH_PREFIX} can’t escape!"); -const u8 gText_HitXTimes[] = _("Hit {B_BUFF1} time(s)!"); -const u8 gText_PkmnFellAsleep[] = _("{B_EFF_NAME_WITH_PREFIX}\nfell asleep!"); -const u8 gText_PkmnMadeSleep[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade {B_EFF_NAME_WITH_PREFIX} sleep!"); -const u8 gText_PkmnAlreadyAsleep[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready asleep!"); -const u8 gText_PkmnAlreadyAsleep2[] = _("{B_ATK_NAME_WITH_PREFIX} is\nalready asleep!"); -const u8 gText_PkmnWasntAffected[] = _("{B_DEF_NAME_WITH_PREFIX}\nwasn’t affected!"); -const u8 gText_PkmnWasPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX}\nwas poisoned!"); -const u8 gText_PkmnPoisonedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\npoisoned {B_EFF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnHurtByPoison[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby poison!"); -const u8 gText_PkmnAlreadyPoisoned[] = _("{B_DEF_NAME_WITH_PREFIX} is already\npoisoned."); -const u8 gText_PkmnBadlyPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX} is badly\npoisoned!"); -const u8 gText_PkmnEnergyDrained[] = _("{B_DEF_NAME_WITH_PREFIX} had its\nenergy drained!"); -const u8 gText_PkmnWasBurned[] = _("{B_EFF_NAME_WITH_PREFIX} was burned!"); -const u8 gText_PkmnBurnedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nburned {B_EFF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnHurtByBurn[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its burn!"); -const u8 gText_PkmnAlreadyHasBurn[] = _("{B_DEF_NAME_WITH_PREFIX} already\nhas a burn."); -const u8 gText_PkmnWasFrozen[] = _("{B_EFF_NAME_WITH_PREFIX} was\nfrozen solid!"); -const u8 gText_PkmnFrozenBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nfroze {B_EFF_NAME_WITH_PREFIX} solid!"); -const u8 gText_PkmnIsFrozen[] = _("{B_ATK_NAME_WITH_PREFIX} is\nfrozen solid!"); -const u8 gText_PkmnWasDefrosted[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndefrosted!"); -const u8 gText_PkmnWasDefrosted2[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted!"); -const u8 gText_PkmnWasDefrostedBy[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted by {B_CURRENT_MOVE}!"); -const u8 gText_PkmnWasParalyzed[] = _("{B_EFF_NAME_WITH_PREFIX} is paralyzed!\nIt may be unable to move!"); -const u8 gText_PkmnWasParalyzedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nparalyzed {B_EFF_NAME_WITH_PREFIX}!\lIt may be unable to move!"); -const u8 gText_PkmnIsParalyzed[] = _("{B_ATK_NAME_WITH_PREFIX} is paralyzed!\nIt can’t move!"); -const u8 gText_PkmnIsAlreadyParalyzed[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready paralyzed!"); -const u8 gText_PkmnHealedParalysis[] = _("{B_DEF_NAME_WITH_PREFIX} was\nhealed of paralysis!"); -const u8 gText_PkmnDreamEaten[] = _("{B_DEF_NAME_WITH_PREFIX}’s\ndream was eaten!"); -const u8 gText_StatsWontIncrease[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\nwon’t go higher!"); -const u8 gText_StatsWontDecrease[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\nwon’t go lower!"); -const u8 gText_TeamStoppedWorking[] = _("Your team’s {B_BUFF1}\nstopped working!"); -const u8 gText_FoeStoppedWorking[] = _("The foe’s {B_BUFF1}\nstopped working!"); -const u8 gText_PkmnIsConfused[] = _("{B_ATK_NAME_WITH_PREFIX} is\nconfused!"); -const u8 gText_PkmnHealedConfusion[] = _("{B_ATK_NAME_WITH_PREFIX} snapped\nout of confusion!"); -const u8 gText_PkmnWasConfused[] = _("{B_EFF_NAME_WITH_PREFIX} became\nconfused!"); -const u8 gText_PkmnAlreadyConfused[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready confused!"); -const u8 gText_PkmnFellInLove[] = _("{B_DEF_NAME_WITH_PREFIX}\nfell in love!"); -const u8 gText_PkmnInLove[] = _("{B_ATK_NAME_WITH_PREFIX} is in love\nwith {B_SCR_ACTIVE_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnImmobilizedByLove[] = _("{B_ATK_NAME_WITH_PREFIX} is\nimmobilized by love!"); -const u8 gText_PkmnBlownAway[] = _("{B_DEF_NAME_WITH_PREFIX} was\nblown away!"); -const u8 gText_PkmnChangedType[] = _("{B_ATK_NAME_WITH_PREFIX} transformed\ninto the {B_BUFF1} type!"); -const u8 gText_PkmnFlinched[] = _("{B_ATK_NAME_WITH_PREFIX} flinched!"); -const u8 gText_PkmnRegainedHealth[] = _("{B_DEF_NAME_WITH_PREFIX} regained\nhealth!"); -const u8 gText_PkmnHPFull[] = _("{B_DEF_NAME_WITH_PREFIX}’s\nHP is full!"); -const u8 gText_PkmnRaisedSpDef[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised SP. DEF!"); -const u8 gText_PkmnRaisedSpDefALittle[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised SP. DEF a little!"); -const u8 gText_PkmnRaisedDef[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised DEFENSE!"); -const u8 gText_PkmnRaisedDefALittle[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised DEFENSE a little!"); -const u8 gText_PkmnCoveredByVeil[] = _("{B_ATK_PREFIX2}’s party is covered\nby a veil!"); -const u8 gText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}’s party is protected\nby SAFEGUARD!"); -const u8 gText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}’s party is no longer\nprotected by SAFEGUARD!"); -const u8 gText_PkmnWentToSleep[] = _("{B_ATK_NAME_WITH_PREFIX} went\nto sleep!"); -const u8 gText_PkmnSleptHealthy[] = _("{B_ATK_NAME_WITH_PREFIX} slept and\nbecame healthy!"); -const u8 gText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipped\nup a whirlwind!"); -const u8 gText_PkmnTookSunlight[] = _("{B_ATK_NAME_WITH_PREFIX} took\nin sunlight!"); -const u8 gText_PkmnLoweredHead[] = _("{B_ATK_NAME_WITH_PREFIX} lowered\nits head!"); -const u8 gText_PkmnIsGlowing[] = _("{B_ATK_NAME_WITH_PREFIX} is glowing!"); -const u8 gText_PkmnFlewHigh[] = _("{B_ATK_NAME_WITH_PREFIX} flew\nup high!"); -const u8 gText_PkmnDugHole[] = _("{B_ATK_NAME_WITH_PREFIX} dug a hole!"); -const u8 gText_PkmnHidUnderwater[] = _("{B_ATK_NAME_WITH_PREFIX} hid\nunderwater!"); -const u8 gText_PkmnSprangUp[] = _("{B_ATK_NAME_WITH_PREFIX} sprang up!"); -const u8 gText_PkmnSqueezedByBind[] = _("{B_DEF_NAME_WITH_PREFIX} was squeezed by\n{B_ATK_NAME_WITH_PREFIX}’s BIND!"); -const u8 gText_PkmnTrappedInVortex[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nin the vortex!"); -const u8 gText_PkmnTrappedBySandTomb[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nby SAND TOMB!"); -const u8 gText_PkmnWrappedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was WRAPPED by\n{B_ATK_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnClamped[] = _("{B_ATK_NAME_WITH_PREFIX} CLAMPED\n{B_DEF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnHurtBy[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby {B_BUFF1}!"); -const u8 gText_PkmnFreedFrom[] = _("{B_ATK_NAME_WITH_PREFIX} was freed\nfrom {B_BUFF1}!"); -const u8 gText_PkmnCrashed[] = _("{B_ATK_NAME_WITH_PREFIX} kept going\nand crashed!"); +static const u8 sText_Trainer1LoseText[] = _("{B_TRAINER1_LOSE_TEXT}"); +static const u8 sText_PkmnGainedEXP[] = _("{B_BUFF1} gained{B_BUFF2}\n{B_BUFF3} EXP. Points!\p"); +static const u8 sText_EmptyString4[] = _(""); +static const u8 sText_ABoosted[] = _(" a boosted"); +static const u8 sText_PkmnGrewToLv[] = _("{B_BUFF1} grew to\nLV. {B_BUFF2}!{UNKNOWN_A}\p"); +static const u8 sText_PkmnLearnedMove[] = _("{B_BUFF1} learned\n{B_BUFF2}!{UNKNOWN_A}\p"); +static const u8 sText_TryToLearnMove1[] = _("{B_BUFF1} is trying to\nlearn {B_BUFF2}.\p"); +static const u8 sText_TryToLearnMove2[] = _("But, {B_BUFF1} can’t learn\nmore than four moves.\p"); +static const u8 sText_TryToLearnMove3[] = _("Delete a move to make\nroom for {B_BUFF2}?"); +static const u8 sText_PkmnForgotMove[] = _("{B_BUFF1} forgot\n{B_BUFF2}.\p"); +static const u8 sText_StopLearningMove[] = _("{PAUSE 32}Stop learning\n{B_BUFF2}?"); +static const u8 sText_DidNotLearnMove[] = _("{B_BUFF1} did not learn\n{B_BUFF2}.\p"); +static const u8 sText_UseNextPkmn[] = _("Use next POKéMON?"); +static const u8 sText_AttackMissed[] = _("{B_ATK_NAME_WITH_PREFIX}’s\nattack missed!"); +static const u8 sText_PkmnProtectedItself[] = _("{B_DEF_NAME_WITH_PREFIX}\nprotected itself!"); +static const u8 sText_AvoidedDamage[] = _("{B_DEF_NAME_WITH_PREFIX} avoided\ndamage with {B_DEF_ABILITY}!"); +static const u8 sText_PkmnMakesGroundMiss[] = _("{B_DEF_NAME_WITH_PREFIX} makes GROUND\nmoves miss with {B_DEF_ABILITY}!"); +static const u8 sText_PkmnAvoidedAttack[] = _("{B_DEF_NAME_WITH_PREFIX} avoided\nthe attack!"); +static const u8 sText_ItDoesntAffect[] = _("It doesn’t affect\n{B_DEF_NAME_WITH_PREFIX}…"); +static const u8 sText_AttackerFainted[] = _("{B_ATK_NAME_WITH_PREFIX}\nfainted!\p"); +static const u8 sText_TargetFainted[] = _("{B_DEF_NAME_WITH_PREFIX}\nfainted!\p"); +static const u8 sText_PlayerGotMoney[] = _("{B_PLAYER_NAME} got ¥{B_BUFF1}\nfor winning!\p"); +static const u8 sText_PlayerWhiteout[] = _("{B_PLAYER_NAME} is out of\nusable POKéMON!\p"); +static const u8 sText_PlayerWhiteout2[] = _("{B_PLAYER_NAME} whited out!{PAUSE_UNTIL_PRESS}"); +static const u8 sText_PreventsEscape[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} prevents\nescape with {B_SCR_ACTIVE_ABILITY}!\p"); +static const u8 sText_CantEscape2[] = _("Can’t escape!\p"); +static const u8 sText_AttackerCantEscape[] = _("{B_ATK_NAME_WITH_PREFIX} can’t escape!"); +static const u8 sText_HitXTimes[] = _("Hit {B_BUFF1} time(s)!"); +static const u8 sText_PkmnFellAsleep[] = _("{B_EFF_NAME_WITH_PREFIX}\nfell asleep!"); +static const u8 sText_PkmnMadeSleep[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade {B_EFF_NAME_WITH_PREFIX} sleep!"); +static const u8 sText_PkmnAlreadyAsleep[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready asleep!"); +static const u8 sText_PkmnAlreadyAsleep2[] = _("{B_ATK_NAME_WITH_PREFIX} is\nalready asleep!"); +static const u8 sText_PkmnWasntAffected[] = _("{B_DEF_NAME_WITH_PREFIX}\nwasn’t affected!"); +static const u8 sText_PkmnWasPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX}\nwas poisoned!"); +static const u8 sText_PkmnPoisonedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\npoisoned {B_EFF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnHurtByPoison[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby poison!"); +static const u8 sText_PkmnAlreadyPoisoned[] = _("{B_DEF_NAME_WITH_PREFIX} is already\npoisoned."); +static const u8 sText_PkmnBadlyPoisoned[] = _("{B_EFF_NAME_WITH_PREFIX} is badly\npoisoned!"); +static const u8 sText_PkmnEnergyDrained[] = _("{B_DEF_NAME_WITH_PREFIX} had its\nenergy drained!"); +static const u8 sText_PkmnWasBurned[] = _("{B_EFF_NAME_WITH_PREFIX} was burned!"); +static const u8 sText_PkmnBurnedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nburned {B_EFF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnHurtByBurn[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby its burn!"); +static const u8 sText_PkmnAlreadyHasBurn[] = _("{B_DEF_NAME_WITH_PREFIX} already\nhas a burn."); +static const u8 sText_PkmnWasFrozen[] = _("{B_EFF_NAME_WITH_PREFIX} was\nfrozen solid!"); +static const u8 sText_PkmnFrozenBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nfroze {B_EFF_NAME_WITH_PREFIX} solid!"); +static const u8 sText_PkmnIsFrozen[] = _("{B_ATK_NAME_WITH_PREFIX} is\nfrozen solid!"); +static const u8 sText_PkmnWasDefrosted[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndefrosted!"); +static const u8 sText_PkmnWasDefrosted2[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted!"); +static const u8 sText_PkmnWasDefrostedBy[] = _("{B_ATK_NAME_WITH_PREFIX} was\ndefrosted by {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnWasParalyzed[] = _("{B_EFF_NAME_WITH_PREFIX} is paralyzed!\nIt may be unable to move!"); +static const u8 sText_PkmnWasParalyzedBy[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nparalyzed {B_EFF_NAME_WITH_PREFIX}!\lIt may be unable to move!"); +static const u8 sText_PkmnIsParalyzed[] = _("{B_ATK_NAME_WITH_PREFIX} is paralyzed!\nIt can’t move!"); +static const u8 sText_PkmnIsAlreadyParalyzed[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready paralyzed!"); +static const u8 sText_PkmnHealedParalysis[] = _("{B_DEF_NAME_WITH_PREFIX} was\nhealed of paralysis!"); +static const u8 sText_PkmnDreamEaten[] = _("{B_DEF_NAME_WITH_PREFIX}’s\ndream was eaten!"); +static const u8 sText_StatsWontIncrease[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\nwon’t go higher!"); +static const u8 sText_StatsWontDecrease[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\nwon’t go lower!"); +static const u8 sText_TeamStoppedWorking[] = _("Your team’s {B_BUFF1}\nstopped working!"); +static const u8 sText_FoeStoppedWorking[] = _("The foe’s {B_BUFF1}\nstopped working!"); +static const u8 sText_PkmnIsConfused[] = _("{B_ATK_NAME_WITH_PREFIX} is\nconfused!"); +static const u8 sText_PkmnHealedConfusion[] = _("{B_ATK_NAME_WITH_PREFIX} snapped\nout of confusion!"); +static const u8 sText_PkmnWasConfused[] = _("{B_EFF_NAME_WITH_PREFIX} became\nconfused!"); +static const u8 sText_PkmnAlreadyConfused[] = _("{B_DEF_NAME_WITH_PREFIX} is\nalready confused!"); +static const u8 sText_PkmnFellInLove[] = _("{B_DEF_NAME_WITH_PREFIX}\nfell in love!"); +static const u8 sText_PkmnInLove[] = _("{B_ATK_NAME_WITH_PREFIX} is in love\nwith {B_SCR_ACTIVE_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnImmobilizedByLove[] = _("{B_ATK_NAME_WITH_PREFIX} is\nimmobilized by love!"); +static const u8 sText_PkmnBlownAway[] = _("{B_DEF_NAME_WITH_PREFIX} was\nblown away!"); +static const u8 sText_PkmnChangedType[] = _("{B_ATK_NAME_WITH_PREFIX} transformed\ninto the {B_BUFF1} type!"); +static const u8 sText_PkmnFlinched[] = _("{B_ATK_NAME_WITH_PREFIX} flinched!"); +static const u8 sText_PkmnRegainedHealth[] = _("{B_DEF_NAME_WITH_PREFIX} regained\nhealth!"); +static const u8 sText_PkmnHPFull[] = _("{B_DEF_NAME_WITH_PREFIX}’s\nHP is full!"); +static const u8 sText_PkmnRaisedSpDef[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised SP. DEF!"); +static const u8 sText_PkmnRaisedSpDefALittle[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised SP. DEF a little!"); +static const u8 sText_PkmnRaisedDef[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised DEFENSE!"); +static const u8 sText_PkmnRaisedDefALittle[] = _("{B_ATK_PREFIX2}’s {B_CURRENT_MOVE}\nraised DEFENSE a little!"); +static const u8 sText_PkmnCoveredByVeil[] = _("{B_ATK_PREFIX2}’s party is covered\nby a veil!"); +static const u8 sText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}’s party is protected\nby SAFEGUARD!"); +static const u8 sText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}’s party is no longer\nprotected by SAFEGUARD!"); +static const u8 sText_PkmnWentToSleep[] = _("{B_ATK_NAME_WITH_PREFIX} went\nto sleep!"); +static const u8 sText_PkmnSleptHealthy[] = _("{B_ATK_NAME_WITH_PREFIX} slept and\nbecame healthy!"); +static const u8 sText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipped\nup a whirlwind!"); +static const u8 sText_PkmnTookSunlight[] = _("{B_ATK_NAME_WITH_PREFIX} took\nin sunlight!"); +static const u8 sText_PkmnLoweredHead[] = _("{B_ATK_NAME_WITH_PREFIX} lowered\nits head!"); +static const u8 sText_PkmnIsGlowing[] = _("{B_ATK_NAME_WITH_PREFIX} is glowing!"); +static const u8 sText_PkmnFlewHigh[] = _("{B_ATK_NAME_WITH_PREFIX} flew\nup high!"); +static const u8 sText_PkmnDugHole[] = _("{B_ATK_NAME_WITH_PREFIX} dug a hole!"); +static const u8 sText_PkmnHidUnderwater[] = _("{B_ATK_NAME_WITH_PREFIX} hid\nunderwater!"); +static const u8 sText_PkmnSprangUp[] = _("{B_ATK_NAME_WITH_PREFIX} sprang up!"); +static const u8 sText_PkmnSqueezedByBind[] = _("{B_DEF_NAME_WITH_PREFIX} was squeezed by\n{B_ATK_NAME_WITH_PREFIX}’s BIND!"); +static const u8 sText_PkmnTrappedInVortex[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nin the vortex!"); +static const u8 sText_PkmnTrappedBySandTomb[] = _("{B_DEF_NAME_WITH_PREFIX} was trapped\nby SAND TOMB!"); +static const u8 sText_PkmnWrappedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was WRAPPED by\n{B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnClamped[] = _("{B_ATK_NAME_WITH_PREFIX} CLAMPED\n{B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnHurtBy[] = _("{B_ATK_NAME_WITH_PREFIX} is hurt\nby {B_BUFF1}!"); +static const u8 sText_PkmnFreedFrom[] = _("{B_ATK_NAME_WITH_PREFIX} was freed\nfrom {B_BUFF1}!"); +static const u8 sText_PkmnCrashed[] = _("{B_ATK_NAME_WITH_PREFIX} kept going\nand crashed!"); const u8 gText_PkmnShroudedInMist[] = _("{B_ATK_PREFIX2} became\nshrouded in MIST!"); -const u8 gText_PkmnProtectedByMist[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is protected\nby MIST!"); +static const u8 sText_PkmnProtectedByMist[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is protected\nby MIST!"); const u8 gText_PkmnGettingPumped[] = _("{B_ATK_NAME_WITH_PREFIX} is getting\npumped!"); -const u8 gText_PkmnHitWithRecoil[] = _("{B_ATK_NAME_WITH_PREFIX} is hit\nwith recoil!"); -const u8 gText_PkmnProtectedItself2[] = _("{B_ATK_NAME_WITH_PREFIX} protected\nitself!"); -const u8 gText_PkmnBuffetedBySandstorm[] = _("{B_ATK_NAME_WITH_PREFIX} is buffeted\nby the sandstorm!"); -const u8 gText_PkmnPeltedByHail[] = _("{B_ATK_NAME_WITH_PREFIX} is pelted\nby HAIL!"); -const u8 gText_PkmnsXWoreOff[] = _("{B_ATK_PREFIX1}’s {B_BUFF1}\nwore off!"); -const u8 gText_PkmnSeeded[] = _("{B_DEF_NAME_WITH_PREFIX} was seeded!"); -const u8 gText_PkmnEvadedAttack[] = _("{B_DEF_NAME_WITH_PREFIX} evaded\nthe attack!"); -const u8 gText_PkmnSappedByLeechSeed[] = _("{B_ATK_NAME_WITH_PREFIX}’s health is\nsapped by LEECH SEED!"); -const u8 gText_PkmnFastAsleep[] = _("{B_ATK_NAME_WITH_PREFIX} is fast\nasleep."); -const u8 gText_PkmnWokeUp[] = _("{B_ATK_NAME_WITH_PREFIX} woke up!"); -const u8 gText_PkmnUproarKeptAwake[] = _("But {B_SCR_ACTIVE_NAME_WITH_PREFIX}’s UPROAR\nkept it awake!"); -const u8 gText_PkmnWokeUpInUproar[] = _("{B_ATK_NAME_WITH_PREFIX} woke up\nin the UPROAR!"); -const u8 gText_PkmnCausedUproar[] = _("{B_ATK_NAME_WITH_PREFIX} caused\nan UPROAR!"); -const u8 gText_PkmnMakingUproar[] = _("{B_ATK_NAME_WITH_PREFIX} is making\nan UPROAR!"); -const u8 gText_PkmnCalmedDown[] = _("{B_ATK_NAME_WITH_PREFIX} calmed down."); -const u8 gText_PkmnCantSleepInUproar[] = _("But {B_DEF_NAME_WITH_PREFIX} can’t\nsleep in an UPROAR!"); -const u8 gText_PkmnStockpiled[] = _("{B_ATK_NAME_WITH_PREFIX} STOCKPILED\n{B_BUFF1}!"); -const u8 gText_PkmnCantStockpile[] = _("{B_ATK_NAME_WITH_PREFIX} can’t\nSTOCKPILE any more!"); -const u8 gText_PkmnCantSleepInUproar2[] = _("But {B_DEF_NAME_WITH_PREFIX} can’t\nsleep in an UPROAR!"); -const u8 gText_UproarKeptPkmnAwake[] = _("But the UPROAR kept\n{B_DEF_NAME_WITH_PREFIX} awake!"); -const u8 gText_PkmnStayedAwakeUsing[] = _("{B_DEF_NAME_WITH_PREFIX} stayed awake\nusing its {B_DEF_ABILITY}!"); -const u8 gText_PkmnStoringEnergy[] = _("{B_ATK_NAME_WITH_PREFIX} is storing\nenergy!"); -const u8 gText_PkmnUnleashedEnergy[] = _("{B_ATK_NAME_WITH_PREFIX} unleashed\nenergy!"); -const u8 gText_PkmnFatigueConfusion[] = _("{B_ATK_NAME_WITH_PREFIX} became\nconfused due to fatigue!"); -const u8 gText_PkmnPickedUpItem[] = _("{B_PLAYER_NAME} picked up\n¥{B_BUFF1}!\p"); -const u8 gText_PkmnUnaffected[] = _("{B_DEF_NAME_WITH_PREFIX} is\nunaffected!"); -const u8 gText_PkmnTransformedInto[] = _("{B_ATK_NAME_WITH_PREFIX} transformed\ninto {B_BUFF1}!"); -const u8 gText_PkmnMadeSubstitute[] = _("{B_ATK_NAME_WITH_PREFIX} made\na SUBSTITUTE!"); -const u8 gText_PkmnHasSubstitute[] = _("{B_ATK_NAME_WITH_PREFIX} already\nhas a SUBSTITUTE!"); -const u8 gText_SubstituteDamaged[] = _("The SUBSTITUTE took damage\nfor {B_DEF_NAME_WITH_PREFIX}!\p"); -const u8 gText_PkmnSubstituteFaded[] = _("{B_DEF_NAME_WITH_PREFIX}’s\nSUBSTITUTE faded!\p"); -const u8 gText_PkmnMustRecharge[] = _("{B_ATK_NAME_WITH_PREFIX} must\nrecharge!"); -const u8 gText_PkmnRageBuilding[] = _("{B_DEF_NAME_WITH_PREFIX}’s RAGE\nis building!"); -const u8 gText_PkmnMoveWasDisabled[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\nwas disabled!"); -const u8 gText_PkmnMoveDisabledNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is disabled\nno more!"); -const u8 gText_PkmnGotEncore[] = _("{B_DEF_NAME_WITH_PREFIX} got\nan ENCORE!"); -const u8 gText_PkmnEncoreEnded[] = _("{B_ATK_NAME_WITH_PREFIX}’s ENCORE\nended!"); -const u8 gText_PkmnTookAim[] = _("{B_ATK_NAME_WITH_PREFIX} took aim\nat {B_DEF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnSketchedMove[] = _("{B_ATK_NAME_WITH_PREFIX} SKETCHED\n{B_BUFF1}!"); -const u8 gText_PkmnTryingToTakeFoe[] = _("{B_ATK_NAME_WITH_PREFIX} is trying\nto take its foe with it!"); -const u8 gText_PkmnTookFoe[] = _("{B_DEF_NAME_WITH_PREFIX} took\n{B_ATK_NAME_WITH_PREFIX} with it!"); -const u8 gText_PkmnReducedPP[] = _("Reduced {B_DEF_NAME_WITH_PREFIX}’s\n{B_BUFF1} by {B_BUFF2}!"); -const u8 gText_PkmnStoleItem[] = _("{B_ATK_NAME_WITH_PREFIX} stole\n{B_DEF_NAME_WITH_PREFIX}’s {B_LAST_ITEM}!"); -const u8 gText_TargetCantEscapeNow[] = _("{B_DEF_NAME_WITH_PREFIX} can’t\nescape now!"); -const u8 gText_PkmnFellIntoNightmare[] = _("{B_DEF_NAME_WITH_PREFIX} fell into\na NIGHTMARE!"); -const u8 gText_PkmnLockedInNightmare[] = _("{B_ATK_NAME_WITH_PREFIX} is locked\nin a NIGHTMARE!"); -const u8 gText_PkmnLaidCurse[] = _("{B_ATK_NAME_WITH_PREFIX} cut its own HP and\nlaid a CURSE on {B_DEF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnAfflictedByCurse[] = _("{B_ATK_NAME_WITH_PREFIX} is afflicted\nby the CURSE!"); -const u8 gText_SpikesScattered[] = _("SPIKES were scattered all around\nthe opponent’s side!"); -const u8 gText_PkmnHurtBySpikes[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is hurt\nby SPIKES!"); -const u8 gText_PkmnIdentified[] = _("{B_ATK_NAME_WITH_PREFIX} identified\n{B_DEF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnPerishCountFell[] = _("{B_ATK_NAME_WITH_PREFIX}’s PERISH count\nfell to {B_BUFF1}!"); -const u8 gText_PkmnBracedItself[] = _("{B_ATK_NAME_WITH_PREFIX} braced\nitself!"); -const u8 gText_PkmnEnduredHit[] = _("{B_DEF_NAME_WITH_PREFIX} ENDURED\nthe hit!"); -const u8 gText_MagnitudeStrength[] = _("MAGNITUDE {B_BUFF1}!"); -const u8 gText_PkmnCutHPMaxedAttack[] = _("{B_ATK_NAME_WITH_PREFIX} cut its own HP\nand maximized ATTACK!"); -const u8 gText_PkmnCopiedStatChanges[] = _("{B_ATK_NAME_WITH_PREFIX} copied\n{B_DEF_NAME_WITH_PREFIX}’s stat changes!"); -const u8 gText_PkmnGotFree[] = _("{B_ATK_NAME_WITH_PREFIX} got free of\n{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}!"); -const u8 gText_PkmnShedLeechSeed[] = _("{B_ATK_NAME_WITH_PREFIX} shed\nLEECH SEED!"); -const u8 gText_PkmnBlewAwaySpikes[] = _("{B_ATK_NAME_WITH_PREFIX} blew away\nSPIKES!"); -const u8 gText_PkmnFledFromBattle[] = _("{B_ATK_NAME_WITH_PREFIX} fled from\nbattle!"); -const u8 gText_PkmnForesawAttack[] = _("{B_ATK_NAME_WITH_PREFIX} foresaw\nan attack!"); -const u8 gText_PkmnTookAttack[] = _("{B_DEF_NAME_WITH_PREFIX} took the\n{B_BUFF1} attack!"); -const u8 gText_PkmnChoseXAsDestiny[] = _("{B_ATK_NAME_WITH_PREFIX} chose\n{B_CURRENT_MOVE} as its destiny!"); -const u8 gText_PkmnAttack[] = _("{B_BUFF1}’s attack!"); -const u8 gText_PkmnCenterAttention[] = _("{B_ATK_NAME_WITH_PREFIX} became the\ncenter of attention!"); -const u8 gText_PkmnChargingPower[] = _("{B_ATK_NAME_WITH_PREFIX} began\ncharging power!"); -const u8 gText_NaturePowerTurnedInto[] = _("NATURE POWER turned into\n{B_CURRENT_MOVE}!"); -const u8 gText_PkmnStatusNormal[] = _("{B_ATK_NAME_WITH_PREFIX}’s status\nreturned to normal!"); -const u8 gText_PkmnSubjectedToTorment[] = _("{B_DEF_NAME_WITH_PREFIX} was subjected\nto TORMENT!"); -const u8 gText_PkmnTighteningFocus[] = _("{B_ATK_NAME_WITH_PREFIX} is tightening\nits focus!"); -const u8 gText_PkmnFellForTaunt[] = _("{B_DEF_NAME_WITH_PREFIX} fell for\nthe TAUNT!"); -const u8 gText_PkmnReadyToHelp[] = _("{B_ATK_NAME_WITH_PREFIX} is ready to\nhelp {B_DEF_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnSwitchedItems[] = _("{B_ATK_NAME_WITH_PREFIX} switched\nitems with its opponent!"); -const u8 gText_PkmnObtainedX[] = _("{B_ATK_NAME_WITH_PREFIX} obtained\n{B_BUFF1}."); -const u8 gText_PkmnObtainedX2[] = _("{B_DEF_NAME_WITH_PREFIX} obtained\n{B_BUFF2}."); -const u8 gText_PkmnObtainedXYObtainedZ[] = _("{B_ATK_NAME_WITH_PREFIX} obtained\n{B_BUFF1}.\p{B_DEF_NAME_WITH_PREFIX} obtained\n{B_BUFF2}."); -const u8 gText_PkmnCopiedFoe[] = _("{B_ATK_NAME_WITH_PREFIX} copied\n{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}!"); -const u8 gText_PkmnMadeWish[] = _("{B_ATK_NAME_WITH_PREFIX} made a WISH!"); -const u8 gText_PkmnWishCameTrue[] = _("{B_BUFF1}’s WISH\ncame true!"); -const u8 gText_PkmnPlantedRoots[] = _("{B_ATK_NAME_WITH_PREFIX} planted its roots!"); -const u8 gText_PkmnAbsorbedNutrients[] = _("{B_ATK_NAME_WITH_PREFIX} absorbed\nnutrients with its roots!"); -const u8 gText_PkmnAnchoredItself[] = _("{B_DEF_NAME_WITH_PREFIX} anchored\nitself with its roots!"); -const u8 gText_PkmnWasMadeDrowsy[] = _("{B_ATK_NAME_WITH_PREFIX} made\n{B_DEF_NAME_WITH_PREFIX} drowsy!"); -const u8 gText_PkmnKnockedOff[] = _("{B_ATK_NAME_WITH_PREFIX} knocked off\n{B_DEF_NAME_WITH_PREFIX}’s {B_LAST_ITEM}!"); -const u8 gText_PkmnSwappedAbilities[] = _("{B_ATK_NAME_WITH_PREFIX} swapped abilities\nwith its opponent!"); -const u8 gText_PkmnSealedOpponentMove[] = _("{B_ATK_NAME_WITH_PREFIX} sealed the\nopponent’s move(s)!"); -const u8 gText_PkmnWantsGrudge[] = _("{B_ATK_NAME_WITH_PREFIX} wants the\nopponent to bear a GRUDGE!"); -const u8 gText_PkmnLostPPGrudge[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1} lost\nall its PP due to the GRUDGE!"); -const u8 gText_PkmnShroudedItself[] = _("{B_ATK_NAME_WITH_PREFIX} shrouded\nitself in {B_CURRENT_MOVE}!"); -const u8 gText_PkmnMoveBounced[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_CURRENT_MOVE}\nwas bounced back by MAGIC COAT!"); -const u8 gText_PkmnWaitsForTarget[] = _("{B_ATK_NAME_WITH_PREFIX} waits for a target\nto make a move!"); -const u8 gText_PkmnSnatchedMove[] = _("{B_DEF_NAME_WITH_PREFIX} SNATCHED\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s move!"); -const u8 gText_ElectricityWeakened[] = _("Electricity’s power was\nweakened!"); -const u8 gText_FireWeakened[] = _("Fire’s power was\nweakened!"); -const u8 gText_XFoundOneY[] = _("{B_ATK_NAME_WITH_PREFIX} found\none {B_LAST_ITEM}!"); -const u8 gText_SoothingAroma[] = _("A soothing aroma wafted\nthrough the area!"); -const u8 gText_ItemsCantBeUsedNow[] = _("Items can’t be used now.{PAUSE 64}"); -const u8 gText_ForXCommaYZ[] = _("For {B_SCR_ACTIVE_NAME_WITH_PREFIX},\n{B_LAST_ITEM} {B_BUFF1}"); -const u8 gText_PkmnUsedXToGetPumped[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} used\n{B_LAST_ITEM} to get pumped!"); -const u8 gText_PkmnLostFocus[] = _("{B_ATK_NAME_WITH_PREFIX} lost its\nfocus and couldn’t move!"); -const u8 gText_PkmnWasDraggedOut[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndragged out!\p"); -const u8 gText_TheWallShattered[] = _("The wall shattered!"); -const u8 gText_ButNoEffect[] = _("But it had no effect!"); -const u8 gText_PkmnHasNoMovesLeft[] = _("{B_ACTIVE_NAME_WITH_PREFIX} has no\nmoves left!\p"); -const u8 gText_PkmnMoveIsDisabled[] = _("{B_ACTIVE_NAME_WITH_PREFIX}’s {B_CURRENT_MOVE}\nis disabled!\p"); -const u8 gText_PkmnCantUseMoveTorment[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use the same\nmove in a row due to the TORMENT!\p"); -const u8 gText_PkmnCantUseMoveTaunt[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use\n{B_CURRENT_MOVE} after the TAUNT!\p"); -const u8 gText_PkmnCantUseMoveSealed[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use the\nsealed {B_CURRENT_MOVE}!\p"); -const u8 gText_PkmnMadeItRain[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade it rain!"); -const u8 gText_PkmnRaisedSpeed[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nraised its SPEED!"); -const u8 gText_PkmnProtectedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was protected\nby {B_DEF_ABILITY}!"); -const u8 gText_PkmnPreventsUsage[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents {B_ATK_NAME_WITH_PREFIX}\lfrom using {B_CURRENT_MOVE}!"); -const u8 gText_PkmnRestoredHPUsing[] = _("{B_DEF_NAME_WITH_PREFIX} restored HP\nusing its {B_DEF_ABILITY}!"); -const u8 gText_PkmnsXMadeYUseless[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade {B_CURRENT_MOVE} useless!"); -const u8 gText_PkmnChangedTypeWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade it the {B_BUFF1} type!"); -const u8 gText_PkmnPreventsParalysisWith[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents paralysis!"); -const u8 gText_PkmnPreventsRomanceWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents romance!"); -const u8 gText_PkmnPreventsPoisoningWith[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents poisoning!"); -const u8 gText_PkmnPreventsConfusionWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents confusion!"); -const u8 gText_PkmnRaisedFirePowerWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nraised its FIRE power!"); -const u8 gText_PkmnAnchorsItselfWith[] = _("{B_DEF_NAME_WITH_PREFIX} anchors\nitself with {B_DEF_ABILITY}!"); -const u8 gText_PkmnCutsAttackWith[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncuts {B_DEF_NAME_WITH_PREFIX}’s ATTACK!"); -const u8 gText_PkmnPreventsStatLossWith[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nprevents stat loss!"); -const u8 gText_PkmnHurtsWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nhurt {B_ATK_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnTraced[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} TRACED\n{B_BUFF1}’s {B_BUFF2}!"); -const u8 gText_PkmnsXPreventsBurns[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_EFF_ABILITY}\nprevents burns!"); -const u8 gText_PkmnsXBlocksY[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nblocks {B_CURRENT_MOVE}!"); -const u8 gText_PkmnsXBlocksY2[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nblocks {B_CURRENT_MOVE}!"); -const u8 gText_PkmnsXRestoredHPALittle2[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_ATK_ABILITY}\nrestored its HP a little!"); -const u8 gText_PkmnsXWhippedUpSandstorm[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nwhipped up a sandstorm!"); -const u8 gText_PkmnsXIntensifiedSun[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nintensified the sun’s rays!"); -const u8 gText_PkmnsXPreventsYLoss[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nprevents {B_BUFF1} loss!"); -const u8 gText_PkmnsXInfatuatedY[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\ninfatuated {B_ATK_NAME_WITH_PREFIX}!"); -const u8 gText_PkmnsXMadeYIneffective[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade {B_CURRENT_MOVE} ineffective!"); -const u8 gText_PkmnsXCuredYProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncured its {B_BUFF1} problem!"); -const u8 gText_ItSuckedLiquidOoze[] = _("It sucked up the\nLIQUID OOZE!"); -const u8 gText_PkmnTransformed[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} transformed!"); -const u8 gText_PkmnsXTookAttack[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\ntook the attack!"); +static const u8 sText_PkmnHitWithRecoil[] = _("{B_ATK_NAME_WITH_PREFIX} is hit\nwith recoil!"); +static const u8 sText_PkmnProtectedItself2[] = _("{B_ATK_NAME_WITH_PREFIX} protected\nitself!"); +static const u8 sText_PkmnBuffetedBySandstorm[] = _("{B_ATK_NAME_WITH_PREFIX} is buffeted\nby the sandstorm!"); +static const u8 sText_PkmnPeltedByHail[] = _("{B_ATK_NAME_WITH_PREFIX} is pelted\nby HAIL!"); +static const u8 sText_PkmnsXWoreOff[] = _("{B_ATK_PREFIX1}’s {B_BUFF1}\nwore off!"); +static const u8 sText_PkmnSeeded[] = _("{B_DEF_NAME_WITH_PREFIX} was seeded!"); +static const u8 sText_PkmnEvadedAttack[] = _("{B_DEF_NAME_WITH_PREFIX} evaded\nthe attack!"); +static const u8 sText_PkmnSappedByLeechSeed[] = _("{B_ATK_NAME_WITH_PREFIX}’s health is\nsapped by LEECH SEED!"); +static const u8 sText_PkmnFastAsleep[] = _("{B_ATK_NAME_WITH_PREFIX} is fast\nasleep."); +static const u8 sText_PkmnWokeUp[] = _("{B_ATK_NAME_WITH_PREFIX} woke up!"); +static const u8 sText_PkmnUproarKeptAwake[] = _("But {B_SCR_ACTIVE_NAME_WITH_PREFIX}’s UPROAR\nkept it awake!"); +static const u8 sText_PkmnWokeUpInUproar[] = _("{B_ATK_NAME_WITH_PREFIX} woke up\nin the UPROAR!"); +static const u8 sText_PkmnCausedUproar[] = _("{B_ATK_NAME_WITH_PREFIX} caused\nan UPROAR!"); +static const u8 sText_PkmnMakingUproar[] = _("{B_ATK_NAME_WITH_PREFIX} is making\nan UPROAR!"); +static const u8 sText_PkmnCalmedDown[] = _("{B_ATK_NAME_WITH_PREFIX} calmed down."); +static const u8 sText_PkmnCantSleepInUproar[] = _("But {B_DEF_NAME_WITH_PREFIX} can’t\nsleep in an UPROAR!"); +static const u8 sText_PkmnStockpiled[] = _("{B_ATK_NAME_WITH_PREFIX} STOCKPILED\n{B_BUFF1}!"); +static const u8 sText_PkmnCantStockpile[] = _("{B_ATK_NAME_WITH_PREFIX} can’t\nSTOCKPILE any more!"); +static const u8 sText_PkmnCantSleepInUproar2[] = _("But {B_DEF_NAME_WITH_PREFIX} can’t\nsleep in an UPROAR!"); +static const u8 sText_UproarKeptPkmnAwake[] = _("But the UPROAR kept\n{B_DEF_NAME_WITH_PREFIX} awake!"); +static const u8 sText_PkmnStayedAwakeUsing[] = _("{B_DEF_NAME_WITH_PREFIX} stayed awake\nusing its {B_DEF_ABILITY}!"); +static const u8 sText_PkmnStoringEnergy[] = _("{B_ATK_NAME_WITH_PREFIX} is storing\nenergy!"); +static const u8 sText_PkmnUnleashedEnergy[] = _("{B_ATK_NAME_WITH_PREFIX} unleashed\nenergy!"); +static const u8 sText_PkmnFatigueConfusion[] = _("{B_ATK_NAME_WITH_PREFIX} became\nconfused due to fatigue!"); +static const u8 sText_PkmnPickedUpItem[] = _("{B_PLAYER_NAME} picked up\n¥{B_BUFF1}!\p"); +static const u8 sText_PkmnUnaffected[] = _("{B_DEF_NAME_WITH_PREFIX} is\nunaffected!"); +static const u8 sText_PkmnTransformedInto[] = _("{B_ATK_NAME_WITH_PREFIX} transformed\ninto {B_BUFF1}!"); +static const u8 sText_PkmnMadeSubstitute[] = _("{B_ATK_NAME_WITH_PREFIX} made\na SUBSTITUTE!"); +static const u8 sText_PkmnHasSubstitute[] = _("{B_ATK_NAME_WITH_PREFIX} already\nhas a SUBSTITUTE!"); +static const u8 sText_SubstituteDamaged[] = _("The SUBSTITUTE took damage\nfor {B_DEF_NAME_WITH_PREFIX}!\p"); +static const u8 sText_PkmnSubstituteFaded[] = _("{B_DEF_NAME_WITH_PREFIX}’s\nSUBSTITUTE faded!\p"); +static const u8 sText_PkmnMustRecharge[] = _("{B_ATK_NAME_WITH_PREFIX} must\nrecharge!"); +static const u8 sText_PkmnRageBuilding[] = _("{B_DEF_NAME_WITH_PREFIX}’s RAGE\nis building!"); +static const u8 sText_PkmnMoveWasDisabled[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\nwas disabled!"); +static const u8 sText_PkmnMoveDisabledNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is disabled\nno more!"); +static const u8 sText_PkmnGotEncore[] = _("{B_DEF_NAME_WITH_PREFIX} got\nan ENCORE!"); +static const u8 sText_PkmnEncoreEnded[] = _("{B_ATK_NAME_WITH_PREFIX}’s ENCORE\nended!"); +static const u8 sText_PkmnTookAim[] = _("{B_ATK_NAME_WITH_PREFIX} took aim\nat {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnSketchedMove[] = _("{B_ATK_NAME_WITH_PREFIX} SKETCHED\n{B_BUFF1}!"); +static const u8 sText_PkmnTryingToTakeFoe[] = _("{B_ATK_NAME_WITH_PREFIX} is trying\nto take its foe with it!"); +static const u8 sText_PkmnTookFoe[] = _("{B_DEF_NAME_WITH_PREFIX} took\n{B_ATK_NAME_WITH_PREFIX} with it!"); +static const u8 sText_PkmnReducedPP[] = _("Reduced {B_DEF_NAME_WITH_PREFIX}’s\n{B_BUFF1} by {B_BUFF2}!"); +static const u8 sText_PkmnStoleItem[] = _("{B_ATK_NAME_WITH_PREFIX} stole\n{B_DEF_NAME_WITH_PREFIX}’s {B_LAST_ITEM}!"); +static const u8 sText_TargetCantEscapeNow[] = _("{B_DEF_NAME_WITH_PREFIX} can’t\nescape now!"); +static const u8 sText_PkmnFellIntoNightmare[] = _("{B_DEF_NAME_WITH_PREFIX} fell into\na NIGHTMARE!"); +static const u8 sText_PkmnLockedInNightmare[] = _("{B_ATK_NAME_WITH_PREFIX} is locked\nin a NIGHTMARE!"); +static const u8 sText_PkmnLaidCurse[] = _("{B_ATK_NAME_WITH_PREFIX} cut its own HP and\nlaid a CURSE on {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnAfflictedByCurse[] = _("{B_ATK_NAME_WITH_PREFIX} is afflicted\nby the CURSE!"); +static const u8 sText_SpikesScattered[] = _("SPIKES were scattered all around\nthe opponent’s side!"); +static const u8 sText_PkmnHurtBySpikes[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is hurt\nby SPIKES!"); +static const u8 sText_PkmnIdentified[] = _("{B_ATK_NAME_WITH_PREFIX} identified\n{B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnPerishCountFell[] = _("{B_ATK_NAME_WITH_PREFIX}’s PERISH count\nfell to {B_BUFF1}!"); +static const u8 sText_PkmnBracedItself[] = _("{B_ATK_NAME_WITH_PREFIX} braced\nitself!"); +static const u8 sText_PkmnEnduredHit[] = _("{B_DEF_NAME_WITH_PREFIX} ENDURED\nthe hit!"); +static const u8 sText_MagnitudeStrength[] = _("MAGNITUDE {B_BUFF1}!"); +static const u8 sText_PkmnCutHPMaxedAttack[] = _("{B_ATK_NAME_WITH_PREFIX} cut its own HP\nand maximized ATTACK!"); +static const u8 sText_PkmnCopiedStatChanges[] = _("{B_ATK_NAME_WITH_PREFIX} copied\n{B_DEF_NAME_WITH_PREFIX}’s stat changes!"); +static const u8 sText_PkmnGotFree[] = _("{B_ATK_NAME_WITH_PREFIX} got free of\n{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}!"); +static const u8 sText_PkmnShedLeechSeed[] = _("{B_ATK_NAME_WITH_PREFIX} shed\nLEECH SEED!"); +static const u8 sText_PkmnBlewAwaySpikes[] = _("{B_ATK_NAME_WITH_PREFIX} blew away\nSPIKES!"); +static const u8 sText_PkmnFledFromBattle[] = _("{B_ATK_NAME_WITH_PREFIX} fled from\nbattle!"); +static const u8 sText_PkmnForesawAttack[] = _("{B_ATK_NAME_WITH_PREFIX} foresaw\nan attack!"); +static const u8 sText_PkmnTookAttack[] = _("{B_DEF_NAME_WITH_PREFIX} took the\n{B_BUFF1} attack!"); +static const u8 sText_PkmnChoseXAsDestiny[] = _("{B_ATK_NAME_WITH_PREFIX} chose\n{B_CURRENT_MOVE} as its destiny!"); +static const u8 sText_PkmnAttack[] = _("{B_BUFF1}’s attack!"); +static const u8 sText_PkmnCenterAttention[] = _("{B_ATK_NAME_WITH_PREFIX} became the\ncenter of attention!"); +static const u8 sText_PkmnChargingPower[] = _("{B_ATK_NAME_WITH_PREFIX} began\ncharging power!"); +static const u8 sText_NaturePowerTurnedInto[] = _("NATURE POWER turned into\n{B_CURRENT_MOVE}!"); +static const u8 sText_PkmnStatusNormal[] = _("{B_ATK_NAME_WITH_PREFIX}’s status\nreturned to normal!"); +static const u8 sText_PkmnSubjectedToTorment[] = _("{B_DEF_NAME_WITH_PREFIX} was subjected\nto TORMENT!"); +static const u8 sText_PkmnTighteningFocus[] = _("{B_ATK_NAME_WITH_PREFIX} is tightening\nits focus!"); +static const u8 sText_PkmnFellForTaunt[] = _("{B_DEF_NAME_WITH_PREFIX} fell for\nthe TAUNT!"); +static const u8 sText_PkmnReadyToHelp[] = _("{B_ATK_NAME_WITH_PREFIX} is ready to\nhelp {B_DEF_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnSwitchedItems[] = _("{B_ATK_NAME_WITH_PREFIX} switched\nitems with its opponent!"); +static const u8 sText_PkmnObtainedX[] = _("{B_ATK_NAME_WITH_PREFIX} obtained\n{B_BUFF1}."); +static const u8 sText_PkmnObtainedX2[] = _("{B_DEF_NAME_WITH_PREFIX} obtained\n{B_BUFF2}."); +static const u8 sText_PkmnObtainedXYObtainedZ[] = _("{B_ATK_NAME_WITH_PREFIX} obtained\n{B_BUFF1}.\p{B_DEF_NAME_WITH_PREFIX} obtained\n{B_BUFF2}."); +static const u8 sText_PkmnCopiedFoe[] = _("{B_ATK_NAME_WITH_PREFIX} copied\n{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}!"); +static const u8 sText_PkmnMadeWish[] = _("{B_ATK_NAME_WITH_PREFIX} made a WISH!"); +static const u8 sText_PkmnWishCameTrue[] = _("{B_BUFF1}’s WISH\ncame true!"); +static const u8 sText_PkmnPlantedRoots[] = _("{B_ATK_NAME_WITH_PREFIX} planted its roots!"); +static const u8 sText_PkmnAbsorbedNutrients[] = _("{B_ATK_NAME_WITH_PREFIX} absorbed\nnutrients with its roots!"); +static const u8 sText_PkmnAnchoredItself[] = _("{B_DEF_NAME_WITH_PREFIX} anchored\nitself with its roots!"); +static const u8 sText_PkmnWasMadeDrowsy[] = _("{B_ATK_NAME_WITH_PREFIX} made\n{B_DEF_NAME_WITH_PREFIX} drowsy!"); +static const u8 sText_PkmnKnockedOff[] = _("{B_ATK_NAME_WITH_PREFIX} knocked off\n{B_DEF_NAME_WITH_PREFIX}’s {B_LAST_ITEM}!"); +static const u8 sText_PkmnSwappedAbilities[] = _("{B_ATK_NAME_WITH_PREFIX} swapped abilities\nwith its opponent!"); +static const u8 sText_PkmnSealedOpponentMove[] = _("{B_ATK_NAME_WITH_PREFIX} sealed the\nopponent’s move(s)!"); +static const u8 sText_PkmnWantsGrudge[] = _("{B_ATK_NAME_WITH_PREFIX} wants the\nopponent to bear a GRUDGE!"); +static const u8 sText_PkmnLostPPGrudge[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1} lost\nall its PP due to the GRUDGE!"); +static const u8 sText_PkmnShroudedItself[] = _("{B_ATK_NAME_WITH_PREFIX} shrouded\nitself in {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnMoveBounced[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_CURRENT_MOVE}\nwas bounced back by MAGIC COAT!"); +static const u8 sText_PkmnWaitsForTarget[] = _("{B_ATK_NAME_WITH_PREFIX} waits for a target\nto make a move!"); +static const u8 sText_PkmnSnatchedMove[] = _("{B_DEF_NAME_WITH_PREFIX} SNATCHED\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s move!"); +static const u8 sText_ElectricityWeakened[] = _("Electricity’s power was\nweakened!"); +static const u8 sText_FireWeakened[] = _("Fire’s power was\nweakened!"); +static const u8 sText_XFoundOneY[] = _("{B_ATK_NAME_WITH_PREFIX} found\none {B_LAST_ITEM}!"); +static const u8 sText_SoothingAroma[] = _("A soothing aroma wafted\nthrough the area!"); +static const u8 sText_ItemsCantBeUsedNow[] = _("Items can’t be used now.{PAUSE 64}"); +static const u8 sText_ForXCommaYZ[] = _("For {B_SCR_ACTIVE_NAME_WITH_PREFIX},\n{B_LAST_ITEM} {B_BUFF1}"); +static const u8 sText_PkmnUsedXToGetPumped[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} used\n{B_LAST_ITEM} to get pumped!"); +static const u8 sText_PkmnLostFocus[] = _("{B_ATK_NAME_WITH_PREFIX} lost its\nfocus and couldn’t move!"); +static const u8 sText_PkmnWasDraggedOut[] = _("{B_DEF_NAME_WITH_PREFIX} was\ndragged out!\p"); +static const u8 sText_TheWallShattered[] = _("The wall shattered!"); +static const u8 sText_ButNoEffect[] = _("But it had no effect!"); +static const u8 sText_PkmnHasNoMovesLeft[] = _("{B_ACTIVE_NAME_WITH_PREFIX} has no\nmoves left!\p"); +static const u8 sText_PkmnMoveIsDisabled[] = _("{B_ACTIVE_NAME_WITH_PREFIX}’s {B_CURRENT_MOVE}\nis disabled!\p"); +static const u8 sText_PkmnCantUseMoveTorment[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use the same\nmove in a row due to the TORMENT!\p"); +static const u8 sText_PkmnCantUseMoveTaunt[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use\n{B_CURRENT_MOVE} after the TAUNT!\p"); +static const u8 sText_PkmnCantUseMoveSealed[] = _("{B_ACTIVE_NAME_WITH_PREFIX} can’t use the\nsealed {B_CURRENT_MOVE}!\p"); +static const u8 sText_PkmnMadeItRain[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade it rain!"); +static const u8 sText_PkmnRaisedSpeed[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nraised its SPEED!"); +static const u8 sText_PkmnProtectedBy[] = _("{B_DEF_NAME_WITH_PREFIX} was protected\nby {B_DEF_ABILITY}!"); +static const u8 sText_PkmnPreventsUsage[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents {B_ATK_NAME_WITH_PREFIX}\lfrom using {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnRestoredHPUsing[] = _("{B_DEF_NAME_WITH_PREFIX} restored HP\nusing its {B_DEF_ABILITY}!"); +static const u8 sText_PkmnsXMadeYUseless[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade {B_CURRENT_MOVE} useless!"); +static const u8 sText_PkmnChangedTypeWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade it the {B_BUFF1} type!"); +static const u8 sText_PkmnPreventsParalysisWith[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents paralysis!"); +static const u8 sText_PkmnPreventsRomanceWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents romance!"); +static const u8 sText_PkmnPreventsPoisoningWith[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents poisoning!"); +static const u8 sText_PkmnPreventsConfusionWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevents confusion!"); +static const u8 sText_PkmnRaisedFirePowerWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nraised its FIRE power!"); +static const u8 sText_PkmnAnchorsItselfWith[] = _("{B_DEF_NAME_WITH_PREFIX} anchors\nitself with {B_DEF_ABILITY}!"); +static const u8 sText_PkmnCutsAttackWith[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncuts {B_DEF_NAME_WITH_PREFIX}’s ATTACK!"); +static const u8 sText_PkmnPreventsStatLossWith[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nprevents stat loss!"); +static const u8 sText_PkmnHurtsWith[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nhurt {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnTraced[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} TRACED\n{B_BUFF1}’s {B_BUFF2}!"); +static const u8 sText_PkmnsXPreventsBurns[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_EFF_ABILITY}\nprevents burns!"); +static const u8 sText_PkmnsXBlocksY[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nblocks {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnsXBlocksY2[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nblocks {B_CURRENT_MOVE}!"); +static const u8 sText_PkmnsXRestoredHPALittle2[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_ATK_ABILITY}\nrestored its HP a little!"); +static const u8 sText_PkmnsXWhippedUpSandstorm[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nwhipped up a sandstorm!"); +static const u8 sText_PkmnsXIntensifiedSun[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nintensified the sun’s rays!"); +static const u8 sText_PkmnsXPreventsYLoss[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nprevents {B_BUFF1} loss!"); +static const u8 sText_PkmnsXInfatuatedY[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\ninfatuated {B_ATK_NAME_WITH_PREFIX}!"); +static const u8 sText_PkmnsXMadeYIneffective[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nmade {B_CURRENT_MOVE} ineffective!"); +static const u8 sText_PkmnsXCuredYProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncured its {B_BUFF1} problem!"); +static const u8 sText_ItSuckedLiquidOoze[] = _("It sucked up the\nLIQUID OOZE!"); +static const u8 sText_PkmnTransformed[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} transformed!"); +static const u8 sText_PkmnsXTookAttack[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\ntook the attack!"); const u8 gText_PkmnsXPreventsSwitching[] = _("{B_BUFF1}’s {B_LAST_ABILITY}\nprevents switching!\p"); -const u8 gText_PreventedFromWorking[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevented {B_SCR_ACTIVE_NAME_WITH_PREFIX}’s\l{B_BUFF1} from working!"); -const u8 gText_PkmnsXMadeItIneffective[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade it ineffective!"); -const u8 gText_PkmnsXPreventsFlinching[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_EFF_ABILITY}\nprevents flinching!"); -const u8 gText_PkmnsXPreventsYsZ[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_ATK_ABILITY}\nprevents {B_DEF_NAME_WITH_PREFIX}’s\l{B_DEF_ABILITY} from working!"); -const u8 gText_PkmnsXCuredItsYProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncured its {B_BUFF1} problem!"); -const u8 gText_PkmnsXHadNoEffectOnY[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nhad no effect on {B_EFF_NAME_WITH_PREFIX}!"); -const u8 gText_StatSharply[] = _("sharply "); +static const u8 sText_PreventedFromWorking[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_DEF_ABILITY}\nprevented {B_SCR_ACTIVE_NAME_WITH_PREFIX}’s\l{B_BUFF1} from working!"); +static const u8 sText_PkmnsXMadeItIneffective[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nmade it ineffective!"); +static const u8 sText_PkmnsXPreventsFlinching[] = _("{B_EFF_NAME_WITH_PREFIX}’s {B_EFF_ABILITY}\nprevents flinching!"); +static const u8 sText_PkmnsXPreventsYsZ[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_ATK_ABILITY}\nprevents {B_DEF_NAME_WITH_PREFIX}’s\l{B_DEF_ABILITY} from working!"); +static const u8 sText_PkmnsXCuredItsYProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\ncured its {B_BUFF1} problem!"); +static const u8 sText_PkmnsXHadNoEffectOnY[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_SCR_ACTIVE_ABILITY}\nhad no effect on {B_EFF_NAME_WITH_PREFIX}!"); +static const u8 sText_StatSharply[] = _("sharply "); const u8 gText_StatRose[] = _("rose!"); -const u8 gText_StatHarshly[] = _("harshly "); -const u8 gText_StatFell[] = _("fell!"); -const u8 gText_PkmnsStatChanged[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); +static const u8 sText_StatHarshly[] = _("harshly "); +static const u8 sText_StatFell[] = _("fell!"); +static const u8 sText_PkmnsStatChanged[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); const u8 gText_PkmnsStatChanged2[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); -const u8 gText_UsingXTheYOfZN[] = _("Using {B_LAST_ITEM}, the {B_BUFF1}\nof {B_SCR_ACTIVE_NAME_WITH_PREFIX} {B_BUFF2}"); -const u8 gText_PkmnsStatChanged3[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); -const u8 gText_PkmnsStatChanged4[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); -const u8 gText_StatsWontIncrease2[] = _("{B_ATK_NAME_WITH_PREFIX}’s stats won’t\ngo any higher!"); -const u8 gText_StatsWontDecrease2[] = _("{B_DEF_NAME_WITH_PREFIX}’s stats won’t\ngo any lower!"); -const u8 gText_CriticalHit[] = _("A critical hit!"); -const u8 gText_OneHitKO[] = _("It’s a one-hit KO!"); -const u8 gText_123Poof[] = _("{PAUSE 32}1, {PAUSE 15}2, and{PAUSE 15}… {PAUSE 15}… {PAUSE 15}… {PAUSE 15}{PLAY_SE 0x0038}Poof!\p"); -const u8 gText_AndEllipsis[] = _("And…\p"); -const u8 gText_HMMovesCantBeForgotten[] = _("HM moves can’t be\nforgotten now.\p"); -const u8 gText_NotVeryEffective[] = _("It’s not very effective…"); -const u8 gText_SuperEffective[] = _("It’s super effective!"); -const u8 gText_GotAwaySafely[] = _("{PLAY_SE 0x0011}Got away safely!\p"); -const u8 gText_PkmnFledUsingIts[] = _("{PLAY_SE 0x0011}{B_ATK_NAME_WITH_PREFIX} fled\nusing its {B_LAST_ITEM}!\p"); -const u8 gText_PkmnFledUsing[] = _("{PLAY_SE 0x0011}{B_ATK_NAME_WITH_PREFIX} fled\nusing {B_ATK_ABILITY}!\p"); -const u8 gText_WildPkmnFled[] = _("{PLAY_SE 0x0011}Wild {B_BUFF1} fled!"); -const u8 gText_PlayerDefeatedLinkTrainer[] = _("Player defeated\n{B_20}!"); -const u8 gText_TwoLinkTrainersDefeated[] = _("Player beat {B_20}\nand {B_21}!"); -const u8 gText_PlayerLostAgainstLinkTrainer[] = _("Player lost against\n{B_20}!"); -const u8 gText_PlayerLostToTwo[] = _("Player lost to {B_20}\nand {B_21}!"); -const u8 gText_PlayerBattledToDrawLinkTrainer[] = _("Player battled to a draw against\n{B_20}!"); -const u8 gText_PlayerBattledToDrawVsTwo[] = _("Player battled to a draw against\n{B_20} and {B_21}!"); -const u8 gText_WildFled[] = _("{PLAY_SE 0x0011}{B_20} fled!"); -const u8 gText_TwoWildFled[] = _("{PLAY_SE 0x0011}{B_20} and\n{B_21} fled!"); -const u8 gText_NoRunningFromTrainers[] = _("No! There’s no running\nfrom a TRAINER battle!\p"); -const u8 gText_CantEscape[] = _("Can’t escape!\p"); -const u8 gText_DontLeaveBirch[] = _("PROF. BIRCH: Don’t leave me like this!\p"); -const u8 gText_ButNothingHappened[] = _("But nothing happened!"); -const u8 gText_ButItFailed[] = _("But it failed!"); -const u8 gText_ItHurtConfusion[] = _("It hurt itself in its\nconfusion!"); -const u8 gText_MirrorMoveFailed[] = _("The MIRROR MOVE failed!"); -const u8 gText_StartedToRain[] = _("It started to rain!"); -const u8 gText_DownpourStarted[] = _("A downpour started!"); -const u8 gText_RainContinues[] = _("Rain continues to fall."); -const u8 gText_DownpourContinues[] = _("The downpour continues."); -const u8 gText_RainStopped[] = _("The rain stopped."); -const u8 gText_SandstormBrewed[] = _("A sandstorm brewed!"); -const u8 gText_SandstormRages[] = _("The sandstorm rages."); -const u8 gText_SandstormSubsided[] = _("The sandstorm subsided."); -const u8 gText_SunlightGotBright[] = _("The sunlight got bright!"); -const u8 gText_SunlightStrong[] = _("The sunlight is strong."); -const u8 gText_SunlightFaded[] = _("The sunlight faded."); -const u8 gText_StartedHail[] = _("It started to hail!"); -const u8 gText_HailContinues[] = _("Hail continues to fall."); -const u8 gText_HailStopped[] = _("The hail stopped."); -const u8 gText_FailedToSpitUp[] = _("But it failed to SPIT UP\na thing!"); -const u8 gText_FailedToSwallow[] = _("But it failed to SWALLOW\na thing!"); -const u8 gText_WindBecameHeatWave[] = _("The wind turned into a\nHEAT WAVE!"); -const u8 gText_StatChangesGone[] = _("All stat changes were\neliminated!"); -const u8 gText_CoinsScattered[] = _("Coins scattered everywhere!"); -const u8 gText_TooWeakForSubstitute[] = _("It was too weak to make\na SUBSTITUTE!"); -const u8 gText_SharedPain[] = _("The battlers shared\ntheir pain!"); -const u8 gText_BellChimed[] = _("A bell chimed!"); -const u8 gText_FaintInThree[] = _("All affected POKéMON will\nfaint in three turns!"); -const u8 gText_NoPPLeft[] = _("There’s no PP left for\nthis move!\p"); -const u8 gText_ButNoPPLeft[] = _("But there was no PP left\nfor the move!"); -const u8 gText_PkmnIgnoresAsleep[] = _("{B_ATK_NAME_WITH_PREFIX} ignored\norders while asleep!"); -const u8 gText_PkmnIgnoredOrders[] = _("{B_ATK_NAME_WITH_PREFIX} ignored\norders!"); -const u8 gText_PkmnBeganToNap[] = _("{B_ATK_NAME_WITH_PREFIX} began to nap!"); -const u8 gText_PkmnLoafing[] = _("{B_ATK_NAME_WITH_PREFIX} is\nloafing around!"); -const u8 gText_PkmnWontObey[] = _("{B_ATK_NAME_WITH_PREFIX} won’t\nobey!"); -const u8 gText_PkmnTurnedAway[] = _("{B_ATK_NAME_WITH_PREFIX} turned away!"); -const u8 gText_PkmnPretendNotNotice[] = _("{B_ATK_NAME_WITH_PREFIX} pretended\nnot to notice!"); -const u8 gText_EnemyAboutToSwitchPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} is\nabout to use {B_BUFF2}.\pWill {B_PLAYER_NAME} change\nPOKéMON?"); -const u8 gText_PkmnLearnedMove2[] = _("{B_ATK_NAME_WITH_PREFIX} learned\n{B_BUFF1}!"); -const u8 gText_PlayerDefeatedLinkTrainerTrainer1[] = _("Player defeated\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!\p"); -const u8 gText_CreptCloser[] = _("{B_PLAYER_NAME} crept closer to\n{B_OPPONENT_MON1_NAME}!"); -const u8 gText_CantGetCloser[] = _("{B_PLAYER_NAME} can’t get any closer!"); -const u8 gText_PkmnWatchingCarefully[] = _("{B_OPPONENT_MON1_NAME} is watching\ncarefully!"); -const u8 gText_PkmnCuriousAboutX[] = _("{B_OPPONENT_MON1_NAME} is curious about\nthe {B_BUFF1}!"); -const u8 gText_PkmnEnthralledByX[] = _("{B_OPPONENT_MON1_NAME} is enthralled by\nthe {B_BUFF1}!"); -const u8 gText_PkmnIgnoredX[] = _("{B_OPPONENT_MON1_NAME} completely ignored\nthe {B_BUFF1}!"); -const u8 gText_ThrewPokeblockAtPkmn[] = _("{B_PLAYER_NAME} threw a {POKEBLOCK}\nat the {B_OPPONENT_MON1_NAME}!"); -const u8 gText_OutOfSafariBalls[] = _("{PLAY_SE 0x0049}ANNOUNCER: You’re out of\nSAFARI BALLS! Game over!\p"); -const u8 gText_OpponentMon1Appeared[] = _("{B_OPPONENT_MON1_NAME} appeared!\p"); -const u8 gText_WildPkmnAppeared[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!\p"); -const u8 gText_WildPkmnAppeared2[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!\p"); -const u8 gText_WildPkmnAppearedPause[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!{PAUSE 127}"); -const u8 gText_TwoWildPkmnAppeared[] = _("Wild {B_OPPONENT_MON1_NAME} and\n{B_OPPONENT_MON2_NAME} appeared!\p"); -const u8 gText_Trainer1WantsToBattle[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nwould like to battle!\p"); -const u8 gText_LinkTrainerWantsToBattle[] = _("{B_20}\nwants to battle!"); -const u8 gText_TwoLinkTrainersWantToBattle[] = _("{B_20} and {B_21}\nwant to battle!"); -const u8 gText_Trainer1SentOutPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME}!"); -const u8 gText_Trainer1SentOutTwoPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME} and {B_OPPONENT_MON2_NAME}!"); -const u8 gText_Trainer1SentOutPkmn2[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_BUFF1}!"); -const u8 gText_LinkTrainerSentOutPkmn[] = _("{B_20} sent out\n{B_OPPONENT_MON1_NAME}!"); -const u8 gText_LinkTrainerSentOutTwoPkmn[] = _("{B_20} sent out\n{B_OPPONENT_MON1_NAME} and {B_OPPONENT_MON2_NAME}!"); -const u8 gText_TwoLinkTrainersSentOutPkmn[] = _("{B_20} sent out {B_LINK_OPPONENT_MON1_NAME}!\n{B_21} sent out {B_LINK_OPPONENT_MON2_NAME}!"); -const u8 gText_LinkTrainerSentOutPkmn2[] = _("{B_20} sent out\n{B_BUFF1}!"); -const u8 gText_LinkTrainerMultiSentOutPkmn[] = _("{B_22} sent out\n{B_BUFF1}!"); -const u8 gText_GoPkmn[] = _("Go! {B_PLAYER_MON1_NAME}!"); -const u8 gText_GoTwoPkmn[] = _("Go! {B_PLAYER_MON1_NAME} and\n{B_PLAYER_MON2_NAME}!"); -const u8 gText_GoPkmn2[] = _("Go! {B_BUFF1}!"); -const u8 gText_DoItPkmn[] = _("Do it! {B_BUFF1}!"); -const u8 gText_GoForItPkmn[] = _("Go for it, {B_BUFF1}!"); -const u8 gText_YourFoesWeakGetEmPkmn[] = _("Your foe’s weak!\nGet ’em, {B_BUFF1}!"); -const u8 gText_LinkPartnerSentOutPkmnGoPkmn[] = _("{B_1F} sent out {B_LINK_PLAYER_MON2_NAME}!\nGo! {B_LINK_PLAYER_MON1_NAME}!"); -const u8 gText_PkmnThatsEnough[] = _("{B_BUFF1}, that’s enough!\nCome back!"); -const u8 gText_PkmnComeBack[] = _("{B_BUFF1}, come back!"); -const u8 gText_PkmnOkComeBack[] = _("{B_BUFF1}, OK!\nCome back!"); -const u8 gText_PkmnGoodComeBack[] = _("{B_BUFF1}, good!\nCome back!"); -const u8 gText_Trainer1WithdrewPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nwithdrew {B_BUFF1}!"); -const u8 gText_LinkTrainer1WithdrewPkmn[] = _("{B_20} withdrew\n{B_BUFF1}!"); -const u8 gText_LinkTrainer2WithdrewPkmn[] = _("{B_22} withdrew\n{B_BUFF1}!"); -const u8 gText_WildPkmnPrefix[] = _("Wild "); -const u8 gText_FoePkmnPrefix[] = _("Foe "); -const u8 gText_EmptyString8[] = _( ""); -const u8 gText_FoePkmnPrefix2[] = _("Foe"); -const u8 gText_AllyPkmnPrefix[] = _("Ally"); -const u8 gText_FoePkmnPrefix3[] = _("Foe"); -const u8 gText_AllyPkmnPrefix2[] = _("Ally"); -const u8 gText_FoePkmnPrefix4[] = _("Foe"); -const u8 gText_AllyPkmnPrefix3[] = _("Ally"); -const u8 gText_AttackerUsedX[] = _("{B_ATK_NAME_WITH_PREFIX} used\n{B_BUFF2}"); -const u8 gText_ExclamationMark[] = _("!"); -const u8 gText_ExclamationMark2[] = _("!"); -const u8 gText_ExclamationMark3[] = _("!"); -const u8 gText_ExclamationMark4[] = _("!"); -const u8 gText_ExclamationMark5[] = _("!"); -const u8 gText_HP2[] = _("HP"); -const u8 gText_Attack2[] = _("ATTACK"); -const u8 gText_Defense2[] = _("DEFENSE"); -const u8 gText_Speed[] = _("SPEED"); -const u8 gText_SpAtk2[] = _("SP. ATK"); -const u8 gText_SpDef2[] = _("SP. DEF"); -const u8 gText_Accuracy[] = _("accuracy"); -const u8 gText_Evasiveness[] = _("evasiveness"); +static const u8 sText_UsingXTheYOfZN[] = _("Using {B_LAST_ITEM}, the {B_BUFF1}\nof {B_SCR_ACTIVE_NAME_WITH_PREFIX} {B_BUFF2}"); +static const u8 sText_PkmnsStatChanged3[] = _("{B_ATK_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); +static const u8 sText_PkmnsStatChanged4[] = _("{B_DEF_NAME_WITH_PREFIX}’s {B_BUFF1}\n{B_BUFF2}"); +static const u8 sText_StatsWontIncrease2[] = _("{B_ATK_NAME_WITH_PREFIX}’s stats won’t\ngo any higher!"); +static const u8 sText_StatsWontDecrease2[] = _("{B_DEF_NAME_WITH_PREFIX}’s stats won’t\ngo any lower!"); +static const u8 sText_CriticalHit[] = _("A critical hit!"); +static const u8 sText_OneHitKO[] = _("It’s a one-hit KO!"); +static const u8 sText_123Poof[] = _("{PAUSE 32}1, {PAUSE 15}2, and{PAUSE 15}… {PAUSE 15}… {PAUSE 15}… {PAUSE 15}{PLAY_SE 0x0038}Poof!\p"); +static const u8 sText_AndEllipsis[] = _("And…\p"); +static const u8 sText_HMMovesCantBeForgotten[] = _("HM moves can’t be\nforgotten now.\p"); +static const u8 sText_NotVeryEffective[] = _("It’s not very effective…"); +static const u8 sText_SuperEffective[] = _("It’s super effective!"); +static const u8 sText_GotAwaySafely[] = _("{PLAY_SE 0x0011}Got away safely!\p"); +static const u8 sText_PkmnFledUsingIts[] = _("{PLAY_SE 0x0011}{B_ATK_NAME_WITH_PREFIX} fled\nusing its {B_LAST_ITEM}!\p"); +static const u8 sText_PkmnFledUsing[] = _("{PLAY_SE 0x0011}{B_ATK_NAME_WITH_PREFIX} fled\nusing {B_ATK_ABILITY}!\p"); +static const u8 sText_WildPkmnFled[] = _("{PLAY_SE 0x0011}Wild {B_BUFF1} fled!"); +static const u8 sText_PlayerDefeatedLinkTrainer[] = _("Player defeated\n{B_20}!"); +static const u8 sText_TwoLinkTrainersDefeated[] = _("Player beat {B_20}\nand {B_21}!"); +static const u8 sText_PlayerLostAgainstLinkTrainer[] = _("Player lost against\n{B_20}!"); +static const u8 sText_PlayerLostToTwo[] = _("Player lost to {B_20}\nand {B_21}!"); +static const u8 sText_PlayerBattledToDrawLinkTrainer[] = _("Player battled to a draw against\n{B_20}!"); +static const u8 sText_PlayerBattledToDrawVsTwo[] = _("Player battled to a draw against\n{B_20} and {B_21}!"); +static const u8 sText_WildFled[] = _("{PLAY_SE 0x0011}{B_20} fled!"); +static const u8 sText_TwoWildFled[] = _("{PLAY_SE 0x0011}{B_20} and\n{B_21} fled!"); +static const u8 sText_NoRunningFromTrainers[] = _("No! There’s no running\nfrom a TRAINER battle!\p"); +static const u8 sText_CantEscape[] = _("Can’t escape!\p"); +static const u8 sText_DontLeaveBirch[] = _("PROF. BIRCH: Don’t leave me like this!\p"); +static const u8 sText_ButNothingHappened[] = _("But nothing happened!"); +static const u8 sText_ButItFailed[] = _("But it failed!"); +static const u8 sText_ItHurtConfusion[] = _("It hurt itself in its\nconfusion!"); +static const u8 sText_MirrorMoveFailed[] = _("The MIRROR MOVE failed!"); +static const u8 sText_StartedToRain[] = _("It started to rain!"); +static const u8 sText_DownpourStarted[] = _("A downpour started!"); +static const u8 sText_RainContinues[] = _("Rain continues to fall."); +static const u8 sText_DownpourContinues[] = _("The downpour continues."); +static const u8 sText_RainStopped[] = _("The rain stopped."); +static const u8 sText_SandstormBrewed[] = _("A sandstorm brewed!"); +static const u8 sText_SandstormRages[] = _("The sandstorm rages."); +static const u8 sText_SandstormSubsided[] = _("The sandstorm subsided."); +static const u8 sText_SunlightGotBright[] = _("The sunlight got bright!"); +static const u8 sText_SunlightStrong[] = _("The sunlight is strong."); +static const u8 sText_SunlightFaded[] = _("The sunlight faded."); +static const u8 sText_StartedHail[] = _("It started to hail!"); +static const u8 sText_HailContinues[] = _("Hail continues to fall."); +static const u8 sText_HailStopped[] = _("The hail stopped."); +static const u8 sText_FailedToSpitUp[] = _("But it failed to SPIT UP\na thing!"); +static const u8 sText_FailedToSwallow[] = _("But it failed to SWALLOW\na thing!"); +static const u8 sText_WindBecameHeatWave[] = _("The wind turned into a\nHEAT WAVE!"); +static const u8 sText_StatChangesGone[] = _("All stat changes were\neliminated!"); +static const u8 sText_CoinsScattered[] = _("Coins scattered everywhere!"); +static const u8 sText_TooWeakForSubstitute[] = _("It was too weak to make\na SUBSTITUTE!"); +static const u8 sText_SharedPain[] = _("The battlers shared\ntheir pain!"); +static const u8 sText_BellChimed[] = _("A bell chimed!"); +static const u8 sText_FaintInThree[] = _("All affected POKéMON will\nfaint in three turns!"); +static const u8 sText_NoPPLeft[] = _("There’s no PP left for\nthis move!\p"); +static const u8 sText_ButNoPPLeft[] = _("But there was no PP left\nfor the move!"); +static const u8 sText_PkmnIgnoresAsleep[] = _("{B_ATK_NAME_WITH_PREFIX} ignored\norders while asleep!"); +static const u8 sText_PkmnIgnoredOrders[] = _("{B_ATK_NAME_WITH_PREFIX} ignored\norders!"); +static const u8 sText_PkmnBeganToNap[] = _("{B_ATK_NAME_WITH_PREFIX} began to nap!"); +static const u8 sText_PkmnLoafing[] = _("{B_ATK_NAME_WITH_PREFIX} is\nloafing around!"); +static const u8 sText_PkmnWontObey[] = _("{B_ATK_NAME_WITH_PREFIX} won’t\nobey!"); +static const u8 sText_PkmnTurnedAway[] = _("{B_ATK_NAME_WITH_PREFIX} turned away!"); +static const u8 sText_PkmnPretendNotNotice[] = _("{B_ATK_NAME_WITH_PREFIX} pretended\nnot to notice!"); +static const u8 sText_EnemyAboutToSwitchPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} is\nabout to use {B_BUFF2}.\pWill {B_PLAYER_NAME} change\nPOKéMON?"); +static const u8 sText_PkmnLearnedMove2[] = _("{B_ATK_NAME_WITH_PREFIX} learned\n{B_BUFF1}!"); +static const u8 sText_PlayerDefeatedLinkTrainerTrainer1[] = _("Player defeated\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!\p"); +static const u8 sText_CreptCloser[] = _("{B_PLAYER_NAME} crept closer to\n{B_OPPONENT_MON1_NAME}!"); +static const u8 sText_CantGetCloser[] = _("{B_PLAYER_NAME} can’t get any closer!"); +static const u8 sText_PkmnWatchingCarefully[] = _("{B_OPPONENT_MON1_NAME} is watching\ncarefully!"); +static const u8 sText_PkmnCuriousAboutX[] = _("{B_OPPONENT_MON1_NAME} is curious about\nthe {B_BUFF1}!"); +static const u8 sText_PkmnEnthralledByX[] = _("{B_OPPONENT_MON1_NAME} is enthralled by\nthe {B_BUFF1}!"); +static const u8 sText_PkmnIgnoredX[] = _("{B_OPPONENT_MON1_NAME} completely ignored\nthe {B_BUFF1}!"); +static const u8 sText_ThrewPokeblockAtPkmn[] = _("{B_PLAYER_NAME} threw a {POKEBLOCK}\nat the {B_OPPONENT_MON1_NAME}!"); +static const u8 sText_OutOfSafariBalls[] = _("{PLAY_SE 0x0049}ANNOUNCER: You’re out of\nSAFARI BALLS! Game over!\p"); +static const u8 sText_OpponentMon1Appeared[] = _("{B_OPPONENT_MON1_NAME} appeared!\p"); +static const u8 sText_WildPkmnAppeared[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!\p"); +static const u8 sText_WildPkmnAppeared2[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!\p"); +static const u8 sText_WildPkmnAppearedPause[] = _("Wild {B_OPPONENT_MON1_NAME} appeared!{PAUSE 127}"); +static const u8 sText_TwoWildPkmnAppeared[] = _("Wild {B_OPPONENT_MON1_NAME} and\n{B_OPPONENT_MON2_NAME} appeared!\p"); +static const u8 sText_Trainer1WantsToBattle[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nwould like to battle!\p"); +static const u8 sText_LinkTrainerWantsToBattle[] = _("{B_20}\nwants to battle!"); +static const u8 sText_TwoLinkTrainersWantToBattle[] = _("{B_20} and {B_21}\nwant to battle!"); +static const u8 sText_Trainer1SentOutPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME}!"); +static const u8 sText_Trainer1SentOutTwoPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME} and {B_OPPONENT_MON2_NAME}!"); +static const u8 sText_Trainer1SentOutPkmn2[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_BUFF1}!"); +static const u8 sText_LinkTrainerSentOutPkmn[] = _("{B_20} sent out\n{B_OPPONENT_MON1_NAME}!"); +static const u8 sText_LinkTrainerSentOutTwoPkmn[] = _("{B_20} sent out\n{B_OPPONENT_MON1_NAME} and {B_OPPONENT_MON2_NAME}!"); +static const u8 sText_TwoLinkTrainersSentOutPkmn[] = _("{B_20} sent out {B_LINK_OPPONENT_MON1_NAME}!\n{B_21} sent out {B_LINK_OPPONENT_MON2_NAME}!"); +static const u8 sText_LinkTrainerSentOutPkmn2[] = _("{B_20} sent out\n{B_BUFF1}!"); +static const u8 sText_LinkTrainerMultiSentOutPkmn[] = _("{B_22} sent out\n{B_BUFF1}!"); +static const u8 sText_GoPkmn[] = _("Go! {B_PLAYER_MON1_NAME}!"); +static const u8 sText_GoTwoPkmn[] = _("Go! {B_PLAYER_MON1_NAME} and\n{B_PLAYER_MON2_NAME}!"); +static const u8 sText_GoPkmn2[] = _("Go! {B_BUFF1}!"); +static const u8 sText_DoItPkmn[] = _("Do it! {B_BUFF1}!"); +static const u8 sText_GoForItPkmn[] = _("Go for it, {B_BUFF1}!"); +static const u8 sText_YourFoesWeakGetEmPkmn[] = _("Your foe’s weak!\nGet ’em, {B_BUFF1}!"); +static const u8 sText_LinkPartnerSentOutPkmnGoPkmn[] = _("{B_1F} sent out {B_LINK_PLAYER_MON2_NAME}!\nGo! {B_LINK_PLAYER_MON1_NAME}!"); +static const u8 sText_PkmnThatsEnough[] = _("{B_BUFF1}, that’s enough!\nCome back!"); +static const u8 sText_PkmnComeBack[] = _("{B_BUFF1}, come back!"); +static const u8 sText_PkmnOkComeBack[] = _("{B_BUFF1}, OK!\nCome back!"); +static const u8 sText_PkmnGoodComeBack[] = _("{B_BUFF1}, good!\nCome back!"); +static const u8 sText_Trainer1WithdrewPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nwithdrew {B_BUFF1}!"); +static const u8 sText_LinkTrainer1WithdrewPkmn[] = _("{B_20} withdrew\n{B_BUFF1}!"); +static const u8 sText_LinkTrainer2WithdrewPkmn[] = _("{B_22} withdrew\n{B_BUFF1}!"); +static const u8 sText_WildPkmnPrefix[] = _("Wild "); +static const u8 sText_FoePkmnPrefix[] = _("Foe "); +static const u8 sText_EmptyString8[] = _( ""); +static const u8 sText_FoePkmnPrefix2[] = _("Foe"); +static const u8 sText_AllyPkmnPrefix[] = _("Ally"); +static const u8 sText_FoePkmnPrefix3[] = _("Foe"); +static const u8 sText_AllyPkmnPrefix2[] = _("Ally"); +static const u8 sText_FoePkmnPrefix4[] = _("Foe"); +static const u8 sText_AllyPkmnPrefix3[] = _("Ally"); +static const u8 sText_AttackerUsedX[] = _("{B_ATK_NAME_WITH_PREFIX} used\n{B_BUFF2}"); +static const u8 sText_ExclamationMark[] = _("!"); +static const u8 sText_ExclamationMark2[] = _("!"); +static const u8 sText_ExclamationMark3[] = _("!"); +static const u8 sText_ExclamationMark4[] = _("!"); +static const u8 sText_ExclamationMark5[] = _("!"); +static const u8 sText_HP2[] = _("HP"); +static const u8 sText_Attack2[] = _("ATTACK"); +static const u8 sText_Defense2[] = _("DEFENSE"); +static const u8 sText_Speed[] = _("SPEED"); +static const u8 sText_SpAtk2[] = _("SP. ATK"); +static const u8 sText_SpDef2[] = _("SP. DEF"); +static const u8 sText_Accuracy[] = _("accuracy"); +static const u8 sText_Evasiveness[] = _("evasiveness"); const u8 * const gStatNamesTable[] = { - gText_HP2, gText_Attack2, gText_Defense2, - gText_Speed, gText_SpAtk2, gText_SpDef2, - gText_Accuracy, gText_Evasiveness + sText_HP2, sText_Attack2, sText_Defense2, + sText_Speed, sText_SpAtk2, sText_SpDef2, + sText_Accuracy, sText_Evasiveness }; -const u8 gText_PokeblockWasTooSpicy[] = _("was too spicy!"); -const u8 gText_PokeblockWasTooDry[] = _("was too dry!"); -const u8 gText_PokeblockWasTooSweet[] = _("was too sweet!"); -const u8 gText_PokeblockWasTooBitter[] = _("was too bitter!"); -const u8 gText_PokeblockWasTooSour[] = _("was too sour!"); +static const u8 sText_PokeblockWasTooSpicy[] = _("was too spicy!"); +static const u8 sText_PokeblockWasTooDry[] = _("was too dry!"); +static const u8 sText_PokeblockWasTooSweet[] = _("was too sweet!"); +static const u8 sText_PokeblockWasTooBitter[] = _("was too bitter!"); +static const u8 sText_PokeblockWasTooSour[] = _("was too sour!"); const u8 * const gPokeblockWasTooXStringTable[] = { - gText_PokeblockWasTooSpicy, gText_PokeblockWasTooDry, - gText_PokeblockWasTooSweet, gText_PokeblockWasTooBitter, - gText_PokeblockWasTooSour + sText_PokeblockWasTooSpicy, sText_PokeblockWasTooDry, + sText_PokeblockWasTooSweet, sText_PokeblockWasTooBitter, + sText_PokeblockWasTooSour }; -const u8 gText_PlayerUsedItem[] = _("{B_PLAYER_NAME} used\n{B_LAST_ITEM}!"); -const u8 gText_WallyUsedItem[] = _("WALLY used\n{B_LAST_ITEM}!"); -const u8 gText_Trainer1UsedItem[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nused {B_LAST_ITEM}!"); -const u8 gText_TrainerBlockedBall[] = _("The TRAINER blocked the BALL!"); -const u8 gText_DontBeAThief[] = _("Don’t be a thief!"); -const u8 gText_ItDodgedBall[] = _("It dodged the thrown BALL!\nThis POKéMON can’t be caught!"); -const u8 gText_YouMissedPkmn[] = _("You missed the POKéMON!"); -const u8 gText_PkmnBrokeFree[] = _("Oh, no!\nThe POKéMON broke free!"); -const u8 gText_ItAppearedCaught[] = _("Aww!\nIt appeared to be caught!"); -const u8 gText_AarghAlmostHadIt[] = _("Aargh!\nAlmost had it!"); -const u8 gText_ShootSoClose[] = _("Shoot!\nIt was so close, too!"); -const u8 gText_GotchaPkmnCaught[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}\p"); -const u8 gText_GotchaPkmnCaught2[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}{PAUSE 127}"); -const u8 gText_GiveNicknameCaptured[] = _("Give a nickname to the\ncaptured {B_OPPONENT_MON1_NAME}?"); -const u8 gText_PkmnSentToPC[] = _("{B_OPPONENT_MON1_NAME} was sent to\n{B_PC_CREATOR_NAME} PC."); -const u8 gText_Someones[] = _("someone’s"); -const u8 gText_Lanettes[] = _("LANETTE’s"); -const u8 gText_PkmnDataAddedToDex[] = _("{B_OPPONENT_MON1_NAME}’s data was\nadded to the POKéDEX.\p"); -const u8 gText_ItIsRaining[] = _("It is raining."); -const u8 gText_SandstormIsRaging[] = _("A sandstorm is raging."); -const u8 gText_BoxIsFull[] = _("The BOX is full!\nYou can’t catch any more!\p"); -const u8 gText_EnigmaBerry[] = _("ENIGMA BERRY"); -const u8 gText_BerrySuffix[] = _(" BERRY"); -const u8 gText_PkmnsItemCuredParalysis[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured paralysis!"); -const u8 gText_PkmnsItemCuredPoison[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured poison!"); -const u8 gText_PkmnsItemHealedBurn[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nhealed its burn!"); -const u8 gText_PkmnsItemDefrostedIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ndefrosted it!"); -const u8 gText_PkmnsItemWokeIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nwoke it from its sleep!"); -const u8 gText_PkmnsItemSnappedOut[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nsnapped it out of confusion!"); -const u8 gText_PkmnsItemCuredProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured its {B_BUFF1} problem!"); -const u8 gText_PkmnsItemNormalizedStatus[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nnormalized its status!"); -const u8 gText_PkmnsItemRestoredHealth[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored health!"); -const u8 gText_PkmnsItemRestoredPP[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored {B_BUFF1}’s PP!"); -const u8 gText_PkmnsItemRestoredStatus[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored its status!"); -const u8 gText_PkmnsItemRestoredHPALittle[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored its HP a little!"); -const u8 gText_ItemAllowsOnlyYMove[] = _("{B_LAST_ITEM} allows the\nuse of only {B_CURRENT_MOVE}!\p"); -const u8 gText_PkmnHungOnWithX[] = _("{B_DEF_NAME_WITH_PREFIX} hung on\nusing its {B_LAST_ITEM}!"); +static const u8 sText_PlayerUsedItem[] = _("{B_PLAYER_NAME} used\n{B_LAST_ITEM}!"); +static const u8 sText_WallyUsedItem[] = _("WALLY used\n{B_LAST_ITEM}!"); +static const u8 sText_Trainer1UsedItem[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME}\nused {B_LAST_ITEM}!"); +static const u8 sText_TrainerBlockedBall[] = _("The TRAINER blocked the BALL!"); +static const u8 sText_DontBeAThief[] = _("Don’t be a thief!"); +static const u8 sText_ItDodgedBall[] = _("It dodged the thrown BALL!\nThis POKéMON can’t be caught!"); +static const u8 sText_YouMissedPkmn[] = _("You missed the POKéMON!"); +static const u8 sText_PkmnBrokeFree[] = _("Oh, no!\nThe POKéMON broke free!"); +static const u8 sText_ItAppearedCaught[] = _("Aww!\nIt appeared to be caught!"); +static const u8 sText_AarghAlmostHadIt[] = _("Aargh!\nAlmost had it!"); +static const u8 sText_ShootSoClose[] = _("Shoot!\nIt was so close, too!"); +static const u8 sText_GotchaPkmnCaught[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}\p"); +static const u8 sText_GotchaPkmnCaught2[] = _("Gotcha!\n{B_OPPONENT_MON1_NAME} was caught!{UNKNOWN_A}{PLAY_BGM MUS_KACHI22}{PAUSE 127}"); +static const u8 sText_GiveNicknameCaptured[] = _("Give a nickname to the\ncaptured {B_OPPONENT_MON1_NAME}?"); +static const u8 sText_PkmnSentToPC[] = _("{B_OPPONENT_MON1_NAME} was sent to\n{B_PC_CREATOR_NAME} PC."); +static const u8 sText_Someones[] = _("someone’s"); +static const u8 sText_Lanettes[] = _("LANETTE’s"); +static const u8 sText_PkmnDataAddedToDex[] = _("{B_OPPONENT_MON1_NAME}’s data was\nadded to the POKéDEX.\p"); +static const u8 sText_ItIsRaining[] = _("It is raining."); +static const u8 sText_SandstormIsRaging[] = _("A sandstorm is raging."); +static const u8 sText_BoxIsFull[] = _("The BOX is full!\nYou can’t catch any more!\p"); +static const u8 sText_EnigmaBerry[] = _("ENIGMA BERRY"); +static const u8 sText_BerrySuffix[] = _(" BERRY"); +static const u8 sText_PkmnsItemCuredParalysis[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured paralysis!"); +static const u8 sText_PkmnsItemCuredPoison[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured poison!"); +static const u8 sText_PkmnsItemHealedBurn[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nhealed its burn!"); +static const u8 sText_PkmnsItemDefrostedIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ndefrosted it!"); +static const u8 sText_PkmnsItemWokeIt[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nwoke it from its sleep!"); +static const u8 sText_PkmnsItemSnappedOut[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nsnapped it out of confusion!"); +static const u8 sText_PkmnsItemCuredProblem[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\ncured its {B_BUFF1} problem!"); +static const u8 sText_PkmnsItemNormalizedStatus[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nnormalized its status!"); +static const u8 sText_PkmnsItemRestoredHealth[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored health!"); +static const u8 sText_PkmnsItemRestoredPP[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored {B_BUFF1}’s PP!"); +static const u8 sText_PkmnsItemRestoredStatus[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored its status!"); +static const u8 sText_PkmnsItemRestoredHPALittle[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s {B_LAST_ITEM}\nrestored its HP a little!"); +static const u8 sText_ItemAllowsOnlyYMove[] = _("{B_LAST_ITEM} allows the\nuse of only {B_CURRENT_MOVE}!\p"); +static const u8 sText_PkmnHungOnWithX[] = _("{B_DEF_NAME_WITH_PREFIX} hung on\nusing its {B_LAST_ITEM}!"); const u8 gText_EmptyString3[] = _(""); -const u8 gText_YouThrowABallNowRight[] = _("You throw a BALL now, right?\nI… I’ll do my best!"); +static const u8 sText_YouThrowABallNowRight[] = _("You throw a BALL now, right?\nI… I’ll do my best!"); // early declaration of strings -const u8 gText_PkmnIncapableOfPower[]; -const u8 gText_GlintAppearsInEye[]; -const u8 gText_PkmnGettingIntoPosition[]; -const u8 gText_PkmnBeganGrowlingDeeply[]; -const u8 gText_PkmnEagerForMore[]; -const u8 gText_DefeatedOpponentByReferee[]; -const u8 gText_LostToOpponentByReferee[]; -const u8 gText_TiedOpponentByReferee[]; -const u8 gText_QuestionForfeitMatch[]; -const u8 gText_ForfeitedMatch[]; -const u8 gText_Trainer1WinText[]; -const u8 gText_Trainer2WinText[]; -const u8 gText_TwoInGameTrainersDefeated[]; -const u8 gText_Trainer2LoseText[]; +static const u8 sText_PkmnIncapableOfPower[]; +static const u8 sText_GlintAppearsInEye[]; +static const u8 sText_PkmnGettingIntoPosition[]; +static const u8 sText_PkmnBeganGrowlingDeeply[]; +static const u8 sText_PkmnEagerForMore[]; +static const u8 sText_DefeatedOpponentByReferee[]; +static const u8 sText_LostToOpponentByReferee[]; +static const u8 sText_TiedOpponentByReferee[]; +static const u8 sText_QuestionForfeitMatch[]; +static const u8 sText_ForfeitedMatch[]; +static const u8 sText_Trainer1WinText[]; +static const u8 sText_Trainer2WinText[]; +static const u8 sText_TwoInGameTrainersDefeated[]; +static const u8 sText_Trainer2LoseText[]; const u8 * const gBattleStringsTable[BATTLESTRINGS_COUNT] = { - gText_Trainer1LoseText, - gText_PkmnGainedEXP, - gText_PkmnGrewToLv, - gText_PkmnLearnedMove, - gText_TryToLearnMove1, - gText_TryToLearnMove2, - gText_TryToLearnMove3, - gText_PkmnForgotMove, - gText_StopLearningMove, - gText_DidNotLearnMove, - gText_PkmnLearnedMove2, - gText_AttackMissed, - gText_PkmnProtectedItself, - gText_StatsWontIncrease2, - gText_AvoidedDamage, - gText_ItDoesntAffect, - gText_AttackerFainted, - gText_TargetFainted, - gText_PlayerGotMoney, - gText_PlayerWhiteout, - gText_PlayerWhiteout2, - gText_PreventsEscape, - gText_HitXTimes, - gText_PkmnFellAsleep, - gText_PkmnMadeSleep, - gText_PkmnAlreadyAsleep, - gText_PkmnAlreadyAsleep2, - gText_PkmnWasntAffected, - gText_PkmnWasPoisoned, - gText_PkmnPoisonedBy, - gText_PkmnHurtByPoison, - gText_PkmnAlreadyPoisoned, - gText_PkmnBadlyPoisoned, - gText_PkmnEnergyDrained, - gText_PkmnWasBurned, - gText_PkmnBurnedBy, - gText_PkmnHurtByBurn, - gText_PkmnWasFrozen, - gText_PkmnFrozenBy, - gText_PkmnIsFrozen, - gText_PkmnWasDefrosted, - gText_PkmnWasDefrosted2, - gText_PkmnWasDefrostedBy, - gText_PkmnWasParalyzed, - gText_PkmnWasParalyzedBy, - gText_PkmnIsParalyzed, - gText_PkmnIsAlreadyParalyzed, - gText_PkmnHealedParalysis, - gText_PkmnDreamEaten, - gText_StatsWontIncrease, - gText_StatsWontDecrease, - gText_TeamStoppedWorking, - gText_FoeStoppedWorking, - gText_PkmnIsConfused, - gText_PkmnHealedConfusion, - gText_PkmnWasConfused, - gText_PkmnAlreadyConfused, - gText_PkmnFellInLove, - gText_PkmnInLove, - gText_PkmnImmobilizedByLove, - gText_PkmnBlownAway, - gText_PkmnChangedType, - gText_PkmnFlinched, - gText_PkmnRegainedHealth, - gText_PkmnHPFull, - gText_PkmnRaisedSpDef, - gText_PkmnRaisedDef, - gText_PkmnCoveredByVeil, - gText_PkmnUsedSafeguard, - gText_PkmnSafeguardExpired, - gText_PkmnWentToSleep, - gText_PkmnSleptHealthy, - gText_PkmnWhippedWhirlwind, - gText_PkmnTookSunlight, - gText_PkmnLoweredHead, - gText_PkmnIsGlowing, - gText_PkmnFlewHigh, - gText_PkmnDugHole, - gText_PkmnSqueezedByBind, - gText_PkmnTrappedInVortex, - gText_PkmnWrappedBy, - gText_PkmnClamped, - gText_PkmnHurtBy, - gText_PkmnFreedFrom, - gText_PkmnCrashed, - gText_PkmnShroudedInMist, - gText_PkmnProtectedByMist, - gText_PkmnGettingPumped, - gText_PkmnHitWithRecoil, - gText_PkmnProtectedItself2, - gText_PkmnBuffetedBySandstorm, - gText_PkmnPeltedByHail, - gText_PkmnSeeded, - gText_PkmnEvadedAttack, - gText_PkmnSappedByLeechSeed, - gText_PkmnFastAsleep, - gText_PkmnWokeUp, - gText_PkmnUproarKeptAwake, - gText_PkmnWokeUpInUproar, - gText_PkmnCausedUproar, - gText_PkmnMakingUproar, - gText_PkmnCalmedDown, - gText_PkmnCantSleepInUproar, - gText_PkmnStockpiled, - gText_PkmnCantStockpile, - gText_PkmnCantSleepInUproar2, - gText_UproarKeptPkmnAwake, - gText_PkmnStayedAwakeUsing, - gText_PkmnStoringEnergy, - gText_PkmnUnleashedEnergy, - gText_PkmnFatigueConfusion, - gText_PkmnPickedUpItem, - gText_PkmnUnaffected, - gText_PkmnTransformedInto, - gText_PkmnMadeSubstitute, - gText_PkmnHasSubstitute, - gText_SubstituteDamaged, - gText_PkmnSubstituteFaded, - gText_PkmnMustRecharge, - gText_PkmnRageBuilding, - gText_PkmnMoveWasDisabled, - gText_PkmnMoveIsDisabled, - gText_PkmnMoveDisabledNoMore, - gText_PkmnGotEncore, - gText_PkmnEncoreEnded, - gText_PkmnTookAim, - gText_PkmnSketchedMove, - gText_PkmnTryingToTakeFoe, - gText_PkmnTookFoe, - gText_PkmnReducedPP, - gText_PkmnStoleItem, - gText_TargetCantEscapeNow, - gText_PkmnFellIntoNightmare, - gText_PkmnLockedInNightmare, - gText_PkmnLaidCurse, - gText_PkmnAfflictedByCurse, - gText_SpikesScattered, - gText_PkmnHurtBySpikes, - gText_PkmnIdentified, - gText_PkmnPerishCountFell, - gText_PkmnBracedItself, - gText_PkmnEnduredHit, - gText_MagnitudeStrength, - gText_PkmnCutHPMaxedAttack, - gText_PkmnCopiedStatChanges, - gText_PkmnGotFree, - gText_PkmnShedLeechSeed, - gText_PkmnBlewAwaySpikes, - gText_PkmnFledFromBattle, - gText_PkmnForesawAttack, - gText_PkmnTookAttack, - gText_PkmnAttack, - gText_PkmnCenterAttention, - gText_PkmnChargingPower, - gText_NaturePowerTurnedInto, - gText_PkmnStatusNormal, - gText_PkmnHasNoMovesLeft, - gText_PkmnSubjectedToTorment, - gText_PkmnCantUseMoveTorment, - gText_PkmnTighteningFocus, - gText_PkmnFellForTaunt, - gText_PkmnCantUseMoveTaunt, - gText_PkmnReadyToHelp, - gText_PkmnSwitchedItems, - gText_PkmnCopiedFoe, - gText_PkmnMadeWish, - gText_PkmnWishCameTrue, - gText_PkmnPlantedRoots, - gText_PkmnAbsorbedNutrients, - gText_PkmnAnchoredItself, - gText_PkmnWasMadeDrowsy, - gText_PkmnKnockedOff, - gText_PkmnSwappedAbilities, - gText_PkmnSealedOpponentMove, - gText_PkmnCantUseMoveSealed, - gText_PkmnWantsGrudge, - gText_PkmnLostPPGrudge, - gText_PkmnShroudedItself, - gText_PkmnMoveBounced, - gText_PkmnWaitsForTarget, - gText_PkmnSnatchedMove, - gText_PkmnMadeItRain, - gText_PkmnRaisedSpeed, - gText_PkmnProtectedBy, - gText_PkmnPreventsUsage, - gText_PkmnRestoredHPUsing, - gText_PkmnChangedTypeWith, - gText_PkmnPreventsParalysisWith, - gText_PkmnPreventsRomanceWith, - gText_PkmnPreventsPoisoningWith, - gText_PkmnPreventsConfusionWith, - gText_PkmnRaisedFirePowerWith, - gText_PkmnAnchorsItselfWith, - gText_PkmnCutsAttackWith, - gText_PkmnPreventsStatLossWith, - gText_PkmnHurtsWith, - gText_PkmnTraced, - gText_StatSharply, - gText_StatRose, - gText_StatHarshly, - gText_StatFell, - gText_PkmnsStatChanged, - gText_PkmnsStatChanged2, - gText_PkmnsStatChanged3, - gText_PkmnsStatChanged4, - gText_CriticalHit, - gText_OneHitKO, - gText_123Poof, - gText_AndEllipsis, - gText_NotVeryEffective, - gText_SuperEffective, - gText_GotAwaySafely, - gText_WildPkmnFled, - gText_NoRunningFromTrainers, - gText_CantEscape, - gText_DontLeaveBirch, - gText_ButNothingHappened, - gText_ButItFailed, - gText_ItHurtConfusion, - gText_MirrorMoveFailed, - gText_StartedToRain, - gText_DownpourStarted, - gText_RainContinues, - gText_DownpourContinues, - gText_RainStopped, - gText_SandstormBrewed, - gText_SandstormRages, - gText_SandstormSubsided, - gText_SunlightGotBright, - gText_SunlightStrong, - gText_SunlightFaded, - gText_StartedHail, - gText_HailContinues, - gText_HailStopped, - gText_FailedToSpitUp, - gText_FailedToSwallow, - gText_WindBecameHeatWave, - gText_StatChangesGone, - gText_CoinsScattered, - gText_TooWeakForSubstitute, - gText_SharedPain, - gText_BellChimed, - gText_FaintInThree, - gText_NoPPLeft, - gText_ButNoPPLeft, - gText_PlayerUsedItem, - gText_WallyUsedItem, - gText_TrainerBlockedBall, - gText_DontBeAThief, - gText_ItDodgedBall, - gText_YouMissedPkmn, - gText_PkmnBrokeFree, - gText_ItAppearedCaught, - gText_AarghAlmostHadIt, - gText_ShootSoClose, - gText_GotchaPkmnCaught, - gText_GotchaPkmnCaught2, - gText_GiveNicknameCaptured, - gText_PkmnSentToPC, - gText_PkmnDataAddedToDex, - gText_ItIsRaining, - gText_SandstormIsRaging, - gText_CantEscape2, - gText_PkmnIgnoresAsleep, - gText_PkmnIgnoredOrders, - gText_PkmnBeganToNap, - gText_PkmnLoafing, - gText_PkmnWontObey, - gText_PkmnTurnedAway, - gText_PkmnPretendNotNotice, - gText_EnemyAboutToSwitchPkmn, - gText_CreptCloser, - gText_CantGetCloser, - gText_PkmnWatchingCarefully, - gText_PkmnCuriousAboutX, - gText_PkmnEnthralledByX, - gText_PkmnIgnoredX, - gText_ThrewPokeblockAtPkmn, - gText_OutOfSafariBalls, - gText_PkmnsItemCuredParalysis, - gText_PkmnsItemCuredPoison, - gText_PkmnsItemHealedBurn, - gText_PkmnsItemDefrostedIt, - gText_PkmnsItemWokeIt, - gText_PkmnsItemSnappedOut, - gText_PkmnsItemCuredProblem, - gText_PkmnsItemRestoredHealth, - gText_PkmnsItemRestoredPP, - gText_PkmnsItemRestoredStatus, - gText_PkmnsItemRestoredHPALittle, - gText_ItemAllowsOnlyYMove, - gText_PkmnHungOnWithX, - gText_EmptyString3, - gText_PkmnsXPreventsBurns, - gText_PkmnsXBlocksY, - gText_PkmnsXRestoredHPALittle2, - gText_PkmnsXWhippedUpSandstorm, - gText_PkmnsXPreventsYLoss, - gText_PkmnsXInfatuatedY, - gText_PkmnsXMadeYIneffective, - gText_PkmnsXCuredYProblem, - gText_ItSuckedLiquidOoze, - gText_PkmnTransformed, - gText_ElectricityWeakened, - gText_FireWeakened, - gText_PkmnHidUnderwater, - gText_PkmnSprangUp, - gText_HMMovesCantBeForgotten, - gText_XFoundOneY, - gText_PlayerDefeatedLinkTrainerTrainer1, - gText_SoothingAroma, - gText_ItemsCantBeUsedNow, - gText_ForXCommaYZ, - gText_UsingXTheYOfZN, - gText_PkmnUsedXToGetPumped, - gText_PkmnsXMadeYUseless, - gText_PkmnTrappedBySandTomb, - gText_EmptyString4, - gText_ABoosted, - gText_PkmnsXIntensifiedSun, - gText_PkmnMakesGroundMiss, - gText_YouThrowABallNowRight, - gText_PkmnsXTookAttack, - gText_PkmnChoseXAsDestiny, - gText_PkmnLostFocus, - gText_UseNextPkmn, - gText_PkmnFledUsingIts, - gText_PkmnFledUsing, - gText_PkmnWasDraggedOut, - gText_PreventedFromWorking, - gText_PkmnsItemNormalizedStatus, - gText_Trainer1UsedItem, - gText_BoxIsFull, - gText_PkmnAvoidedAttack, - gText_PkmnsXMadeItIneffective, - gText_PkmnsXPreventsFlinching, - gText_PkmnAlreadyHasBurn, - gText_StatsWontDecrease2, - gText_PkmnsXBlocksY2, - gText_PkmnsXWoreOff, - gText_PkmnRaisedDefALittle, - gText_PkmnRaisedSpDefALittle, - gText_TheWallShattered, - gText_PkmnsXPreventsYsZ, - gText_PkmnsXCuredItsYProblem, - gText_AttackerCantEscape, - gText_PkmnObtainedX, - gText_PkmnObtainedX2, - gText_PkmnObtainedXYObtainedZ, - gText_ButNoEffect, - gText_PkmnsXHadNoEffectOnY, - gText_TwoInGameTrainersDefeated, - gText_Trainer2LoseText, - gText_PkmnIncapableOfPower, - gText_GlintAppearsInEye, - gText_PkmnGettingIntoPosition, - gText_PkmnBeganGrowlingDeeply, - gText_PkmnEagerForMore, - gText_DefeatedOpponentByReferee, - gText_LostToOpponentByReferee, - gText_TiedOpponentByReferee, - gText_QuestionForfeitMatch, - gText_ForfeitedMatch, - gText_PkmnTransferredSomeonesPC, - gText_PkmnTransferredLanettesPC, - gText_PkmnBoxSomeonesPCFull, - gText_PkmnBoxLanettesPCFull, - gText_Trainer1WinText, - gText_Trainer2WinText, + sText_Trainer1LoseText, // 12 + sText_PkmnGainedEXP, // 13 + sText_PkmnGrewToLv, // 14 + sText_PkmnLearnedMove, // 15 + sText_TryToLearnMove1, // 16 + sText_TryToLearnMove2, // 17 + sText_TryToLearnMove3, // 18 + sText_PkmnForgotMove, // 19 + sText_StopLearningMove, // 20 + sText_DidNotLearnMove, // 21 + sText_PkmnLearnedMove2, // 22 + sText_AttackMissed, // 23 + sText_PkmnProtectedItself, // 24 + sText_StatsWontIncrease2, // 25 + sText_AvoidedDamage, // 26 + sText_ItDoesntAffect, // 27 + sText_AttackerFainted, // 28 + sText_TargetFainted, // 29 + sText_PlayerGotMoney, // 30 + sText_PlayerWhiteout, // 31 + sText_PlayerWhiteout2, // 32 + sText_PreventsEscape, // 33 + sText_HitXTimes, // 34 + sText_PkmnFellAsleep, // 35 + sText_PkmnMadeSleep, // 36 + sText_PkmnAlreadyAsleep, // 37 + sText_PkmnAlreadyAsleep2, // 38 + sText_PkmnWasntAffected, // 39 + sText_PkmnWasPoisoned, // 40 + sText_PkmnPoisonedBy, // 41 + sText_PkmnHurtByPoison, // 42 + sText_PkmnAlreadyPoisoned, // 43 + sText_PkmnBadlyPoisoned, // 44 + sText_PkmnEnergyDrained, // 45 + sText_PkmnWasBurned, // 46 + sText_PkmnBurnedBy, // 47 + sText_PkmnHurtByBurn, // 48 + sText_PkmnWasFrozen, // 49 + sText_PkmnFrozenBy, // 50 + sText_PkmnIsFrozen, // 51 + sText_PkmnWasDefrosted, // 52 + sText_PkmnWasDefrosted2, // 53 + sText_PkmnWasDefrostedBy, // 54 + sText_PkmnWasParalyzed, // 55 + sText_PkmnWasParalyzedBy, // 56 + sText_PkmnIsParalyzed, // 57 + sText_PkmnIsAlreadyParalyzed, // 58 + sText_PkmnHealedParalysis, // 59 + sText_PkmnDreamEaten, // 60 + sText_StatsWontIncrease, // 61 + sText_StatsWontDecrease, // 62 + sText_TeamStoppedWorking, // 63 + sText_FoeStoppedWorking, // 64 + sText_PkmnIsConfused, // 65 + sText_PkmnHealedConfusion, // 66 + sText_PkmnWasConfused, // 67 + sText_PkmnAlreadyConfused, // 68 + sText_PkmnFellInLove, // 69 + sText_PkmnInLove, // 70 + sText_PkmnImmobilizedByLove, // 71 + sText_PkmnBlownAway, // 72 + sText_PkmnChangedType, // 73 + sText_PkmnFlinched, // 74 + sText_PkmnRegainedHealth, // 75 + sText_PkmnHPFull, // 76 + sText_PkmnRaisedSpDef, // 77 + sText_PkmnRaisedDef, // 78 + sText_PkmnCoveredByVeil, // 79 + sText_PkmnUsedSafeguard, // 80 + sText_PkmnSafeguardExpired, // 81 + sText_PkmnWentToSleep, // 82 + sText_PkmnSleptHealthy, // 83 + sText_PkmnWhippedWhirlwind, // 84 + sText_PkmnTookSunlight, // 85 + sText_PkmnLoweredHead, // 86 + sText_PkmnIsGlowing, // 87 + sText_PkmnFlewHigh, // 88 + sText_PkmnDugHole, // 89 + sText_PkmnSqueezedByBind, // 90 + sText_PkmnTrappedInVortex, // 91 + sText_PkmnWrappedBy, // 92 + sText_PkmnClamped, // 93 + sText_PkmnHurtBy, // 94 + sText_PkmnFreedFrom, // 95 + sText_PkmnCrashed, // 96 + gText_PkmnShroudedInMist, // 97 + sText_PkmnProtectedByMist, // 98 + gText_PkmnGettingPumped, // 99 + sText_PkmnHitWithRecoil, // 100 + sText_PkmnProtectedItself2, // 101 + sText_PkmnBuffetedBySandstorm, // 102 + sText_PkmnPeltedByHail, // 103 + sText_PkmnSeeded, // 104 + sText_PkmnEvadedAttack, // 105 + sText_PkmnSappedByLeechSeed, // 106 + sText_PkmnFastAsleep, // 107 + sText_PkmnWokeUp, // 108 + sText_PkmnUproarKeptAwake, // 109 + sText_PkmnWokeUpInUproar, // 110 + sText_PkmnCausedUproar, // 111 + sText_PkmnMakingUproar, // 112 + sText_PkmnCalmedDown, // 113 + sText_PkmnCantSleepInUproar, // 114 + sText_PkmnStockpiled, // 115 + sText_PkmnCantStockpile, // 116 + sText_PkmnCantSleepInUproar2, // 117 + sText_UproarKeptPkmnAwake, // 118 + sText_PkmnStayedAwakeUsing, // 119 + sText_PkmnStoringEnergy, // 120 + sText_PkmnUnleashedEnergy, // 121 + sText_PkmnFatigueConfusion, // 122 + sText_PkmnPickedUpItem, // 123 + sText_PkmnUnaffected, // 124 + sText_PkmnTransformedInto, // 125 + sText_PkmnMadeSubstitute, // 126 + sText_PkmnHasSubstitute, // 127 + sText_SubstituteDamaged, // 128 + sText_PkmnSubstituteFaded, // 129 + sText_PkmnMustRecharge, // 130 + sText_PkmnRageBuilding, // 131 + sText_PkmnMoveWasDisabled, // 132 + sText_PkmnMoveIsDisabled, // 133 + sText_PkmnMoveDisabledNoMore, // 134 + sText_PkmnGotEncore, // 135 + sText_PkmnEncoreEnded, // 136 + sText_PkmnTookAim, // 137 + sText_PkmnSketchedMove, // 138 + sText_PkmnTryingToTakeFoe, // 139 + sText_PkmnTookFoe, // 140 + sText_PkmnReducedPP, // 141 + sText_PkmnStoleItem, // 142 + sText_TargetCantEscapeNow, // 143 + sText_PkmnFellIntoNightmare, // 144 + sText_PkmnLockedInNightmare, // 145 + sText_PkmnLaidCurse, // 146 + sText_PkmnAfflictedByCurse, // 147 + sText_SpikesScattered, // 148 + sText_PkmnHurtBySpikes, // 149 + sText_PkmnIdentified, // 150 + sText_PkmnPerishCountFell, // 151 + sText_PkmnBracedItself, // 152 + sText_PkmnEnduredHit, // 153 + sText_MagnitudeStrength, // 154 + sText_PkmnCutHPMaxedAttack, // 155 + sText_PkmnCopiedStatChanges, // 156 + sText_PkmnGotFree, // 157 + sText_PkmnShedLeechSeed, // 158 + sText_PkmnBlewAwaySpikes, // 159 + sText_PkmnFledFromBattle, // 160 + sText_PkmnForesawAttack, // 161 + sText_PkmnTookAttack, // 162 + sText_PkmnAttack, // 163 + sText_PkmnCenterAttention, // 164 + sText_PkmnChargingPower, // 165 + sText_NaturePowerTurnedInto, // 166 + sText_PkmnStatusNormal, // 167 + sText_PkmnHasNoMovesLeft, // 168 + sText_PkmnSubjectedToTorment, // 169 + sText_PkmnCantUseMoveTorment, // 170 + sText_PkmnTighteningFocus, // 171 + sText_PkmnFellForTaunt, // 172 + sText_PkmnCantUseMoveTaunt, // 173 + sText_PkmnReadyToHelp, // 174 + sText_PkmnSwitchedItems, // 175 + sText_PkmnCopiedFoe, // 176 + sText_PkmnMadeWish, // 177 + sText_PkmnWishCameTrue, // 178 + sText_PkmnPlantedRoots, // 179 + sText_PkmnAbsorbedNutrients, // 180 + sText_PkmnAnchoredItself, // 181 + sText_PkmnWasMadeDrowsy, // 182 + sText_PkmnKnockedOff, // 183 + sText_PkmnSwappedAbilities, // 184 + sText_PkmnSealedOpponentMove, // 185 + sText_PkmnCantUseMoveSealed, // 186 + sText_PkmnWantsGrudge, // 187 + sText_PkmnLostPPGrudge, // 188 + sText_PkmnShroudedItself, // 189 + sText_PkmnMoveBounced, // 190 + sText_PkmnWaitsForTarget, // 191 + sText_PkmnSnatchedMove, // 192 + sText_PkmnMadeItRain, // 193 + sText_PkmnRaisedSpeed, // 194 + sText_PkmnProtectedBy, // 195 + sText_PkmnPreventsUsage, // 196 + sText_PkmnRestoredHPUsing, // 197 + sText_PkmnChangedTypeWith, // 198 + sText_PkmnPreventsParalysisWith, // 199 + sText_PkmnPreventsRomanceWith, // 200 + sText_PkmnPreventsPoisoningWith, // 201 + sText_PkmnPreventsConfusionWith, // 202 + sText_PkmnRaisedFirePowerWith, // 203 + sText_PkmnAnchorsItselfWith, // 204 + sText_PkmnCutsAttackWith, // 205 + sText_PkmnPreventsStatLossWith, // 206 + sText_PkmnHurtsWith, // 207 + sText_PkmnTraced, // 208 + sText_StatSharply, // 209 + gText_StatRose, // 210 + sText_StatHarshly, // 211 + sText_StatFell, // 212 + sText_PkmnsStatChanged, // 213 + gText_PkmnsStatChanged2, // 214 + sText_PkmnsStatChanged3, // 215 + sText_PkmnsStatChanged4, // 216 + sText_CriticalHit, // 217 + sText_OneHitKO, // 218 + sText_123Poof, // 219 + sText_AndEllipsis, // 220 + sText_NotVeryEffective, // 221 + sText_SuperEffective, // 222 + sText_GotAwaySafely, // 223 + sText_WildPkmnFled, // 224 + sText_NoRunningFromTrainers, // 225 + sText_CantEscape, // 226 + sText_DontLeaveBirch, // 227 + sText_ButNothingHappened, // 228 + sText_ButItFailed, // 229 + sText_ItHurtConfusion, // 230 + sText_MirrorMoveFailed, // 231 + sText_StartedToRain, // 232 + sText_DownpourStarted, // 233 + sText_RainContinues, // 234 + sText_DownpourContinues, // 235 + sText_RainStopped, // 236 + sText_SandstormBrewed, // 237 + sText_SandstormRages, // 238 + sText_SandstormSubsided, // 239 + sText_SunlightGotBright, // 240 + sText_SunlightStrong, // 241 + sText_SunlightFaded, // 242 + sText_StartedHail, // 243 + sText_HailContinues, // 244 + sText_HailStopped, // 245 + sText_FailedToSpitUp, // 246 + sText_FailedToSwallow, // 247 + sText_WindBecameHeatWave, // 248 + sText_StatChangesGone, // 249 + sText_CoinsScattered, // 250 + sText_TooWeakForSubstitute, // 251 + sText_SharedPain, // 252 + sText_BellChimed, // 253 + sText_FaintInThree, // 254 + sText_NoPPLeft, // 255 + sText_ButNoPPLeft, // 256 + sText_PlayerUsedItem, // 257 + sText_WallyUsedItem, // 258 + sText_TrainerBlockedBall, // 259 + sText_DontBeAThief, // 260 + sText_ItDodgedBall, // 261 + sText_YouMissedPkmn, // 262 + sText_PkmnBrokeFree, // 263 + sText_ItAppearedCaught, // 264 + sText_AarghAlmostHadIt, // 265 + sText_ShootSoClose, // 266 + sText_GotchaPkmnCaught, // 267 + sText_GotchaPkmnCaught2, // 268 + sText_GiveNicknameCaptured, // 269 + sText_PkmnSentToPC, // 270 + sText_PkmnDataAddedToDex, // 271 + sText_ItIsRaining, // 272 + sText_SandstormIsRaging, // 273 + sText_CantEscape2, // 274 + sText_PkmnIgnoresAsleep, // 275 + sText_PkmnIgnoredOrders, // 276 + sText_PkmnBeganToNap, // 277 + sText_PkmnLoafing, // 278 + sText_PkmnWontObey, // 279 + sText_PkmnTurnedAway, // 280 + sText_PkmnPretendNotNotice, // 281 + sText_EnemyAboutToSwitchPkmn, // 282 + sText_CreptCloser, // 283 + sText_CantGetCloser, // 284 + sText_PkmnWatchingCarefully, // 285 + sText_PkmnCuriousAboutX, // 286 + sText_PkmnEnthralledByX, // 287 + sText_PkmnIgnoredX, // 288 + sText_ThrewPokeblockAtPkmn, // 289 + sText_OutOfSafariBalls, // 290 + sText_PkmnsItemCuredParalysis, // 291 + sText_PkmnsItemCuredPoison, // 292 + sText_PkmnsItemHealedBurn, // 293 + sText_PkmnsItemDefrostedIt, // 294 + sText_PkmnsItemWokeIt, // 295 + sText_PkmnsItemSnappedOut, // 296 + sText_PkmnsItemCuredProblem, // 297 + sText_PkmnsItemRestoredHealth, // 298 + sText_PkmnsItemRestoredPP, // 299 + sText_PkmnsItemRestoredStatus, // 300 + sText_PkmnsItemRestoredHPALittle, // 301 + sText_ItemAllowsOnlyYMove, // 302 + sText_PkmnHungOnWithX, // 303 + gText_EmptyString3, // 304 + sText_PkmnsXPreventsBurns, // 305 + sText_PkmnsXBlocksY, // 306 + sText_PkmnsXRestoredHPALittle2, // 307 + sText_PkmnsXWhippedUpSandstorm, // 308 + sText_PkmnsXPreventsYLoss, // 309 + sText_PkmnsXInfatuatedY, // 310 + sText_PkmnsXMadeYIneffective, // 311 + sText_PkmnsXCuredYProblem, // 312 + sText_ItSuckedLiquidOoze, // 313 + sText_PkmnTransformed, // 314 + sText_ElectricityWeakened, // 315 + sText_FireWeakened, // 316 + sText_PkmnHidUnderwater, // 317 + sText_PkmnSprangUp, // 318 + sText_HMMovesCantBeForgotten, // 319 + sText_XFoundOneY, // 320 + sText_PlayerDefeatedLinkTrainerTrainer1, // 321 + sText_SoothingAroma, // 322 + sText_ItemsCantBeUsedNow, // 323 + sText_ForXCommaYZ, // 324 + sText_UsingXTheYOfZN, // 325 + sText_PkmnUsedXToGetPumped, // 326 + sText_PkmnsXMadeYUseless, // 327 + sText_PkmnTrappedBySandTomb, // 328 + sText_EmptyString4, // 329 + sText_ABoosted, // 330 + sText_PkmnsXIntensifiedSun, // 331 + sText_PkmnMakesGroundMiss, // 332 + sText_YouThrowABallNowRight, // 333 + sText_PkmnsXTookAttack, // 334 + sText_PkmnChoseXAsDestiny, // 335 + sText_PkmnLostFocus, // 336 + sText_UseNextPkmn, // 337 + sText_PkmnFledUsingIts, // 338 + sText_PkmnFledUsing, // 339 + sText_PkmnWasDraggedOut, // 340 + sText_PreventedFromWorking, // 341 + sText_PkmnsItemNormalizedStatus, // 342 + sText_Trainer1UsedItem, // 343 + sText_BoxIsFull, // 344 + sText_PkmnAvoidedAttack, // 345 + sText_PkmnsXMadeItIneffective, // 346 + sText_PkmnsXPreventsFlinching, // 347 + sText_PkmnAlreadyHasBurn, // 348 + sText_StatsWontDecrease2, // 349 + sText_PkmnsXBlocksY2, // 350 + sText_PkmnsXWoreOff, // 351 + sText_PkmnRaisedDefALittle, // 352 + sText_PkmnRaisedSpDefALittle, // 353 + sText_TheWallShattered, // 354 + sText_PkmnsXPreventsYsZ, // 355 + sText_PkmnsXCuredItsYProblem, // 356 + sText_AttackerCantEscape, // 357 + sText_PkmnObtainedX, // 358 + sText_PkmnObtainedX2, // 359 + sText_PkmnObtainedXYObtainedZ, // 360 + sText_ButNoEffect, // 361 + sText_PkmnsXHadNoEffectOnY, // 362 + sText_TwoInGameTrainersDefeated, // 363 + sText_Trainer2LoseText, // 364 + sText_PkmnIncapableOfPower, // 365 + sText_GlintAppearsInEye, // 366 + sText_PkmnGettingIntoPosition, // 367 + sText_PkmnBeganGrowlingDeeply, // 368 + sText_PkmnEagerForMore, // 369 + sText_DefeatedOpponentByReferee, // 370 + sText_LostToOpponentByReferee, // 371 + sText_TiedOpponentByReferee, // 372 + sText_QuestionForfeitMatch, // 373 + sText_ForfeitedMatch, // 374 + gText_PkmnTransferredSomeonesPC, // 375 + gText_PkmnTransferredLanettesPC, // 376 + gText_PkmnBoxSomeonesPCFull, // 377 + gText_PkmnBoxLanettesPCFull, // 378 + sText_Trainer1WinText, // 379 + sText_Trainer2WinText, // 380 }; const u16 gMissStringIds[] = @@ -1176,16 +1174,16 @@ const u8 gText_BattleSwitchWhich3[] = _("{UP_ARROW}"); const u8 gText_BattleSwitchWhich4[] = _("{ESCAPE 4}"); const u8 gText_BattleSwitchWhich5[] = _("-"); -const u8 gText_HP[] = _("HP"); -const u8 gText_Attack[] = _("ATTACK"); -const u8 gText_Defense[] = _("DEFENSE"); -const u8 gText_SpAtk[] = _("SP. ATK"); -const u8 gText_SpDef[] = _("SP. DEF"); +static const u8 sText_HP[] = _("HP"); +static const u8 sText_Attack[] = _("ATTACK"); +static const u8 sText_Defense[] = _("DEFENSE"); +static const u8 sText_SpAtk[] = _("SP. ATK"); +static const u8 sText_SpDef[] = _("SP. DEF"); const u8 * const gStatNamesTable2[] = { - gText_HP, gText_SpAtk, gText_Attack, - gText_SpDef, gText_Defense, gText_Speed + sText_HP, sText_SpAtk, sText_Attack, + sText_SpDef, sText_Defense, sText_Speed }; const u8 gText_SafariBalls[] = _("{HIGHLIGHT DARK_GREY}SAFARI BALLS"); @@ -1202,10 +1200,10 @@ const u8 gText_BattleWallyName[] = _("WALLY"); const u8 gText_Win[] = _("{HIGHLIGHT TRANSPARENT}Win"); const u8 gText_Loss[] = _("{HIGHLIGHT TRANSPARENT}Loss"); const u8 gText_Draw[] = _("{HIGHLIGHT TRANSPARENT}Draw"); -const u8 gText_SpaceIs[] = _(" is"); -const u8 gText_ApostropheS[] = _("’s"); +static const u8 sText_SpaceIs[] = _(" is"); +static const u8 sText_ApostropheS[] = _("’s"); -const u8 gText_UnknownMoveTypes[][17] = +static const u8 sATypeMove_Table[][17] = { _("a NORMAL move"), _("a FIGHTING move"), @@ -1228,17 +1226,17 @@ const u8 gText_UnknownMoveTypes[][17] = }; const u8 gText_BattleTourney[] = _("BATTLE TOURNEY"); -const u8 gText_Round1[] = _("Round 1"); -const u8 gText_Round2[] = _("Round 2"); -const u8 gText_Semifinal[] = _("Semifinal"); -const u8 gText_Final[] = _("Final"); +static const u8 sText_Round1[] = _("Round 1"); +static const u8 sText_Round2[] = _("Round 2"); +static const u8 sText_Semifinal[] = _("Semifinal"); +static const u8 sText_Final[] = _("Final"); const u8 * const gRoundsStringTable[] = { - gText_Round1, - gText_Round2, - gText_Semifinal, - gText_Final + sText_Round1, + sText_Round2, + sText_Semifinal, + sText_Final }; const u8 gText_TheGreatNewHope[] = _("The great new hope!\p"); @@ -1253,17 +1251,17 @@ const u8 gText_Mind[] = _("Mind"); const u8 gText_Skill[] = _("Skill"); const u8 gText_Body[] = _("Body"); const u8 gText_Judgement[] = _("{B_BUFF1}{CLEAR 13}Judgment{CLEAR 13}{B_BUFF2}"); -const u8 gText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME}!\p{B_TRAINER2_CLASS} {B_TRAINER2_NAME} sent\nout {B_OPPONENT_MON2_NAME}!"); -const u8 gText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_CLASS} {B_TRAINER2_NAME} sent\nout {B_BUFF1}!"); -const u8 gText_TwoTrainersWantToBattle[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} and\n{B_TRAINER2_CLASS} {B_TRAINER2_NAME}\lwant to battle!\p"); -const u8 gText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_CLASS} {B_PARTNER_NAME} sent\nout {B_PLAYER_MON2_NAME}!\lGo, {B_PLAYER_MON1_NAME}!"); -const u8 gText_TwoInGameTrainersDefeated[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} and\n{B_TRAINER2_CLASS} {B_TRAINER2_NAME}\lwere defeated!\p"); -const u8 gText_Trainer2LoseText[] = _("{B_TRAINER2_LOSE_TEXT}"); -const u8 gText_PkmnIncapableOfPower[] = _("{B_ATK_NAME_WITH_PREFIX} appears incapable\nof using its power!"); -const u8 gText_GlintAppearsInEye[] = _("A glint appears in\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s eyes!"); -const u8 gText_PkmnGettingIntoPosition[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is getting into\nposition!"); -const u8 gText_PkmnBeganGrowlingDeeply[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} began growling deeply!"); -const u8 gText_PkmnEagerForMore[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is eager for more!"); +static const u8 sText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} sent\nout {B_OPPONENT_MON1_NAME}!\p{B_TRAINER2_CLASS} {B_TRAINER2_NAME} sent\nout {B_OPPONENT_MON2_NAME}!"); +static const u8 sText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_CLASS} {B_TRAINER2_NAME} sent\nout {B_BUFF1}!"); +static const u8 sText_TwoTrainersWantToBattle[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} and\n{B_TRAINER2_CLASS} {B_TRAINER2_NAME}\lwant to battle!\p"); +static const u8 sText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_CLASS} {B_PARTNER_NAME} sent\nout {B_PLAYER_MON2_NAME}!\lGo, {B_PLAYER_MON1_NAME}!"); +static const u8 sText_TwoInGameTrainersDefeated[] = _("{B_TRAINER1_CLASS} {B_TRAINER1_NAME} and\n{B_TRAINER2_CLASS} {B_TRAINER2_NAME}\lwere defeated!\p"); +static const u8 sText_Trainer2LoseText[] = _("{B_TRAINER2_LOSE_TEXT}"); +static const u8 sText_PkmnIncapableOfPower[] = _("{B_ATK_NAME_WITH_PREFIX} appears incapable\nof using its power!"); +static const u8 sText_GlintAppearsInEye[] = _("A glint appears in\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}’s eyes!"); +static const u8 sText_PkmnGettingIntoPosition[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is getting into\nposition!"); +static const u8 sText_PkmnBeganGrowlingDeeply[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} began growling deeply!"); +static const u8 sText_PkmnEagerForMore[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} is eager for more!"); const u16 gStringIds_85CCF0A[] = { @@ -1271,43 +1269,43 @@ const u16 gStringIds_85CCF0A[] = STRINGID_PKMNBEGANGROWLINGDEEPLY, STRINGID_PKMNEAGERFORMORE }; -const u8 gText_RefIfNothingIsDecided[] = _("REFEREE: If nothing is decided in\n3 turns, we will go to judging!"); -const u8 gText_RefThatsIt[] = _("REFEREE: That’s it! We will now go to\njudging to determine the winner!"); -const u8 gText_RefJudgeMind[] = _("REFEREE: Judging category 1, Mind!\nThe POKéMON showing the most guts!\p"); -const u8 gText_RefJudgeSkill[] = _("REFEREE: Judging category 2, Skill!\nThe POKéMON using moves the best!\p"); -const u8 gText_RefJudgeBody[] = _("REFEREE: Judging category 3, Body!\nThe POKéMON with the most vitality!\p"); -const u8 gText_RefJudgement1[] = _("REFEREE: Judgment: {B_BUFF1} to {B_BUFF2}!\nThe winner is {B_PLAYER_NAME}’s {B_PLAYER_MON1_NAME}!\p"); -const u8 gText_RefJudgement2[] = _("REFEREE: Judgment: {B_BUFF1} to {B_BUFF2}!\nThe winner is {B_TRAINER1_NAME}’s {B_OPPONENT_MON1_NAME}!\p"); -const u8 gText_RefJudgement3[] = _("REFEREE: Judgment: 3 to 3!\nWe have a draw!\p"); -const u8 gText_DefeatedOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} defeated the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); -const u8 gText_LostToOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} lost to the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); -const u8 gText_TiedOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} tied the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); -const u8 gText_RefCommenceBattle[] = _("REFEREE: {B_PLAYER_MON1_NAME} VS {B_OPPONENT_MON1_NAME}!\nCommence battling!"); +static const u8 sText_RefIfNothingIsDecided[] = _("REFEREE: If nothing is decided in\n3 turns, we will go to judging!"); +static const u8 sText_RefThatsIt[] = _("REFEREE: That’s it! We will now go to\njudging to determine the winner!"); +static const u8 sText_RefJudgeMind[] = _("REFEREE: Judging category 1, Mind!\nThe POKéMON showing the most guts!\p"); +static const u8 sText_RefJudgeSkill[] = _("REFEREE: Judging category 2, Skill!\nThe POKéMON using moves the best!\p"); +static const u8 sText_RefJudgeBody[] = _("REFEREE: Judging category 3, Body!\nThe POKéMON with the most vitality!\p"); +static const u8 sText_RefJudgement1[] = _("REFEREE: Judgment: {B_BUFF1} to {B_BUFF2}!\nThe winner is {B_PLAYER_NAME}’s {B_PLAYER_MON1_NAME}!\p"); +static const u8 sText_RefJudgement2[] = _("REFEREE: Judgment: {B_BUFF1} to {B_BUFF2}!\nThe winner is {B_TRAINER1_NAME}’s {B_OPPONENT_MON1_NAME}!\p"); +static const u8 sText_RefJudgement3[] = _("REFEREE: Judgment: 3 to 3!\nWe have a draw!\p"); +static const u8 sText_DefeatedOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} defeated the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); +static const u8 sText_LostToOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} lost to the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); +static const u8 sText_TiedOpponentByReferee[] = _("{B_PLAYER_MON1_NAME} tied the opponent\n{B_OPPONENT_MON1_NAME} in a REFEREE’s decision!"); +static const u8 sText_RefCommenceBattle[] = _("REFEREE: {B_PLAYER_MON1_NAME} VS {B_OPPONENT_MON1_NAME}!\nCommence battling!"); const u8 * const gRefereeStringsTable[] = { - gText_RefIfNothingIsDecided, - gText_RefThatsIt, - gText_RefJudgeMind, - gText_RefJudgeSkill, - gText_RefJudgeBody, - gText_RefJudgement1, - gText_RefJudgement2, - gText_RefJudgement3, - gText_RefCommenceBattle, + sText_RefIfNothingIsDecided, + sText_RefThatsIt, + sText_RefJudgeMind, + sText_RefJudgeSkill, + sText_RefJudgeBody, + sText_RefJudgement1, + sText_RefJudgement2, + sText_RefJudgement3, + sText_RefCommenceBattle, }; -const u8 gText_QuestionForfeitMatch[] = _("Would you like to forfeit the match\nand quit now?"); -const u8 gText_ForfeitedMatch[] = _("{B_PLAYER_NAME} forfeited the match!"); -const u8 gText_Trainer1WinText[] = _("{B_TRAINER1_WIN_TEXT}"); -const u8 gText_Trainer2WinText[] = _("{B_TRAINER2_WIN_TEXT}"); -const u8 gText_Trainer1Fled[] = _( "{PLAY_SE 0x0011}{B_TRAINER1_CLASS} {B_TRAINER1_NAME} fled!"); -const u8 gText_PlayerLostAgainstTrainer1[] = _("Player lost against\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!"); -const u8 gText_PlayerBattledToDrawTrainer1[] = _("Player battled to a draw against\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!"); +static const u8 sText_QuestionForfeitMatch[] = _("Would you like to forfeit the match\nand quit now?"); +static const u8 sText_ForfeitedMatch[] = _("{B_PLAYER_NAME} forfeited the match!"); +static const u8 sText_Trainer1WinText[] = _("{B_TRAINER1_WIN_TEXT}"); +static const u8 sText_Trainer2WinText[] = _("{B_TRAINER2_WIN_TEXT}"); +static const u8 sText_Trainer1Fled[] = _( "{PLAY_SE 0x0011}{B_TRAINER1_CLASS} {B_TRAINER1_NAME} fled!"); +static const u8 sText_PlayerLostAgainstTrainer1[] = _("Player lost against\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!"); +static const u8 sText_PlayerBattledToDrawTrainer1[] = _("Player battled to a draw against\n{B_TRAINER1_CLASS} {B_TRAINER1_NAME}!"); const u8 gText_RecordBattleToPass[] = _("Would you like to record your battle\non your FRONTIER PASS?"); const u8 gText_BattleRecordedOnPass[] = _("{B_PLAYER_NAME}’s battle result was recorded\non the FRONTIER PASS."); -const u8 gText_LinkTrainerWantsToBattlePause[] = _("{B_20}\nwants to battle!{PAUSE 49}"); -const u8 gText_TwoLinkTrainersWantToBattlePause[] = _("{B_20} and {B_21}\nwant to battle!{PAUSE 49}"); +static const u8 sText_LinkTrainerWantsToBattlePause[] = _("{B_20}\nwants to battle!{PAUSE 49}"); +static const u8 sText_TwoLinkTrainersWantToBattlePause[] = _("{B_20} and {B_21}\nwant to battle!{PAUSE 49}"); // This is four lists of moves which use a different attack string in Japanese // to the default. See the documentation for sub_814F950 for more detail. @@ -1444,45 +1442,45 @@ void BufferStringBattle(u16 stringID) { if (gBattleTypeFlags & BATTLE_TYPE_x800000) { - stringPtr = gText_TwoTrainersWantToBattle; + stringPtr = sText_TwoTrainersWantToBattle; } else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) - stringPtr = gText_TwoLinkTrainersWantToBattlePause; + stringPtr = sText_TwoLinkTrainersWantToBattlePause; else - stringPtr = gText_TwoLinkTrainersWantToBattle; + stringPtr = sText_TwoLinkTrainersWantToBattle; } else { if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00) - stringPtr = gText_Trainer1WantsToBattle; + stringPtr = sText_Trainer1WantsToBattle; else if (gBattleTypeFlags & BATTLE_TYPE_RECORDED) - stringPtr = gText_LinkTrainerWantsToBattlePause; + stringPtr = sText_LinkTrainerWantsToBattlePause; else - stringPtr = gText_LinkTrainerWantsToBattle; + stringPtr = sText_LinkTrainerWantsToBattle; } } else { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - stringPtr = gText_TwoTrainersWantToBattle; + stringPtr = sText_TwoTrainersWantToBattle; else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - stringPtr = gText_TwoTrainersWantToBattle; + stringPtr = sText_TwoTrainersWantToBattle; else - stringPtr = gText_Trainer1WantsToBattle; + stringPtr = sText_Trainer1WantsToBattle; } } else { if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) - stringPtr = gText_WildPkmnAppeared2; + stringPtr = sText_WildPkmnAppeared2; else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) // interesting, looks like they had something planned for wild double battles - stringPtr = gText_TwoWildPkmnAppeared; + stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) - stringPtr = gText_WildPkmnAppearedPause; + stringPtr = sText_WildPkmnAppearedPause; else - stringPtr = gText_WildPkmnAppeared; + stringPtr = sText_WildPkmnAppeared; } break; case STRINGID_INTROSENDOUT: // poke first send-out @@ -1491,17 +1489,17 @@ void BufferStringBattle(u16 stringID) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - stringPtr = gText_InGamePartnerSentOutZGoN; + stringPtr = sText_InGamePartnerSentOutZGoN; else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - stringPtr = gText_GoTwoPkmn; + stringPtr = sText_GoTwoPkmn; else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = gText_LinkPartnerSentOutPkmnGoPkmn; + stringPtr = sText_LinkPartnerSentOutPkmnGoPkmn; else - stringPtr = gText_GoTwoPkmn; + stringPtr = sText_GoTwoPkmn; } else { - stringPtr = gText_GoPkmn; + stringPtr = sText_GoPkmn; } } else @@ -1509,24 +1507,24 @@ void BufferStringBattle(u16 stringID) if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) - stringPtr = gText_TwoTrainersSentPkmn; + stringPtr = sText_TwoTrainersSentPkmn; else if (gBattleTypeFlags & BATTLE_TYPE_x800000) - stringPtr = gText_TwoTrainersSentPkmn; + stringPtr = sText_TwoTrainersSentPkmn; else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = gText_TwoLinkTrainersSentOutPkmn; + stringPtr = sText_TwoLinkTrainersSentOutPkmn; else if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) - stringPtr = gText_LinkTrainerSentOutTwoPkmn; + stringPtr = sText_LinkTrainerSentOutTwoPkmn; else - stringPtr = gText_Trainer1SentOutTwoPkmn; + stringPtr = sText_Trainer1SentOutTwoPkmn; } else { if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) - stringPtr = gText_Trainer1SentOutPkmn; + stringPtr = sText_Trainer1SentOutPkmn; else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00) - stringPtr = gText_Trainer1SentOutPkmn; + stringPtr = sText_Trainer1SentOutPkmn; else - stringPtr = gText_LinkTrainerSentOutPkmn; + stringPtr = sText_LinkTrainerSentOutPkmn; } } break; @@ -1534,26 +1532,26 @@ void BufferStringBattle(u16 stringID) if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) { if (*(&gBattleStruct->hpScale) == 0) - stringPtr = gText_PkmnThatsEnough; + stringPtr = sText_PkmnThatsEnough; else if (*(&gBattleStruct->hpScale) == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - stringPtr = gText_PkmnComeBack; + stringPtr = sText_PkmnComeBack; else if (*(&gBattleStruct->hpScale) == 2) - stringPtr = gText_PkmnOkComeBack; + stringPtr = sText_PkmnOkComeBack; else - stringPtr = gText_PkmnGoodComeBack; + stringPtr = sText_PkmnGoodComeBack; } else { if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_800 || gBattleTypeFlags & BATTLE_TYPE_x2000000) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = gText_LinkTrainer2WithdrewPkmn; + stringPtr = sText_LinkTrainer2WithdrewPkmn; else - stringPtr = gText_LinkTrainer1WithdrewPkmn; + stringPtr = sText_LinkTrainer1WithdrewPkmn; } else { - stringPtr = gText_Trainer1WithdrewPkmn; + stringPtr = sText_Trainer1WithdrewPkmn; } } break; @@ -1561,13 +1559,13 @@ void BufferStringBattle(u16 stringID) if (GetBattlerSide(gBattleScripting.battler) == B_SIDE_PLAYER) { if (*(&gBattleStruct->hpScale) == 0 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - stringPtr = gText_GoPkmn2; + stringPtr = sText_GoPkmn2; else if (*(&gBattleStruct->hpScale) == 1) - stringPtr = gText_DoItPkmn; + stringPtr = sText_DoItPkmn; else if (*(&gBattleStruct->hpScale) == 2) - stringPtr = gText_GoForItPkmn; + stringPtr = sText_GoForItPkmn; else - stringPtr = gText_YourFoesWeakGetEmPkmn; + stringPtr = sText_YourFoesWeakGetEmPkmn; } else { @@ -1576,18 +1574,18 @@ void BufferStringBattle(u16 stringID) if (gBattleTypeFlags & BATTLE_TYPE_x800000) { if (gBattleScripting.battler == 1) - stringPtr = gText_Trainer1SentOutPkmn2; + stringPtr = sText_Trainer1SentOutPkmn2; else - stringPtr = gText_Trainer2SentOutPkmn; + stringPtr = sText_Trainer2SentOutPkmn; } else { if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = gText_LinkTrainerMultiSentOutPkmn; + stringPtr = sText_LinkTrainerMultiSentOutPkmn; else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00) - stringPtr = gText_Trainer1SentOutPkmn2; + stringPtr = sText_Trainer1SentOutPkmn2; else - stringPtr = gText_LinkTrainerSentOutPkmn2; + stringPtr = sText_LinkTrainerSentOutPkmn2; } } else @@ -1595,13 +1593,13 @@ void BufferStringBattle(u16 stringID) if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) { if (gBattleScripting.battler == 1) - stringPtr = gText_Trainer1SentOutPkmn2; + stringPtr = sText_Trainer1SentOutPkmn2; else - stringPtr = gText_Trainer2SentOutPkmn; + stringPtr = sText_Trainer2SentOutPkmn; } else { - stringPtr = gText_Trainer1SentOutPkmn2; + stringPtr = sText_Trainer1SentOutPkmn2; } } } @@ -1610,12 +1608,12 @@ void BufferStringBattle(u16 stringID) sub_814F8F8(gBattleTextBuff1); // buff1 doesn't appear in the string, leftover from japanese move names? if (gStringInfo->currentMove > LAST_MOVE_INDEX) - StringCopy(gBattleTextBuff2, gText_UnknownMoveTypes[*(&gBattleStruct->stringMoveType)]); + StringCopy(gBattleTextBuff2, sATypeMove_Table[*(&gBattleStruct->stringMoveType)]); else StringCopy(gBattleTextBuff2, gMoveNames[gStringInfo->currentMove]); sub_814F950(gBattleTextBuff2); - stringPtr = gText_AttackerUsedX; + stringPtr = sText_AttackerUsedX; break; case STRINGID_BATTLEEND: // battle end if (gBattleTextBuff1[0] & B_OUTCOME_LINK_BATTLE_RAN) @@ -1625,11 +1623,11 @@ void BufferStringBattle(u16 stringID) gBattleTextBuff1[0] ^= (B_OUTCOME_LOST | B_OUTCOME_WON); if (gBattleTextBuff1[0] == B_OUTCOME_LOST || gBattleTextBuff1[0] == B_OUTCOME_DREW) - stringPtr = gText_GotAwaySafely; + stringPtr = sText_GotAwaySafely; else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) - stringPtr = gText_TwoWildFled; + stringPtr = sText_TwoWildFled; else - stringPtr = gText_WildFled; + stringPtr = sText_WildFled; } else { @@ -1642,15 +1640,15 @@ void BufferStringBattle(u16 stringID) { case B_OUTCOME_WON: if (gBattleTypeFlags & BATTLE_TYPE_x800000) - stringPtr = gText_TwoInGameTrainersDefeated; + stringPtr = sText_TwoInGameTrainersDefeated; else - stringPtr = gText_TwoLinkTrainersDefeated; + stringPtr = sText_TwoLinkTrainersDefeated; break; case B_OUTCOME_LOST: - stringPtr = gText_PlayerLostToTwo; + stringPtr = sText_PlayerLostToTwo; break; case B_OUTCOME_DREW: - stringPtr = gText_PlayerBattledToDrawVsTwo; + stringPtr = sText_PlayerBattledToDrawVsTwo; break; } } @@ -1659,13 +1657,13 @@ void BufferStringBattle(u16 stringID) switch (gBattleTextBuff1[0]) { case B_OUTCOME_WON: - stringPtr = gText_PlayerDefeatedLinkTrainerTrainer1; + stringPtr = sText_PlayerDefeatedLinkTrainerTrainer1; break; case B_OUTCOME_LOST: - stringPtr = gText_PlayerLostAgainstTrainer1; + stringPtr = sText_PlayerLostAgainstTrainer1; break; case B_OUTCOME_DREW: - stringPtr = gText_PlayerBattledToDrawTrainer1; + stringPtr = sText_PlayerBattledToDrawTrainer1; break; } } @@ -1674,13 +1672,13 @@ void BufferStringBattle(u16 stringID) switch (gBattleTextBuff1[0]) { case B_OUTCOME_WON: - stringPtr = gText_PlayerDefeatedLinkTrainer; + stringPtr = sText_PlayerDefeatedLinkTrainer; break; case B_OUTCOME_LOST: - stringPtr = gText_PlayerLostAgainstLinkTrainer; + stringPtr = sText_PlayerLostAgainstLinkTrainer; break; case B_OUTCOME_DREW: - stringPtr = gText_PlayerBattledToDrawLinkTrainer; + stringPtr = sText_PlayerBattledToDrawLinkTrainer; break; } } @@ -1707,7 +1705,7 @@ u32 BattleStringExpandPlaceholdersToDisplayedString(const u8* src) BattleStringExpandPlaceholders(src, gDisplayedStringBattle); } -static const u8* TryGetStatusString(u8* src) +static const u8* TryGetStatusString(u8 *src) { u32 i; u8 status[8]; @@ -1738,13 +1736,13 @@ static const u8* TryGetStatusString(u8* src) return NULL; } -#define HANDLE_NICKNAME_STRING_CASE(bank, monIndex) \ - if (GetBattlerSide(bank) != B_SIDE_PLAYER) \ +#define HANDLE_NICKNAME_STRING_CASE(battlerId, monIndex) \ + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) \ { \ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) \ - toCpy = gText_FoePkmnPrefix; \ + toCpy = sText_FoePkmnPrefix; \ else \ - toCpy = gText_WildPkmnPrefix; \ + toCpy = sText_WildPkmnPrefix; \ while (*toCpy != EOS) \ { \ dst[dstID] = *toCpy; \ @@ -1760,10 +1758,10 @@ static const u8* TryGetStatusString(u8* src) StringGetEnd10(text); \ toCpy = text; -u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) +u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) { u32 dstID = 0; // if they used dstID, why not use srcID as well? - const u8* toCpy = NULL; + const u8 *toCpy = NULL; u8 text[30]; u8 multiplayerID; s32 i; @@ -1868,7 +1866,7 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) StringGetEnd10(text); toCpy = text; break; - case B_TXT_ATK_NAME_WITH_PREFIX_MON1: // attacker name with prefix, only bank 0/1 + case B_TXT_ATK_NAME_WITH_PREFIX_MON1: // attacker name with prefix, only battlerId 0/1 HANDLE_NICKNAME_STRING_CASE(gBattlerAttacker, gBattlerPartyIndexes[GetBattlerAtPosition(GET_BATTLER_SIDE(gBattlerAttacker))]) break; @@ -1887,24 +1885,24 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) case B_TXT_DEF_NAME_WITH_PREFIX: // target name with prefix HANDLE_NICKNAME_STRING_CASE(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]) break; - case B_TXT_EFF_NAME_WITH_PREFIX: // effect bank name with prefix + case B_TXT_EFF_NAME_WITH_PREFIX: // effect battlerId name with prefix HANDLE_NICKNAME_STRING_CASE(gEffectBattler, gBattlerPartyIndexes[gEffectBattler]) break; - case B_TXT_ACTIVE_NAME_WITH_PREFIX: // active bank name with prefix + case B_TXT_ACTIVE_NAME_WITH_PREFIX: // active battlerId name with prefix HANDLE_NICKNAME_STRING_CASE(gActiveBattler, gBattlerPartyIndexes[gActiveBattler]) break; - case B_TXT_SCR_ACTIVE_NAME_WITH_PREFIX: // scripting active bank name with prefix + case B_TXT_SCR_ACTIVE_NAME_WITH_PREFIX: // scripting active battlerId name with prefix HANDLE_NICKNAME_STRING_CASE(gBattleScripting.battler, gBattlerPartyIndexes[gBattleScripting.battler]) break; case B_TXT_CURRENT_MOVE: // current move name if (gStringInfo->currentMove > LAST_MOVE_INDEX) - toCpy = gText_UnknownMoveTypes[gBattleStruct->stringMoveType]; + toCpy = sATypeMove_Table[gBattleStruct->stringMoveType]; else toCpy = gMoveNames[gStringInfo->currentMove]; break; case B_TXT_LAST_MOVE: // originally used move name if (gStringInfo->originallyUsedMove > LAST_MOVE_INDEX) - toCpy = gText_UnknownMoveTypes[gBattleStruct->stringMoveType]; + toCpy = sATypeMove_Table[gBattleStruct->stringMoveType]; else toCpy = gMoveNames[gStringInfo->originallyUsedMove]; break; @@ -1919,12 +1917,12 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) || (gBattleScripting.multiplayerId == 0 && !(gPotentialItemEffectBattler & BIT_SIDE))) { StringCopy(text, gEnigmaBerries[gPotentialItemEffectBattler].name); - StringAppend(text, gText_BerrySuffix); + StringAppend(text, sText_BerrySuffix); toCpy = text; } else { - toCpy = gText_EnigmaBerry; + toCpy = sText_EnigmaBerry; } } else @@ -1932,11 +1930,11 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) if (gLinkPlayers[gBattleScripting.multiplayerId].lp_field_18 == gPotentialItemEffectBattler) { StringCopy(text, gEnigmaBerries[gPotentialItemEffectBattler].name); - StringAppend(text, gText_BerrySuffix); + StringAppend(text, sText_BerrySuffix); toCpy = text; } else - toCpy = gText_EnigmaBerry; + toCpy = sText_EnigmaBerry; } } else @@ -1963,12 +1961,12 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) case B_TXT_SCR_ACTIVE_ABILITY: // scripting active ability toCpy = gAbilityNames[gBattlerAbilities[gBattleScripting.battler]]; break; - case B_TXT_EFF_ABILITY: // effect bank ability + case B_TXT_EFF_ABILITY: // effect battlerId ability toCpy = gAbilityNames[gBattlerAbilities[gEffectBattler]]; break; case B_TXT_TRAINER1_CLASS: // trainer class name if (gBattleTypeFlags & BATTLE_TYPE_SECRET_BASE) - toCpy = gTrainerClassNames[GetSecretBaseTrainerNameIndex()]; + toCpy = gTrainerClassNames[GetSecretBaseTrainerClass()]; else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_C00) toCpy = gTrainerClassNames[sub_8068BB0()]; else if (gTrainerBattleOpponent_A == TRAINER_OPPONENT_3FE) @@ -2074,45 +2072,45 @@ u32 BattleStringExpandPlaceholders(const u8* src, u8* dst) break; case B_TXT_PC_CREATOR_NAME: // lanette pc if (FlagGet(FLAG_SYS_PC_LANETTE)) - toCpy = gText_Lanettes; + toCpy = sText_Lanettes; else - toCpy = gText_Someones; + toCpy = sText_Someones; break; case B_TXT_ATK_PREFIX2: if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix2; + toCpy = sText_AllyPkmnPrefix2; else - toCpy = gText_FoePkmnPrefix3; + toCpy = sText_FoePkmnPrefix3; break; case B_TXT_DEF_PREFIX2: if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix2; + toCpy = sText_AllyPkmnPrefix2; else - toCpy = gText_FoePkmnPrefix3; + toCpy = sText_FoePkmnPrefix3; break; case B_TXT_ATK_PREFIX1: if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix; + toCpy = sText_AllyPkmnPrefix; else - toCpy = gText_FoePkmnPrefix2; + toCpy = sText_FoePkmnPrefix2; break; case B_TXT_DEF_PREFIX1: if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix; + toCpy = sText_AllyPkmnPrefix; else - toCpy = gText_FoePkmnPrefix2; + toCpy = sText_FoePkmnPrefix2; break; case B_TXT_ATK_PREFIX3: if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix3; + toCpy = sText_AllyPkmnPrefix3; else - toCpy = gText_FoePkmnPrefix4; + toCpy = sText_FoePkmnPrefix4; break; case B_TXT_DEF_PREFIX3: if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) - toCpy = gText_AllyPkmnPrefix3; + toCpy = sText_AllyPkmnPrefix3; else - toCpy = gText_FoePkmnPrefix4; + toCpy = sText_FoePkmnPrefix4; break; case B_TXT_TRAINER2_CLASS: if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) @@ -2258,9 +2256,9 @@ static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) else { if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - StringAppend(dst, gText_FoePkmnPrefix); + StringAppend(dst, sText_FoePkmnPrefix); else - StringAppend(dst, gText_WildPkmnPrefix); + StringAppend(dst, sText_WildPkmnPrefix); GetMonData(&gEnemyParty[src[srcID + 2]], MON_DATA_NICKNAME, text); } @@ -2301,10 +2299,10 @@ static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) if (gLinkPlayers[gBattleScripting.multiplayerId].lp_field_18 == gPotentialItemEffectBattler) { StringCopy(dst, gEnigmaBerries[gPotentialItemEffectBattler].name); - StringAppend(dst, gText_BerrySuffix); + StringAppend(dst, sText_BerrySuffix); } else - StringAppend(dst, gText_EnigmaBerry); + StringAppend(dst, sText_EnigmaBerry); } else CopyItemName(hword, dst); @@ -2337,29 +2335,29 @@ static void sub_814F8F8(u8* textBuff) if (counter >= 0) { if (counter <= 2) - StringCopy(textBuff, gText_SpaceIs); // is + StringCopy(textBuff, sText_SpaceIs); // is else if (counter <= 4) - StringCopy(textBuff, gText_ApostropheS); // 's + StringCopy(textBuff, sText_ApostropheS); // 's } } // Appends "!" to the text buffer `dst`. In the original Japanese this looked // into the table of moves at sUnknownMoveTable and varied the line accordingly. // -// gText_ExclamationMark was a plain "!", used for any attack not on the list. +// sText_ExclamationMark was a plain "!", used for any attack not on the list. // It resulted in the translation "<NAME>'s <ATTACK>!". // -// gText_ExclamationMark2 was "を つかった!". This resulted in the translation +// sText_ExclamationMark2 was "を つかった!". This resulted in the translation // "<NAME> used <ATTACK>!", which was used for all attacks in English. // -// gText_ExclamationMark3 was "した!". This was used for those moves whose +// sText_ExclamationMark3 was "した!". This was used for those moves whose // names were verbs, such as Recover, and resulted in translations like "<NAME> // recovered itself!". // -// gText_ExclamationMark4 was "を した!" This resulted in a translation of +// sText_ExclamationMark4 was "を した!" This resulted in a translation of // "<NAME> did an <ATTACK>!". // -// gText_ExclamationMark5 was " こうげき!" This resulted in a translation of +// sText_ExclamationMark5 was " こうげき!" This resulted in a translation of // "<NAME>'s <ATTACK> attack!". static void sub_814F950(u8* dst) { @@ -2380,19 +2378,19 @@ static void sub_814F950(u8* dst) switch (counter) { case 0: - StringCopy(dst, gText_ExclamationMark); + StringCopy(dst, sText_ExclamationMark); break; case 1: - StringCopy(dst, gText_ExclamationMark2); + StringCopy(dst, sText_ExclamationMark2); break; case 2: - StringCopy(dst, gText_ExclamationMark3); + StringCopy(dst, sText_ExclamationMark3); break; case 3: - StringCopy(dst, gText_ExclamationMark4); + StringCopy(dst, sText_ExclamationMark4); break; case 4: - StringCopy(dst, gText_ExclamationMark5); + StringCopy(dst, sText_ExclamationMark5); break; } } diff --git a/src/battle_records.c b/src/battle_records.c new file mode 100644 index 000000000..a148f998f --- /dev/null +++ b/src/battle_records.c @@ -0,0 +1,510 @@ +#include "global.h" +#include "battle_records.h" +#include "bg.h" +#include "window.h" +#include "link.h" +#include "battle.h" +#include "overworld.h" +#include "text.h" +#include "text_window.h" +#include "strings.h" +#include "string_util.h" +#include "trainer_card.h" +#include "menu.h" +#include "menu_helpers.h" +#include "palette.h" +#include "main.h" +#include "scanline_effect.h" +#include "international_string_util.h" +#include "sound.h" +#include "constants/songs.h" +#include "malloc.h" +#include "gpu_regs.h" +#include "constants/game_stat.h" + +extern void PrintOnTrainerHillRecordsWindow(void); // pokenav.s + +// this file's functions +static void Task_CloseTrainerHillRecordsOnButton(u8 taskId); +static void Task_BeginPaletteFade(u8 taskId); +static void Task_ExitTrainerHillRecords(u8 taskId); +static void RemoveTrainerHillRecordsWindow(u8 windowId); +static void CB2_ShowTrainerHillRecords(void); + +// EWRAM variables +EWRAM_DATA u8 gRecordsWindowId = 0; +EWRAM_DATA static u8 *sTilemapBuffer = NULL; + +// const rom data +static const u32 sTrainerHillWindowTileset[] = INCBIN_U32("graphics/unknown/unknown_5B3484.4bpp"); +static const u16 sTrainerHillWindowPalette[] = INCBIN_U16("graphics/unknown/unknown_5B3484.gbapal"); +static const u32 sTrainerHillWindowTilemap[] = INCBIN_U32("graphics/unknown/unknown_5B3564.bin"); + +static const struct BgTemplate sTrainerHillRecordsBgTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 0, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 3, + .charBaseIndex = 1, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0 + } +}; + +static const struct WindowTemplate sTrainerHillRecordsWindowTemplates[] = +{ + {0x0, 0x2, 0x1, 0x1A, 0x12, 0xF, 0x14}, + DUMMY_WIN_TEMPLATE +}; + +static const struct WindowTemplate sLinkBattleRecordsWindow = {0x0, 0x2, 0x1, 0x1A, 0x11, 0xF, 0x1}; + +static const u8 sText_DashesNoPlayer[] = _("-------"); +static const u8 sText_DashesNoScore[] = _("----"); + +// code +static void ClearLinkBattleRecord(struct LinkBattleRecord *record) +{ + CpuFill16(0, record, sizeof(struct LinkBattleRecord)); + record->name[0] = EOS; + record->trainerId = 0; + record->wins = 0; + record->losses = 0; + record->draws = 0; +} + +static void ClearLinkBattleRecords(struct LinkBattleRecord *records) +{ + s32 i; + for (i = 0; i < LINK_B_RECORDS_COUNT; i++) + { + ClearLinkBattleRecord(records + i); + } + SetGameStat(GAME_STAT_LINK_BATTLE_WINS, 0); + SetGameStat(GAME_STAT_LINK_BATTLE_LOSSES, 0); + SetGameStat(GAME_STAT_LINK_BATTLE_DRAWS, 0); +} + +static s32 GetLinkBattleRecordTotalBattles(struct LinkBattleRecord *record) +{ + return record->wins + record->losses + record->draws; +} + +static s32 FindLinkBattleRecord(struct LinkBattleRecord *records, const u8 *name, u16 trainerId) +{ + s32 i; + + for (i = 0; i < LINK_B_RECORDS_COUNT; i++) + { + if (!StringCompareN(records[i].name, name, OT_NAME_LENGTH) && records[i].trainerId == trainerId) + return i; + } + + return LINK_B_RECORDS_COUNT; +} + +static void SortLinkBattleRecords(struct LinkBattleRecords *records) +{ + s32 i, j; + + for (i = LINK_B_RECORDS_COUNT - 1; i > 0; i--) + { + for (j = i - 1; j >= 0; j--) + { + s32 totalBattlesI = GetLinkBattleRecordTotalBattles(&records->entries[i]); + s32 totalBattlesJ = GetLinkBattleRecordTotalBattles(&records->entries[j]); + + if (totalBattlesI > totalBattlesJ) + { + struct LinkBattleRecord temp1; + u8 temp2; + + temp1 = records->entries[i]; + records->entries[i] = records->entries[j]; + records->entries[j] = temp1; + + temp2 = records->languages[i]; + records->languages[i] = records->languages[j]; + records->languages[j] = temp2; + } + } + } +} + +static void UpdateLinkBattleRecord(struct LinkBattleRecord *record, s32 battleOutcome) +{ + switch (battleOutcome) + { + case B_OUTCOME_WON: + record->wins++; + if (record->wins > 9999) + record->wins = 9999; + break; + case B_OUTCOME_LOST: + record->losses++; + if (record->losses > 9999) + record->losses = 9999; + break; + case B_OUTCOME_DREW: + record->draws++; + if (record->draws > 9999) + record->draws = 9999; + break; + } +} + +static void UpdateLinkBattleGameStats(s32 battleOutcome) +{ + u8 stat; + + switch (battleOutcome) + { + case B_OUTCOME_WON: + stat = GAME_STAT_LINK_BATTLE_WINS; + break; + case B_OUTCOME_LOST: + stat = GAME_STAT_LINK_BATTLE_LOSSES; + break; + case B_OUTCOME_DREW: + stat = GAME_STAT_LINK_BATTLE_DRAWS; + break; + default: + return; + } + + if (GetGameStat(stat) < 9999) + IncrementGameStat(stat); +} + +static void UpdateLinkBattleRecords(struct LinkBattleRecords *records, const u8 *name, u16 trainerId, s32 battleOutcome, u8 battlerId) +{ + s32 index; + + UpdateLinkBattleGameStats(battleOutcome); + SortLinkBattleRecords(records); + index = FindLinkBattleRecord(records->entries, name, trainerId); + if (index == LINK_B_RECORDS_COUNT) + { + index = LINK_B_RECORDS_COUNT - 1; + ClearLinkBattleRecord(&records->entries[index]); + StringCopyN(records->entries[index].name, name, OT_NAME_LENGTH); + records->entries[index].trainerId = trainerId; + records->languages[index] = gLinkPlayers[battlerId].language; + } + UpdateLinkBattleRecord(&records->entries[index], battleOutcome); + SortLinkBattleRecords(records); +} + +void ClearPlayerLinkBattleRecords(void) +{ + ClearLinkBattleRecords(gSaveBlock1Ptr->linkBattleRecords.entries); +} + +static void IncTrainerCardWins(s32 battlerId) +{ + u16 *wins = &gTrainerCards[battlerId].linkBattleWins; + (*wins)++; + if (*wins > 9999) + *wins = 9999; +} + +static void IncTrainerCardLosses(s32 battlerId) +{ + u16 *losses = &gTrainerCards[battlerId].linkBattleLosses; + (*losses)++; + if (*losses > 9999) + *losses = 9999; +} + +static void UpdateTrainerCardWinsLosses(s32 battlerId) +{ + switch (gBattleOutcome) + { + case B_OUTCOME_WON: + IncTrainerCardWins(BATTLE_OPPOSITE(battlerId)); + IncTrainerCardLosses(battlerId); + break; + case B_OUTCOME_LOST: + IncTrainerCardLosses(BATTLE_OPPOSITE(battlerId)); + IncTrainerCardWins(battlerId); + break; + } +} + +void UpdatePlayerLinkBattleRecords(s32 battlerId) +{ + if (InUnionRoom() != TRUE) + { + UpdateTrainerCardWinsLosses(battlerId); + UpdateLinkBattleRecords( + &gSaveBlock1Ptr->linkBattleRecords, + gTrainerCards[battlerId].playerName, + gTrainerCards[battlerId].trainerId, + gBattleOutcome, + battlerId); + } +} + +static void PrintLinkBattleWinsLossesDraws(struct LinkBattleRecord *records) +{ + s32 x; + + ConvertIntToDecimalStringN(gStringVar1, GetGameStat(GAME_STAT_LINK_BATTLE_WINS), STR_CONV_MODE_LEFT_ALIGN, 4); + ConvertIntToDecimalStringN(gStringVar2, GetGameStat(GAME_STAT_LINK_BATTLE_LOSSES), STR_CONV_MODE_LEFT_ALIGN, 4); + ConvertIntToDecimalStringN(gStringVar3, GetGameStat(GAME_STAT_LINK_BATTLE_DRAWS), STR_CONV_MODE_LEFT_ALIGN, 4); + StringExpandPlaceholders(gStringVar4, gText_TotalRecordWLD); + + x = GetStringCenterAlignXOffset(1, gStringVar4, 0xD0); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar4, x, 0x11, 0, NULL); +} + +static void PrintLinkBattleRecord(struct LinkBattleRecord *record, u8 y, s32 language) +{ + if (record->wins == 0 && record->losses == 0 && record->draws == 0) + { + // empty slot + PrintTextOnWindow(gRecordsWindowId, 1, sText_DashesNoPlayer, 8, (y * 8) + 1, 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, sText_DashesNoScore, 80, (y * 8) + 1, 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, sText_DashesNoScore, 128, (y * 8) + 1, 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, sText_DashesNoScore, 176, (y * 8) + 1, 0, NULL); + } + else + { + StringFillWithTerminator(gStringVar1, 8); + StringCopyN(gStringVar1, record->name, 7); + ConvertInternationalString(gStringVar1, language); + + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar1, 8, (y * 8) + 1, 0, NULL); + + ConvertIntToDecimalStringN(gStringVar1, record->wins, STR_CONV_MODE_RIGHT_ALIGN, 4); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar1, 80, (y * 8) + 1, 0, NULL); + + ConvertIntToDecimalStringN(gStringVar1, record->losses, STR_CONV_MODE_RIGHT_ALIGN, 4); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar1, 128, (y * 8) + 1, 0, NULL); + + ConvertIntToDecimalStringN(gStringVar1, record->draws, STR_CONV_MODE_RIGHT_ALIGN, 4); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar1, 176, (y * 8) + 1, 0, NULL); + } +} + +void ShowLinkBattleRecords(void) +{ + s32 i, x; + + gRecordsWindowId = AddWindow(&sLinkBattleRecordsWindow); + NewMenuHelpers_DrawStdWindowFrame(gRecordsWindowId, FALSE); + FillWindowPixelBuffer(gRecordsWindowId, 0x11); + StringExpandPlaceholders(gStringVar4, gText_PlayersBattleResults); + + x = GetStringCenterAlignXOffset(1, gStringVar4, 208); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar4, x, 1, 0, NULL); + PrintLinkBattleWinsLossesDraws(gSaveBlock1Ptr->linkBattleRecords.entries); + + StringExpandPlaceholders(gStringVar4, gText_WinLoseDraw); + PrintTextOnWindow(gRecordsWindowId, 1, gStringVar4, 0, 41, 0, NULL); + + for (i = 0; i < LINK_B_RECORDS_COUNT; i++) + { + PrintLinkBattleRecord(&gSaveBlock1Ptr->linkBattleRecords.entries[i], 7 + (i * 2), gSaveBlock1Ptr->linkBattleRecords.languages[i]); + } + + PutWindowTilemap(gRecordsWindowId); + CopyWindowToVram(gRecordsWindowId, 3); +} + +void RemoveRecordsWindow(void) +{ + sub_819746C(gRecordsWindowId, FALSE); + RemoveWindow(gRecordsWindowId); +} + +static void Task_TrainerHillWaitForPaletteFade(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_CloseTrainerHillRecordsOnButton; +} + +static void Task_CloseTrainerHillRecordsOnButton(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + task->func = Task_BeginPaletteFade; + } +} + +static void Task_BeginPaletteFade(u8 taskId) +{ + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_ExitTrainerHillRecords; +} + +static void Task_ExitTrainerHillRecords(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetMainCallback2(CB2_ReturnToFieldContinueScript); + Free(sTilemapBuffer); + RemoveTrainerHillRecordsWindow(0); + FreeAllWindowBuffers(); + DestroyTask(taskId); + } +} + +static void RemoveTrainerHillRecordsWindow(u8 windowId) +{ + FillWindowPixelBuffer(windowId, 0); + ClearWindowTilemap(windowId); + CopyWindowToVram(windowId, 2); + RemoveWindow(windowId); +} + +static void ClearVramOamPlttRegs(void) +{ + DmaClearLarge16(3, (void*)(VRAM), VRAM_SIZE, 0x1000); + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); + + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 0); + SetGpuReg(REG_OFFSET_WINOUT, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); +} + +static void ClearTasksAndGraphicalStructs(void) +{ + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); +} + +static void ResetBgCoordinates(void) +{ + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); +} + +static void SetDispcntReg(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_BG0_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_1D_MAP); +} + +static void LoadTrainerHillRecordsWindowGfx(u8 bgId) +{ + LoadBgTiles(bgId, sTrainerHillWindowTileset, sizeof(sTrainerHillWindowTileset), 0); + CopyToBgTilemapBufferRect(bgId, sTrainerHillWindowTilemap, 0, 0, 0x20, 0x20); + LoadPalette(sTrainerHillWindowPalette, 0, 0x20); +} + +static void VblankCB_TrainerHillRecords(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void MainCB2_TrainerHillRecords(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +void ShowTrainerHillRecords(void) +{ + SetVBlankCallback(NULL); + SetMainCallback2(CB2_ShowTrainerHillRecords); +} + +static void CB2_ShowTrainerHillRecords(void) +{ + switch (gMain.state) + { + case 0: + SetVBlankCallback(NULL); + ClearVramOamPlttRegs(); + gMain.state++; + break; + case 1: + ClearTasksAndGraphicalStructs(); + gMain.state++; + break; + case 2: + sTilemapBuffer = AllocZeroed(0x800); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sTrainerHillRecordsBgTemplates, ARRAY_COUNT(sTrainerHillRecordsBgTemplates)); + SetBgTilemapBuffer(3, sTilemapBuffer); + ResetBgCoordinates(); + gMain.state++; + break; + case 3: + LoadTrainerHillRecordsWindowGfx(3); + LoadPalette(stdpal_get(0), 0xF0, 0x20); + gMain.state++; + break; + case 4: + if (IsDma3ManagerBusyWithBgCopy() != TRUE) + { + ShowBg(0); + ShowBg(3); + CopyBgTilemapBufferToVram(3); + gMain.state++; + } + break; + case 5: + InitWindows(sTrainerHillRecordsWindowTemplates); + DeactivateAllTextPrinters(); + gMain.state++; + break; + case 6: + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + gMain.state++; + break; + case 7: + SetDispcntReg(); + SetVBlankCallback(VblankCB_TrainerHillRecords); + PrintOnTrainerHillRecordsWindow(); + CreateTask(Task_TrainerHillWaitForPaletteFade, 8); + SetMainCallback2(MainCB2_TrainerHillRecords); + gMain.state = 0; + break; + } +} diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4d40d83a8..811aba128 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12,7 +12,6 @@ #include "constants/hold_effects.h" #include "util.h" #include "pokemon.h" -#include "calculate_base_damage.h" #include "random.h" #include "battle_controllers.h" #include "battle_interface.h" @@ -32,7 +31,6 @@ #include "bg.h" #include "string_util.h" #include "pokemon_icon.h" -#include "pokemon_item_effects.h" #include "m4a.h" #include "mail.h" #include "event_data.h" @@ -50,15 +48,6 @@ extern u16 gBattle_BG2_Y; extern u16 gBattle_BG3_X; extern struct MusicPlayerInfo gMPlayInfo_BGM; -struct TrainerMoney -{ - u8 classId; - u8 value; -}; - -extern const struct BattleMove gBattleMoves[]; -extern const u8 gTypeEffectiveness[336]; -extern const struct TrainerMoney gTrainerMoneyTable[]; extern const u8* const gBattleScriptsForMoveEffects[]; // functions @@ -78,28 +67,12 @@ extern bool8 sub_81B1250(void); // ? extern bool8 InBattlePike(void); extern bool8 InBattlePyramid(void); extern u16 GetBattlePyramidPickupItemId(void); -extern u8 sav1_map_get_light_level(void); +extern u8 Overworld_GetMapTypeOfSaveblockLocation(void); extern u8 sub_813B21C(void); extern u16 get_unknown_box_id(void); -// strings -extern const u8 gText_BattleYesNoChoice[]; - -// read via orr -#define BSScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24) -#define BSScriptRead16(ptr) ((ptr)[0] | ((ptr)[1] << 8)) -#define BSScriptReadPtr(ptr) ((void *)BSScriptRead32(ptr)) - -// read via add -#define BS2ScriptRead32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) -#define BS2ScriptRead16(ptr) ((ptr)[0] + ((ptr)[1] << 8)) -#define BS2ScriptReadPtr(ptr) ((void *)BS2ScriptRead32(ptr)) - #define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED)) -#define TARGET_TURN_DAMAGED (gSpecialStatuses[gBattlerTarget].physicalDmg != 0 \ - || gSpecialStatuses[gBattlerTarget].specialDmg != 0) - // this file's functions static bool8 IsTwoTurnsMove(u16 move); static void TrySetDestinyBondToHappen(void); @@ -1036,7 +1009,7 @@ static void atk00_attackcanceler(void) RecordAbilityBattle(gBattlerTarget, gLastUsedAbility); } else if (DEFENDER_IS_PROTECTED - && (gCurrentMove != MOVE_CURSE || (gBattleMons[gBattlerAttacker].type1 == TYPE_GHOST || gBattleMons[gBattlerAttacker].type2 == TYPE_GHOST)) + && (gCurrentMove != MOVE_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) && ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)))) { CancelMultiTurnMoves(gBattlerAttacker); @@ -1059,7 +1032,7 @@ static void JumpIfMoveFailed(u8 adder, u16 move) { gLastLandedMoves[gBattlerTarget] = 0; gLastHitByType[gBattlerTarget] = 0; - BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + BS_ptr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -1144,14 +1117,14 @@ static bool8 AccuracyCalcHelper(u16 move) static void atk01_accuracycheck(void) { - u16 move = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + u16 move = T2_READ_16(gBattlescriptCurrInstr + 5); if (move == 0xFFFE || move == 0xFFFF) { if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && move == 0xFFFF && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) gBattlescriptCurrInstr += 7; else if (gStatuses3[gBattlerTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else if (!JumpIfMoveAffectedByProtect(0)) gBattlescriptCurrInstr += 7; } @@ -1410,7 +1383,7 @@ static void atk06_typecalc(void) GET_MOVE_TYPE(gCurrentMove, moveType); // check stab - if (gBattleMons[gBattlerAttacker].type1 == moveType || gBattleMons[gBattlerAttacker].type2 == moveType) + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType)) { gBattleMoveDamage = gBattleMoveDamage * 15; gBattleMoveDamage = gBattleMoveDamage / 10; @@ -1588,7 +1561,7 @@ u8 TypeCalc(u16 move, u8 attacker, u8 defender) moveType = gBattleMoves[move].type; // check stab - if (gBattleMons[attacker].type1 == moveType || gBattleMons[attacker].type2 == moveType) + if (IS_BATTLER_OF_TYPE(attacker, moveType)) { gBattleMoveDamage = gBattleMoveDamage * 15; gBattleMoveDamage = gBattleMoveDamage / 10; @@ -2169,7 +2142,7 @@ static void atk10_printstring(void) { if (gBattleControllerExecFlags == 0) { - u16 var = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + u16 var = T2_READ_16(gBattlescriptCurrInstr + 1); PrepareStringBattle(var, gBattlerAttacker); gBattlescriptCurrInstr += 3; gBattleCommunication[MSG_DISPLAY] = 1; @@ -2180,7 +2153,7 @@ static void atk11_printselectionstring(void) { gActiveBattler = gBattlerAttacker; - BtlController_EmitPrintSelectionString(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1)); + BtlController_EmitPrintSelectionString(0, T2_READ_16(gBattlescriptCurrInstr + 1)); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 3; @@ -2197,7 +2170,7 @@ static void atk12_waitmessage(void) } else { - u16 toWait = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + u16 toWait = T2_READ_16(gBattlescriptCurrInstr + 1); if (++gPauseCounterBattle >= toWait) { gPauseCounterBattle = 0; @@ -2212,7 +2185,7 @@ static void atk13_printfromtable(void) { if (gBattleControllerExecFlags == 0) { - const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u16 *ptr = (const u16*) T1_READ_PTR(gBattlescriptCurrInstr + 1); ptr += gBattleCommunication[MULTISTRING_CHOOSER]; PrepareStringBattle(*ptr, gBattlerAttacker); @@ -2226,7 +2199,7 @@ static void atk14_printselectionstringfromtable(void) { if (gBattleControllerExecFlags == 0) { - const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u16 *ptr = (const u16*) T1_READ_PTR(gBattlescriptCurrInstr + 1); ptr += gBattleCommunication[MULTISTRING_CHOOSER]; gActiveBattler = gBattlerAttacker; @@ -2346,8 +2319,7 @@ void SetMoveEffect(bool8 primary, u8 certain) } RESET_RETURN } - if ((gBattleMons[gEffectBattler].type1 == TYPE_POISON || gBattleMons[gEffectBattler].type2 == TYPE_POISON - || gBattleMons[gEffectBattler].type1 == TYPE_STEEL || gBattleMons[gEffectBattler].type2 == TYPE_STEEL) + if ((IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) || IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) { @@ -2357,13 +2329,9 @@ void SetMoveEffect(bool8 primary, u8 certain) gBattleCommunication[MULTISTRING_CHOOSER] = 2; RESET_RETURN } - if (gBattleMons[gEffectBattler].type1 == TYPE_POISON) - break; - if (gBattleMons[gEffectBattler].type2 == TYPE_POISON) - break; - if (gBattleMons[gEffectBattler].type1 == TYPE_STEEL) + if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON)) break; - if (gBattleMons[gEffectBattler].type2 == TYPE_STEEL) + if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) break; if (gBattleMons[gEffectBattler].status1) break; @@ -2392,8 +2360,7 @@ void SetMoveEffect(bool8 primary, u8 certain) } RESET_RETURN } - if ((gBattleMons[gEffectBattler].type1 == TYPE_FIRE - || gBattleMons[gEffectBattler].type2 == TYPE_FIRE) + if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE) && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) { @@ -2403,9 +2370,7 @@ void SetMoveEffect(bool8 primary, u8 certain) gBattleCommunication[MULTISTRING_CHOOSER] = 2; RESET_RETURN } - if (gBattleMons[gEffectBattler].type1 == TYPE_FIRE) - break; - if (gBattleMons[gEffectBattler].type2 == TYPE_FIRE) + if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE)) break; if (gBattleMons[gEffectBattler].ability == ABILITY_WATER_VEIL) break; @@ -2417,9 +2382,7 @@ void SetMoveEffect(bool8 primary, u8 certain) case STATUS1_FREEZE: if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY) noSunCanFreeze = FALSE; - if (gBattleMons[gEffectBattler].type1 == TYPE_ICE) - break; - if (gBattleMons[gEffectBattler].type2 == TYPE_ICE) + if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE)) break; if (gBattleMons[gEffectBattler].status1) break; @@ -2481,8 +2444,7 @@ void SetMoveEffect(bool8 primary, u8 certain) } RESET_RETURN } - if ((gBattleMons[gEffectBattler].type1 == TYPE_POISON || gBattleMons[gEffectBattler].type2 == TYPE_POISON - || gBattleMons[gEffectBattler].type1 == TYPE_STEEL || gBattleMons[gEffectBattler].type2 == TYPE_STEEL) + if ((IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) || IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD) && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)) { @@ -2494,10 +2456,7 @@ void SetMoveEffect(bool8 primary, u8 certain) } if (gBattleMons[gEffectBattler].status1) break; - if (gBattleMons[gEffectBattler].type1 != TYPE_POISON - && gBattleMons[gEffectBattler].type2 != TYPE_POISON - && gBattleMons[gEffectBattler].type1 != TYPE_STEEL - && gBattleMons[gEffectBattler].type2 != TYPE_STEEL) + if (!IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) && !IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL)) { if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY) break; @@ -3014,7 +2973,7 @@ static void atk19_tryfaintmon(void) gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); if (gHitMarker & HITMARKER_FAINTED(gActiveBattler)) { - BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 3); + BS_ptr = T1_READ_PTR(gBattlescriptCurrInstr + 3); BattleScriptPop(); gBattlescriptCurrInstr = BS_ptr; @@ -3124,8 +3083,8 @@ static void atk1B_cleareffectsonfaint(void) static void atk1C_jumpifstatus(void) { u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + u32 flags = T2_READ_32(gBattlescriptCurrInstr + 2); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 6); if (gBattleMons[battlerId].status1 & flags && gBattleMons[battlerId].hp) gBattlescriptCurrInstr = jumpPtr; @@ -3136,8 +3095,8 @@ static void atk1C_jumpifstatus(void) static void atk1D_jumpifstatus2(void) { u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + u32 flags = T2_READ_32(gBattlescriptCurrInstr + 2); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 6); if (gBattleMons[battlerId].status2 & flags && gBattleMons[battlerId].hp) gBattlescriptCurrInstr = jumpPtr; @@ -3149,7 +3108,7 @@ static void atk1E_jumpifability(void) { u8 battlerId; u8 ability = gBattlescriptCurrInstr[2]; - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3); if (gBattlescriptCurrInstr[1] == BS_ATTACKER_SIDE) { @@ -3203,8 +3162,8 @@ static void atk1F_jumpifsideaffecting(void) else side = GET_BATTLER_SIDE(gBattlerTarget); - flags = BS2ScriptRead16(gBattlescriptCurrInstr + 2); - jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 4); + flags = T2_READ_16(gBattlescriptCurrInstr + 2); + jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 4); if (gSideStatuses[side] & flags) gBattlescriptCurrInstr = jumpPtr; @@ -3247,7 +3206,7 @@ static void atk20_jumpifstat(void) } if (ret) - gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 5); else gBattlescriptCurrInstr += 9; } @@ -3258,8 +3217,8 @@ static void atk21_jumpifstatus3condition(void) const u8 *jumpPtr; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2); - jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7); + flags = T2_READ_32(gBattlescriptCurrInstr + 2); + jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 7); if (gBattlescriptCurrInstr[6]) { @@ -3281,9 +3240,9 @@ static void atk22_jumpiftype(void) { u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); u8 type = gBattlescriptCurrInstr[2]; - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3); - if (gBattleMons[battlerId].type1 == type || gBattleMons[battlerId].type2 == type) + if (IS_BATTLER_OF_TYPE(battlerId, type)) gBattlescriptCurrInstr = jumpPtr; else gBattlescriptCurrInstr += 7; @@ -3398,7 +3357,7 @@ static void atk23_getexp(void) if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !gBattleStruct->wildVictorySong) { BattleStopLowHpSound(); - PlayBGM(0x161); + PlayBGM(MUS_KACHI2); gBattleStruct->wildVictorySong++; } @@ -3631,14 +3590,14 @@ static void atk24(void) if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if (foundOpponent + foundPlayer > 1) - gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; } else { if (foundOpponent != 0 && foundPlayer != 0) - gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; } @@ -3649,7 +3608,7 @@ static void atk24(void) } } #else -__attribute__((naked)) +NAKED static void atk24(void) { asm("\n\ @@ -3972,20 +3931,20 @@ static void atk27_decrementmultihit(void) if (--gMultiHitCounter == 0) gBattlescriptCurrInstr += 5; else - gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 1); } static void atk28_goto(void) { - gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 1); } static void atk29_jumpifbyte(void) { u8 caseID = gBattlescriptCurrInstr[1]; - const u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); + const u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 2); u8 value = gBattlescriptCurrInstr[6]; - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 7); gBattlescriptCurrInstr += 11; @@ -4021,9 +3980,9 @@ static void atk29_jumpifbyte(void) static void atk2A_jumpifhalfword(void) { u8 caseID = gBattlescriptCurrInstr[1]; - const u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); - u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 6); - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 8); + const u16* memHword = T2_READ_PTR(gBattlescriptCurrInstr + 2); + u16 value = T2_READ_16(gBattlescriptCurrInstr + 6); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 8); gBattlescriptCurrInstr += 12; @@ -4059,9 +4018,9 @@ static void atk2A_jumpifhalfword(void) static void atk2B_jumpifword(void) { u8 caseID = gBattlescriptCurrInstr[1]; - const u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); - u32 value = BSScriptRead32(gBattlescriptCurrInstr + 6); - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + const u32* memWord = T2_READ_PTR(gBattlescriptCurrInstr + 2); + u32 value = T1_READ_32(gBattlescriptCurrInstr + 6); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 10); gBattlescriptCurrInstr += 14; @@ -4096,10 +4055,10 @@ static void atk2B_jumpifword(void) static void atk2C_jumpifarrayequal(void) { - const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + const u8* mem1 = T2_READ_PTR(gBattlescriptCurrInstr + 1); + const u8* mem2 = T2_READ_PTR(gBattlescriptCurrInstr + 5); u32 size = gBattlescriptCurrInstr[9]; - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 10); u8 i; for (i = 0; i < size; i++) @@ -4119,10 +4078,10 @@ static void atk2C_jumpifarrayequal(void) static void atk2D_jumpifarraynotequal(void) { u8 equalBytes = 0; - const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + const u8* mem1 = T2_READ_PTR(gBattlescriptCurrInstr + 1); + const u8* mem2 = T2_READ_PTR(gBattlescriptCurrInstr + 5); u32 size = gBattlescriptCurrInstr[9]; - const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10); + const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 10); u8 i; for (i = 0; i < size; i++) @@ -4142,7 +4101,7 @@ static void atk2D_jumpifarraynotequal(void) static void atk2E_setbyte(void) { - u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 1); *memByte = gBattlescriptCurrInstr[5]; gBattlescriptCurrInstr += 6; @@ -4150,22 +4109,22 @@ static void atk2E_setbyte(void) static void atk2F_addbyte(void) { - u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 1); *memByte += gBattlescriptCurrInstr[5]; gBattlescriptCurrInstr += 6; } static void atk30_subbyte(void) { - u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 1); *memByte -= gBattlescriptCurrInstr[5]; gBattlescriptCurrInstr += 6; } static void atk31_copyarray(void) { - u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); + u8* dest = T2_READ_PTR(gBattlescriptCurrInstr + 1); + const u8* src = T2_READ_PTR(gBattlescriptCurrInstr + 5); s32 size = gBattlescriptCurrInstr[9]; s32 i; @@ -4179,9 +4138,9 @@ static void atk31_copyarray(void) static void atk32_copyarraywithindex(void) { - u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5); - const u8* index = BS2ScriptReadPtr(gBattlescriptCurrInstr + 9); + u8* dest = T2_READ_PTR(gBattlescriptCurrInstr + 1); + const u8* src = T2_READ_PTR(gBattlescriptCurrInstr + 5); + const u8* index = T2_READ_PTR(gBattlescriptCurrInstr + 9); s32 size = gBattlescriptCurrInstr[13]; s32 i; @@ -4195,15 +4154,15 @@ static void atk32_copyarraywithindex(void) static void atk33_orbyte(void) { - u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 1); *memByte |= gBattlescriptCurrInstr[5]; gBattlescriptCurrInstr += 6; } static void atk34_orhalfword(void) { - u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + u16* memHword = T2_READ_PTR(gBattlescriptCurrInstr + 1); + u16 val = T2_READ_16(gBattlescriptCurrInstr + 5); *memHword |= val; gBattlescriptCurrInstr += 7; @@ -4211,8 +4170,8 @@ static void atk34_orhalfword(void) static void atk35_orword(void) { - u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5); + u32* memWord = T2_READ_PTR(gBattlescriptCurrInstr + 1); + u32 val = T2_READ_32(gBattlescriptCurrInstr + 5); *memWord |= val; gBattlescriptCurrInstr += 9; @@ -4220,15 +4179,15 @@ static void atk35_orword(void) static void atk36_bicbyte(void) { - u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); + u8* memByte = T2_READ_PTR(gBattlescriptCurrInstr + 1); *memByte &= ~(gBattlescriptCurrInstr[5]); gBattlescriptCurrInstr += 6; } static void atk37_bichalfword(void) { - u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5); + u16* memHword = T2_READ_PTR(gBattlescriptCurrInstr + 1); + u16 val = T2_READ_16(gBattlescriptCurrInstr + 5); *memHword &= ~val; gBattlescriptCurrInstr += 7; @@ -4236,8 +4195,8 @@ static void atk37_bichalfword(void) static void atk38_bicword(void) { - u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1); - u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5); + u32* memWord = T2_READ_PTR(gBattlescriptCurrInstr + 1); + u32 val = T2_READ_32(gBattlescriptCurrInstr + 5); *memWord &= ~val; gBattlescriptCurrInstr += 9; @@ -4247,7 +4206,7 @@ static void atk39_pause(void) { if (gBattleControllerExecFlags == 0) { - u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 1); + u16 value = T2_READ_16(gBattlescriptCurrInstr + 1); if (++gPauseCounterBattle >= value) { gPauseCounterBattle = 0; @@ -4306,7 +4265,7 @@ static void atk3F_end3(void) // pops the main function stack static void atk41_call(void) { BattleScriptPush(gBattlescriptCurrInstr + 5); - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } static void atk42_jumpiftype2(void) @@ -4314,7 +4273,7 @@ static void atk42_jumpiftype2(void) u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); if (gBattlescriptCurrInstr[2] == gBattleMons[battlerId].type1 || gBattlescriptCurrInstr[2] == gBattleMons[battlerId].type2) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 3); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); else gBattlescriptCurrInstr += 7; } @@ -4322,7 +4281,7 @@ static void atk42_jumpiftype2(void) static void atk43_jumpifabilitypresent(void) { if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, gBattlescriptCurrInstr[1], 0, 0)) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -4337,7 +4296,7 @@ static void atk45_playanimation(void) const u16* argumentPtr; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3); + argumentPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3); if (gBattlescriptCurrInstr[2] == B_ANIM_STATS_CHANGE || gBattlescriptCurrInstr[2] == B_ANIM_SNATCH_MOVE @@ -4379,8 +4338,8 @@ static void atk46_playanimation2(void) // animation Id is stored in the first po const u8* animationIdPtr; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - animationIdPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2); - argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6); + animationIdPtr = T2_READ_PTR(gBattlescriptCurrInstr + 2); + argumentPtr = T2_READ_PTR(gBattlescriptCurrInstr + 6); if (*animationIdPtr == B_ANIM_STATS_CHANGE || *animationIdPtr == B_ANIM_SNATCH_MOVE @@ -4438,31 +4397,34 @@ static void atk47_setgraphicalstatchangevalues(void) gBattlescriptCurrInstr++; } -#ifdef NONMATCHING static void atk48_playstatchangeanimation(void) { u32 currStat = 0; - s16 statAnimId = 0; - s16 checkingStatAnimId = 0; - s32 changeableStats = 0; - u32 statsToCheck = 0; + u16 statAnimId = 0; + s32 changeableStatsCount = 0; + u8 statsToCheck = 0; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); statsToCheck = gBattlescriptCurrInstr[2]; if (gBattlescriptCurrInstr[3] & ATK48_STAT_NEGATIVE) // goes down { - checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x2D : 0x15; + s16 startingStatAnimId; + if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) + startingStatAnimId = 0x2D; + else + startingStatAnimId = 0x15; + while (statsToCheck != 0) { if (statsToCheck & 1) { - if (!(gBattlescriptCurrInstr[3] & ATK48_LOWER_FAIL_CHECK)) + if (gBattlescriptCurrInstr[3] & ATK48_DONT_CHECK_LOWER) { if (gBattleMons[gActiveBattler].statStages[currStat] > 0) { - statAnimId = checkingStatAnimId; - changeableStats++; + statAnimId = startingStatAnimId + currStat; + changeableStatsCount++; } } else if (!gSideTimers[GET_BATTLER_SIDE(gActiveBattler)].mistTimer @@ -4473,15 +4435,15 @@ static void atk48_playstatchangeanimation(void) { if (gBattleMons[gActiveBattler].statStages[currStat] > 0) { - statAnimId = checkingStatAnimId; - changeableStats++; + statAnimId = startingStatAnimId + currStat; + changeableStatsCount++; } } } - statsToCheck >>= 1, checkingStatAnimId++, currStat++; + statsToCheck >>= 1, currStat++; } - if (changeableStats > 1) // more than one stat, so the color is gray + if (changeableStatsCount > 1) // more than one stat, so the color is gray { if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) statAnimId = 0x3A; @@ -4491,18 +4453,23 @@ static void atk48_playstatchangeanimation(void) } else // goes up { - checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x26 : 0xE; + s16 startingStatAnimId; + if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) + startingStatAnimId = 0x26; + else + startingStatAnimId = 0xE; + while (statsToCheck != 0) { if (statsToCheck & 1 && gBattleMons[gActiveBattler].statStages[currStat] < 0xC) { - statAnimId = checkingStatAnimId; - changeableStats++; + statAnimId = startingStatAnimId + currStat; + changeableStatsCount++; } - statsToCheck >>= 1, checkingStatAnimId += 1, currStat++; + statsToCheck >>= 1, currStat++; } - if (changeableStats > 1) // more than one stat, so the color is gray + if (changeableStatsCount > 1) // more than one stat, so the color is gray { if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) statAnimId = 0x38; @@ -4511,15 +4478,15 @@ static void atk48_playstatchangeanimation(void) } } - if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats < 2) + if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStatsCount < 2) { gBattlescriptCurrInstr += 4; } - else if (changeableStats != 0 && gBattleScripting.field_1B == 0) + else if (changeableStatsCount != 0 && gBattleScripting.field_1B == 0) { BtlController_EmitBattleAnimation(0, B_ANIM_STATS_CHANGE, statAnimId); MarkBattlerForControllerExec(gActiveBattler); - if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats > 1) + if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStatsCount > 1) gBattleScripting.field_1B = 1; gBattlescriptCurrInstr += 4; } @@ -4528,261 +4495,6 @@ static void atk48_playstatchangeanimation(void) gBattlescriptCurrInstr += 4; } } -#else -__attribute__((naked)) -static void atk48_playstatchangeanimation(void) -{ - asm("\n\ - .syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r10\n\ - mov r6, r9\n\ - mov r5, r8\n\ - push {r5-r7}\n\ - sub sp, 0x4\n\ - movs r7, 0\n\ - movs r0, 0\n\ - mov r8, r0\n\ - movs r3, 0\n\ - ldr r5, =gBattlescriptCurrInstr\n\ - ldr r0, [r5]\n\ - ldrb r0, [r0, 0x1]\n\ - str r3, [sp]\n\ - bl GetBattlerForBattleScript\n\ - ldr r2, =gActiveBattler\n\ - strb r0, [r2]\n\ - ldr r0, [r5]\n\ - ldrb r4, [r0, 0x2]\n\ - ldrb r1, [r0, 0x3]\n\ - movs r0, 0x1\n\ - ands r0, r1\n\ - ldr r3, [sp]\n\ - cmp r0, 0\n\ - beq _0804BAEC\n\ - movs r0, 0x2\n\ - ands r0, r1\n\ - movs r1, 0x15\n\ - cmp r0, 0\n\ - beq _0804BA18\n\ - movs r1, 0x2D\n\ -_0804BA18:\n\ - cmp r4, 0\n\ - beq _0804BAC0\n\ - movs r0, 0x1\n\ - mov r10, r0\n\ - ldr r0, =gBattleMons + 0x18\n\ - mov r9, r0\n\ - lsls r5, r1, 16\n\ -_0804BA26:\n\ - adds r0, r4, 0\n\ - mov r1, r10\n\ - ands r0, r1\n\ - cmp r0, 0\n\ - beq _0804BAB2\n\ - ldr r0, =gBattlescriptCurrInstr\n\ - ldr r0, [r0]\n\ - ldrb r1, [r0, 0x3]\n\ - movs r0, 0x8\n\ - ands r0, r1\n\ - cmp r0, 0\n\ - beq _0804BA58\n\ - ldr r0, =gActiveBattler\n\ - ldrb r1, [r0]\n\ - movs r0, 0x58\n\ - muls r0, r1\n\ - adds r0, r7, r0\n\ - b _0804BAA0\n\ - .pool\n\ -_0804BA58:\n\ - ldr r6, =gActiveBattler\n\ - ldrb r0, [r6]\n\ - str r3, [sp]\n\ - bl GetBattlerPosition\n\ - mov r1, r10\n\ - ands r1, r0\n\ - lsls r0, r1, 1\n\ - adds r0, r1\n\ - lsls r0, 2\n\ - ldr r1, =gSideTimers\n\ - adds r0, r1\n\ - ldrb r0, [r0, 0x4]\n\ - ldr r3, [sp]\n\ - cmp r0, 0\n\ - bne _0804BAB2\n\ - ldr r0, =gBattleMons\n\ - ldrb r2, [r6]\n\ - movs r1, 0x58\n\ - muls r2, r1\n\ - adds r0, r2, r0\n\ - adds r0, 0x20\n\ - ldrb r0, [r0]\n\ - cmp r0, 0x1D\n\ - beq _0804BAB2\n\ - cmp r0, 0x49\n\ - beq _0804BAB2\n\ - cmp r0, 0x33\n\ - bne _0804BA96\n\ - cmp r7, 0x6\n\ - beq _0804BAB2\n\ -_0804BA96:\n\ - cmp r0, 0x34\n\ - bne _0804BA9E\n\ - cmp r7, 0x1\n\ - beq _0804BAB2\n\ -_0804BA9E:\n\ - adds r0, r7, r2\n\ -_0804BAA0:\n\ - add r0, r9\n\ - ldrb r0, [r0]\n\ - lsls r0, 24\n\ - asrs r0, 24\n\ - cmp r0, 0\n\ - ble _0804BAB2\n\ - lsrs r0, r5, 16\n\ - mov r8, r0\n\ - adds r3, 0x1\n\ -_0804BAB2:\n\ - lsrs r4, 1\n\ - movs r1, 0x80\n\ - lsls r1, 9\n\ - adds r5, r1\n\ - adds r7, 0x1\n\ - cmp r4, 0\n\ - bne _0804BA26\n\ -_0804BAC0:\n\ - ldr r0, =gBattlescriptCurrInstr\n\ - mov r9, r0\n\ - cmp r3, 0x1\n\ - ble _0804BB4E\n\ - ldr r0, [r0]\n\ - ldrb r1, [r0, 0x3]\n\ - movs r0, 0x2\n\ - ands r0, r1\n\ - movs r1, 0x39\n\ - mov r8, r1\n\ - cmp r0, 0\n\ - beq _0804BB4E\n\ - movs r0, 0x3A\n\ - b _0804BB4C\n\ - .pool\n\ -_0804BAEC:\n\ - movs r0, 0x2\n\ - ands r0, r1\n\ - movs r1, 0xE\n\ - cmp r0, 0\n\ - beq _0804BAF8\n\ - movs r1, 0x26\n\ -_0804BAF8:\n\ - mov r9, r5\n\ - cmp r4, 0\n\ - beq _0804BB34\n\ - ldr r6, =gBattleMons + 0x18\n\ - adds r5, r2, 0\n\ - lsls r2, r1, 16\n\ -_0804BB04:\n\ - movs r0, 0x1\n\ - ands r0, r4\n\ - cmp r0, 0\n\ - beq _0804BB26\n\ - ldrb r1, [r5]\n\ - movs r0, 0x58\n\ - muls r0, r1\n\ - adds r0, r7, r0\n\ - adds r0, r6\n\ - ldrb r0, [r0]\n\ - lsls r0, 24\n\ - asrs r0, 24\n\ - cmp r0, 0xB\n\ - bgt _0804BB26\n\ - lsrs r1, r2, 16\n\ - mov r8, r1\n\ - adds r3, 0x1\n\ -_0804BB26:\n\ - lsrs r4, 1\n\ - movs r0, 0x80\n\ - lsls r0, 9\n\ - adds r2, r0\n\ - adds r7, 0x1\n\ - cmp r4, 0\n\ - bne _0804BB04\n\ -_0804BB34:\n\ - cmp r3, 0x1\n\ - ble _0804BB4E\n\ - mov r1, r9\n\ - ldr r0, [r1]\n\ - ldrb r1, [r0, 0x3]\n\ - movs r0, 0x2\n\ - ands r0, r1\n\ - movs r1, 0x37\n\ - mov r8, r1\n\ - cmp r0, 0\n\ - beq _0804BB4E\n\ - movs r0, 0x38\n\ -_0804BB4C:\n\ - mov r8, r0\n\ -_0804BB4E:\n\ - mov r1, r9\n\ - ldr r2, [r1]\n\ - ldrb r1, [r2, 0x3]\n\ - movs r0, 0x4\n\ - ands r0, r1\n\ - cmp r0, 0\n\ - beq _0804BB6C\n\ - cmp r3, 0x1\n\ - bgt _0804BB6C\n\ - adds r0, r2, 0x4\n\ - mov r1, r9\n\ - b _0804BBBA\n\ - .pool\n\ -_0804BB6C:\n\ - cmp r3, 0\n\ - beq _0804BBB4\n\ - ldr r4, =gBattleScripting\n\ - ldrb r0, [r4, 0x1B]\n\ - cmp r0, 0\n\ - bne _0804BBB4\n\ - movs r0, 0\n\ - movs r1, 0x1\n\ - mov r2, r8\n\ - str r3, [sp]\n\ - bl BtlController_EmitBattleAnimation\n\ - ldr r0, =gActiveBattler\n\ - ldrb r0, [r0]\n\ - bl MarkBattlerForControllerExec\n\ - ldr r0, =gBattlescriptCurrInstr\n\ - ldr r0, [r0]\n\ - ldrb r1, [r0, 0x3]\n\ - movs r0, 0x4\n\ - ands r0, r1\n\ - ldr r3, [sp]\n\ - cmp r0, 0\n\ - beq _0804BBA4\n\ - cmp r3, 0x1\n\ - ble _0804BBA4\n\ - movs r0, 0x1\n\ - strb r0, [r4, 0x1B]\n\ -_0804BBA4:\n\ - ldr r1, =gBattlescriptCurrInstr\n\ - b _0804BBB6\n\ - .pool\n\ -_0804BBB4:\n\ - mov r1, r9\n\ -_0804BBB6:\n\ - ldr r0, [r1]\n\ - adds r0, 0x4\n\ -_0804BBBA:\n\ - str r0, [r1]\n\ - add sp, 0x4\n\ - pop {r3-r5}\n\ - mov r8, r3\n\ - mov r9, r4\n\ - mov r10, r5\n\ - pop {r4-r7}\n\ - pop {r0}\n\ - bx r0\n\ - .syntax divided"); -} -#endif // NONMATCHING #define ATK49_LAST_CASE 17 @@ -5273,10 +4985,9 @@ static void atk4E_switchinanim(void) static void atk4F_jumpifcantswitch(void) { - s32 val = 0; - s32 compareVar = 0; - struct Pokemon *party = NULL; - s32 r7 = 0; + s32 i; + s32 lastMonId; + struct Pokemon *party; gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1] & ~(ATK4F_DONT_CHECK_STATUSES)); @@ -5284,7 +4995,7 @@ static void atk4F_jumpifcantswitch(void) && ((gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)) || (gStatuses3[gActiveBattler] & STATUS3_ROOTED))) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); } else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { @@ -5296,21 +5007,21 @@ static void atk4F_jumpifcantswitch(void) else party = gPlayerParty; - val = 0; - if (2 & gActiveBattler) - val = 3; + i = 0; + if (gActiveBattler & 2) + i = 3; - for (compareVar = val + 3; val < compareVar; val++) + for (lastMonId = i + 3; i < lastMonId; i++) { - if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[val], MON_DATA_IS_EGG) - && GetMonData(&party[val], MON_DATA_HP) != 0 - && gBattlerPartyIndexes[gActiveBattler] != val) + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0 + && gBattlerPartyIndexes[gActiveBattler] != i) break; } - if (val == compareVar) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + if (i == lastMonId) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -5322,18 +5033,18 @@ static void atk4F_jumpifcantswitch(void) { party = gPlayerParty; - val = 0; + i = 0; if (sub_806D82C(GetBattlerMultiplayerId(gActiveBattler)) == TRUE) - val = 3; + i = 3; } else { party = gEnemyParty; if (gActiveBattler == 1) - val = 0; + i = 0; else - val = 3; + i = 3; } } else @@ -5343,23 +5054,22 @@ static void atk4F_jumpifcantswitch(void) else party = gPlayerParty; - - val = 0; + i = 0; if (sub_806D82C(GetBattlerMultiplayerId(gActiveBattler)) == TRUE) - val = 3; + i = 3; } - for (compareVar = val + 3; val < compareVar; val++) + for (lastMonId = i + 3; i < lastMonId; i++) { - if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[val], MON_DATA_IS_EGG) - && GetMonData(&party[val], MON_DATA_HP) != 0 - && gBattlerPartyIndexes[gActiveBattler] != val) + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0 + && gBattlerPartyIndexes[gActiveBattler] != i) break; } - if (val == compareVar) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + if (i == lastMonId) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -5367,59 +5077,62 @@ static void atk4F_jumpifcantswitch(void) { party = gEnemyParty; - val = 0; - if (gActiveBattler == 3) - val = 3; + i = 0; + if (gActiveBattler == B_POSITION_OPPONENT_RIGHT) + i = 3; - for (compareVar = val + 3; val < compareVar; val++) + for (lastMonId = i + 3; i < lastMonId; i++) { - if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[val], MON_DATA_IS_EGG) - && GetMonData(&party[val], MON_DATA_HP) != 0 - && gBattlerPartyIndexes[gActiveBattler] != val) + if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && GetMonData(&party[i], MON_DATA_HP) != 0 + && gBattlerPartyIndexes[gActiveBattler] != i) break; } - if (val == compareVar) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + if (i == lastMonId) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } else { + u8 battlerIn1, battlerIn2; + if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT) { - r7 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - compareVar = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + battlerIn2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); else - compareVar = r7; + battlerIn2 = battlerIn1; party = gEnemyParty; } else { - r7 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); + battlerIn1 = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - compareVar = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); + battlerIn2 = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); else - compareVar = r7; + battlerIn2 = battlerIn1; party = gPlayerParty; } - for (val = 0; val < 6; val++) + + for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[val], MON_DATA_HP) != 0 - && GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE - && !GetMonData(&party[val], MON_DATA_IS_EGG) - && val != gBattlerPartyIndexes[r7] && val != gBattlerPartyIndexes[compareVar]) + if (GetMonData(&party[i], MON_DATA_HP) != 0 + && GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE + && !GetMonData(&party[i], MON_DATA_IS_EGG) + && i != gBattlerPartyIndexes[battlerIn1] && i != gBattlerPartyIndexes[battlerIn2]) break; } - if (val == 6) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + if (i == 6) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -5444,7 +5157,7 @@ static void atk50_openpartyscreen(void) battlerId = 0; flags = 0; - jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 2); if (gBattlescriptCurrInstr[1] == 5) { @@ -5804,8 +5517,7 @@ static void atk52_switchineffects(void) if (!(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES_DAMAGED) && (gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SPIKES) - && gBattleMons[gActiveBattler].type1 != TYPE_FLYING - && gBattleMons[gActiveBattler].type2 != TYPE_FLYING + && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING) && gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE) { u8 spikesDmg; @@ -5885,7 +5597,7 @@ static void atk53_trainerslidein(void) static void atk54_playse(void) { gActiveBattler = gBattlerAttacker; - BtlController_EmitPlaySE(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1)); + BtlController_EmitPlaySE(0, T2_READ_16(gBattlescriptCurrInstr + 1)); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 3; @@ -5894,7 +5606,7 @@ static void atk54_playse(void) static void atk55_fanfare(void) { gActiveBattler = gBattlerAttacker; - BtlController_EmitPlayFanfareOrBGM(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), FALSE); + BtlController_EmitPlayFanfareOrBGM(0, T2_READ_16(gBattlescriptCurrInstr + 1), FALSE); MarkBattlerForControllerExec(gActiveBattler); gBattlescriptCurrInstr += 3; @@ -5929,8 +5641,8 @@ static void atk58_returntoball(void) static void atk59_handlelearnnewmove(void) { - const u8 *jumpPtr1 = BSScriptReadPtr(gBattlescriptCurrInstr + 1); - const u8 *jumpPtr2 = BSScriptReadPtr(gBattlescriptCurrInstr + 5); + const u8 *jumpPtr1 = T1_READ_PTR(gBattlescriptCurrInstr + 1); + const u8 *jumpPtr2 = T1_READ_PTR(gBattlescriptCurrInstr + 5); u16 ret = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterMonId], gBattlescriptCurrInstr[9]); while (ret == 0xFFFE) @@ -6047,7 +5759,7 @@ static void atk5A_yesnoboxlearnmove(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); PREPARE_MOVE_BUFFER(gBattleTextBuff2, moveId) @@ -6117,7 +5829,7 @@ static void atk5B_yesnoboxstoplearningmove(void) PlaySE(SE_SELECT); if (gBattleCommunication[1] != 0) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; @@ -6126,7 +5838,7 @@ static void atk5B_yesnoboxstoplearningmove(void) else if (gMain.newKeys & B_BUTTON) { PlaySE(SE_SELECT); - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); HandleBattleWindow(0x18, 0x8, 0x1D, 0xD, WINDOW_CLEAR); } break; @@ -6351,7 +6063,7 @@ static void atk65_status2animation(void) if (gBattleControllerExecFlags == 0) { gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - wantedToAnimate = BSScriptRead32(gBattlescriptCurrInstr + 2); + wantedToAnimate = T1_READ_32(gBattlescriptCurrInstr + 2); if (!(gStatuses3[gActiveBattler] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[gActiveBattler].substituteHP == 0 && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) @@ -6370,7 +6082,7 @@ static void atk66_chosenstatusanimation(void) if (gBattleControllerExecFlags == 0) { gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); - wantedStatus = BSScriptRead32(gBattlescriptCurrInstr + 3); + wantedStatus = T1_READ_32(gBattlescriptCurrInstr + 3); if (!(gStatuses3[gActiveBattler] & STATUS3_SEMI_INVULNERABLE) && gDisableStructs[gActiveBattler].substituteHP == 0 && !(gHitMarker & HITMARKER_NO_ANIMATIONS)) @@ -6821,7 +6533,7 @@ static void atk71_buffermovetolearn(void) static void atk72_jumpifplayerran(void) { if (TryRunFromBattle(gBattlerFainted)) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; } @@ -6882,8 +6594,7 @@ static void atk74_hpthresholds2(void) static void atk75_useitemonopponent(void) { gBattlerInMenuId = gBattlerAttacker; - ExecuteTableBasedItemEffect(&gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]], gLastUsedItem, gBattlerPartyIndexes[gBattlerAttacker], 0, 1); - + PokemonUseItemEffects(&gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]], gLastUsedItem, gBattlerPartyIndexes[gBattlerAttacker], 0, 1); gBattlescriptCurrInstr += 1; } @@ -7151,7 +6862,7 @@ static void atk79_setatkhptozero(void) static void atk7A_jumpifnexttargetvalid(void) { - const u8 *jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8 *jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { @@ -7176,7 +6887,7 @@ static void atk7A_jumpifnexttargetvalid(void) static void atk7B_tryhealhalfhealth(void) { - const u8* failPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8* failPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (gBattlescriptCurrInstr[5] == BS_ATTACKER) gBattlerTarget = gBattlerAttacker; @@ -7286,7 +6997,7 @@ static void atk7F_setseeded(void) gMoveResultFlags |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = 1; } - else if (gBattleMons[gBattlerTarget].type1 == TYPE_GRASS || gBattleMons[gBattlerTarget].type2 == TYPE_GRASS) + else if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS)) { gMoveResultFlags |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = 2; @@ -7325,7 +7036,7 @@ static void atk80_manipulatedamage(void) static void atk81_trysetrest(void) { - const u8 *failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8 *failJump = T1_READ_PTR(gBattlescriptCurrInstr + 1); gActiveBattler = gBattlerTarget = gBattlerAttacker; gBattleMoveDamage = gBattleMons[gBattlerTarget].maxHP * (-1); @@ -7349,7 +7060,7 @@ static void atk81_trysetrest(void) static void atk82_jumpifnotfirstturn(void) { - const u8* failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8* failJump = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (gDisableStructs[gBattlerAttacker].isFirstTurn) gBattlescriptCurrInstr += 5; @@ -7391,7 +7102,7 @@ bool8 UproarWakeUpCheck(u8 battlerId) static void atk84_jumpifcantmakeasleep(void) { - const u8 *jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8 *jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (UproarWakeUpCheck(gBattlerTarget)) { @@ -7431,7 +7142,7 @@ static void atk85_stockpile(void) static void atk86_stockpiletobasedamage(void) { - const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8* jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) { gBattlescriptCurrInstr = jumpPtr; @@ -7457,7 +7168,7 @@ static void atk86_stockpiletobasedamage(void) static void atk87_stockpiletohpheal(void) { - const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + const u8* jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1); if (gDisableStructs[gBattlerAttacker].stockpileCounter == 0) { @@ -7667,7 +7378,7 @@ static u8 ChangeStatBuffs(s8 statValue, u8 statId, u8 flags, const u8 *BS_ptr) static void atk89_statbuffchange(void) { - const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + const u8* jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 2); if (ChangeStatBuffs(gBattleScripting.statChanger & 0xF0, GET_STAT_BUFF_ID(gBattleScripting.statChanger), gBattlescriptCurrInstr[1], jumpPtr) == STAT_CHANGE_WORKED) gBattlescriptCurrInstr += 6; } @@ -7739,7 +7450,7 @@ static bool8 TryDoForceSwitchOut(void) u16 random = Random() & 0xFF; if ((u32)((random * (gBattleMons[gBattlerAttacker].level + gBattleMons[gBattlerTarget].level) >> 8) + 1) <= (gBattleMons[gBattlerTarget].level / 4)) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); return FALSE; } *(gBattleStruct->field_58 + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget]; @@ -7869,7 +7580,7 @@ static void atk8F_forcerandomswitch(void) if (validMons <= minNeeded) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -7930,7 +7641,7 @@ static void atk90_tryconversiontypechange(void) // randomly changes user's type if (moveType == TYPE_MYSTERY) { - if (gBattleMons[gBattlerAttacker].type1 == TYPE_GHOST || gBattleMons[gBattlerAttacker].type2 == TYPE_GHOST) + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) moveType = TYPE_GHOST; else moveType = TYPE_NORMAL; @@ -7944,7 +7655,7 @@ static void atk90_tryconversiontypechange(void) // randomly changes user's type if (moveChecked == validMoves) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -7957,7 +7668,7 @@ static void atk90_tryconversiontypechange(void) // randomly changes user's type if (moveType == TYPE_MYSTERY) { - if (gBattleMons[gBattlerAttacker].type1 == TYPE_GHOST || gBattleMons[gBattlerAttacker].type2 == TYPE_GHOST) + if (IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST)) moveType = TYPE_GHOST; else moveType = TYPE_NORMAL; @@ -7965,10 +7676,8 @@ static void atk90_tryconversiontypechange(void) // randomly changes user's type } while (moveType == gBattleMons[gBattlerAttacker].type1 || moveType == gBattleMons[gBattlerAttacker].type2); - gBattleMons[gBattlerAttacker].type1 = moveType; - gBattleMons[gBattlerAttacker].type2 = moveType; - - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType) + SET_BATTLER_TYPE(gBattlerAttacker, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); gBattlescriptCurrInstr += 5; } @@ -8095,7 +7804,7 @@ static void atk93_tryKO(void) gBattleCommunication[MULTISTRING_CHOOSER] = 0; else gBattleCommunication[MULTISTRING_CHOOSER] = 1; - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } } @@ -8152,8 +7861,7 @@ static void atk96_weatherdamage(void) } if (gBattleWeather & WEATHER_HAIL) { - if (gBattleMons[gBattlerAttacker].type1 != TYPE_ICE - && gBattleMons[gBattlerAttacker].type2 != TYPE_ICE + if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_ICE) && !(gStatuses3[gBattlerAttacker] & STATUS3_UNDERGROUND) && !(gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)) { @@ -8213,7 +7921,7 @@ static void atk97_tryinfatuating(void) || GetGenderFromSpeciesAndPersonality(speciesAttacker, personalityAttacker) == MON_GENDERLESS || GetGenderFromSpeciesAndPersonality(speciesTarget, personalityTarget) == MON_GENDERLESS) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -8377,7 +8085,7 @@ static void atk9D_mimicattackcopy(void) || gLastMoves[gBattlerTarget] == 0 || gLastMoves[gBattlerTarget] == 0xFFFF) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -8405,7 +8113,7 @@ static void atk9D_mimicattackcopy(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } } @@ -8480,7 +8188,7 @@ static void atkA1_counterdamagecalculator(void) else { gSpecialStatuses[gBattlerAttacker].flag20 = 1; - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8503,7 +8211,7 @@ static void atkA2_mirrorcoatdamagecalculator(void) // a copy of atkA1 with the p else { gSpecialStatuses[gBattlerAttacker].flag20 = 1; - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8528,7 +8236,7 @@ static void atkA3_disablelastusedattack(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8560,7 +8268,7 @@ static void atkA4_trysetencore(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8584,7 +8292,7 @@ static void atkA5_painsplitdmgcalc(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8593,12 +8301,12 @@ static void atkA6_settypetorandomresistance(void) // conversion 2 if (gLastLandedMoves[gBattlerAttacker] == 0 || gLastLandedMoves[gBattlerAttacker] == 0xFFFF) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else if (IsTwoTurnsMove(gLastLandedMoves[gBattlerAttacker]) && gBattleMons[gLastHitBy[gBattlerAttacker]].status2 & STATUS2_MULTIPLETURNS) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -8612,13 +8320,10 @@ static void atkA6_settypetorandomresistance(void) // conversion 2 if (TYPE_EFFECT_ATK_TYPE(i) == gLastHitByType[gBattlerAttacker] && TYPE_EFFECT_MULTIPLIER(i) <= TYPE_MUL_NOT_EFFECTIVE - && gBattleMons[gBattlerAttacker].type1 != TYPE_EFFECT_DEF_TYPE(i) - && gBattleMons[gBattlerAttacker].type2 != TYPE_EFFECT_DEF_TYPE(i)) + && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_EFFECT_DEF_TYPE(i))) { - gBattleMons[gBattlerAttacker].type1 = TYPE_EFFECT_DEF_TYPE(i); - gBattleMons[gBattlerAttacker].type2 = TYPE_EFFECT_DEF_TYPE(i); - - PREPARE_TYPE_BUFFER(gBattleTextBuff1, TYPE_EFFECT_DEF_TYPE(i)) + SET_BATTLER_TYPE(gBattlerAttacker, TYPE_EFFECT_DEF_TYPE(i)); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, TYPE_EFFECT_DEF_TYPE(i)); gBattlescriptCurrInstr += 5; return; @@ -8635,12 +8340,9 @@ static void atkA6_settypetorandomresistance(void) // conversion 2 default: if (TYPE_EFFECT_ATK_TYPE(j) == gLastHitByType[gBattlerAttacker] && TYPE_EFFECT_MULTIPLIER(j) <= 5 - && gBattleMons[gBattlerAttacker].type1 != TYPE_EFFECT_DEF_TYPE(i) - && gBattleMons[gBattlerAttacker].type2 != TYPE_EFFECT_DEF_TYPE(i)) + && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_EFFECT_DEF_TYPE(i))) { - gBattleMons[gBattlerAttacker].type1 = TYPE_EFFECT_DEF_TYPE(rands); - gBattleMons[gBattlerAttacker].type2 = TYPE_EFFECT_DEF_TYPE(rands); - + SET_BATTLER_TYPE(gBattlerAttacker, TYPE_EFFECT_DEF_TYPE(rands)); PREPARE_TYPE_BUFFER(gBattleTextBuff1, TYPE_EFFECT_DEF_TYPE(rands)) gBattlescriptCurrInstr += 5; @@ -8650,7 +8352,7 @@ static void atkA6_settypetorandomresistance(void) // conversion 2 } } - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8684,7 +8386,7 @@ static void atkA8_copymovepermanently(void) // sketch if (i != 4) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else // sketch worked { @@ -8711,7 +8413,7 @@ static void atkA8_copymovepermanently(void) // sketch } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8792,7 +8494,7 @@ static void atkA9_trychoosesleeptalkmove(void) gCurrMovePos = movePosition; gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED); gBattlerTarget = GetMoveTarget(gRandomMove, 0); - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8877,12 +8579,12 @@ static void atkAD_tryspiteppreduce(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -8986,7 +8688,7 @@ static void atkAF_cursetarget(void) { if (gBattleMons[gBattlerTarget].status2 & STATUS2_CURSED) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9006,7 +8708,7 @@ static void atkB0_trysetspikes(void) if (gSideTimers[targetSide].spikesAmount == 3) { gSpecialStatuses[gBattlerAttacker].flag20 = 1; - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9045,7 +8747,7 @@ static void atkB2_trysetperishsong(void) PressurePPLoseOnUsingPerishSong(gBattlerAttacker); if (notAffectedCount == gBattlersCount) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; } @@ -9089,7 +8791,7 @@ static void atkB4_jumpifconfusedandstatmaxed(void) { if (gBattleMons[gBattlerTarget].status2 & STATUS2_CONFUSION && gBattleMons[gBattlerTarget].statStages[gBattlescriptCurrInstr[1]] == 0xC) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -9267,7 +8969,7 @@ static void atkBA_jumpifnopursuitswitchdmg(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9307,7 +9009,7 @@ static void atkBC_maxattackhalvehp(void) // belly drum } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9387,185 +9089,39 @@ static void atkC0_recoverbasedonsunlight(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } -#ifdef NONMATCHING static void atkC1_hiddenpowercalc(void) { - u32 powerBits = 0; - u32 typeBits = 0; + u8 powerBits; + u8 typeBits; - powerBits |= ((gBattleMons[gBattlerAttacker].hpIV & 2) >> 1); - powerBits |= ((gBattleMons[gBattlerAttacker].attackIV & 2) << 0); - powerBits |= ((gBattleMons[gBattlerAttacker].defenseIV & 2) << 1); - powerBits |= ((gBattleMons[gBattlerAttacker].speedIV & 2) << 2); - powerBits |= ((gBattleMons[gBattlerAttacker].spAttackIV & 2) << 3); - powerBits |= ((gBattleMons[gBattlerAttacker].spDefenseIV & 2) << 4); + powerBits = ((gBattleMons[gBattlerAttacker].hpIV & 2) >> 1) + | ((gBattleMons[gBattlerAttacker].attackIV & 2) << 0) + | ((gBattleMons[gBattlerAttacker].defenseIV & 2) << 1) + | ((gBattleMons[gBattlerAttacker].speedIV & 2) << 2) + | ((gBattleMons[gBattlerAttacker].spAttackIV & 2) << 3) + | ((gBattleMons[gBattlerAttacker].spDefenseIV & 2) << 4); - typeBits |= ((gBattleMons[gBattlerAttacker].hpIV & 1) << 0); - typeBits |= ((gBattleMons[gBattlerAttacker].attackIV & 1) << 1); - typeBits |= ((gBattleMons[gBattlerAttacker].defenseIV & 1) << 2); - typeBits |= ((gBattleMons[gBattlerAttacker].speedIV & 1) << 3); - typeBits |= ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4); - typeBits |= ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5); + typeBits = ((gBattleMons[gBattlerAttacker].hpIV & 1) << 0) + | ((gBattleMons[gBattlerAttacker].attackIV & 1) << 1) + | ((gBattleMons[gBattlerAttacker].defenseIV & 1) << 2) + | ((gBattleMons[gBattlerAttacker].speedIV & 1) << 3) + | ((gBattleMons[gBattlerAttacker].spAttackIV & 1) << 4) + | ((gBattleMons[gBattlerAttacker].spDefenseIV & 1) << 5); gDynamicBasePower = (40 * powerBits) / 63 + 30; gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1; - if (gBattleStruct->dynamicMoveType > 8) + if (gBattleStruct->dynamicMoveType >= TYPE_MYSTERY) gBattleStruct->dynamicMoveType++; gBattleStruct->dynamicMoveType |= 0xC0; gBattlescriptCurrInstr++; } -#else -__attribute__((naked)) -static void atkC1_hiddenpowercalc(void) -{ - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r10\n\ - mov r6, r9\n\ - mov r5, r8\n\ - push {r5-r7}\n\ - ldr r2, =gBattleMons\n\ - ldr r0, =gBattlerAttacker\n\ - ldrb r1, [r0]\n\ - movs r0, 0x58\n\ - adds r4, r1, 0\n\ - muls r4, r0\n\ - adds r4, r2\n\ - ldrb r0, [r4, 0x14]\n\ - mov r10, r0\n\ - mov r7, r10\n\ - lsls r7, 27\n\ - adds r0, r7, 0\n\ - lsrs r0, 27\n\ - mov r10, r0\n\ - movs r1, 0x2\n\ - mov r2, r10\n\ - ands r2, r1\n\ - asrs r2, 1\n\ - ldrh r7, [r4, 0x14]\n\ - mov r9, r7\n\ - mov r0, r9\n\ - lsls r0, 22\n\ - mov r9, r0\n\ - lsrs r3, r0, 27\n\ - adds r0, r1, 0\n\ - ands r0, r3\n\ - orrs r2, r0\n\ - ldrb r7, [r4, 0x15]\n\ - mov r8, r7\n\ - mov r0, r8\n\ - lsls r0, 25\n\ - mov r8, r0\n\ - lsrs r3, r0, 27\n\ - adds r0, r1, 0\n\ - ands r0, r3\n\ - lsls r0, 1\n\ - orrs r2, r0\n\ - ldr r6, [r4, 0x14]\n\ - lsls r6, 12\n\ - lsrs r3, r6, 27\n\ - adds r0, r1, 0\n\ - ands r0, r3\n\ - lsls r0, 2\n\ - orrs r2, r0\n\ - ldrh r5, [r4, 0x16]\n\ - lsls r5, 23\n\ - lsrs r3, r5, 27\n\ - adds r0, r1, 0\n\ - ands r0, r3\n\ - lsls r0, 3\n\ - orrs r2, r0\n\ - ldrb r3, [r4, 0x17]\n\ - lsls r3, 26\n\ - lsrs r0, r3, 27\n\ - ands r1, r0\n\ - lsls r1, 4\n\ - orrs r2, r1\n\ - movs r1, 0x1\n\ - adds r4, r1, 0\n\ - mov r7, r10\n\ - ands r4, r7\n\ - mov r0, r9\n\ - lsrs r0, 27\n\ - mov r9, r0\n\ - adds r0, r1, 0\n\ - mov r7, r9\n\ - ands r0, r7\n\ - lsls r0, 1\n\ - orrs r4, r0\n\ - mov r0, r8\n\ - lsrs r0, 27\n\ - mov r8, r0\n\ - adds r0, r1, 0\n\ - mov r7, r8\n\ - ands r0, r7\n\ - lsls r0, 2\n\ - orrs r4, r0\n\ - lsrs r6, 27\n\ - adds r0, r1, 0\n\ - ands r0, r6\n\ - lsls r0, 3\n\ - orrs r4, r0\n\ - lsrs r5, 27\n\ - adds r0, r1, 0\n\ - ands r0, r5\n\ - lsls r0, 4\n\ - orrs r4, r0\n\ - lsrs r3, 27\n\ - ands r1, r3\n\ - lsls r1, 5\n\ - orrs r4, r1\n\ - ldr r5, =gDynamicBasePower\n\ - lsls r0, r2, 2\n\ - adds r0, r2\n\ - lsls r0, 3\n\ - movs r1, 0x3F\n\ - bl __divsi3\n\ - adds r0, 0x1E\n\ - strh r0, [r5]\n\ - ldr r6, =gBattleStruct\n\ - ldr r5, [r6]\n\ - lsls r0, r4, 4\n\ - subs r0, r4\n\ - movs r1, 0x3F\n\ - bl __divsi3\n\ - adds r0, 0x1\n\ - strb r0, [r5, 0x13]\n\ - ldr r1, [r6]\n\ - ldrb r0, [r1, 0x13]\n\ - cmp r0, 0x8\n\ - bls _080544F0\n\ - adds r0, 0x1\n\ - strb r0, [r1, 0x13]\n\ -_080544F0:\n\ - ldr r2, [r6]\n\ - ldrb r0, [r2, 0x13]\n\ - movs r1, 0xC0\n\ - orrs r0, r1\n\ - strb r0, [r2, 0x13]\n\ - ldr r1, =gBattlescriptCurrInstr\n\ - ldr r0, [r1]\n\ - adds r0, 0x1\n\ - str r0, [r1]\n\ - pop {r3-r5}\n\ - mov r8, r3\n\ - mov r9, r4\n\ - mov r10, r5\n\ - pop {r4-r7}\n\ - pop {r0}\n\ - bx r0\n\ - .pool\n\ - .syntax divided"); -} -#endif // NONMATCHING - static void atkC2_selectfirstvalidtarget(void) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) @@ -9582,7 +9138,7 @@ static void atkC3_trysetfutureattack(void) { if (gWishFutureKnock.futureSightCounter[gBattlerTarget] != 0) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9617,7 +9173,7 @@ static void atkC4_trydobeatup(void) if (gBattleMons[gBattlerTarget].hp == 0) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9647,9 +9203,9 @@ static void atkC4_trydobeatup(void) gBattleCommunication[0]++; } else if (beforeLoop != 0) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 5); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 5); } } @@ -9722,7 +9278,7 @@ static void atkC9_jumpifattackandspecialattackcannotfall(void) // memento && gBattleMons[gBattlerTarget].statStages[STAT_SPATK] == 0 && gBattleCommunication[6] != 1) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9770,7 +9326,7 @@ static void atkCD_cureifburnedparalysedorpoisoned(void) // refresh } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9778,7 +9334,7 @@ static void atkCE_settorment(void) { if (gBattleMons[gBattlerTarget].status2 & STATUS2_TORMENT) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9792,7 +9348,7 @@ static void atkCF_jumpifnodamage(void) if (gProtectStructs[gBattlerAttacker].physicalDmg || gProtectStructs[gBattlerAttacker].specialDmg) gBattlescriptCurrInstr += 5; else - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } static void atkD0_settaunt(void) @@ -9805,7 +9361,7 @@ static void atkD0_settaunt(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9823,7 +9379,7 @@ static void atkD1_trysethelpinghand(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9838,7 +9394,7 @@ static void atkD2_tryswapitems(void) // trick | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_x2000000)))) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9854,7 +9410,7 @@ static void atkD2_tryswapitems(void) // trick && (gWishFutureKnock.knockedOffPokes[sideAttacker] & gBitTable[gBattlerPartyIndexes[gBattlerAttacker]] || gWishFutureKnock.knockedOffPokes[sideTarget] & gBitTable[gBattlerPartyIndexes[gBattlerTarget]])) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } // can't swap if two pokemon don't have an item // or if either of them is an enigma berry or a mail @@ -9864,7 +9420,7 @@ static void atkD2_tryswapitems(void) // trick || IS_ITEM_MAIL(gBattleMons[gBattlerAttacker].item) || IS_ITEM_MAIL(gBattleMons[gBattlerTarget].item)) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } // check if ability prevents swapping else if (gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD) @@ -9925,7 +9481,7 @@ static void atkD3_trycopyability(void) // role play } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -9942,7 +9498,7 @@ static void atkD4_trywish(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); } break; case 1: // heal effect @@ -9954,7 +9510,7 @@ static void atkD4_trywish(void) gBattleMoveDamage *= -1; if (gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; @@ -9966,7 +9522,7 @@ static void atkD5_trysetroots(void) // ingrain { if (gStatuses3[gBattlerAttacker] & STATUS3_ROOTED) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -9993,7 +9549,7 @@ static void atkD7_setyawn(void) if (gStatuses3[gBattlerTarget] & STATUS3_YAWN || gBattleMons[gBattlerTarget].status1 & STATUS1_ANY) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10006,7 +9562,7 @@ static void atkD8_setdamagetohealthdifference(void) { if (gBattleMons[gBattlerTarget].hp <= gBattleMons[gBattlerAttacker].hp) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10035,7 +9591,7 @@ static void atkDA_tryswapabilities(void) // skill swap || gBattleMons[gBattlerTarget].ability == ABILITY_WONDER_GUARD || gMoveResultFlags & MOVE_RESULT_NO_EFFECT) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10051,7 +9607,7 @@ static void atkDB_tryimprision(void) { if ((gStatuses3[gBattlerAttacker] & STATUS3_IMPRISONED_OTHERS)) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10085,7 +9641,7 @@ static void atkDB_tryimprision(void) } } if (battlerId == gBattlersCount) // In Generation 3 games, Imprison fails if the user doesn't share any moves with any of the foes - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -10093,7 +9649,7 @@ static void atkDC_trysetgrudge(void) { if (gStatuses3[gBattlerAttacker] & STATUS3_GRUDGE) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10168,7 +9724,7 @@ static void atkDE_asistattackselect(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -10178,7 +9734,7 @@ static void atkDF_trysetmagiccoat(void) gSpecialStatuses[gBattlerAttacker].flag20 = 1; if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10192,7 +9748,7 @@ static void atkE0_trysetsnatch(void) // snatch gSpecialStatuses[gBattlerAttacker].flag20 = 1; if (gCurrentTurnActionNumber == gBattlersCount - 1) // moves last turn { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10219,7 +9775,7 @@ static void atkE1_trygetintimidatetarget(void) } if (gBattlerTarget >= gBattlersCount) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); else gBattlescriptCurrInstr += 5; } @@ -10245,7 +9801,7 @@ static void atkE3_jumpifhasnohp(void) gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); if (gBattleMons[gActiveBattler].hp == 0) - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2); else gBattlescriptCurrInstr += 6; } @@ -10413,7 +9969,7 @@ static void atkE8_settypebasedhalvers(void) // water and mud sport if (worked) gBattlescriptCurrInstr += 5; else - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } static void atkE9_setweatherballtype(void) @@ -10456,25 +10012,22 @@ static void atkEA_tryrecycleitem(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } static void atkEB_settypetoterrain(void) { - if (gBattleMons[gBattlerAttacker].type1 != sTerrainToType[gBattleTerrain] - && gBattleMons[gBattlerAttacker].type2 != sTerrainToType[gBattleTerrain]) + if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, sTerrainToType[gBattleTerrain])) { - gBattleMons[gBattlerAttacker].type1 = sTerrainToType[gBattleTerrain]; - gBattleMons[gBattlerAttacker].type2 = sTerrainToType[gBattleTerrain]; - - PREPARE_TYPE_BUFFER(gBattleTextBuff1, sTerrainToType[gBattleTerrain]) + SET_BATTLER_TYPE(gBattlerAttacker, sTerrainToType[gBattleTerrain]); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, sTerrainToType[gBattleTerrain]); gBattlescriptCurrInstr += 5; } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -10496,7 +10049,7 @@ static void atkEC_pursuitrelated(void) } else { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } } @@ -10572,16 +10125,13 @@ static void atkEF_handleballthrow(void) switch (gLastUsedItem) { case ITEM_NET_BALL: - if (gBattleMons[gBattlerTarget].type1 == TYPE_WATER - || gBattleMons[gBattlerTarget].type2 == TYPE_WATER - || gBattleMons[gBattlerTarget].type1 == TYPE_BUG - || gBattleMons[gBattlerTarget].type2 == TYPE_BUG) + if (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_WATER) || IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_BUG)) ballMultiplier = 30; else ballMultiplier = 10; break; case ITEM_DIVE_BALL: - if (sav1_map_get_light_level() == 5) + if (Overworld_GetMapTypeOfSaveblockLocation() == 5) ballMultiplier = 35; else ballMultiplier = 10; @@ -10722,7 +10272,7 @@ static void atkF1_trysetcaughtmondexflags(void) if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT)) { - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } else { @@ -10914,14 +10464,14 @@ static void atkF3_trygivecaughtmonnick(void) if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active ) { SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick); - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); } break; case 4: if (CalculatePlayerPartyCount() == 6) gBattlescriptCurrInstr += 5; else - gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1); + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1); break; } } diff --git a/src/battle_setup.c b/src/battle_setup.c index 52ed99b21..15af005c4 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -5,7 +5,6 @@ #include "battle_transition.h" #include "main.h" #include "task.h" -#include "pokemon_3.h" #include "safari_zone.h" #include "script.h" #include "constants/game_stat.h" @@ -32,6 +31,8 @@ #include "string_util.h" #include "overworld.h" #include "field_weather.h" +#include "gym_leader_rematch.h" +#include "field_map_obj_helpers.h" enum { @@ -54,19 +55,12 @@ extern bool8 InBattlePyramid(void); extern bool8 InBattlePike(void); extern bool32 InTrainerHill(void); extern bool32 FieldPoisonEffectIsRunning(void); -extern void overworld_free_bg_tilemaps(void); extern void prev_quest_postbuffer_cursor_backup_reset(void); extern void ResetPoisonStepCounter(void); extern void sub_81BE72C(void); -extern void FreezeMapObjects(void); extern void sub_808BCF4(void); extern void sub_80EECC8(void); -extern void Overworld_ClearSavedMusic(void); -extern void CB2_WhiteOut(void); extern void sub_80AF6F0(void); -extern void PlayBattleBGM(void); -extern void sub_81DA57C(void); -extern u8 Overworld_GetFlashLevel(void); extern u16 sub_81A9AA8(u8 localId); extern u16 sub_81D6180(u8 localId); extern bool8 GetBattlePyramidTrainerFlag(u8 mapObjId); @@ -251,84 +245,84 @@ static const struct TrainerBattleParameter sTrainerBContinueScriptBattleParams[] const struct RematchTrainer gRematchTable[REMATCH_TABLE_ENTRIES] = { - {{0x0025, 0x0028, 0x0029, 0x002a, 0x002b}, 0x0000, 0x0021}, - {{0x02e1, 0x032c, 0x032d, 0x032e, 0x032f}, 0x0000, 0x0014}, - {{0x002c, 0x002f, 0x0030, 0x0031, 0x0032}, 0x0000, 0x001a}, - {{0x0039, 0x003c, 0x003d, 0x003e, 0x003f}, 0x0000, 0x0018}, - {{0x0040, 0x0043, 0x0044, 0x0045, 0x0046}, 0x0000, 0x0018}, - {{0x02af, 0x02b0, 0x02b1, 0x02b2, 0x02b3}, 0x0000, 0x0027}, - {{0x02ff, 0x033c, 0x033d, 0x033e, 0x033f}, 0x0000, 0x0024}, - {{0x005e, 0x0065, 0x0066, 0x0067, 0x0068}, 0x0000, 0x001a}, - {{0x004e, 0x0054, 0x0055, 0x0056, 0x0057}, 0x0000, 0x001a}, - {{0x006c, 0x006e, 0x006f, 0x0070, 0x0071}, 0x0018, 0x0014}, - {{0x0072, 0x0078, 0x0079, 0x007a, 0x007b}, 0x0000, 0x0013}, - {{0x0090, 0x034c, 0x034d, 0x034e, 0x034f}, 0x0018, 0x0038}, - {{0x007f, 0x0084, 0x0085, 0x0086, 0x0087}, 0x0000, 0x0024}, - {{0x0088, 0x008b, 0x008c, 0x008d, 0x008e}, 0x0000, 0x0013}, - {{0x008f, 0x0093, 0x0094, 0x0095, 0x0096}, 0x0000, 0x001d}, - {{0x009b, 0x00af, 0x00b0, 0x00b1, 0x00b2}, 0x0000, 0x0016}, - {{0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb}, 0x0000, 0x001e}, - {{0x02a0, 0x0338, 0x0339, 0x033a, 0x033b}, 0x0000, 0x002a}, - {{0x00c3, 0x0340, 0x0341, 0x0342, 0x0343}, 0x0000, 0x0026}, - {{0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8}, 0x0000, 0x0021}, - {{0x00ce, 0x00cf, 0x00d0, 0x00d1, 0x00d2}, 0x0000, 0x001d}, - {{0x00d8, 0x00db, 0x00dc, 0x00dd, 0x00de}, 0x0018, 0x000d}, - {{0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad}, 0x0018, 0x0001}, - {{0x00e2, 0x00e4, 0x00e5, 0x00e6, 0x00e7}, 0x0000, 0x0023}, - {{0x00ee, 0x00ef, 0x00f0, 0x00f1, 0x00f2}, 0x0000, 0x0026}, - {{0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd}, 0x0000, 0x0026}, - {{0x00fe, 0x0101, 0x0102, 0x0103, 0x0104}, 0x0000, 0x0024}, - {{0x0118, 0x011a, 0x011b, 0x011c, 0x011d}, 0x0000, 0x001f}, - {{0x0111, 0x0114, 0x0115, 0x0116, 0x0117}, 0x0000, 0x001f}, - {{0x011f, 0x0120, 0x0121, 0x0122, 0x0123}, 0x0000, 0x0020}, - {{0x012e, 0x012f, 0x0130, 0x0131, 0x0132}, 0x0000, 0x0019}, - {{0x0125, 0x0127, 0x0128, 0x0129, 0x012a}, 0x0000, 0x0012}, - {{0x0133, 0x0134, 0x0135, 0x0136, 0x0137}, 0x0000, 0x001e}, - {{0x0139, 0x013a, 0x013b, 0x013c, 0x013d}, 0x0018, 0x000c}, - {{0x013e, 0x0148, 0x0149, 0x014a, 0x014b}, 0x0000, 0x0011}, - {{0x0153, 0x015a, 0x015b, 0x015c, 0x015d}, 0x0000, 0x0015}, - {{0x0178, 0x017b, 0x017c, 0x017d, 0x017e}, 0x0000, 0x002b}, - {{0x0171, 0x0172, 0x0173, 0x0174, 0x0175}, 0x0000, 0x0020}, - {{0x0166, 0x0168, 0x0169, 0x016a, 0x016b}, 0x0000, 0x0019}, - {{0x016c, 0x016d, 0x016e, 0x016f, 0x0170}, 0x0000, 0x0020}, - {{0x0182, 0x0184, 0x0185, 0x0186, 0x0187}, 0x0000, 0x002b}, - {{0x0161, 0x0162, 0x0163, 0x0164, 0x0165}, 0x0000, 0x0019}, - {{0x0179, 0x0334, 0x0335, 0x0336, 0x0337}, 0x0000, 0x0029}, - {{0x0188, 0x0189, 0x018a, 0x018b, 0x018c}, 0x0018, 0x0001}, - {{0x0196, 0x0199, 0x019a, 0x019b, 0x019c}, 0x0000, 0x0023}, - {{0x01a3, 0x01a5, 0x01a6, 0x01a7, 0x01a8}, 0x0000, 0x001c}, - {{0x01ab, 0x01ae, 0x01af, 0x01b0, 0x01b1}, 0x0000, 0x001e}, - {{0x01b2, 0x01b5, 0x01b6, 0x01b7, 0x01b8}, 0x0000, 0x001c}, - {{0x01c1, 0x01d1, 0x01d2, 0x01d3, 0x01d4}, 0x0000, 0x0027}, - {{0x01da, 0x01dd, 0x01de, 0x01df, 0x01e0}, 0x0018, 0x000d}, - {{0x01e1, 0x01e2, 0x01e7, 0x01e8, 0x01e9}, 0x0000, 0x0012}, - {{0x01ec, 0x01f1, 0x01f2, 0x01f3, 0x01f4}, 0x0000, 0x0028}, - {{0x02e4, 0x0330, 0x0331, 0x0332, 0x0333}, 0x0000, 0x0017}, - {{0x0200, 0x0203, 0x0204, 0x0205, 0x0206}, 0x0000, 0x0019}, - {{0x0221, 0x0224, 0x0225, 0x0226, 0x0227}, 0x0000, 0x0020}, - {{0x021a, 0x021d, 0x021e, 0x021f, 0x0220}, 0x0000, 0x0020}, - {{0x0009, 0x0348, 0x0349, 0x034a, 0x034b}, 0x0018, 0x0011}, - {{0x022f, 0x0232, 0x0233, 0x0234, 0x0235}, 0x0000, 0x0022}, - {{0x0228, 0x022b, 0x022c, 0x022d, 0x022e}, 0x0000, 0x0022}, - {{0x025c, 0x025f, 0x0260, 0x0261, 0x0262}, 0x0000, 0x0013}, - {{0x026d, 0x026e, 0x026f, 0x0270, 0x0271}, 0x0018, 0x000b}, - {{0x0273, 0x027c, 0x027d, 0x027e, 0x027f}, 0x0000, 0x001b}, - {{0x0001, 0x0344, 0x0345, 0x0346, 0x0347}, 0x0018, 0x000c}, - {{0x0282, 0x0283, 0x0284, 0x0285, 0x0286}, 0x0018, 0x003e}, - {{0x0291, 0x0292, 0x0293, 0x0294, 0x0294}, 0x0018, 0x002b}, - {{0x0109, 0x0302, 0x0303, 0x0304, 0x0305}, 0x0000, 0x0003}, - {{0x010a, 0x0306, 0x0307, 0x0308, 0x0309}, 0x0000, 0x000b}, - {{0x010b, 0x030a, 0x030b, 0x030c, 0x030d}, 0x0000, 0x0002}, - {{0x010c, 0x030e, 0x030f, 0x0310, 0x0311}, 0x0000, 0x000c}, - {{0x010d, 0x0312, 0x0313, 0x0314, 0x0315}, 0x0000, 0x0000}, - {{0x010e, 0x0316, 0x0317, 0x0318, 0x0319}, 0x0000, 0x0004}, - {{0x010f, 0x031a, 0x031b, 0x031c, 0x031d}, 0x0000, 0x0006}, - {{0x0110, 0x031e, 0x031f, 0x0320, 0x0321}, 0x0000, 0x0007}, - {{0x0105, 0x0105, 0x0105, 0x0105, 0x0105}, 0x0000, 0x0008}, - {{0x0106, 0x0106, 0x0106, 0x0106, 0x0106}, 0x0000, 0x0008}, - {{0x0107, 0x0107, 0x0107, 0x0107, 0x0107}, 0x0000, 0x0008}, - {{0x0108, 0x0108, 0x0108, 0x0108, 0x0108}, 0x0000, 0x0008}, - {{0x014f, 0x014f, 0x014f, 0x014f, 0x014f}, 0x0000, 0x0008}, + {{TRAINER_ROSE_1, TRAINER_ROSE_2, TRAINER_ROSE_3, TRAINER_ROSE_4, TRAINER_ROSE_5}, 0x0, 0x21}, + {{TRAINER_ANDRES_1, TRAINER_ANDRES_2, TRAINER_ANDRES_3, TRAINER_ANDRES_4, TRAINER_ANDRES_5}, 0x0, 0x14}, + {{TRAINER_DUSTY_1, TRAINER_DUSTY_2, TRAINER_DUSTY_3, TRAINER_DUSTY_4, TRAINER_DUSTY_5}, 0x0, 0x1a}, + {{TRAINER_LOLA_1, TRAINER_LOLA_2, TRAINER_LOLA_3, TRAINER_LOLA_4, TRAINER_LOLA_5}, 0x0, 0x18}, + {{TRAINER_RICKY_1, TRAINER_RICKY_2, TRAINER_RICKY_3, TRAINER_RICKY_4, TRAINER_RICKY_5}, 0x0, 0x18}, + {{TRAINER_LILA_AND_ROY_1, TRAINER_LILA_AND_ROY_2, TRAINER_LILA_AND_ROY_3, TRAINER_LILA_AND_ROY_4, TRAINER_LILA_AND_ROY_5}, 0x0, 0x27}, + {{TRAINER_CRISTIN_1, TRAINER_CRISTIN_2, TRAINER_CRISTIN_3, TRAINER_CRISTIN_4, TRAINER_CRISTIN_5}, 0x0, 0x24}, + {{TRAINER_BROOKE_1, TRAINER_BROOKE_2, TRAINER_BROOKE_3, TRAINER_BROOKE_4, TRAINER_BROOKE_5}, 0x0, 0x1a}, + {{TRAINER_WILTON_1, TRAINER_WILTON_2, TRAINER_WILTON_3, TRAINER_WILTON_4, TRAINER_WILTON_5}, 0x0, 0x1a}, + {{TRAINER_VALERIE_1, TRAINER_VALERIE_2, TRAINER_VALERIE_3, TRAINER_VALERIE_4, TRAINER_VALERIE_5}, 0x18, 0x14}, + {{TRAINER_CINDY_1, TRAINER_CINDY_3, TRAINER_CINDY_4, TRAINER_CINDY_5, TRAINER_CINDY_6}, 0x0, 0x13}, + {{TRAINER_THALIA_1, TRAINER_THALIA_2, TRAINER_THALIA_3, TRAINER_THALIA_4, TRAINER_THALIA_5}, 0x18, 0x38}, + {{TRAINER_JESSICA_1, TRAINER_JESSICA_2, TRAINER_JESSICA_3, TRAINER_JESSICA_4, TRAINER_JESSICA_5}, 0x0, 0x24}, + {{TRAINER_WINSTON_1, TRAINER_WINSTON_2, TRAINER_WINSTON_3, TRAINER_WINSTON_4, TRAINER_WINSTON_5}, 0x0, 0x13}, + {{TRAINER_STEVE_1, TRAINER_STEVE_2, TRAINER_STEVE_3, TRAINER_STEVE_4, TRAINER_STEVE_5}, 0x0, 0x1d}, + {{TRAINER_TONY_1, TRAINER_TONY_2, TRAINER_TONY_3, TRAINER_TONY_4, TRAINER_TONY_5}, 0x0, 0x16}, + {{TRAINER_NOB_1, TRAINER_NOB_2, TRAINER_NOB_3, TRAINER_NOB_4, TRAINER_NOB_5}, 0x0, 0x1e}, + {{TRAINER_KOJI_1, TRAINER_KOJI_2, TRAINER_KOJI_3, TRAINER_KOJI_4, TRAINER_KOJI_5}, 0x0, 0x2a}, + {{TRAINER_FERNANDO_1, TRAINER_FERNANDO_2, TRAINER_FERNANDO_3, TRAINER_FERNANDO_4, TRAINER_FERNANDO_5}, 0x0, 0x26}, + {{TRAINER_DALTON_1, TRAINER_DALTON_2, TRAINER_DALTON_3, TRAINER_DALTON_4, TRAINER_DALTON_5}, 0x0, 0x21}, + {{TRAINER_BERNIE_1, TRAINER_BERNIE_2, TRAINER_BERNIE_3, TRAINER_BERNIE_4, TRAINER_BERNIE_5}, 0x0, 0x1d}, + {{TRAINER_ETHAN_1, TRAINER_ETHAN_2, TRAINER_ETHAN_3, TRAINER_ETHAN_4, TRAINER_ETHAN_5}, 0x18, 0xd}, + {{TRAINER_JOHN_AND_JAY_1, TRAINER_JOHN_AND_JAY_2, TRAINER_JOHN_AND_JAY_3, TRAINER_JOHN_AND_JAY_4, TRAINER_JOHN_AND_JAY_5}, 0x18, 0x1}, + {{TRAINER_JEFFREY_1, TRAINER_JEFFREY_2, TRAINER_JEFFREY_3, TRAINER_JEFFREY_4, TRAINER_JEFFREY_5}, 0x0, 0x23}, + {{TRAINER_CAMERON_1, TRAINER_CAMERON_2, TRAINER_CAMERON_3, TRAINER_CAMERON_4, TRAINER_CAMERON_5}, 0x0, 0x26}, + {{TRAINER_JACKI_1, TRAINER_JACKI_2, TRAINER_JACKI_3, TRAINER_JACKI_4, TRAINER_JACKI_5}, 0x0, 0x26}, + {{TRAINER_WALTER_1, TRAINER_WALTER_2, TRAINER_WALTER_3, TRAINER_WALTER_4, TRAINER_WALTER_5}, 0x0, 0x24}, + {{TRAINER_KAREN_1, TRAINER_KAREN_2, TRAINER_KAREN_3, TRAINER_KAREN_4, TRAINER_KAREN_5}, 0x0, 0x1f}, + {{TRAINER_JERRY_1, TRAINER_JERRY_2, TRAINER_JERRY_3, TRAINER_JERRY_4, TRAINER_JERRY_5}, 0x0, 0x1f}, + {{TRAINER_ANNA_AND_MEG_1, TRAINER_ANNA_AND_MEG_2, TRAINER_ANNA_AND_MEG_3, TRAINER_ANNA_AND_MEG_4, TRAINER_ANNA_AND_MEG_5}, 0x0, 0x20}, + {{TRAINER_ISABEL_1, TRAINER_ISABEL_2, TRAINER_ISABEL_3, TRAINER_ISABEL_4, TRAINER_ISABEL_5}, 0x0, 0x19}, + {{TRAINER_MIGUEL_1, TRAINER_MIGUEL_2, TRAINER_MIGUEL_3, TRAINER_MIGUEL_4, TRAINER_MIGUEL_5}, 0x0, 0x12}, + {{TRAINER_TIMOTHY_1, TRAINER_TIMOTHY_2, TRAINER_TIMOTHY_3, TRAINER_TIMOTHY_4, TRAINER_TIMOTHY_5}, 0x0, 0x1e}, + {{TRAINER_SHELBY_1, TRAINER_SHELBY_2, TRAINER_SHELBY_3, TRAINER_SHELBY_4, TRAINER_SHELBY_5}, 0x18, 0xc}, + {{TRAINER_CALVIN_1, TRAINER_CALVIN_2, TRAINER_CALVIN_3, TRAINER_CALVIN_4, TRAINER_CALVIN_5}, 0x0, 0x11}, + {{TRAINER_ELLIOT_1, TRAINER_ELLIOT_2, TRAINER_ELLIOT_3, TRAINER_ELLIOT_4, TRAINER_ELLIOT_5}, 0x0, 0x15}, + {{TRAINER_ISAIAH_1, TRAINER_ISAIAH_2, TRAINER_ISAIAH_3, TRAINER_ISAIAH_4, TRAINER_ISAIAH_5}, 0x0, 0x2b}, + {{TRAINER_MARIA_1, TRAINER_MARIA_2, TRAINER_MARIA_3, TRAINER_MARIA_4, TRAINER_MARIA_5}, 0x0, 0x20}, + {{TRAINER_ABIGAIL_1, TRAINER_ABIGAIL_2, TRAINER_ABIGAIL_3, TRAINER_ABIGAIL_4, TRAINER_ABIGAIL_5}, 0x0, 0x19}, + {{TRAINER_DYLAN_1, TRAINER_DYLAN_2, TRAINER_DYLAN_3, TRAINER_DYLAN_4, TRAINER_DYLAN_5}, 0x0, 0x20}, + {{TRAINER_KATELYN_1, TRAINER_KATELYN_2, TRAINER_KATELYN_3, TRAINER_KATELYN_4, TRAINER_KATELYN_5}, 0x0, 0x2b}, + {{TRAINER_BENJAMIN_1, TRAINER_BENJAMIN_2, TRAINER_BENJAMIN_3, TRAINER_BENJAMIN_4, TRAINER_BENJAMIN_5}, 0x0, 0x19}, + {{TRAINER_PABLO_1, TRAINER_PABLO_2, TRAINER_PABLO_3, TRAINER_PABLO_4, TRAINER_PABLO_5}, 0x0, 0x29}, + {{TRAINER_NICOLAS_1, TRAINER_NICOLAS_2, TRAINER_NICOLAS_3, TRAINER_NICOLAS_4, TRAINER_NICOLAS_5}, 0x18, 0x1}, + {{TRAINER_ROBERT_1, TRAINER_ROBERT_2, TRAINER_ROBERT_3, TRAINER_ROBERT_4, TRAINER_ROBERT_5}, 0x0, 0x23}, + {{TRAINER_LAO_1, TRAINER_LAO_2, TRAINER_LAO_3, TRAINER_LAO_4, TRAINER_LAO_5}, 0x0, 0x1c}, + {{TRAINER_CYNDY_1, TRAINER_CYNDY_2, TRAINER_CYNDY_3, TRAINER_CYNDY_4, TRAINER_CYNDY_5}, 0x0, 0x1e}, + {{TRAINER_MADELINE_1, TRAINER_MADELINE_2, TRAINER_MADELINE_3, TRAINER_MADELINE_4, TRAINER_MADELINE_5}, 0x0, 0x1c}, + {{TRAINER_JENNY_1, TRAINER_JENNY_2, TRAINER_JENNY_3, TRAINER_JENNY_4, TRAINER_JENNY_5}, 0x0, 0x27}, + {{TRAINER_DIANA_1, TRAINER_DIANA_2, TRAINER_DIANA_3, TRAINER_DIANA_4, TRAINER_DIANA_5}, 0x18, 0xd}, + {{TRAINER_AMY_AND_LIV_1, TRAINER_AMY_AND_LIV_2, TRAINER_AMY_AND_LIV_4, TRAINER_AMY_AND_LIV_5, TRAINER_AMY_AND_LIV_6}, 0x0, 0x12}, + {{TRAINER_ERNEST_1, TRAINER_ERNEST_2, TRAINER_ERNEST_3, TRAINER_ERNEST_4, TRAINER_ERNEST_5}, 0x0, 0x28}, + {{TRAINER_CORY_1, TRAINER_CORY_2, TRAINER_CORY_3, TRAINER_CORY_4, TRAINER_CORY_5}, 0x0, 0x17}, + {{TRAINER_EDWIN_1, TRAINER_EDWIN_2, TRAINER_EDWIN_3, TRAINER_EDWIN_4, TRAINER_EDWIN_5}, 0x0, 0x19}, + {{TRAINER_LYDIA_1, TRAINER_LYDIA_2, TRAINER_LYDIA_3, TRAINER_LYDIA_4, TRAINER_LYDIA_5}, 0x0, 0x20}, + {{TRAINER_ISAAC_1, TRAINER_ISAAC_2, TRAINER_ISAAC_3, TRAINER_ISAAC_4, TRAINER_ISAAC_5}, 0x0, 0x20}, + {{TRAINER_GABRIELLE_1, TRAINER_GABRIELLE_2, TRAINER_GABRIELLE_3, TRAINER_GABRIELLE_4, TRAINER_GABRIELLE_5}, 0x18, 0x11}, + {{TRAINER_CATHERINE_1, TRAINER_CATHERINE_2, TRAINER_CATHERINE_3, TRAINER_CATHERINE_4, TRAINER_CATHERINE_5}, 0x0, 0x22}, + {{TRAINER_JACKSON_1, TRAINER_JACKSON_2, TRAINER_JACKSON_3, TRAINER_JACKSON_4, TRAINER_JACKSON_5}, 0x0, 0x22}, + {{TRAINER_HALEY_1, TRAINER_HALEY_2, TRAINER_HALEY_3, TRAINER_HALEY_4, TRAINER_HALEY_5}, 0x0, 0x13}, + {{TRAINER_JAMES_1, TRAINER_JAMES_2, TRAINER_JAMES_3, TRAINER_JAMES_4, TRAINER_JAMES_5}, 0x18, 0xb}, + {{TRAINER_TRENT_1, TRAINER_TRENT_2, TRAINER_TRENT_3, TRAINER_TRENT_4, TRAINER_TRENT_5}, 0x0, 0x1b}, + {{TRAINER_SAWYER_1, TRAINER_SAWYER_2, TRAINER_SAWYER_3, TRAINER_SAWYER_4, TRAINER_SAWYER_5}, 0x18, 0xc}, + {{TRAINER_KIRA_AND_DAN_1, TRAINER_KIRA_AND_DAN_2, TRAINER_KIRA_AND_DAN_3, TRAINER_KIRA_AND_DAN_4, TRAINER_KIRA_AND_DAN_5}, 0x18, 0x3e}, + {{TRAINER_WALLY_3, 0x292, 0x293, 0x294, 0x294}, 0x18, 0x2b}, + {{TRAINER_ROXANNE_1, TRAINER_ROXANNE_2, TRAINER_ROXANNE_3, TRAINER_ROXANNE_4, TRAINER_ROXANNE_5}, 0x0, 0x3}, + {{TRAINER_BRAWLY_1, TRAINER_BRAWLY_2, TRAINER_BRAWLY_3, TRAINER_BRAWLY_4, TRAINER_BRAWLY_5}, 0x0, 0xb}, + {{TRAINER_WATTSON_1, TRAINER_WATTSON_2, TRAINER_WATTSON_3, TRAINER_WATTSON_4, TRAINER_WATTSON_5}, 0x0, 0x2}, + {{TRAINER_FLANNERY_1, TRAINER_FLANNERY_2, TRAINER_FLANNERY_3, TRAINER_FLANNERY_4, TRAINER_FLANNERY_5}, 0x0, 0xc}, + {{TRAINER_NORMAN_1, TRAINER_NORMAN_2, TRAINER_NORMAN_3, TRAINER_NORMAN_4, TRAINER_NORMAN_5}, 0x0, 0x0}, + {{TRAINER_WINONA_1, TRAINER_WINONA_2, TRAINER_WINONA_3, TRAINER_WINONA_4, TRAINER_WINONA_5}, 0x0, 0x4}, + {{TRAINER_TATE_AND_LIZA_1, TRAINER_TATE_AND_LIZA_2, TRAINER_TATE_AND_LIZA_3, TRAINER_TATE_AND_LIZA_4, TRAINER_TATE_AND_LIZA_5}, 0x0, 0x6}, + {{TRAINER_JUAN_1, TRAINER_JUAN_2, TRAINER_JUAN_3, TRAINER_JUAN_4, TRAINER_JUAN_5}, 0x0, 0x7}, + {{TRAINER_SIDNEY, TRAINER_SIDNEY, TRAINER_SIDNEY, TRAINER_SIDNEY, TRAINER_SIDNEY}, 0x0, 0x8}, + {{TRAINER_PHOEBE, TRAINER_PHOEBE, TRAINER_PHOEBE, TRAINER_PHOEBE, TRAINER_PHOEBE}, 0x0, 0x8}, + {{TRAINER_GLACIA, TRAINER_GLACIA, TRAINER_GLACIA, TRAINER_GLACIA, TRAINER_GLACIA}, 0x0, 0x8}, + {{TRAINER_DRAKE, TRAINER_DRAKE, TRAINER_DRAKE, TRAINER_DRAKE, TRAINER_DRAKE}, 0x0, 0x8}, + {{TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE, TRAINER_WALLACE}, 0x0, 0x8}, }; static const u16 sBadgeFlags[8] = @@ -473,7 +467,7 @@ void StartWallyTutorialBattle(void) { CreateMaleMon(&gEnemyParty[0], SPECIES_RALTS, 5); ScriptContext2_Enable(); - gMain.savedCallback = c2_exit_to_overworld_1_continue_scripts_restart_music; + gMain.savedCallback = CB2_ReturnToFieldContinueScript; gBattleTypeFlags = BATTLE_TYPE_WALLY_TUTORIAL; CreateBattleStartTask(B_TRANSITION_SLICE, 0); } @@ -602,7 +596,7 @@ static void CB2_EndWildBattle(void) } else { - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); gFieldCallback = sub_80AF6F0; } } @@ -615,13 +609,13 @@ static void CB2_EndScriptedWildBattle(void) if (IsPlayerDefeated(gBattleOutcome) == TRUE) { if (InBattlePyramid()) - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); else SetMainCallback2(CB2_WhiteOut); } else { - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } } @@ -938,19 +932,19 @@ static void CB2_StartFirstBattle(void) static void CB2_EndFirstBattle(void) { Overworld_ClearSavedMusic(); - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } static void sub_80B1218(void) { if (GetGameStat(GAME_STAT_WILD_BATTLES) % 60 == 0) - sub_81DA57C(); + UpdateGymLeaderRematch(); } static void sub_80B1234(void) { if (GetGameStat(GAME_STAT_TRAINER_BATTLES) % 20 == 0) - sub_81DA57C(); + UpdateGymLeaderRematch(); } // why not just use the macros? maybe its because they didnt want to uncast const every time? @@ -1314,18 +1308,18 @@ static void CB2_EndTrainerBattle(void) { if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT) { - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } else if (IsPlayerDefeated(gBattleOutcome) == TRUE) { if (InBattlePyramid() || sub_81D5C18()) - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); else SetMainCallback2(CB2_WhiteOut); } else { - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); if (!InBattlePyramid() && !sub_81D5C18()) { RegisterTrainerInMatchCall(); @@ -1338,7 +1332,7 @@ static void CB2_EndRematchBattle(void) { if (gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT) { - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } else if (IsPlayerDefeated(gBattleOutcome) == TRUE) { @@ -1346,7 +1340,7 @@ static void CB2_EndRematchBattle(void) } else { - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); RegisterTrainerInMatchCall(); SetBattledTrainersFlags(); HandleRematchVarsOnBattleEnd(); diff --git a/src/battle_transition.c b/src/battle_transition.c index e0d208f23..8b9b50140 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -919,7 +919,7 @@ static void CB2_TestBattleTransition(void) if (IsBattleTransitionDone()) { sTestingTransitionState = 0; - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); } break; } diff --git a/src/battle_tv.c b/src/battle_tv.c new file mode 100644 index 000000000..e5d97be30 --- /dev/null +++ b/src/battle_tv.c @@ -0,0 +1,1576 @@ +#include "global.h" +#include "pokemon.h" +#include "battle.h" +#include "battle_tv.h" +#include "constants/battle_string_ids.h" +#include "constants/battle_anim.h" +#include "constants/moves.h" +#include "constants/species.h" +#include "battle_message.h" +#include "tv.h" + +extern struct StringInfoBattle *gStringInfo; + +// this file's functions +static bool8 sub_817E0B8(u16 stringId); +static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3); +static void TrySetBattleSeminarShow(void); +static void AddPointsOnFainting(bool8 targetFainted); +static void AddPointsBasedOnWeather(u16 weatherFlags, u16 moveId, u8 moveSlot); +static bool8 ShouldCalculateDamage(u16 moveId, s32 *dmg, u16 *powerOverride); + +// const rom data +static const u16 sVariableDmgMoves[] = +{ + MOVE_COUNTER, MOVE_FISSURE, MOVE_BIDE, MOVE_MIRROR_COAT, + MOVE_HORN_DRILL, MOVE_FLAIL, MOVE_REVERSAL, MOVE_HIDDEN_POWER, + MOVE_SHEER_COLD, MOVE_FOCUS_PUNCH, MOVE_ERUPTION, + MOVE_WATER_SPOUT, MOVE_DREAM_EATER, MOVE_WEATHER_BALL, + MOVE_SNORE, MOVE_PAIN_SPLIT, MOVE_GUILLOTINE, + MOVE_FRUSTRATION, MOVE_RETURN, MOVE_ENDEAVOR, + MOVE_PRESENT, MOVE_REVENGE, 0xFFFF, + // those are handled by the function itself + MOVE_MAGNITUDE, MOVE_PSYWAVE, 0xFFFF +}; + +static const u16 sUnknown_0860A4E0[] = +{ + 0x0001, 0x0001, 0x0001, 0x0004, 0x0001, 0x0001, 0x0001, 0x0000, 0x0005, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0005, 0x0005, 0x0004, 0x0005, 0x0001, 0x0003, 0x0001, + 0x0003, 0x0005, 0x0001, 0x0007, 0x0001, 0x0007, 0x0007, 0x0001, 0x0005, 0x0002, 0x0004, 0x0001, 0x0001, 0x0001, 0x0005, 0x0001, + 0x0002, 0x0004, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0007, 0x0004, 0x0004, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0004, 0x0001, 0x0001, 0x0001, 0x0004, + 0x0005, 0x0002, 0x0004, 0x0001, 0x0004, 0x0001, 0x0007, 0x0002, 0x0001, 0x0005, 0x0007, 0x0003, 0x0003, 0x0004, 0x0003, 0x0003, + 0x0003, 0x0003, 0x0003, 0x0002, 0x0004, 0x0001, 0x0005, 0x0001, 0x0001, 0x0004, 0x0005, 0x0003, 0x0001, 0x0002, 0x0001, 0x0005, + 0x0004, 0x0003, 0x0006, 0x0004, 0x0003, 0x0003, 0x0003, 0x0002, 0x0004, 0x0001, 0x0001, 0x0001, 0x0005, 0x0001, 0x0001, 0x0007, + 0x0002, 0x0002, 0x0001, 0x0001, 0x0004, 0x0004, 0x0004, 0x0001, 0x0004, 0x0004, 0x0001, 0x0001, 0x0001, 0x0001, 0x0007, 0x0007, + 0x0006, 0x0003, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003, 0x0001, 0x0001, 0x0004, 0x0004, + 0x0003, 0x0003, 0x0003, 0x0001, 0x0004, 0x0007, 0x0007, 0x0005, 0x0007, 0x0001, 0x0007, 0x0001, 0x0005, 0x0000, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0002, 0x0002, 0x0006, 0x0003, 0x0006, 0x0004, 0x0004, 0x0002, 0x0005, 0x0002, 0x0001, 0x0001, 0x0006, + 0x0006, 0x0006, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0006, 0x0001, 0x0004, 0x0001, 0x0001, 0x0003, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0004, 0x0001, 0x0001, 0x0003 +}; +static const u16 sUnknown_0860A68C[] = +{ + 0x0004, 0xfffd, 0xfffa +}; +static const u16 sUnknown_0860A692[] = +{ + 0x0004, 0x0004, 0x0006, 0x0006, 0x0007, 0x0006, 0x0002 +}; +static const u16 sUnknown_0860A6A0[] = +{ + 0x0091, 0x0003, 0x00fa, 0x0003, 0x00be, 0x0003, 0x0080, 0x0003, 0x006e, 0x0003, 0x0098, 0x0003, 0x0143, 0x0003, 0x0123, 0x0003, + 0x007f, 0x0003, 0x014a, 0x0003, 0x0039, 0x0003, 0x0134, 0x0003, 0x0038, 0x0003, 0x003d, 0x0003, 0x015a, 0x0000, 0x0037, 0x0003, + 0x0160, 0x0003, 0x0137, 0x0003, 0x0057, 0x0003, 0x004c, 0xfffc, 0x013b, 0xfffc, 0x00ac, 0xfffc, 0x0035, 0xfffc, 0x00dd, 0xfffc, + 0x007e, 0xfffc, 0x0101, 0xfffc, 0x0034, 0xfffc, 0x0133, 0xfffc, 0x012b, 0xfffc, 0x011c, 0xfffc, 0x0053, 0xfffc, 0x0007, 0xfffc, + 0x004c, 0xfffc, 0xffff, 0x0000 +}; +static const u16 sUnknown_0860A728[] = +{ + 0x013b, 0x0003, 0x00ac, 0x0003, 0x0035, 0x0003, 0x00dd, 0x0003, 0x007e, 0x0003, 0x0101, 0x0003, 0x0034, 0x0003, 0x0133, 0x0003, + 0x012b, 0x0003, 0x011c, 0x0003, 0x0053, 0x0003, 0x0007, 0x0003, 0x004c, 0x0005, 0x00eb, 0x0003, 0x00ea, 0x0003, 0x00ec, 0x0003, + 0x0137, 0x0003, 0xffff, 0x0000 +}; +static const u16 sUnknown_0860A770[] = +{ + 0x0137, 0x0003, 0x004c, 0xfffd, 0xffff, 0x0000 +}; +static const u16 sUnknown_0860A77C[] = +{ + 0x0137, 0x0003, 0x004c, 0xfffd, 0xffff, 0x0000 +}; +static const u16 sUnknown_0860A788[] = +{ + 0x0055, 0x0003, 0x0009, 0x0003, 0x00d1, 0x0003, 0x0054, 0x0003, 0x00c0, 0x0003, 0x015f, 0x0003, 0x0056, 0x0000, 0x0057, 0x0003, + 0x0158, 0x0003, 0xffff, 0x0000 +}; +static const u16 sUnknown_0860A7B0[] = +{ + 0x0005, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003 +}; +static const u16 sUnknown_0860A7BE[] = +{ + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005 +}; +static const u16 sUnknown_0860A7C8[] = +{ + 0x0004 +}; +static const u16 sUnknown_0860A7CA[] = +{ + 0x0005 +}; +static const u16 sUnknown_0860A7CC[] = +{ + 0x0005 +}; +static const u16 sUnknown_0860A7CE[] = +{ + 0x0003 +}; +static const u16 sUnknown_0860A7D0[] = +{ + 0x0003 +}; +static const u16 sUnknown_0860A7D2[] = +{ + 0x0004 +}; +static const u16 sUnknown_0860A7D4[] = +{ + 0x0003 +}; +static const u16 sUnknown_0860A7D6[] = +{ + 0x0006 +}; +static const u16 sUnknown_0860A7D8[] = +{ + 0x0006 +}; +static const u16 sUnknown_0860A7DA[] = +{ + 0x0006 +}; +static const u16 sUnknown_0860A7DC[] = +{ + 0x0004 +}; +static const u16 sUnknown_0860A7DE[] = +{ + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002 +}; +static const u16 sUnknown_0860A7EC[] = +{ + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004 +}; +static const u16 sUnknown_0860A7FA[] = +{ + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; +static const u16 sUnknown_0860A808[] = +{ + 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002 +}; +static const u16 sUnknown_0860A816[] = +{ + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004 +}; +static const u16 sUnknown_0860A824[] = +{ + 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe, 0xfffe +}; + +static const u16 *const sPointsArray[] = +{ + sUnknown_0860A4E0, + sUnknown_0860A68C, + sUnknown_0860A692, + sUnknown_0860A6A0, + sUnknown_0860A728, + sUnknown_0860A770, + sUnknown_0860A77C, + sUnknown_0860A788, + sUnknown_0860A7B0, + sUnknown_0860A7BE, + sUnknown_0860A7C8, + sUnknown_0860A7CA, + sUnknown_0860A7CC, + sUnknown_0860A7CE, + sUnknown_0860A7D0, + sUnknown_0860A7D2, + sUnknown_0860A7D4, + sUnknown_0860A7D6, + sUnknown_0860A7D8, + sUnknown_0860A7DA, + sUnknown_0860A7DA, + sUnknown_0860A7DC, + sUnknown_0860A7DE, + sUnknown_0860A7EC, + sUnknown_0860A7FA, + sUnknown_0860A808, + sUnknown_0860A816, + sUnknown_0860A824 +}; + +static const u16 sUnknown_0860A8A4[] = +{ + STRINGID_PKMNPERISHCOUNTFELL, STRINGID_PKMNWISHCAMETRUE, STRINGID_PKMNLOSTPPGRUDGE, + STRINGID_PKMNTOOKFOE, STRINGID_PKMNABSORBEDNUTRIENTS, STRINGID_PKMNANCHOREDITSELF, + STRINGID_PKMNAFFLICTEDBYCURSE, STRINGID_PKMNSAPPEDBYLEECHSEED, STRINGID_PKMNLOCKEDINNIGHTMARE, + STRINGID_PKMNHURTBY, STRINGID_PKMNHURTBYBURN, STRINGID_PKMNHURTBYPOISON, + STRINGID_PKMNHURTBYSPIKES, STRINGID_ATTACKERFAINTED, STRINGID_TARGETFAINTED, + STRINGID_PKMNHITWITHRECOIL, STRINGID_PKMNCRASHED, 0xFFFF +}; + +// code +void BattleTv_SetDataBasedOnString(u16 stringId) +{ + struct BattleTv *tvPtr; + u32 atkSide, defSide, effSide, scriptingSide; + struct Pokemon *atkMon, *defMon; + u8 moveSlot; + u32 atkFlank, defFlank, effFlank; + u8 *perishCount; + u16 *statStringId, *finishedMoveId; + + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) && stringId != STRINGID_ITDOESNTAFFECT && stringId != STRINGID_NOTVERYEFFECTIVE) + return; + + tvPtr = &gBattleStruct->tv; + + atkSide = GetBattlerSide(gBattlerAttacker); + defSide = GetBattlerSide(gBattlerTarget); + effSide = GetBattlerSide(gEffectBattler); + scriptingSide = GetBattlerSide(gStringInfo->scrActive); + + if (atkSide == B_SIDE_PLAYER) + atkMon = &gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]]; + else + atkMon = &gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]]; + + if (defSide == B_SIDE_PLAYER) + defMon = &gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]]; + else + defMon = &gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]; + + moveSlot = GetBattlerMoveSlotId(gBattlerAttacker, gStringInfo->currentMove); + + if (moveSlot >= 4 && sub_817E0B8(stringId) && stringId > BATTLESTRINGS_ID_ADDER) + { + tvPtr->side[atkSide].faintCause = 15; + return; + } + + perishCount = (u8 *)(gBattleTextBuff1 + 4); + statStringId = (u16 *)(gBattleTextBuff2 + 2); + finishedMoveId = (u16 *)(gBattleTextBuff1 + 2); + + atkFlank = GetBattlerPosition(gBattlerAttacker) / 2; + defFlank = GetBattlerPosition(gBattlerTarget) / 2; + effFlank = GetBattlerPosition(gEffectBattler) / 2; + + switch (stringId) + { + case STRINGID_ITDOESNTAFFECT: + AddMovePoints(1, moveSlot, 2, 0); + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)) + TrySetBattleSeminarShow(); + break; + case STRINGID_NOTVERYEFFECTIVE: + AddMovePoints(1, moveSlot, 1, 0); + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) && GetMonData(defMon, MON_DATA_HP, NULL) != 0) + TrySetBattleSeminarShow(); + break; + case STRINGID_SUPEREFFECTIVE: + AddMovePoints(1, moveSlot, 0, 0); + break; + case STRINGID_PKMNFORESAWATTACK: + tvPtr->side[atkSide].futureSightMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].futureSightMoveSlot = moveSlot; + break; + case STRINGID_PKMNCHOSEXASDESTINY: + tvPtr->side[atkSide].doomDesireMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].doomDesireMoveSlot = moveSlot; + break; + case STRINGID_FAINTINTHREE: + tvPtr->side[atkSide].perishSongMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].perishSongMoveSlot = moveSlot; + tvPtr->side[atkSide].perishSong = 1; + break; + case STRINGID_PKMNPERISHCOUNTFELL: + if (*perishCount == 0) + tvPtr->side[atkSide].faintCause = 10; + break; + case STRINGID_PKMNWISHCAMETRUE: + if (tvPtr->side[defSide].wishMonId != 0) + { + AddMovePoints(2, 3, defSide, + (tvPtr->side[defSide].wishMonId - 1) * 4 + tvPtr->side[defSide].wishMoveSlot); + } + break; + case STRINGID_PKMNWANTSGRUDGE: + tvPtr->side[atkSide].grudgeMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].grudgeMoveSlot = moveSlot; + break; + case STRINGID_PKMNLOSTPPGRUDGE: + if (tvPtr->side[defSide].grudgeMonId != 0) + { + AddMovePoints(2, 4, defSide, + (tvPtr->side[defSide].grudgeMonId - 1) * 4 + tvPtr->side[defSide].grudgeMoveSlot); + } + break; + case STRINGID_PKMNTRYINGTOTAKEFOE: + tvPtr->side[atkSide].destinyBondMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].destinyBondMoveSlot = moveSlot; + break; + case STRINGID_PKMNTOOKFOE: + if (tvPtr->side[defSide].destinyBondMonId != 0) + tvPtr->side[atkSide].faintCause = 11; + break; + case STRINGID_PKMNPLANTEDROOTS: + tvPtr->pos[atkSide][atkFlank].ingrainMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[atkSide][atkFlank].ingrainMoveSlot = moveSlot; + break; + case STRINGID_PKMNABSORBEDNUTRIENTS: + if (tvPtr->pos[atkSide][atkFlank].ingrainMonId != 0) + { + AddMovePoints(2, 6, atkSide, + (tvPtr->pos[atkSide][atkFlank].ingrainMonId - 1) * 4 + tvPtr->pos[atkSide][atkFlank].ingrainMoveSlot); + } + break; + case STRINGID_PKMNANCHOREDITSELF: + if (tvPtr->pos[defSide][defFlank].ingrainMonId != 0) + { + AddMovePoints(2, 6, defSide, + (tvPtr->pos[defSide][defFlank].ingrainMonId - 1) * 4 + tvPtr->pos[defSide][defFlank].ingrainMoveSlot); + } + break; + case STRINGID_PKMNTRANSFORMEDINTO: + gBattleStruct->anyMonHasTransformed = TRUE; + break; + case STRINGID_CRITICALHIT: + AddMovePoints(0x12, moveSlot, 0, 0); + break; + case STRINGID_PKMNSSTATCHANGED: + if (gBattleTextBuff1[2] != 0) + { + if (*statStringId == STRINGID_STATSHARPLY) + AddMovePoints(0x17, moveSlot, gBattleTextBuff1[2] - 1, 0); + else + AddMovePoints(0x16, moveSlot, gBattleTextBuff1[2] - 1, 0); + } + break; + case STRINGID_PKMNSSTATCHANGED2: + if (gBattleTextBuff1[2] != 0) + { + if (gBattlerAttacker == gBattlerTarget) + { + if (*statStringId == STRINGID_STATSHARPLY) + AddMovePoints(0x17, moveSlot, gBattleTextBuff1[2] - 1, 0); + else + AddMovePoints(0x16, moveSlot, gBattleTextBuff1[2] - 1, 0); + } + else + { + AddMovePoints(0x1B, moveSlot, gBattleTextBuff1[2] - 1, 0); + } + } + break; + case STRINGID_PKMNSSTATCHANGED3: + if (gBattleTextBuff1[2] != 0) + AddMovePoints(0x18, moveSlot, gBattleTextBuff1[2] - 1, 0); + break; + case STRINGID_PKMNSSTATCHANGED4: + if (gBattleTextBuff1[2] != 0) + { + if (*statStringId == STRINGID_STATHARSHLY) + AddMovePoints(0x1A, moveSlot, gBattleTextBuff1[2] - 1, 0); + else + AddMovePoints(0x19, moveSlot, gBattleTextBuff1[2] - 1, 0); + } + break; + case STRINGID_PKMNLAIDCURSE: + tvPtr->pos[defSide][defFlank].curseMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][defFlank].curseMoveSlot = moveSlot; + break; + case STRINGID_PKMNAFFLICTEDBYCURSE: + if (GetMonData(atkMon, MON_DATA_HP, NULL) + && tvPtr->pos[atkSide][atkFlank].curseMonId != 0) + { + AddMovePoints(8, 0, tvPtr->pos[atkSide][atkFlank].curseMonId - 1, tvPtr->pos[atkSide][atkFlank].curseMoveSlot); + tvPtr->side[atkSide].faintCause = 1; + tvPtr->side[atkSide].faintCauseMonId = atkFlank; + } + break; + case STRINGID_PKMNSEEDED: + tvPtr->pos[defSide][defFlank].leechSeedMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][defFlank].leechSeedMoveSlot = moveSlot; + break; + case STRINGID_PKMNSAPPEDBYLEECHSEED: + if (tvPtr->pos[atkSide][atkFlank].leechSeedMonId != 0) + { + AddMovePoints(8, 1, tvPtr->pos[atkSide][atkFlank].leechSeedMonId - 1, tvPtr->pos[atkSide][atkFlank].leechSeedMoveSlot); + tvPtr->side[atkSide].faintCause = 2; + tvPtr->side[atkSide].faintCauseMonId = atkFlank; + } + break; + case STRINGID_PKMNFELLINTONIGHTMARE: + tvPtr->pos[defSide][defFlank].nightmareMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][defFlank].nightmareMoveSlot = moveSlot; + break; + case STRINGID_PKMNLOCKEDINNIGHTMARE: + if (GetMonData(atkMon, MON_DATA_HP, NULL) != 0 + && tvPtr->pos[atkSide][atkFlank].nightmareMonId != 0) + { + AddMovePoints(8, 5, tvPtr->pos[atkSide][atkFlank].nightmareMonId - 1, tvPtr->pos[atkSide][atkFlank].nightmareMoveSlot); + tvPtr->side[atkSide].faintCause = 5; + tvPtr->side[atkSide].faintCauseMonId = atkFlank; + } + break; + case STRINGID_PKMNSQUEEZEDBYBIND: + case STRINGID_PKMNTRAPPEDINVORTEX: + case STRINGID_PKMNWRAPPEDBY: + case STRINGID_PKMNCLAMPED: + case STRINGID_PKMNTRAPPEDBYSANDTOMB: + tvPtr->pos[defSide][defFlank].wrapMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][defFlank].wrapMoveSlot = moveSlot; + break; + case STRINGID_PKMNHURTBY: + if (GetMonData(atkMon, MON_DATA_HP, NULL) != 0 + && tvPtr->pos[atkSide][atkFlank].wrapMonId != 0) + { + AddMovePoints(8, 6, tvPtr->pos[atkSide][atkFlank].wrapMonId - 1, tvPtr->pos[atkSide][atkFlank].wrapMoveSlot); + tvPtr->side[atkSide].faintCause = 6; + tvPtr->side[atkSide].faintCauseMonId = atkFlank; + } + break; + case STRINGID_PKMNWASBURNED: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].brnMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].brnMoveSlot = moveSlot; + break; + case STRINGID_PKMNHURTBYBURN: + if (GetMonData(atkMon, MON_DATA_HP, NULL) != 0) + { + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].brnMonId != 0) + AddMovePoints(8, 4, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].brnMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].brnMoveSlot); + tvPtr->side[atkSide].faintCause = 4; + tvPtr->side[atkSide].faintCauseMonId = gBattlerPartyIndexes[gBattlerAttacker]; + } + break; + case STRINGID_PKMNWASPOISONED: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].psnMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].psnMoveSlot = moveSlot; + break; + case STRINGID_PKMNBADLYPOISONED: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].badPsnMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].badPsnMoveSlot = moveSlot; + break; + case STRINGID_PKMNHURTBYPOISON: + if (GetMonData(atkMon, MON_DATA_HP, NULL) != 0) + { + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].psnMonId != 0) + AddMovePoints(8, 2, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].psnMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].psnMoveSlot); + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].badPsnMonId != 0) + AddMovePoints(8, 3, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].badPsnMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].badPsnMoveSlot); + tvPtr->side[atkSide].faintCause = 3; + tvPtr->side[atkSide].faintCauseMonId = gBattlerPartyIndexes[gBattlerAttacker]; + } + break; + case STRINGID_PKMNFELLINLOVE: + tvPtr->pos[defSide][defFlank].attractMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][defFlank].attractMoveSlot = moveSlot; + break; + case STRINGID_PKMNIMMOBILIZEDBYLOVE: + if (tvPtr->pos[atkSide][atkFlank].attractMonId != 0) + AddMovePoints(9, 0, tvPtr->pos[atkSide][atkFlank].attractMonId - 1, tvPtr->pos[atkSide][atkFlank].attractMoveSlot); + break; + case STRINGID_PKMNWASPARALYZED: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].prlzMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].prlzMoveSlot = moveSlot; + break; + case STRINGID_PKMNISPARALYZED: + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].prlzMonId != 0) + AddMovePoints(9, 2, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].prlzMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].prlzMoveSlot); + break; + case STRINGID_PKMNFELLASLEEP: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].slpMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].slpMoveSlot = moveSlot; + break; + case STRINGID_PKMNFASTASLEEP: + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].slpMonId != 0 + && gStringInfo->currentMove != MOVE_SNORE + && gStringInfo->currentMove != MOVE_SLEEP_TALK) + AddMovePoints(9, 3, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].slpMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].slpMoveSlot); + break; + case STRINGID_PKMNWASFROZEN: + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].frzMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->mon[effSide][gBattlerPartyIndexes[gEffectBattler]].frzMoveSlot = moveSlot; + break; + case STRINGID_PKMNISFROZEN: + if (tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].frzMonId != 0) + AddMovePoints(9, 4, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].frzMonId - 1, tvPtr->mon[atkSide][gBattlerPartyIndexes[gBattlerAttacker]].frzMoveSlot); + break; + case STRINGID_PKMNWASCONFUSED: + tvPtr->pos[effSide][effFlank].confusionMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[effSide][effFlank].confusionMoveSlot = moveSlot; + break; + case STRINGID_ITHURTCONFUSION: + if (tvPtr->pos[atkSide][atkFlank].confusionMonId != 0) + AddMovePoints(9, 1, tvPtr->pos[atkSide][atkFlank].confusionMonId - 1, tvPtr->pos[atkSide][atkFlank].confusionMoveSlot); + tvPtr->side[atkSide].faintCause = 12; + break; + case STRINGID_SPIKESSCATTERED: + tvPtr->side[defSide].spikesMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[defSide].spikesMoveSlot = moveSlot; + break; + case STRINGID_PKMNHURTBYSPIKES: + if (tvPtr->side[scriptingSide].spikesMonId != 0) + { + AddMovePoints(10, scriptingSide ^ BIT_SIDE, tvPtr->side[scriptingSide].spikesMonId - 1, tvPtr->side[scriptingSide].spikesMoveSlot); + tvPtr->side[scriptingSide].faintCause = 7; + } + break; + case STRINGID_PKMNBLEWAWAYSPIKES: + tvPtr->side[atkSide].spikesMonId = 0; + tvPtr->side[atkSide].spikesMoveSlot = 0; + break; + case STRINGID_FIREWEAKENED: + tvPtr->pos[atkSide][atkFlank].waterSportMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[atkSide][atkFlank].waterSportMoveSlot = moveSlot; + break; + case STRINGID_ELECTRICITYWEAKENED: + tvPtr->pos[atkSide][atkFlank].mudSportMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[atkSide][atkFlank].mudSportMoveSlot = moveSlot; + break; + case STRINGID_ATTACKERFAINTED: + AddPointsOnFainting(FALSE); + case STRINGID_RETURNMON: + if (tvPtr->pos[atkSide][atkFlank].waterSportMonId != 0) + { + tvPtr->pos[atkSide][atkFlank].waterSportMonId = 0; + tvPtr->pos[atkSide][atkFlank].waterSportMoveSlot = 0; + } + if (tvPtr->pos[atkSide][atkFlank].mudSportMonId != 0) + { + tvPtr->pos[atkSide][atkFlank].mudSportMonId = 0; + tvPtr->pos[atkSide][atkFlank].mudSportMoveSlot = 0; + } + break; + case STRINGID_TARGETFAINTED: + AddPointsOnFainting(TRUE); + if (tvPtr->pos[atkSide][defFlank].waterSportMonId != 0) + { + tvPtr->pos[atkSide][defFlank].waterSportMonId = 0; + tvPtr->pos[atkSide][defFlank].waterSportMoveSlot = 0; + } + if (tvPtr->pos[atkSide][defFlank].mudSportMonId != 0) + { + tvPtr->pos[atkSide][defFlank].mudSportMonId = 0; + tvPtr->pos[atkSide][defFlank].mudSportMoveSlot = 0; + } + break; + case STRINGID_PKMNRAISEDDEF: + case STRINGID_PKMNRAISEDDEFALITTLE: + tvPtr->side[atkSide].reflectMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].reflectMoveSlot = moveSlot; + break; + case STRINGID_PKMNRAISEDSPDEF: + case STRINGID_PKMNRAISEDSPDEFALITTLE: + tvPtr->side[atkSide].lightScreenMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].lightScreenMoveSlot = moveSlot; + break; + case STRINGID_PKMNSXWOREOFF: + if (*finishedMoveId == MOVE_REFLECT) + { + tvPtr->side[atkSide].reflectMonId = 0; + tvPtr->side[atkSide].reflectMoveSlot = 0; + } + if (*finishedMoveId == MOVE_LIGHT_SCREEN) + { + tvPtr->side[atkSide].lightScreenMonId = 0; + tvPtr->side[atkSide].lightScreenMoveSlot = 0; + } + if (*finishedMoveId == MOVE_MIST) + { + tvPtr->side[atkSide].mistMonId = 0; + tvPtr->side[atkSide].mistMoveSlot = 0; + } + break; + case STRINGID_PKMNCOVEREDBYVEIL: + tvPtr->side[atkSide].safeguardMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].safeguardMoveSlot = moveSlot; + break; + case STRINGID_PKMNUSEDSAFEGUARD: + if (tvPtr->side[defSide].safeguardMonId != 0) + AddMovePoints(15, 0, tvPtr->side[defSide].safeguardMonId - 1, tvPtr->side[defSide].safeguardMoveSlot); + break; + case STRINGID_PKMNSAFEGUARDEXPIRED: + tvPtr->side[atkSide].safeguardMonId = 0; + tvPtr->side[atkSide].safeguardMoveSlot = 0; + break; + case STRINGID_PKMNSHROUDEDINMIST: + tvPtr->side[atkSide].mistMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].mistMoveSlot = moveSlot; + break; + case STRINGID_PKMNPROTECTEDBYMIST: + if (tvPtr->side[defSide].mistMonId != 0) + AddMovePoints(16, 0, tvPtr->side[defSide].mistMonId - 1, tvPtr->side[defSide].mistMoveSlot); + break; + case STRINGID_THEWALLSHATTERED: + tvPtr->side[defSide].reflectMonId = 0; + tvPtr->side[defSide].reflectMoveSlot = 0; + tvPtr->side[defSide].lightScreenMonId = 0; + tvPtr->side[defSide].lightScreenMoveSlot = 0; + AddMovePoints(17, 0, gBattlerPartyIndexes[gBattlerAttacker], moveSlot); + break; + case STRINGID_PKMNFLINCHED: + if (tvPtr->pos[atkSide][0].attackedByMonId != 0) + AddMovePoints(21, 0, tvPtr->pos[atkSide][0].attackedByMonId - 1, tvPtr->pos[atkSide][0].attackedByMoveSlot); + if (tvPtr->pos[atkSide][1].attackedByMonId != 0) + AddMovePoints(21, 0, tvPtr->pos[atkSide][1].attackedByMonId - 1, tvPtr->pos[atkSide][1].attackedByMoveSlot); + break; + case STRINGID_PKMNCRASHED: + case STRINGID_PKMNHITWITHRECOIL: + tvPtr->side[atkSide].faintCause = 14; + break; + } +} + +static bool8 sub_817E0B8(u16 stringId) +{ + s32 i = 0; + + do + { + if (sUnknown_0860A8A4[i] == stringId) + break; + i++; + } while (sUnknown_0860A8A4[i] != 0xFFFF); + + if (sUnknown_0860A8A4[i] == 0xFFFF) + return TRUE; + else + return FALSE; +} + +void BattleTv_SetDataBasedOnMove(u16 move, u16 weatherFlags, struct DisableStruct *disableStructPtr) +{ + struct BattleTv *tvPtr; + u32 atkSide, defSide; + u8 moveSlot; + + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)) + return; + + tvPtr = &gBattleStruct->tv; + + atkSide = GetBattlerSide(gBattlerAttacker); + defSide = GetBattlerSide(gBattlerTarget); + moveSlot = GetBattlerMoveSlotId(gBattlerAttacker, move); + + if (moveSlot >= 4) + { + tvPtr->side[atkSide].faintCause = 15; + return; + } + + tvPtr->pos[defSide][GetBattlerPosition(gBattlerAttacker) / 2].attackedByMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->pos[defSide][GetBattlerPosition(gBattlerAttacker) / 2].attackedByMoveSlot = moveSlot; + tvPtr->side[atkSide].usedMoveSlot = moveSlot; + AddMovePoints(0, moveSlot, gBattleMoves[move].effect, 0); + AddPointsBasedOnWeather(weatherFlags, move, moveSlot); + if (disableStructPtr->chargeTimer1 != 0) + AddMovePoints(7, move, moveSlot, 0); + + if (move == MOVE_WISH) + { + tvPtr->side[atkSide].wishMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide].wishMoveSlot = moveSlot; + } + if (move == MOVE_SELF_DESTRUCT || move == MOVE_EXPLOSION) + { + tvPtr->side[atkSide ^ BIT_SIDE].explosionMonId = gBattlerPartyIndexes[gBattlerAttacker] + 1; + tvPtr->side[atkSide ^ BIT_SIDE].explosionMoveSlot = moveSlot; + tvPtr->side[atkSide ^ BIT_SIDE].faintCause = 13; + tvPtr->side[atkSide ^ BIT_SIDE].explosion = 1; + } + + AddMovePoints(13, gBattleMoves[move].type, gBattleMoves[move].power, 0); + AddMovePoints(14, gBattleMoves[move].type, gBattleMoves[move].power, 0); + AddMovePoints(11, gBattleMoves[move].type, 0, 0); + AddMovePoints(12, gBattleMoves[move].type, 0, 0); +} + +void BattleTv_SetDataBasedOnAnimation(u8 animationId) +{ + struct BattleTv *tvPtr; + u32 atkSide; + + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)) + return; + + tvPtr = &gBattleStruct->tv; + atkSide = GetBattlerSide(gBattlerAttacker); + switch (animationId) + { + case B_ANIM_FUTURE_SIGHT_HIT: + if (tvPtr->side[atkSide].futureSightMonId != 0) + { + AddMovePoints(2, 0, atkSide, + (tvPtr->side[atkSide].futureSightMonId - 1) * 4 + tvPtr->side[atkSide].futureSightMoveSlot); + tvPtr->side[atkSide].faintCause = 8; + } + break; + case B_ANIM_DOOM_DESIRE_HIT: + if (tvPtr->side[atkSide].doomDesireMonId != 0) + { + AddMovePoints(2, 1, atkSide, + (tvPtr->side[atkSide].doomDesireMonId - 1) * 4 + tvPtr->side[atkSide].doomDesireMoveSlot); + tvPtr->side[atkSide].faintCause = 9; + } + break; + } +} + +#ifdef NONMATCHING +// for loop has an unused stack variable +void TryPutLinkBattleTvShowOnAir(void) +{ + u16 playerBestSpecies = 0, opponentBestSpecies = 0; + s16 playerBestSum = 0, opponentBestSum = SHRT_MAX; + u8 playerBestMonId = 0, opponentBestMonId = 0; + struct BattleTvMovePoints *movePoints = NULL; + u8 countPlayer = 0, countOpponent = 0; + s16 sum = 0; + u16 species = 0; + u16 moveId = 0; + s32 i, j; + + if (gBattleStruct->anyMonHasTransformed) + return; + + movePoints = &gBattleStruct->tvMovePoints; + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + countPlayer++; + if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + countOpponent++; + } + + if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) || countPlayer != countOpponent) + return; + + for (i = 0; i < PARTY_SIZE; i++) + { + species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL); + if (species != SPECIES_NONE && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG, NULL)) + { + for (sum = 0, j = 0; j < 4; j++) + sum += movePoints->points[0][i * 4 + j]; + + if (playerBestSum < sum) + { + playerBestMonId = i; + playerBestSum = sum; + playerBestSpecies = species; + } + } + + species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES, NULL); + if (species != SPECIES_NONE && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG, NULL)) + { + for (sum = 0, j = 0; j < 4; j++) + sum += movePoints->points[1][i * 4 + j]; + + if (opponentBestSum == sum) + { + if (GetMonData(&gEnemyParty[i], MON_DATA_EXP, NULL) > GetMonData(&gEnemyParty[opponentBestMonId], MON_DATA_EXP, NULL)) + { + opponentBestMonId = i; + opponentBestSum = sum; + opponentBestSpecies = species; + } + } + else if (opponentBestSum > sum) + { + opponentBestMonId = i; + opponentBestSum = sum; + opponentBestSpecies = species; + } + } + } + + for (sum = 0, i = 0, j = 0; j < 4; j++) + { + if (sum < movePoints->points[0][playerBestMonId * 4 + j]) + { + sum = movePoints->points[0][playerBestMonId * 4 + j]; + i = j; + } + } + + moveId = GetMonData(&gPlayerParty[playerBestMonId], MON_DATA_MOVE1 + i, NULL); + if (playerBestSum == 0 || moveId == 0) + return; + + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if ((playerBestMonId < 3 && !sub_806D82C(gBattleScripting.multiplayerId)) + || (playerBestMonId >= 3 && sub_806D82C(gBattleScripting.multiplayerId))) + { + j = (opponentBestMonId < 3) ? 0 : 1; + PutBattleUpdateOnTheAir(sub_806EF84(j, gBattleScripting.multiplayerId), moveId, playerBestSpecies, opponentBestSpecies); + } + } + else + { + PutBattleUpdateOnTheAir(gBattleScripting.multiplayerId ^ 1, moveId, playerBestSpecies, opponentBestSpecies); + } +} + +#else +NAKED +void TryPutLinkBattleTvShowOnAir(void) +{ + asm_unified( + "push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x20\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + movs r1, 0\n\ + str r1, [sp, 0x4]\n\ + movs r2, 0\n\ + str r2, [sp, 0x8]\n\ + ldr r3, =0x00007fff\n\ + str r3, [sp, 0xC]\n\ + movs r4, 0\n\ + str r4, [sp, 0x10]\n\ + movs r7, 0\n\ + str r7, [sp, 0x14]\n\ + mov r8, r0\n\ + ldr r0, =gBattleStruct\n\ + ldr r1, [r0]\n\ + adds r0, r1, 0\n\ + adds r0, 0xB3\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _0817E42A\n\ + b _0817E670\n\ +_0817E42A:\n\ + movs r2, 0xD2\n\ + lsls r2, 1\n\ + adds r2, r1\n\ + mov r10, r2\n\ + movs r6, 0\n\ +_0817E434:\n\ + movs r0, 0x64\n\ + adds r4, r6, 0\n\ + muls r4, r0\n\ + ldr r0, =gPlayerParty\n\ + adds r0, r4, r0\n\ + movs r1, 0xB\n\ + movs r2, 0\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0817E454\n\ + mov r0, r8\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ +_0817E454:\n\ + ldr r5, =gEnemyParty\n\ + adds r0, r4, r5\n\ + movs r1, 0xB\n\ + movs r2, 0\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _0817E46A\n\ + adds r0, r7, 0x1\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ +_0817E46A:\n\ + adds r6, 0x1\n\ + cmp r6, 0x5\n\ + ble _0817E434\n\ + ldr r0, =gBattleTypeFlags\n\ + ldr r0, [r0]\n\ + movs r1, 0x2\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _0817E47E\n\ + b _0817E670\n\ +_0817E47E:\n\ + cmp r8, r7\n\ + beq _0817E484\n\ + b _0817E670\n\ +_0817E484:\n\ + movs r6, 0\n\ + lsls r3, r6, 1\n\ + str r3, [sp, 0x18]\n\ + movs r4, 0x64\n\ + mov r8, r4\n\ +_0817E48E:\n\ + mov r1, r8\n\ + muls r1, r6\n\ + ldr r0, =gPlayerParty\n\ + adds r4, r1, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + movs r2, 0\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ + adds r0, r6, 0x1\n\ + mov r9, r0\n\ + cmp r7, 0\n\ + beq _0817E4EE\n\ + adds r0, r4, 0\n\ + movs r1, 0x2D\n\ + movs r2, 0\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _0817E4EE\n\ + movs r4, 0\n\ + lsls r0, r6, 3\n\ + mov r2, r10\n\ + adds r1, r0, r2\n\ + movs r3, 0x3\n\ +_0817E4C4:\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + ldrh r4, [r1]\n\ + adds r0, r4\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + adds r1, 0x2\n\ + subs r3, 0x1\n\ + cmp r3, 0\n\ + bge _0817E4C4\n\ + ldr r1, [sp, 0x8]\n\ + lsls r0, r1, 16\n\ + lsls r1, r4, 16\n\ + cmp r0, r1\n\ + bge _0817E4EE\n\ + lsls r0, r6, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x10]\n\ + lsrs r1, 16\n\ + str r1, [sp, 0x8]\n\ + str r7, [sp]\n\ +_0817E4EE:\n\ + mov r0, r8\n\ + muls r0, r6\n\ + ldr r2, =gEnemyParty\n\ + adds r4, r0, r2\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + movs r2, 0\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ + ldr r3, [sp, 0x8]\n\ + lsls r3, 16\n\ + str r3, [sp, 0x1C]\n\ + cmp r7, 0\n\ + beq _0817E5A0\n\ + adds r0, r4, 0\n\ + movs r1, 0x2D\n\ + movs r2, 0\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _0817E5A0\n\ + movs r4, 0\n\ + ldr r0, [sp, 0xC]\n\ + lsls r2, r0, 16\n\ + movs r3, 0x1\n\ + lsls r1, r3, 1\n\ + adds r1, 0x1\n\ + lsls r1, 4\n\ + lsls r0, r6, 3\n\ + adds r0, r1\n\ + mov r3, r10\n\ + adds r1, r0, r3\n\ + movs r3, 0x3\n\ +_0817E534:\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + ldrh r4, [r1]\n\ + adds r0, r4\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + adds r1, 0x2\n\ + subs r3, 0x1\n\ + cmp r3, 0\n\ + bge _0817E534\n\ + asrs r1, r2, 16\n\ + lsls r5, r4, 16\n\ + asrs r0, r5, 16\n\ + cmp r1, r0\n\ + bne _0817E590\n\ + mov r0, r8\n\ + muls r0, r6\n\ + ldr r1, =gEnemyParty\n\ + adds r0, r1\n\ + movs r1, 0x19\n\ + movs r2, 0\n\ + bl GetMonData\n\ + adds r4, r0, 0\n\ + ldr r2, [sp, 0x14]\n\ + mov r0, r8\n\ + muls r0, r2\n\ + ldr r3, =gEnemyParty\n\ + adds r0, r3\n\ + movs r1, 0x19\n\ + movs r2, 0\n\ + bl GetMonData\n\ + cmp r4, r0\n\ + bls _0817E5A0\n\ + b _0817E594\n\ + .pool\n\ +_0817E590:\n\ + cmp r1, r0\n\ + ble _0817E5A0\n\ +_0817E594:\n\ + lsls r0, r6, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x14]\n\ + lsrs r5, 16\n\ + str r5, [sp, 0xC]\n\ + str r7, [sp, 0x4]\n\ +_0817E5A0:\n\ + mov r6, r9\n\ + cmp r6, 0x5\n\ + bgt _0817E5A8\n\ + b _0817E48E\n\ +_0817E5A8:\n\ + movs r4, 0\n\ + movs r6, 0\n\ + movs r3, 0\n\ + ldr r5, =gPlayerParty\n\ + ldr r7, [sp, 0x10]\n\ + lsls r0, r7, 3\n\ + mov r1, r10\n\ + adds r2, r0, r1\n\ +_0817E5B8:\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + movs r7, 0\n\ + ldrsh r1, [r2, r7]\n\ + cmp r0, r1\n\ + bge _0817E5C8\n\ + ldrh r4, [r2]\n\ + adds r6, r3, 0\n\ +_0817E5C8:\n\ + adds r2, 0x2\n\ + adds r3, 0x1\n\ + cmp r3, 0x3\n\ + ble _0817E5B8\n\ + movs r0, 0x64\n\ + ldr r1, [sp, 0x10]\n\ + muls r0, r1\n\ + adds r0, r5\n\ + adds r1, r6, 0\n\ + adds r1, 0xD\n\ + movs r2, 0\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + ldr r2, [sp, 0x1C]\n\ + cmp r2, 0\n\ + beq _0817E670\n\ + cmp r4, 0\n\ + beq _0817E670\n\ + ldr r0, =gBattleTypeFlags\n\ + ldr r0, [r0]\n\ + movs r1, 0x40\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0817E65C\n\ + ldr r3, [sp, 0x10]\n\ + cmp r3, 0x2\n\ + bhi _0817E620\n\ + ldr r0, =gBattleScripting\n\ + adds r0, 0x25\n\ + ldrb r0, [r0]\n\ + bl sub_806D82C\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _0817E630\n\ + b _0817E670\n\ + .pool\n\ +_0817E620:\n\ + ldr r0, =gBattleScripting\n\ + adds r0, 0x25\n\ + ldrb r0, [r0]\n\ + bl sub_806D82C\n\ + lsls r0, 16\n\ + cmp r0, 0\n\ + beq _0817E670\n\ +_0817E630:\n\ + movs r3, 0\n\ + ldr r7, [sp, 0x14]\n\ + cmp r7, 0x2\n\ + bls _0817E63A\n\ + movs r3, 0x1\n\ +_0817E63A:\n\ + lsls r0, r3, 24\n\ + lsrs r0, 24\n\ + ldr r1, =gBattleScripting\n\ + adds r1, 0x25\n\ + ldrb r1, [r1]\n\ + bl sub_806EF84\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + adds r1, r4, 0\n\ + ldr r2, [sp]\n\ + ldr r3, [sp, 0x4]\n\ + bl PutBattleUpdateOnTheAir\n\ + b _0817E670\n\ + .pool\n\ +_0817E65C:\n\ + ldr r0, =gBattleScripting\n\ + adds r0, 0x25\n\ + ldrb r1, [r0]\n\ + movs r0, 0x1\n\ + eors r0, r1\n\ + adds r1, r4, 0\n\ + ldr r2, [sp]\n\ + ldr r3, [sp, 0x4]\n\ + bl PutBattleUpdateOnTheAir\n\ +_0817E670:\n\ + add sp, 0x20\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool"); +} +#endif + +static void AddMovePoints(u8 caseId, u16 arg1, u8 arg2, u8 arg3) +{ + struct BattleTvMovePoints *movePoints = &gBattleStruct->tvMovePoints; + struct BattleTv *tvPtr = &gBattleStruct->tv; + u32 atkSide = GetBattlerSide(gBattlerAttacker); + u32 defSide = GetBattlerSide(gBattlerTarget); + const u16 *ptr; + s32 i; + + switch (caseId) + { + case 0: + case 1: + case 18: + case 22 ... 27: + movePoints->points[atkSide][gBattlerPartyIndexes[gBattlerAttacker] * 4 + arg1] += sPointsArray[caseId][arg2]; + break; + case 3 ... 7: + i = 0; + ptr = sPointsArray[caseId]; + do + { + if (arg1 == ptr[i]) + { + movePoints->points[atkSide][gBattlerPartyIndexes[gBattlerAttacker] * 4 + arg2] += ptr[i+1]; + break; + } + i += 2; + } while (ptr[i] != 0xFFFF); + break; + case 19: + tvPtr->side[arg2 ^ 1].faintCause = 0; + movePoints->points[arg2][0 * 4 + arg3] += sPointsArray[caseId][arg1]; + break; + case 20: + tvPtr->side[arg2].faintCause = 0; + case 2: + movePoints->points[arg2][0 * 4 + arg3] += sPointsArray[caseId][arg1]; + break; + case 17: + movePoints->points[atkSide][arg2 * 4 + arg3] += sPointsArray[caseId][arg1]; + break; + case 8: + case 9: + case 15: + case 16: + case 21: + movePoints->points[atkSide ^ BIT_SIDE][arg2 * 4 + arg3] += sPointsArray[caseId][arg1]; + break; + case 10: + movePoints->points[arg1][arg2 * 4 + arg3] += sPointsArray[caseId][0]; + break; + case 11: + if (tvPtr->pos[defSide][0].waterSportMonId != -(tvPtr->pos[defSide][1].waterSportMonId) && arg1 == 10) + { + if (tvPtr->pos[defSide][0].waterSportMonId != 0) + { + u32 id = (tvPtr->pos[defSide][0].waterSportMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->pos[defSide][0].waterSportMoveSlot] += sPointsArray[caseId][0]; + } + if (tvPtr->pos[defSide][1].waterSportMonId != 0) + { + u32 id = (tvPtr->pos[defSide][1].waterSportMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->pos[defSide][1].waterSportMoveSlot] += sPointsArray[caseId][0]; + } + } + break; + case 12: + if (tvPtr->pos[defSide][0].mudSportMonId != -(tvPtr->pos[defSide][1].mudSportMonId) && arg1 == 13) + { + if (tvPtr->pos[defSide][0].mudSportMonId != 0) + { + u32 id = (tvPtr->pos[defSide][0].mudSportMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->pos[defSide][0].mudSportMoveSlot] += sPointsArray[caseId][0]; + } + if (tvPtr->pos[defSide][1].mudSportMonId != 0) + { + u32 id = (tvPtr->pos[defSide][1].mudSportMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->pos[defSide][1].mudSportMoveSlot] += sPointsArray[caseId][0]; + } + } + break; + case 13: + if (arg1 <= 8 && arg2 != 0 && tvPtr->side[defSide].reflectMonId != 0) + { + u32 id = (tvPtr->side[defSide].reflectMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->side[defSide].reflectMoveSlot] += sPointsArray[caseId][0]; + } + break; + case 14: + if (arg1 > 8 && arg2 != 0 && tvPtr->side[defSide].lightScreenMonId != 0) + { + u32 id = (tvPtr->side[defSide].lightScreenMonId - 1) * 4; + movePoints->points[defSide][id + tvPtr->side[defSide].lightScreenMoveSlot] += sPointsArray[caseId][0]; + } + break; + } +} + +static void AddPointsOnFainting(bool8 targetFainted) +{ + struct BattleTv *tvPtr = &gBattleStruct->tv; + u32 atkSide = GetBattlerSide(gBattlerAttacker); + u32 defSide = GetBattlerSide(gBattlerTarget); + u32 atkArrId = tvPtr->side[atkSide].faintCauseMonId; + s32 i; + + if (tvPtr->side[atkSide].faintCause != 0) + { + switch (tvPtr->side[atkSide].faintCause) + { + case 1: + if (tvPtr->pos[atkSide][atkArrId].curseMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->pos[atkSide][atkArrId].curseMonId - 1) * 4 + tvPtr->pos[atkSide][atkArrId].curseMoveSlot); + } + break; + case 2: + if (tvPtr->pos[atkSide][atkArrId].leechSeedMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->pos[atkSide][atkArrId].leechSeedMonId - 1) * 4 + tvPtr->pos[atkSide][atkArrId].leechSeedMoveSlot); + } + break; + case 3: + if (tvPtr->mon[atkSide][atkArrId].psnMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->mon[atkSide][atkArrId].psnMonId - 1) * 4 + tvPtr->mon[atkSide][atkArrId].psnMoveSlot); + } + if (tvPtr->mon[atkSide][atkArrId].badPsnMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->mon[atkSide][atkArrId].badPsnMonId - 1) * 4 + tvPtr->mon[atkSide][atkArrId].badPsnMoveSlot); + } + break; + case 4: + if (tvPtr->mon[atkSide][atkArrId].brnMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->mon[atkSide][atkArrId].brnMonId - 1) * 4 + tvPtr->mon[atkSide][atkArrId].brnMoveSlot); + } + break; + case 5: + if (tvPtr->pos[atkSide][atkArrId].nightmareMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->pos[atkSide][atkArrId].nightmareMonId - 1) * 4 + tvPtr->pos[atkSide][atkArrId].nightmareMoveSlot); + } + break; + case 6: + if (tvPtr->pos[atkSide][atkArrId].wrapMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->pos[atkSide][atkArrId].wrapMonId - 1) * 4 + tvPtr->pos[atkSide][atkArrId].wrapMoveSlot); + } + break; + case 7: + if (tvPtr->side[atkSide].spikesMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->side[atkSide].spikesMonId - 1) * 4 + tvPtr->side[atkSide].spikesMoveSlot); + } + break; + case 8: + if (tvPtr->side[atkSide].futureSightMonId != 0) + { + AddMovePoints(20, 0, atkSide, + (tvPtr->side[atkSide].futureSightMonId - 1) * 4 + tvPtr->side[atkSide].futureSightMoveSlot); + } + break; + case 9: + if (tvPtr->side[atkSide].doomDesireMonId != 0) + { + AddMovePoints(20, 0, atkSide, + (tvPtr->side[atkSide].doomDesireMonId - 1) * 4 + tvPtr->side[atkSide].doomDesireMoveSlot); + } + break; + case 10: + if (tvPtr->side[atkSide].perishSong + && tvPtr->side[atkSide].perishSongMonId - 1 != gBattlerPartyIndexes[gBattlerAttacker]) + { + AddMovePoints(19, 0, atkSide, + (tvPtr->side[atkSide].perishSongMonId - 1) * 4 + tvPtr->side[atkSide].perishSongMoveSlot); + } + if (tvPtr->side[atkSide ^ BIT_SIDE].perishSong) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->side[atkSide ^ BIT_SIDE].perishSongMonId - 1) * 4 + tvPtr->side[atkSide ^ BIT_SIDE].perishSongMoveSlot); + } + break; + case 11: + if (tvPtr->side[atkSide ^ BIT_SIDE].destinyBondMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->side[atkSide ^ BIT_SIDE].destinyBondMonId - 1) * 4 + tvPtr->side[atkSide ^ BIT_SIDE].destinyBondMoveSlot); + } + break; + case 12: + for (i = 0; i < 2; i++) + { + if (tvPtr->pos[atkSide][i].confusionMonId != 0) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->pos[atkSide][i].confusionMonId - 1) * 4 + tvPtr->pos[atkSide][i].confusionMoveSlot); + } + } + break; + case 13: + if (tvPtr->side[atkSide].explosion) + { + AddMovePoints(19, 0, atkSide, + (tvPtr->side[atkSide].explosionMonId - 1) * 4 + tvPtr->side[atkSide].explosionMoveSlot); + } + if (tvPtr->side[atkSide ^ BIT_SIDE].explosion) + { + AddMovePoints(19, 0, atkSide ^ BIT_SIDE, + (tvPtr->side[atkSide ^ BIT_SIDE].explosionMonId - 1) * 4 + tvPtr->side[atkSide ^ BIT_SIDE].explosionMoveSlot); + } + break; + case 14: + if (targetFainted == TRUE) + { + AddMovePoints(20, 0, atkSide, + (gBattlerPartyIndexes[gBattlerAttacker]) * 4 + tvPtr->side[atkSide].usedMoveSlot); + } + break; + case 15: + break; + } + } + else + { + if (tvPtr->side[defSide].faintCause == 7) + { + if (tvPtr->side[defSide].spikesMonId != 0) + { + AddMovePoints(19, 0, defSide ^ BIT_SIDE, + (tvPtr->side[defSide].spikesMonId - 1) * 4 + tvPtr->side[defSide].spikesMoveSlot); + } + } + else + { + AddMovePoints(20, 0, atkSide, + (gBattlerPartyIndexes[gBattlerAttacker]) * 4 + tvPtr->side[atkSide].usedMoveSlot); + } + } +} + +static void TrySetBattleSeminarShow(void) +{ + s32 i; + s32 dmgByMove[4]; + u16 powerOverride; + u16 currMoveSaved; + + if (gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) + return; + else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_OPPONENT) + return; + else if (gBattleMons[gBattlerAttacker].statStages[STAT_ACC] <= 5) + return; + else if (gBattleMons[gBattlerTarget].statStages[STAT_EVASION] > 6) + return; + else if (gCurrentMove == MOVE_HIDDEN_POWER || gCurrentMove == MOVE_WEATHER_BALL) + return; + else if (gBattleTypeFlags & (BATTLE_TYPE_PALACE | BATTLE_TYPE_PIKE | BATTLE_TYPE_PYRAMID)) + return; + else if (gBattleMoves[gBattleMons[gBattlerAttacker].moves[gMoveSelectionCursor[gBattlerAttacker]]].power == 0) + return; + + i = 0; + currMoveSaved = gBattleMons[gBattlerAttacker].moves[gMoveSelectionCursor[gBattlerAttacker]]; + do + { + if (currMoveSaved == sVariableDmgMoves[i]) + break; + i++; + } while (sVariableDmgMoves[i] != 0xFFFF); + + if (sVariableDmgMoves[i] != 0xFFFF) + return; + + dmgByMove[gMoveSelectionCursor[gBattlerAttacker]] = gBattleMoveDamage; + currMoveSaved = gCurrentMove; + for (i = 0; i < 4; i++) + { + gCurrentMove = gBattleMons[gBattlerAttacker].moves[i]; + powerOverride = 0; + if (ShouldCalculateDamage(gCurrentMove, &dmgByMove[i], &powerOverride)) + { + u8 moveResultFlags; + u16 sideStatus = gSideStatuses[GET_BATTLER_SIDE(gBattlerTarget)]; + gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBattlerAttacker], &gBattleMons[gBattlerTarget], gCurrentMove, + sideStatus, powerOverride, + 0, gBattlerAttacker, gBattlerTarget); + + if (gStatuses3[gBattlerAttacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC) + gBattleMoveDamage *= 2; + if (gProtectStructs[gBattlerAttacker].helpingHand) + gBattleMoveDamage = gBattleMoveDamage * 15 / 10; + + moveResultFlags = TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget); + dmgByMove[i] = gBattleMoveDamage; + if (dmgByMove[i] == 0 && !(moveResultFlags & MOVE_RESULT_NO_EFFECT)) + dmgByMove[i] = 1; + } + } + + for (i = 0; i < 4; i++) + { + if (i != gMoveSelectionCursor[gBattlerAttacker] && dmgByMove[i] > dmgByMove[gMoveSelectionCursor[gBattlerAttacker]]) + { + u16 opponentSpecies, playerSpecies; + s32 bestMoveId; + + if (gMoveSelectionCursor[gBattlerAttacker] != 0) + bestMoveId = 0; + else + bestMoveId = 1; + + for (i = 0; i < 4; i++) + { + if (i != gMoveSelectionCursor[gBattlerAttacker] && dmgByMove[i] > dmgByMove[bestMoveId]) + bestMoveId = i; + } + + opponentSpecies = GetMonData(&gEnemyParty [gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_SPECIES, NULL); + playerSpecies = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]], MON_DATA_SPECIES, NULL); + sub_80EE35C(opponentSpecies, playerSpecies, gMoveSelectionCursor[gBattlerAttacker], gBattleMons[gBattlerAttacker].moves, gBattleMons[gBattlerAttacker].moves[bestMoveId]); + break; + } + } + + gBattleMoveDamage = dmgByMove[gMoveSelectionCursor[gBattlerAttacker]]; + gCurrentMove = currMoveSaved; +} + +static bool8 ShouldCalculateDamage(u16 moveId, s32 *dmg, u16 *powerOverride) +{ + if (gBattleMoves[moveId].power == 0) + { + *dmg = 0; + return FALSE; + } + else + { + s32 i = 0; + do + { + if (moveId == sVariableDmgMoves[i]) + break; + i++; + } while (sVariableDmgMoves[i] != 0xFFFF); + + if (sVariableDmgMoves[i] != 0xFFFF) + { + *dmg = 0; + return FALSE; + } + else if (moveId == MOVE_PSYWAVE) + { + *dmg = gBattleMons[gBattlerAttacker].level; + *dmg /= 2; + return FALSE; + } + else if (moveId == MOVE_MAGNITUDE) + { + *powerOverride = 10; + return TRUE; + } + else + { + return TRUE; + } + } +} + +void BattleTv_ClearExplosionFaintCause(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + struct BattleTv *tvPtr = &gBattleStruct->tv; + + tvPtr->side[B_SIDE_PLAYER].faintCause = 0; + tvPtr->side[B_SIDE_OPPONENT].faintCause = 0; + + tvPtr->side[B_SIDE_PLAYER].faintCauseMonId = 0; + tvPtr->side[B_SIDE_OPPONENT].faintCauseMonId = 0; + + tvPtr->side[B_SIDE_PLAYER].explosionMonId = 0; + tvPtr->side[B_SIDE_OPPONENT].explosionMonId = 0; + + tvPtr->side[B_SIDE_PLAYER].explosionMoveSlot = 0; + tvPtr->side[B_SIDE_OPPONENT].explosionMoveSlot = 0; + + tvPtr->side[B_SIDE_PLAYER].explosion = 0; + tvPtr->side[B_SIDE_OPPONENT].explosion = 0; + } +} + +u8 GetBattlerMoveSlotId(u8 battlerId, u16 moveId) +{ + s32 i; + struct Pokemon *party; + + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + party = gPlayerParty; + else + party = gEnemyParty; + + i = 0; + while (1) + { + if (i >= 4) + break; + if (GetMonData(&party[gBattlerPartyIndexes[battlerId]], MON_DATA_MOVE1 + i, NULL) == moveId) + break; + i++; + } + + return i; +} + +static void AddPointsBasedOnWeather(u16 weatherFlags, u16 moveId, u8 moveSlot) +{ + if (weatherFlags & WEATHER_RAIN_ANY) + AddMovePoints(3, moveId, moveSlot, 0); + else if (weatherFlags & WEATHER_SUN_ANY) + AddMovePoints(4, moveId, moveSlot, 0); + else if (weatherFlags & WEATHER_SANDSTORM_ANY) + AddMovePoints(5, moveId, moveSlot, 0); + else if (weatherFlags & WEATHER_HAIL_ANY) + AddMovePoints(6, moveId, moveSlot, 0); +} diff --git a/src/battle_util.c b/src/battle_util.c index ddd61ae19..172ec6659 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -20,12 +20,9 @@ #include "battle_ai_script_commands.h" #include "battle_controllers.h" #include "event_data.h" -#include "calculate_base_damage.h" #include "link.h" #include "berry.h" -extern const struct BattleMove gBattleMoves[]; - extern u8 weather_get_current(void); // rom const data @@ -1666,36 +1663,31 @@ u8 CastformDataTypeChange(u8 battler) u8 formChange = 0; if (gBattleMons[battler].species != SPECIES_CASTFORM || gBattleMons[battler].ability != ABILITY_FORECAST || gBattleMons[battler].hp == 0) return CASTFORM_NO_CHANGE; - if (!WEATHER_HAS_EFFECT && gBattleMons[battler].type1 != TYPE_NORMAL && gBattleMons[battler].type2 != TYPE_NORMAL) + if (!WEATHER_HAS_EFFECT && !IS_BATTLER_OF_TYPE(battler, TYPE_NORMAL)) { - gBattleMons[battler].type1 = TYPE_NORMAL; - gBattleMons[battler].type2 = TYPE_NORMAL; + SET_BATTLER_TYPE(battler, TYPE_NORMAL); return CASTFORM_TO_NORMAL; } if (!WEATHER_HAS_EFFECT) return CASTFORM_NO_CHANGE; - if (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL)) && gBattleMons[battler].type1 != TYPE_NORMAL && gBattleMons[battler].type2 != TYPE_NORMAL) + if (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL_ANY)) && !IS_BATTLER_OF_TYPE(battler, TYPE_NORMAL)) { - gBattleMons[battler].type1 = TYPE_NORMAL; - gBattleMons[battler].type2 = TYPE_NORMAL; + SET_BATTLER_TYPE(battler, TYPE_NORMAL); formChange = CASTFORM_TO_NORMAL; } - if (gBattleWeather & WEATHER_SUN_ANY && gBattleMons[battler].type1 != TYPE_FIRE && gBattleMons[battler].type2 != TYPE_FIRE) + if (gBattleWeather & WEATHER_SUN_ANY && !IS_BATTLER_OF_TYPE(battler, TYPE_FIRE)) { - gBattleMons[battler].type1 = TYPE_FIRE; - gBattleMons[battler].type2 = TYPE_FIRE; + SET_BATTLER_TYPE(battler, TYPE_FIRE); formChange = CASTFORM_TO_FIRE; } - if (gBattleWeather & WEATHER_RAIN_ANY && gBattleMons[battler].type1 != TYPE_WATER && gBattleMons[battler].type2 != TYPE_WATER) + if (gBattleWeather & WEATHER_RAIN_ANY && !IS_BATTLER_OF_TYPE(battler, TYPE_WATER)) { - gBattleMons[battler].type1 = TYPE_WATER; - gBattleMons[battler].type2 = TYPE_WATER; + SET_BATTLER_TYPE(battler, TYPE_WATER); formChange = CASTFORM_TO_WATER; } - if (gBattleWeather & WEATHER_HAIL && gBattleMons[battler].type1 != TYPE_ICE && gBattleMons[battler].type2 != TYPE_ICE) + if (gBattleWeather & WEATHER_HAIL_ANY && !IS_BATTLER_OF_TYPE(battler, TYPE_ICE)) { - gBattleMons[battler].type1 = TYPE_ICE; - gBattleMons[battler].type2 = TYPE_ICE; + SET_BATTLER_TYPE(battler, TYPE_ICE); formChange = CASTFORM_TO_ICE; } return formChange; @@ -2025,14 +2017,12 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && move != MOVE_STRUGGLE && gBattleMoves[move].power != 0 - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) - && gBattleMons[battler].type1 != moveType - && gBattleMons[battler].type2 != moveType + && TARGET_TURN_DAMAGED + && !IS_BATTLER_OF_TYPE(battler, moveType) && gBattleMons[battler].hp != 0) { - gBattleMons[battler].type1 = moveType; - gBattleMons[battler].type2 = moveType; - PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType) + SET_BATTLER_TYPE(battler, moveType); + PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType); BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ColorChangeActivates; effect++; @@ -2042,7 +2032,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) { gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16; @@ -2057,7 +2047,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) && (Random() % 10) == 0) { @@ -2080,7 +2070,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) && (Random() % 3) == 0) { @@ -2095,7 +2085,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) && (Random() % 3) == 0) { @@ -2111,7 +2101,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (Random() % 3) == 0) { gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN; @@ -2126,7 +2116,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA && gBattleMons[gBattlerAttacker].hp != 0 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT) - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && gBattleMons[gBattlerTarget].hp != 0 && (Random() % 3) == 0 && gBattleMons[gBattlerAttacker].ability != ABILITY_OBLIVIOUS @@ -3136,7 +3126,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn) { case HOLD_EFFECT_FLINCH: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && (gSpecialStatuses[gBattlerTarget].physicalDmg || gSpecialStatuses[gBattlerTarget].specialDmg) + && TARGET_TURN_DAMAGED && (Random() % 100) < atkQuality && gBattleMoves[gCurrentMove].flags & FLAG_KINGSROCK_AFFECTED && gBattleMons[gBattlerTarget].hp) @@ -3188,14 +3178,14 @@ void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands gBattleScriptingCommandsTable[*gBattlescriptCurrInstr](); } -u8 GetMoveTarget(u16 move, u8 useMoveTarget) +u8 GetMoveTarget(u16 move, u8 setTarget) { u8 targetBank = 0; u8 moveTarget; u8 side; - if (useMoveTarget) - moveTarget = useMoveTarget - 1; + if (setTarget) + moveTarget = setTarget - 1; else moveTarget = gBattleMoves[move].target; @@ -3256,8 +3246,8 @@ u8 GetMoveTarget(u16 move, u8 useMoveTarget) else targetBank = GetBattlerAtPosition((GetBattlerPosition(gBattlerAttacker) & BIT_SIDE) ^ BIT_SIDE); break; + case MOVE_TARGET_USER_OR_SELECTED: case MOVE_TARGET_USER: - case MOVE_TARGET_x10: targetBank = gBattlerAttacker; break; } diff --git a/src/battle_util2.c b/src/battle_util2.c index c1bbabc85..1d2f1e95b 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -76,26 +76,26 @@ void FreeBattleResources(void) void AdjustFriendshipOnBattleFaint(u8 battlerId) { - u8 opposingBank; + u8 opposingBattlerId; if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) { - u8 opposingBank2; + u8 opposingBattlerId2; - opposingBank = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - opposingBank2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + opposingBattlerId2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - if (gBattleMons[opposingBank2].level > gBattleMons[opposingBank].level) - opposingBank = opposingBank2; + if (gBattleMons[opposingBattlerId2].level > gBattleMons[opposingBattlerId].level) + opposingBattlerId = opposingBattlerId2; } else { - opposingBank = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); } - if (gBattleMons[opposingBank].level > gBattleMons[battlerId].level) + if (gBattleMons[opposingBattlerId].level > gBattleMons[battlerId].level) { - if (gBattleMons[opposingBank].level - gBattleMons[battlerId].level > 29) + if (gBattleMons[opposingBattlerId].level - gBattleMons[battlerId].level > 29) AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battlerId]], 8); else AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battlerId]], 6); diff --git a/src/berry.c b/src/berry.c index 74b7090c0..e128eb0ec 100644 --- a/src/berry.c +++ b/src/berry.c @@ -1218,7 +1218,7 @@ void FieldObjectInteractionRemoveBerryTree(void) u8 PlayerHasBerries(void) { - return IsBagPocketNonEmpty(BAG_BERRIES); + return IsBagPocketNonEmpty(POCKET_BERRIES); } void ResetBerryTreeSparkleFlags(void) diff --git a/src/berry_blender.c b/src/berry_blender.c index 848798442..48034a8c2 100644 --- a/src/berry_blender.c +++ b/src/berry_blender.c @@ -29,6 +29,8 @@ #include "pokeblock.h" #include "trig.h" #include "tv.h" +#include "item_menu.h" +#include "battle_records.h" #define BLENDER_SCORE_BEST 0 #define BLENDER_SCORE_GOOD 1 @@ -128,10 +130,8 @@ struct BerryBlenderData extern struct MusicPlayerInfo gMPlayInfo_SE2; extern struct MusicPlayerInfo gMPlayInfo_BGM; -extern u16 gSpecialVar_ItemId; extern u8 gInGameOpponentsNo; extern u8 gUnknown_020322D5; -extern u8 gResultsWindowId; // graphics extern const u8 gBerryBlenderArrowTiles[]; @@ -152,10 +152,12 @@ extern const u8 gText_BlenderMaxSpeedRecord[]; extern const u8 gText_234Players[]; extern void sub_800A418(void); +extern u8 sub_800A9D8(void); extern void sub_809882C(u8, u16, u8); extern void copy_textbox_border_tile_patterns_to_vram(u8, u16, u8); extern void sub_81AABF0(void (*callback)(void)); extern void sub_800B4C0(void); +extern void ClearLinkCallback(void); extern void sub_8009F8C(void); extern void sub_8153430(void); extern bool8 sub_8153474(void); @@ -947,10 +949,10 @@ static void sub_807FAC8(void) sBerryBlenderData->syncArrowSpriteIds[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSpriteIds[i]], i + 8); } - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } SetVBlankCallback(VBlankCB0_BerryBlender); sBerryBlenderData->mainState++; @@ -1153,10 +1155,10 @@ static void sub_8080018(void) sBerryBlenderData->syncArrowSprite2Ids[i] = CreateSprite(&sBlenderSyncArrow_SpriteTemplate, sBlenderSyncArrowsPos[i][0], sBlenderSyncArrowsPos[i][1], 1); StartSpriteAnim(&gSprites[sBerryBlenderData->syncArrowSprite2Ids[i]], i + 8); } - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } sBerryBlenderData->mainState++; break; @@ -1869,7 +1871,7 @@ static void sub_8081370(u16 a0) static bool32 sub_80814B0(u16 arg0, u16 arg1, u16 arg2) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { if ((arg0 & 0xFF00) == arg2) return TRUE; @@ -2311,7 +2313,7 @@ static void sub_8081E20(void) static void sub_8081F94(u16 *a0) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) *a0 = 0x2F00; else *a0 = 0x2FFF; @@ -2340,7 +2342,7 @@ static void CB2_HandleBlenderEndGame(void) sBerryBlenderData->field_4C -= 32; if (sBerryBlenderData->field_4C <= 0) { - sub_8009F8C(); + ClearLinkCallback(); sBerryBlenderData->field_4C = 0; if (gReceivedRemoteLinkPlayers != 0) @@ -2360,7 +2362,7 @@ static void CB2_HandleBlenderEndGame(void) } else if (sub_800A520()) { - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { sBerryBlenderData->gameBlock.timeRPM.time = sBerryBlenderData->gameFrameTime; sBerryBlenderData->gameBlock.timeRPM.max_RPM = sBerryBlenderData->max_RPM; @@ -2389,7 +2391,7 @@ static void CB2_HandleBlenderEndGame(void) ResetBlockReceivedFlags(); sBerryBlenderData->gameEndState++; - if (gReceivedRemoteLinkPlayers != 0 && gLinkVSyncDisabled) + if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType) { struct BlenderGameBlock *receivedBlock = (struct BlenderGameBlock*)(&gBlockRecvBuffer); @@ -2469,7 +2471,7 @@ static void CB2_HandleBlenderEndGame(void) sub_8081F94(&gSendCmd[0]); if (sBerryBlenderData->yesNoAnswer == 0) { - if (IsBagPocketNonEmpty(BAG_BERRIES) == FALSE) // no berries + if (IsBagPocketNonEmpty(POCKET_BERRIES) == FALSE) // no berries { sBerryBlenderData->playAgainState = CANT_PLAY_NO_BERRIES; gSendCmd[1] = 0x9999; @@ -2687,7 +2689,7 @@ static void CB2_HandlePlayerLinkPlayAgainChoice(void) if (gReceivedRemoteLinkPlayers == 0) { FREE_AND_SET_NULL(sBerryBlenderData); - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } break; } @@ -2737,7 +2739,7 @@ static void CB2_HandlePlayerPlayAgainChoice(void) if (sBerryBlenderData->playAgainState == PLAY_AGAIN_OK) SetMainCallback2(DoBerryBlending); else - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); FreeAllWindowBuffers(); UnsetBgTilemapBuffer(2); @@ -2866,7 +2868,7 @@ static void sub_8082D28(void) if (gReceivedRemoteLinkPlayers != 0) playerId = GetMultiplayerId(); - if (gLinkVSyncDisabled && gReceivedRemoteLinkPlayers != 0) + if (gWirelessCommType && gReceivedRemoteLinkPlayers != 0) { if (playerId == 0) { @@ -3482,13 +3484,13 @@ void ShowBerryBlenderRecordWindow(void) u8 text[32]; winTemplate = sBlenderRecordWindowTemplate; - gResultsWindowId = AddWindow(&winTemplate); - NewMenuHelpers_DrawStdWindowFrame(gResultsWindowId, 0); - FillWindowPixelBuffer(gResultsWindowId, 0x11); + gRecordsWindowId = AddWindow(&winTemplate); + NewMenuHelpers_DrawStdWindowFrame(gRecordsWindowId, 0); + FillWindowPixelBuffer(gRecordsWindowId, 0x11); xPos = GetStringCenterAlignXOffset(1, gText_BlenderMaxSpeedRecord, 0x90); - PrintTextOnWindow(gResultsWindowId, 1, gText_BlenderMaxSpeedRecord, xPos, 1, 0, NULL); - PrintTextOnWindow(gResultsWindowId, 1, gText_234Players, 4, 0x29, 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, gText_BlenderMaxSpeedRecord, xPos, 1, 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, gText_234Players, 4, 0x29, 0, NULL); for (i = 0, yPos = 0x29; i < BLENDER_SCORES_NO; i++) { @@ -3503,11 +3505,11 @@ void ShowBerryBlenderRecordWindow(void) txtPtr = StringAppend(txtPtr, sText_RPM); xPos = GetStringRightAlignXOffset(1, text, 0x8C); - PrintTextOnWindow(gResultsWindowId, 1, text, xPos, yPos + (i * 16), 0, NULL); + PrintTextOnWindow(gRecordsWindowId, 1, text, xPos, yPos + (i * 16), 0, NULL); } - PutWindowTilemap(gResultsWindowId); - CopyWindowToVram(gResultsWindowId, 3); + PutWindowTilemap(gRecordsWindowId); + CopyWindowToVram(gRecordsWindowId, 3); } static void sub_8083F3C(u8 taskId) diff --git a/src/berry_tag_screen.c b/src/berry_tag_screen.c index f86f350bf..9a6e78c81 100644 --- a/src/berry_tag_screen.c +++ b/src/berry_tag_screen.c @@ -515,9 +515,9 @@ static void Task_HandleInput(u8 taskId) static void TryChangeDisplayedBerry(u8 taskId, s8 toMove) { s16 *data = gTasks[taskId].data; - s16 currPocketPosition = gUnknown_0203CE58.unk12[3] + gUnknown_0203CE58.unk8[3]; + s16 currPocketPosition = gUnknown_0203CE58.scrollPosition[3] + gUnknown_0203CE58.cursorPosition[3]; u32 newPocketPosition = currPocketPosition + toMove; - if (newPocketPosition < 46 && BagGetItemIdByPocketPosition(BAG_BERRIES, newPocketPosition) != 0) + if (newPocketPosition < 46 && BagGetItemIdByPocketPosition(POCKET_BERRIES, newPocketPosition) != 0) { if (toMove < 0) data[1] = 2; @@ -533,11 +533,11 @@ static void TryChangeDisplayedBerry(u8 taskId, s8 toMove) static void HandleBagCursorPositionChange(s8 toMove) { - u16 *scrollPos = &gUnknown_0203CE58.unk12[3]; - u16 *cursorPos = &gUnknown_0203CE58.unk8[3]; + u16 *scrollPos = &gUnknown_0203CE58.scrollPosition[3]; + u16 *cursorPos = &gUnknown_0203CE58.cursorPosition[3]; if (toMove > 0) { - if (*cursorPos < 4 || BagGetItemIdByPocketPosition(BAG_BERRIES, *scrollPos + 8) == 0) + if (*cursorPos < 4 || BagGetItemIdByPocketPosition(POCKET_BERRIES, *scrollPos + 8) == 0) *cursorPos += toMove; else *scrollPos += toMove; @@ -550,7 +550,7 @@ static void HandleBagCursorPositionChange(s8 toMove) *scrollPos += toMove; } - sBerryTag->berryId = ItemIdToBerryType(BagGetItemIdByPocketPosition(BAG_BERRIES, *scrollPos + *cursorPos)); + sBerryTag->berryId = ItemIdToBerryType(BagGetItemIdByPocketPosition(POCKET_BERRIES, *scrollPos + *cursorPos)); } static void Task_DisplayAnotherBerry(u8 taskId) @@ -463,7 +463,7 @@ bool8 IsDma3ManagerBusyWithBgCopy(void) return FALSE; } #else -__attribute__((naked)) +NAKED bool8 IsDma3ManagerBusyWithBgCopy(void) { asm("push {r4-r7,lr}\n\ @@ -965,9 +965,9 @@ void CopyBgTilemapBufferToVram(u8 bg) } } -void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u8 height) +void CopyToBgTilemapBufferRect(u8 bg, const void* src, u8 destX, u8 destY, u8 width, u8 height) { - void* srcCopy; + const void* srcCopy; u16 destX16; u16 destY16; u16 mode; @@ -1048,7 +1048,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8 } } }*/ -__attribute__((naked)) +NAKED void CopyRectToBgTilemapBufferRect(u8 bg, const void* src, u8 srcX, u8 srcY, u8 srcWidth, u8 srcHeight, u8 destX, u8 destY, u8 rectWidth, u8 rectHeight, u8 palette1, u16 tileOffset, u16 palette2) { asm("push {r4-r7,lr}\n\ @@ -1495,7 +1495,7 @@ void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 pal *dest = test; } #else -__attribute__((naked)) +NAKED void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 palette2) { asm("push {r4-r6,lr}\n\ diff --git a/src/bike.c b/src/bike.c index 64af7c711..e827707cd 100644 --- a/src/bike.c +++ b/src/bike.c @@ -12,9 +12,7 @@ extern bool8 gBikeCyclingChallenge; extern u8 gBikeCollisions; -extern bool8 gUnknown_02037348; -extern u8 sub_8093514(u8 direction); extern u8 sub_808B980(u8 direction); extern u8 sub_808B9BC(u8 direction); extern u8 sub_808B9A4(u8 direction); @@ -989,7 +987,7 @@ bool8 player_should_look_direction_be_enforced_upon_movement(void) void GetOnOffBike(u8 transitionFlags) { - gUnknown_02037348 = FALSE; + gUnusedBikeCameraAheadPanback = FALSE; if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) { diff --git a/src/birch_pc.c b/src/birch_pc.c new file mode 100644 index 000000000..3148832be --- /dev/null +++ b/src/birch_pc.c @@ -0,0 +1,89 @@ +#include "global.h" +#include "event_data.h" +#include "field_message_box.h" +#include "pokedex.h" +#include "constants/species.h" +#include "strings.h" + +bool16 ScriptGetPokedexInfo(void) +{ + if (gSpecialVar_0x8004 == 0) // is national dex not present? + { + gSpecialVar_0x8005 = GetHoennPokedexCount(0); + gSpecialVar_0x8006 = GetHoennPokedexCount(1); + } + else + { + gSpecialVar_0x8005 = GetNationalPokedexCount(0); + gSpecialVar_0x8006 = GetNationalPokedexCount(1); + } + + return IsNationalPokedexEnabled(); +} + +// This shows your Hoenn Pokedex rating and not your National Dex. +const u8 *GetPokedexRatingText(u16 count) +{ + if (count < 10) + return gBirchDexRatingText_LessThan10; + if (count < 20) + return gBirchDexRatingText_LessThan20; + if (count < 30) + return gBirchDexRatingText_LessThan30; + if (count < 40) + return gBirchDexRatingText_LessThan40; + if (count < 50) + return gBirchDexRatingText_LessThan50; + if (count < 60) + return gBirchDexRatingText_LessThan60; + if (count < 70) + return gBirchDexRatingText_LessThan70; + if (count < 80) + return gBirchDexRatingText_LessThan80; + if (count < 90) + return gBirchDexRatingText_LessThan90; + if (count < 100) + return gBirchDexRatingText_LessThan100; + if (count < 110) + return gBirchDexRatingText_LessThan110; + if (count < 120) + return gBirchDexRatingText_LessThan120; + if (count < 130) + return gBirchDexRatingText_LessThan130; + if (count < 140) + return gBirchDexRatingText_LessThan140; + if (count < 150) + return gBirchDexRatingText_LessThan150; + if (count < 160) + return gBirchDexRatingText_LessThan160; + if (count < 170) + return gBirchDexRatingText_LessThan170; + if (count < 180) + return gBirchDexRatingText_LessThan180; + if (count < 190) + return gBirchDexRatingText_LessThan190; + if (count < 200) + return gBirchDexRatingText_LessThan200; + if (count == 200) + { + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_JIRACHI), 1) + || GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_DEOXYS), 1)) // Jirachi or Deoxys is not counted towards the dex completion. If either of these flags are enabled, it means the actual count is less than 200. + return gBirchDexRatingText_LessThan200; + return gBirchDexRatingText_DexCompleted; + } + if (count == 201) + { + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_JIRACHI), 1) + && GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_DEOXYS), 1)) // If both of these flags are enabled, it means the actual count is less than 200. + return gBirchDexRatingText_LessThan200; + return gBirchDexRatingText_DexCompleted; + } + if (count == 202) + return gBirchDexRatingText_DexCompleted; // Hoenn dex is considered complete, even though the hoenn dex count is 210. + return gBirchDexRatingText_LessThan10; +} + +void ShowPokedexRatingMessage(void) +{ + ShowFieldMessage(GetPokedexRatingText(gSpecialVar_0x8004)); +} diff --git a/src/blit.c b/src/blit.c new file mode 100644 index 000000000..b4d5f7de5 --- /dev/null +++ b/src/blit.c @@ -0,0 +1,209 @@ +#include "global.h" +#include "blit.h" + +void BlitBitmapRect4BitWithoutColorKey(struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height) +{ + BlitBitmapRect4Bit(src, dst, srcX, srcY, dstX, dstY, width, height, 0xFF); +} + +void BlitBitmapRect4Bit(struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey) +{ + s32 xEnd; + s32 yEnd; + s32 multiplierSrcY; + s32 multiplierDstY; + s32 loopSrcY, loopDstY; + s32 loopSrcX, loopDstX; + u8 *pixelsSrc; + u8 *pixelsDst; + s32 toOrr; + s32 toAnd; + s32 toShift; + + if (dst->width - dstX < width) + xEnd = (dst->width - dstX) + srcX; + else + xEnd = srcX + width; + + if (dst->height - dstY < height) + yEnd = (dst->height - dstY) + srcY; + else + yEnd = height + srcY; + + multiplierSrcY = (src->width + (src->width & 7)) >> 3; + multiplierDstY = (dst->width + (dst->width & 7)) >> 3; + + if (colorKey == 0xFF) + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B); + pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B); + toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF); + toShift = ((loopDstX & 1) << 2); + toOrr <<= toShift; + toAnd = 0xF0 >> (toShift); + *pixelsDst = toOrr | (*pixelsDst & toAnd); + } + } + } + else + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B); + pixelsDst = dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + (((loopDstY >> 3) * multiplierDstY) << 5) + ((u32)(loopDstY << 0x1d) >> 0x1B); + toOrr = ((*pixelsSrc >> ((loopSrcX & 1) << 2)) & 0xF); + if (toOrr != colorKey) + { + toShift = ((loopDstX & 1) << 2); + toOrr <<= toShift; + toAnd = 0xF0 >> (toShift); + *pixelsDst = toOrr | (*pixelsDst & toAnd); + } + } + } + } +} + +void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue) +{ + s32 xEnd; + s32 yEnd; + s32 multiplierY; + s32 loopX, loopY; + s32 toOrr1, toOrr2; + + xEnd = x + width; + if (xEnd > surface->width) + xEnd = surface->width; + + yEnd = y + height; + if (yEnd > surface->height) + yEnd = surface->height; + + multiplierY = (surface->width + (surface->width & 7)) >> 3; + toOrr1 = (u32)(fillValue << 0x1C) >> 0x18; + toOrr2 = (fillValue & 0xF); + + for (loopY = y; loopY < yEnd; loopY++) + { + for (loopX = x; loopX < xEnd; loopX++) + { + u8 *pixels = surface->pixels + ((loopX >> 1) & 3) + ((loopX >> 3) << 5) + (((loopY >> 3) * multiplierY) << 5) + ((u32)(loopY << 0x1d) >> 0x1B); + if ((loopX << 0x1F) != 0) + *pixels = toOrr1 | (*pixels & 0xF); + else + *pixels = toOrr2 | (*pixels & 0xF0); + } + } +} + +void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height, u8 colorKey, u8 paletteOffset) +{ + s32 palOffsetBits; + s32 xEnd; + s32 yEnd; + s32 multiplierSrcY; + s32 multiplierDstY; + s32 loopSrcY, loopDstY; + s32 loopSrcX, loopDstX; + u8 *pixelsSrc; + u8 *pixelsDst; + s32 colorKeyBits; + + palOffsetBits = (u32)(paletteOffset << 0x1C) >> 0x18; + colorKeyBits = (u32)(colorKey << 0x1C) >> 0x18; + + if (dst->width - dstX < width) + xEnd = (dst->width - dstX) + srcX; + else + xEnd = width + srcX; + + if (dst->height - dstY < height) + yEnd = (srcY + dst->height) - dstY; + else + yEnd = srcY + height; + + multiplierSrcY = (src->width + (src->width & 7)) >> 3; + multiplierDstY = (dst->width + (dst->width & 7)) >> 3; + + if (colorKey == 0xFF) + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b); + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a); + if (loopSrcX & 1) + { + *pixelsDst = palOffsetBits + (*pixelsSrc >> 4); + } + else + { + pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b); + *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF); + } + } + } + } + else + { + for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++) + { + pixelsSrc = src->pixels + ((srcX >> 1) & 3) + ((srcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b); + for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++) + { + if (loopSrcX & 1) + { + if ((*pixelsSrc & 0xF0) != colorKeyBits) + { + pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a); + *pixelsDst = palOffsetBits + (*pixelsSrc >> 4); + } + } + else + { + pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1b); + if ((*pixelsSrc & 0xF) != colorKey) + { + pixelsDst = dst->pixels + (loopDstX & 7) + ((loopDstX >> 3) << 6) + (((loopDstY >> 3) * multiplierDstY) << 6) + ((u32)(loopDstY << 0x1d) >> 0x1a); + *pixelsDst = palOffsetBits + (*pixelsSrc & 0xF); + } + } + } + } + } +} + +void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue) +{ + s32 xEnd; + s32 yEnd; + s32 multiplierY; + s32 loopX, loopY; + + xEnd = x + width; + if (xEnd > surface->width) + xEnd = surface->width; + + yEnd = y + height; + if (yEnd > surface->height) + yEnd = surface->height; + + multiplierY = (surface->width + (surface->width & 7)) >> 3; + + for (loopY = y; loopY < yEnd; loopY++) + { + for (loopX = x; loopX < xEnd; loopX++) + { + u8 *pixels = surface->pixels + (loopX & 7) + ((loopX >> 3) << 6) + (((loopY >> 3) * multiplierY) << 6) + ((u32)(loopY << 0x1d) >> 0x1a); + *pixels = fillValue; + } + } +} diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c index d6924de9f..35277fe87 100644 --- a/src/braille_puzzles.c +++ b/src/braille_puzzles.c @@ -25,7 +25,7 @@ enum }; extern u8 gBraillePuzzleCallbackFlag; -extern u8 gUnknown_085EFE74[][2]; +extern const u8 gUnknown_085EFE74[][2]; void SealedChamberShakingEffect(u8); void sub_8179860(void); @@ -375,37 +375,49 @@ bool8 FldEff_UsePuzzleEffect(void) return FALSE; } -// can't get this one to match due to the weird macro-like varsets with strange bitshifting. -// to note: 0x10000 is loaded in, and its obviously supposed to be 1, but i cant get 0x80 << 9 to be loaded in without using it directly. -// maybe there's some way of writing it that works? -#ifdef NONMATCHING -// ShouldDoBrailleRegicePuzzle bool8 ShouldDoBrailleRegicePuzzle(void) { u8 i; - if (gSaveBlock1Ptr->location.mapGroup == 0x18 && gSaveBlock1Ptr->location.mapNum == 0x43) + if (gSaveBlock1Ptr->location.mapGroup == 0x18 + && gSaveBlock1Ptr->location.mapNum == 0x43) { - // _08179A1A if (FlagGet(FLAG_SYS_BRAILLE_WAIT) != FALSE) return FALSE; - if (FlagGet(2) == FALSE) + if (FlagGet(FLAG_0x002) == FALSE) return FALSE; - if (FlagGet(3) == TRUE) + if (FlagGet(FLAG_0x003) == TRUE) return FALSE; for (i = 0; i < 36; i++) { - if (gSaveBlock1Ptr->pos.x == gUnknown_085EFE74[i][0] && gSaveBlock1Ptr->pos.y == gUnknown_085EFE74[i][1]) + u8 xPos = gUnknown_085EFE74[i][0]; + u8 yPos = gUnknown_085EFE74[i][1]; + if (gSaveBlock1Ptr->pos.x == xPos && gSaveBlock1Ptr->pos.y == yPos) { + u16 varValue; + if (i < 16) - VarSet(0x403B, (0x10000 << i | VarGet(0x403B) << 16) >> 16); // correct + { + u16 val = VarGet(0x403B); + val |= 1 << i; + VarSet(0x403B, val); + } else if (i < 32) - VarSet(0x403C, (0x10000 << (i - 16) | VarGet(0x403C) << 16) >> 16); // hmm? + { + u16 val = VarGet(0x403C); + val |= 1 << (i - 16); + VarSet(0x403C, val); + } else - VarSet(0x403D, (0x10000 << (i - 32) | VarGet(0x403D) << 16) >> 16); // hmm? - - if (VarGet(0x403B) != 0xFFFF || VarGet(0x403C) != 0xFF || VarGet(0x403D) != 0xF) + { + u16 val = VarGet(0x403D); + val |= 1 << (i - 32); + VarSet(0x403D, val); + } + + varValue = VarGet(0x403B); + if (varValue != 0xFFFF || VarGet(0x403C) != varValue || VarGet(0x403D) != 0xF) return FALSE; if (gSaveBlock1Ptr->pos.x == 8 && gSaveBlock1Ptr->pos.y == 21) @@ -414,170 +426,10 @@ bool8 ShouldDoBrailleRegicePuzzle(void) return FALSE; } } + + FlagSet(FLAG_0x003); + FlagClear(FLAG_0x002); } - // TODO: Find what flags 2 and 3 are. - FlagSet(3); - FlagClear(2); + return FALSE; } -#else -__attribute__((naked)) -bool8 ShouldDoBrailleRegicePuzzle(void) -{ - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r9\n\ - mov r6, r8\n\ - push {r6,r7}\n\ - ldr r4, =gSaveBlock1Ptr\n\ - ldr r0, [r4]\n\ - ldrh r1, [r0, 0x4]\n\ - ldr r0, =0x00004318\n\ - cmp r1, r0\n\ - beq _08179A1A\n\ - b _08179B5A\n\ -_08179A1A:\n\ - ldr r0, =0x000008b1\n\ - bl FlagGet\n\ - lsls r0, 24\n\ - cmp r0, 0\n\ - beq _08179A28\n\ - b _08179B5A\n\ -_08179A28:\n\ - movs r0, 0x2\n\ - bl FlagGet\n\ - lsls r0, 24\n\ - cmp r0, 0\n\ - bne _08179A36\n\ - b _08179B5A\n\ -_08179A36:\n\ - movs r0, 0x3\n\ - bl FlagGet\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - cmp r0, 0x1\n\ - bne _08179A58\n\ - b _08179B5A\n\ - .pool\n\ -_08179A54:\n\ - movs r0, 0x1\n\ - b _08179B5C\n\ -_08179A58:\n\ - movs r5, 0\n\ - mov r8, r4\n\ - ldr r4, =gUnknown_085EFE74\n\ - adds r0, r4, 0x1\n\ - mov r12, r0\n\ - ldr r6, =0x0000403b\n\ - ldr r1, =0x0000403c\n\ - mov r9, r1\n\ -_08179A68:\n\ - lsls r0, r5, 1\n\ - adds r1, r0, r4\n\ - add r0, r12\n\ - ldrb r3, [r0]\n\ - mov r7, r8\n\ - ldr r2, [r7]\n\ - movs r7, 0\n\ - ldrsh r0, [r2, r7]\n\ - ldrb r1, [r1]\n\ - cmp r0, r1\n\ - bne _08179B44\n\ - movs r1, 0x2\n\ - ldrsh r0, [r2, r1]\n\ - cmp r0, r3\n\ - bne _08179B44\n\ - cmp r5, 0xF\n\ - bhi _08179AB0\n\ - adds r0, r6, 0\n\ - bl VarGet\n\ - lsls r0, 16\n\ - movs r1, 0x80\n\ - lsls r1, 9\n\ - lsls r1, r5\n\ - orrs r1, r0\n\ - lsrs r1, 16\n\ - adds r0, r6, 0\n\ - bl VarSet\n\ - b _08179AF0\n\ - .pool\n\ -_08179AB0:\n\ - cmp r5, 0x1F\n\ - bhi _08179AD2\n\ - mov r0, r9\n\ - bl VarGet\n\ - lsls r0, 16\n\ - adds r2, r5, 0\n\ - subs r2, 0x10\n\ - movs r1, 0x80\n\ - lsls r1, 9\n\ - lsls r1, r2\n\ - orrs r1, r0\n\ - lsrs r1, 16\n\ - mov r0, r9\n\ - bl VarSet\n\ - b _08179AF0\n\ -_08179AD2:\n\ - ldr r4, =0x0000403d\n\ - adds r0, r4, 0\n\ - bl VarGet\n\ - lsls r0, 16\n\ - adds r2, r5, 0\n\ - subs r2, 0x20\n\ - movs r1, 0x80\n\ - lsls r1, 9\n\ - lsls r1, r2\n\ - orrs r1, r0\n\ - lsrs r1, 16\n\ - adds r0, r4, 0\n\ - bl VarSet\n\ -_08179AF0:\n\ - ldr r0, =0x0000403b\n\ - bl VarGet\n\ - lsls r0, 16\n\ - lsrs r4, r0, 16\n\ - ldr r0, =0x0000ffff\n\ - cmp r4, r0\n\ - bne _08179B5A\n\ - ldr r0, =0x0000403c\n\ - bl VarGet\n\ - lsls r0, 16\n\ - lsrs r0, 16\n\ - cmp r0, r4\n\ - bne _08179B5A\n\ - ldr r0, =0x0000403d\n\ - bl VarGet\n\ - lsls r0, 16\n\ - lsrs r0, 16\n\ - cmp r0, 0xF\n\ - bne _08179B5A\n\ - ldr r0, =gSaveBlock1Ptr\n\ - ldr r0, [r0]\n\ - ldr r1, [r0]\n\ - ldr r0, =0x00150008\n\ - cmp r1, r0\n\ - beq _08179A54\n\ - b _08179B5A\n\ - .pool\n\ -_08179B44:\n\ - adds r0, r5, 0x1\n\ - lsls r0, 24\n\ - lsrs r5, r0, 24\n\ - cmp r5, 0x23\n\ - bls _08179A68\n\ - movs r0, 0x3\n\ - bl FlagSet\n\ - movs r0, 0x2\n\ - bl FlagClear\n\ -_08179B5A:\n\ - movs r0, 0\n\ -_08179B5C:\n\ - pop {r3,r4}\n\ - mov r8, r3\n\ - mov r9, r4\n\ - pop {r4-r7}\n\ - pop {r1}\n\ - bx r1\n\ - .syntax divided"); -} -#endif diff --git a/src/calculate_base_damage.c b/src/calculate_base_damage.c deleted file mode 100644 index 98468caa2..000000000 --- a/src/calculate_base_damage.c +++ /dev/null @@ -1,275 +0,0 @@ -#include "global.h" -#include "constants/abilities.h" -#include "battle.h" -#include "battle_setup.h" -#include "constants/hold_effects.h" -#include "event_data.h" -#include "item.h" -#include "constants/items.h" -#include "pokemon.h" -#include "constants/species.h" -#include "constants/moves.h" -#include "constants/battle_move_effects.h" - -bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank); - -extern const struct BattleMove gBattleMoves[]; -extern const u8 gHoldEffectToType[][2]; -extern const u8 gStatStageRatios[][2]; - -#define APPLY_STAT_MOD(var, mon, stat, statIndex) \ -{ \ - (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \ - (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \ -} - -s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef) -{ - u32 i; - s32 damage = 0; - s32 damageHelper; - u8 type; - u16 attack, defense; - u16 spAttack, spDefense; - u8 defenderHoldEffect; - u8 defenderHoldEffectParam; - u8 attackerHoldEffect; - u8 attackerHoldEffectParam; - - if (!powerOverride) - gBattleMovePower = gBattleMoves[move].power; - else - gBattleMovePower = powerOverride; - - if (!typeOverride) - type = gBattleMoves[move].type; - else - type = typeOverride & 0x3F; - - attack = attacker->attack; - defense = defender->defense; - spAttack = attacker->spAttack; - spDefense = defender->spDefense; - - if (attacker->item == ITEM_ENIGMA_BERRY) - { - attackerHoldEffect = gEnigmaBerries[bankAtk].holdEffect; - attackerHoldEffectParam = gEnigmaBerries[bankAtk].holdEffectParam; - } - else - { - attackerHoldEffect = ItemId_GetHoldEffect(attacker->item); - attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item); - } - - if (defender->item == ITEM_ENIGMA_BERRY) - { - defenderHoldEffect = gEnigmaBerries[bankDef].holdEffect; - defenderHoldEffectParam = gEnigmaBerries[bankDef].holdEffectParam; - } - else - { - defenderHoldEffect = ItemId_GetHoldEffect(defender->item); - defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item); - } - - if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER) - attack *= 2; - - if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, bankAtk)) - attack = (110 * attack) / 100; - if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, bankDef)) - defense = (110 * defense) / 100; - if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankAtk)) - spAttack = (110 * spAttack) / 100; - if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, bankDef)) - spDefense = (110 * spDefense) / 100; - - for (i = 0; i < 17; i++) - { - if (attackerHoldEffect == gHoldEffectToType[i][0] - && type == gHoldEffectToType[i][1]) - { - if (type <= 8) - attack = (attack * (attackerHoldEffectParam + 100)) / 100; - else - spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100; - break; - } - } - - if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND) - attack = (150 * attack) / 100; - if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS)) - spAttack = (150 * spAttack) / 100; - if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS)) - spDefense = (150 * spDefense) / 100; - if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL) - spAttack *= 2; - if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL) - spDefense *= 2; - if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU) - spAttack *= 2; - if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO) - defense *= 2; - if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK)) - attack *= 2; - if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE)) - spAttack /= 2; - if (attacker->ability == ABILITY_HUSTLE) - attack = (150 * attack) / 100; - if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0)) - spAttack = (150 * spAttack) / 100; - if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0)) - spAttack = (150 * spAttack) / 100; - if (attacker->ability == ABILITY_GUTS && attacker->status1) - attack = (150 * attack) / 100; - if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1) - defense = (150 * defense) / 100; - if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0)) - gBattleMovePower /= 2; - if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0)) - gBattleMovePower /= 2; - if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3)) - gBattleMovePower = (150 * gBattleMovePower) / 100; - if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3)) - gBattleMovePower = (150 * gBattleMovePower) / 100; - if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3)) - gBattleMovePower = (150 * gBattleMovePower) / 100; - if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3)) - gBattleMovePower = (150 * gBattleMovePower) / 100; - if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) - defense /= 2; - - if (IS_MOVE_PHYSICAL(type)) - { - if (gCritMultiplier == 2) - { - if (attacker->statStages[STAT_ATK] > 6) - APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK) - else - damage = attack; - } - else - APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK) - - damage = damage * gBattleMovePower; - damage *= (2 * attacker->level / 5 + 2); - - if (gCritMultiplier == 2) - { - if (defender->statStages[STAT_DEF] < 6) - APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF) - else - damageHelper = defense; - } - else - APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF) - - damage = damage / damageHelper; - damage /= 50; - - if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS) - damage /= 2; - - if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1) - { - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) - damage = 2 * (damage / 3); - else - damage /= 2; - } - - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) - damage /= 2; - - // moves always do at least 1 damage. - if (damage == 0) - damage = 1; - } - - if (type == TYPE_MYSTERY) - damage = 0; // is ??? type. does 0 damage. - - if (IS_MOVE_SPECIAL(type)) - { - if (gCritMultiplier == 2) - { - if (attacker->statStages[STAT_SPATK] > 6) - APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK) - else - damage = spAttack; - } - else - APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK) - - damage = damage * gBattleMovePower; - damage *= (2 * attacker->level / 5 + 2); - - if (gCritMultiplier == 2) - { - if (defender->statStages[STAT_SPDEF] < 6) - APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF) - else - damageHelper = spDefense; - } - else - APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF) - - damage = (damage / damageHelper); - damage /= 50; - - if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1) - { - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) - damage = 2 * (damage / 3); - else - damage /= 2; - } - - if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) - damage /= 2; - - // are effects of weather negated with cloud nine or air lock - if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0) - && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0)) - { - if (gBattleWeather & WEATHER_RAIN_TEMPORARY) - { - switch (type) - { - case TYPE_FIRE: - damage /= 2; - break; - case TYPE_WATER: - damage = (15 * damage) / 10; - break; - } - } - - // any weather except sun weakens solar beam - if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM) - damage /= 2; - - // sunny - if (gBattleWeather & WEATHER_SUN_ANY) - { - switch (type) - { - case TYPE_FIRE: - damage = (15 * damage) / 10; - break; - case TYPE_WATER: - damage /= 2; - break; - } - } - } - - // flash fire triggered - if ((gBattleResources->flags->flags[bankAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE) - damage = (15 * damage) / 10; - } - - return damage + 2; -} diff --git a/src/clear_save_data_screen.c b/src/clear_save_data_screen.c index 6d6a1545b..ca2037d2f 100644 --- a/src/clear_save_data_screen.c +++ b/src/clear_save_data_screen.c @@ -14,8 +14,6 @@ extern u8 gText_ClearAllSaveData[]; extern u8 gText_ClearingData[]; -extern u16 gUnknown_0860F074[]; - static void Task_DoClearSaveDataScreenYesNo(u8); static void Task_ClearSaveDataScreenYesNoChoice(u8); static void Task_ClearSaveData(u8); diff --git a/src/clock.c b/src/clock.c index 7cea30166..71c433ed2 100644 --- a/src/clock.c +++ b/src/clock.c @@ -83,7 +83,7 @@ static void UpdatePerMinute(struct Time *localTime) static void ReturnFromStartWallClock(void) { InitTimeBasedEvents(); - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } void StartWallClock(void) diff --git a/src/credits.c b/src/credits.c new file mode 100644 index 000000000..168f3e8a3 --- /dev/null +++ b/src/credits.c @@ -0,0 +1,2355 @@ +#include "global.h" +#include "palette.h" +#include "main.h" +#include "task.h" +#include "bg.h" +#include "malloc.h" +#include "window.h" +#include "text.h" +#include "menu.h" +#include "international_string_util.h" +#include "constants/songs.h" +#include "gpu_regs.h" +#include "m4a.h" +#include "constants/rgb.h" +#include "battle_dome_cards.h" +#include "starter_choose.h" +#include "decompress.h" +#include "intro_credits_graphics.h" +#include "sound.h" +#include "trig.h" +#include "graphics.h" +#include "pokedex.h" +#include "constants/vars.h" +#include "event_data.h" +#include "random.h" + +enum +{ + PAGE_TITLE, + PAGE_DIRECTOR, + PAGE_ART_DIRECTOR, + PAGE_WORLD_DIRECTOR, + PAGE_LEAD_PROGRAMMER, + PAGE_PROGRAMMERS_1, + PAGE_PROGRAMMERS_2, + PAGE_PROGRAMMERS_3, + PAGE_PROGRAMMERS_4, + PAGE_GRAPHIC_DESIGNERS_1, + PAGE_GRAPHIC_DESIGNERS_2, + PAGE_GRAPHIC_DESIGNERS_3, + PAGE_MUSIC_COMPOSITION, + PAGE_SOUND_EFFECTS, + PAGE_GAME_DESIGNERS_1, + PAGE_GAME_DESIGNERS_2, + PAGE_GAME_DESIGNERS_3, + PAGE_SCENARIO_PLOT, + PAGE_SCENARIO, + PAGE_SCRIPT_DESIGNERS, + PAGE_MAP_DESIGNERS, + PAGE_BATTLE_FRONTIER_DATA, + PAGE_PARAMETRIC_DESIGNERS, + PAGE_POKEDEX_TEXT, + PAGE_ENVIRONMENT_AND_TOOL_PROGRAMS_1, + PAGE_PKMN_DESIGNERS_1, + PAGE_PKMN_DESIGNERS_2, + PAGE_PKMN_DESIGNERS_3, + PAGE_PKMN_DESIGNERS_4, + PAGE_SUPPORT_PROGRAMMERS, + PAGE_NCL_PRODUCT_TESTING, + PAGE_PACKAGE_AND_MANUAL, + PAGE_SPECIAL_THANKS_1, + PAGE_SPECIAL_THANKS_2, + PAGE_SPECIAL_THANKS_3, + PAGE_SPECIAL_THANKS_4, + PAGE_INFORMATION_SUPERVISORS, + PAGE_ARTWORK_1, + PAGE_ARTWORK_2, + PAGE_ARTWORK_3, + PAGE_COORDINATORS, + PAGE_ENGLISH_VERSION, + PAGE_TRANSLATOR, + PAGE_TEXT_EDITOR, + PAGE_NCL_COORDINATOR, + PAGE_PROGRAMMERS_5, + PAGE_GRAPHIC_DESIGNER, + PAGE_ENVIRONMENT_AND_TOOL_PROGRAMS_2, + PAGE_NOA_TESTING, + PAGE_BRAILLE_CODE_CHECK_1, + PAGE_BRAILLE_CODE_CHECK_2, + PAGE_SPECIAL_THANKS_5, + PAGE_TASK_MANAGERS, + PAGE_PRODUCERS, + PAGE_EXECUTIVE_DIRECTOR, + PAGE_EXECUTIVE_PRODUCERS_1, + PAGE_EXECUTIVE_PRODUCERS_2, + PAGE_COUNT +}; + +#define COLOR_DARK_GREEN RGB(7, 11, 6) +#define COLOR_LIGHT_GREEN RGB(13, 20, 12) + +enum +{ + TDA_0 = 0, + TDA_TASK_C_ID = 1, + TDA_TASK_E_ID = 2, + TDA_TASK_D_ID = 3, + TDA_4 = 4, + TDA_PLAYER_CYCLIST = 5, + TDA_RIVAL_CYCLIST = 6, + TDA_7 = 7, // Has something to do with the bike scene + TDA_11 = 11, // Gets set depending on whether the bike or the grass scene should be shown + TDA_12 = 12, + TDA_13 = 13, + TDA_14 = 14, + TDA_TASK_B_ID = 15, + + // Appears to be responsible for text + TDB_0 = 0, + TDB_TASK_A_ID = 1, + TDB_CURRENT_PAGE = 2, + TDB_3 = 3, + + TDC_0 = 0, + TDC_1 = 1, + TDC_2 = 2, + TDC_3 = 3, + TDC_4 = 4, + TDC_5 = 5, + + TDD_STATE = 0, + TDD_TASK_A_ID = 1, + TDD_2 = 2, + TDD_3 = 3, + + TDE_0 = 0, + TDE_1 = 1, + TDE_TASK_A_ID = 2, +}; + +struct Unk201C000 +{ + u16 unk0[71]; + u16 unk8E; + u16 unk90; + u16 unk92; + u16 unk94; + u16 unk96[386]; + u16 unk39A; + u16 unk39C[7]; +}; + +struct CreditsEntry +{ + u8 var_0; + u8 var_1; + const u8 *text; +}; + +static EWRAM_DATA s16 gUnknown_0203BCE0 = 0; +static EWRAM_DATA u16 gUnknown_0203BCE2 = 0; // TASK A +EWRAM_DATA bool8 gHasHallOfFameRecords = 0; +static EWRAM_DATA u8 gUnknown_0203BCE5 = 0; +static EWRAM_DATA struct Unk201C000 *gUnknown_0203BCE8 = {0}; + +static const u16 gUnknown_085E56F0[][16] = +{ + INCBIN_U16("graphics/credits/credits_1.gbapal"), + INCBIN_U16("graphics/credits/credits_2.gbapal"), + INCBIN_U16("graphics/credits/credits_3.gbapal"), + INCBIN_U16("graphics/credits/credits_4.gbapal"), +}; + +static const u8 gCreditsCopyrightEnd_Gfx[] = INCBIN_U8("graphics/credits/the_end_copyright.4bpp.lz"); + +static void sub_81772B8(struct Sprite *sprite); + +static const u8 gUnknown_085E5BAC[] = +{ + 0, 1, 0, + 0xFF, 1, 0xFF, + 0xFF, 1, 0xFF, + 0xFF, 1, 0xFF, + 0xFF, 1, 0xFF, +}; + +static const u8 gUnknown_085E5BBB[] = +{ + 1, 0xFF, 1, + 1, 0xFF, 1, + 1, 2, 1, + 1, 0xFF, 1, + 1, 0xFF, 1, +}; + +static const u8 gUnknown_085E5BCA[] = +{ + 1, 0, 0, + 1, 0xFF, 0xFF, + 1, 2, 2, + 1, 0xFF, 0xFF, + 1, 0x80, 0x80, +}; + +static const u8 gUnknown_085E5BD9[] = +{ + 1, 3, 1, + 1, 4, 1, + 1, 5, 1, + 1, 0xC4, 1, + 1, 0xC3, 1, +}; + +static const u8 gUnknown_085E5BE8[] = +{ + 1, 6, 7, + 1, 8, 9, + 1, 0xFF, 1, + 1, 0x88, 0x89, + 1, 0x86, 0x87, +}; + +static const u8 gCreditsText_EmptyString[] = _(""); +static const u8 gCreditsText_PkmnEmeraldVersion[] = _("POKéMON EMERALD VERSION"); +static const u8 gCreditsText_Credits[] = _("Credits"); +static const u8 gCreditsText_ExecutiveDirector[] = _("Executive Director"); +static const u8 gCreditsText_Director[] = _("Director"); +static const u8 gCreditsText_ArtDirector[] = _("Art Director"); +static const u8 gCreditsText_BattleDirector[] = _("Battle Director"); +static const u8 gCreditsText_MainProgrammer[] = _("Main Programmer"); +static const u8 gCreditsText_BattleSystemPgrms[] = _("Battle System Programmers"); +static const u8 gCreditsText_FieldSystemPgrms[] = _("Field System Programmer"); +static const u8 gCreditsText_Programmers[] = _("Programmers"); +static const u8 gCreditsText_MainGraphicDesigner[] = _("Main Graphic Designer"); +static const u8 gCreditsText_GraphicDesigners[] = _("Graphic Designers"); +static const u8 gCreditsText_PkmnDesigners[] = _("POKéMON Designers"); +static const u8 gCreditsText_MusicComposition[] = _("Music Composition"); +static const u8 gCreditsText_SoundEffectsAndPkmnVoices[] = _("Sound Effects & POKéMON Voices"); +static const u8 gCreditsText_GameDesigners[] = _("Game Designers"); +static const u8 gCreditsText_ScenarioPlot[] = _("Scenario Plot"); +static const u8 gCreditsText_Scenario[] = _("Scenario"); +static const u8 gCreditsText_ScriptDesigners[] = _("Script Designers"); +static const u8 gCreditsText_MapDesigners[] = _("Map Designers"); +static const u8 gCreditsText_MapDataDesigners[] = _("Map Data Designers"); +static const u8 gCreditsText_ParametricDesigners[] = _("Parametric Designers"); +static const u8 gCreditsText_PokedexText[] = _("POKéDEX Text"); +static const u8 gCreditsText_EnvAndToolPgrms[] = _("Environment & Tool Programmers"); +static const u8 gCreditsText_NCLProductTesting[] = _("NCL Product Testing"); +static const u8 gCreditsText_SpecialThanks[] = _("Special Thanks"); +static const u8 gCreditsText_Coordinators[] = _("Coordinators"); +static const u8 gCreditsText_Producers[] = _("Producers"); +static const u8 gCreditsText_ExecProducers[] = _("Executive Producers"); +static const u8 gCreditsText_InfoSupervisors[] = _("Information Supervisors"); +static const u8 gCreditsText_TaskManagers[] = _("Task Managers"); +static const u8 gCreditsText_BrailleCodeCheck[] = _("Braille Code Check"); +static const u8 gCreditsText_WorldDirector[] = _("World Director"); +static const u8 gCreditsText_BattleFrontierData[] = _("Battle Frontier Data"); +static const u8 gCreditsText_SupportProgrammers[] = _("Support Programmers"); +static const u8 gCreditsText_Artwork[] = _("Artwork"); +static const u8 gCreditsText_LeadProgrammer[] = _("Lead Programmer"); +static const u8 gCreditsText_LeadGraphicArtist[] = _("Lead Graphic Artist"); +static const u8 gCreditsText_SatoshiTajiri[] = _("Satoshi Tajiri"); +static const u8 gCreditsText_JunichiMasuda[] = _("Junichi Masuda"); +static const u8 gCreditsText_KenSugimori[] = _("Ken Sugimori"); +static const u8 gCreditsText_ShigekiMorimoto[] = _("Shigeki Morimoto"); +static const u8 gCreditsText_TetsuyaWatanabe[] = _("Tetsuya Watanabe"); +static const u8 gCreditsText_HisashiSogabe[] = _("Hisashi Sogabe"); +static const u8 gCreditsText_SosukeTamada[] = _("Sosuke Tamada"); +static const u8 gCreditsText_AkitoMori[] = _("Akito Mori"); +static const u8 gCreditsText_KeitaKagaya[] = _("Keita Kagaya"); +static const u8 gCreditsText_YoshinoriMatsuda[] = _("Yoshinori Matsuda"); +static const u8 gCreditsText_HiroyukiNakamura[] = _("Hiroyuki Nakamura"); +static const u8 gCreditsText_MasaoTaya[] = _("Masao Taya"); +static const u8 gCreditsText_SatoshiNohara[] = _("Satoshi Nohara"); +static const u8 gCreditsText_TomomichiOhta[] = _("Tomomichi Ohta"); +static const u8 gCreditsText_MiyukiIwasawa[] = _("Miyuki Iwasawa"); +static const u8 gCreditsText_TakenoriOhta[] = _("Takenori Ohta"); +static const u8 gCreditsText_HironobuYoshida[] = _("Hironobu Yoshida"); +static const u8 gCreditsText_MotofumiFujiwara[] = _("Motofumi Fujiwara"); +static const u8 gCreditsText_SatoshiOhta[] = _("Satoshi Ohta"); +static const u8 gCreditsText_AsukaIwashita[] = _("Asuka Iwashita"); +static const u8 gCreditsText_AimiTomita[] = _("Aimi Tomita"); +static const u8 gCreditsText_TakaoUnno[] = _("Takao Unno"); +static const u8 gCreditsText_KanakoEo[] = _("Kanako Eo"); +static const u8 gCreditsText_JunOkutani[] = _("Jun Okutani"); +static const u8 gCreditsText_AtsukoNishida[] = _("Atsuko Nishida"); +static const u8 gCreditsText_MuneoSaito[] = _("Muneo Saito"); +static const u8 gCreditsText_RenaYoshikawa[] = _("Rena Yoshikawa"); +static const u8 gCreditsText_GoIchinose[] = _("Go Ichinose"); +static const u8 gCreditsText_MorikazuAoki[] = _("Morikazu Aoki"); +static const u8 gCreditsText_KojiNishino[] = _("Koji Nishino"); +static const u8 gCreditsText_KenjiMatsushima[] = _("Kenji Matsushima"); +static const u8 gCreditsText_TetsujiOhta[] = _("Tetsuji Ohta"); +static const u8 gCreditsText_HitomiSato[] = _("Hitomi Sato"); +static const u8 gCreditsText_TakeshiKawachimaru[] = _("Takeshi Kawachimaru"); +static const u8 gCreditsText_TeruyukiShimoyamada[] = _("Teruyuki Shimoyamada"); +static const u8 gCreditsText_ShigeruOhmori[] = _("Shigeru Ohmori"); +static const u8 gCreditsText_TadashiTakahashi[] = _("Tadashi Takahashi"); +static const u8 gCreditsText_ToshinobuMatsumiya[] = _("Toshinobu Matsumiya"); +static const u8 gCreditsText_AkihitoTomisawa[] = _("Akihito Tomisawa"); +static const u8 gCreditsText_HirokiEnomoto[] = _("Hiroki Enomoto"); +static const u8 gCreditsText_KazuyukiTerada[] = _("Kazuyuki Terada"); +static const u8 gCreditsText_YuriSakurai[] = _("Yuri Sakurai"); +static const u8 gCreditsText_HiromiSagawa[] = _("Hiromi Sagawa"); +static const u8 gCreditsText_KenjiTominaga[] = _("Kenji Tominaga"); +static const u8 gCreditsText_YoshioTajiri[] = _("Yoshio Tajiri"); +static const u8 gCreditsText_TeikoSasaki[] = _("Teiko Sasaki"); +static const u8 gCreditsText_SachikoHamano[] = _("Sachiko Hamano"); +static const u8 gCreditsText_ChieMatsumiya[] = _("Chie Matsumiya"); +static const u8 gCreditsText_AkikoShinozaki[] = _("Akiko Shinozaki"); +static const u8 gCreditsText_AstukoFujii[] = _("Astuko Fujii"); +static const u8 gCreditsText_NozomuSaito[] = _("Nozomu Saito"); +static const u8 gCreditsText_KenkichiToyama[] = _("Kenkichi Toyama"); +static const u8 gCreditsText_SuguruNakatsui[] = _("Suguru Nakatsui"); +static const u8 gCreditsText_YumiFunasaka[] = _("Yumi Funasaka"); +static const u8 gCreditsText_NaokoYanase[] = _("Naoko Yanase"); +static const u8 gCreditsText_NCLSuperMarioClub[] = _("NCL Super Mario Club"); +static const u8 gCreditsText_AtsushiTada[] = _("Atsushi Tada"); +static const u8 gCreditsText_TakahiroOhnishi[] = _("Takahiro Ohnishi"); +static const u8 gCreditsText_NorihideOkamura[] = _("Norihide Okamura"); +static const u8 gCreditsText_HiroNakamura[] = _("Hiro Nakamura"); +static const u8 gCreditsText_HiroyukiUesugi[] = _("Hiroyuki Uesugi"); +static const u8 gCreditsText_TerukiMurakawa[] = _("Teruki Murakawa"); +static const u8 gCreditsText_AkiraKinashi[] = _("Akira Kinashi"); +static const u8 gCreditsText_MichikoTakizawa[] = _("Michiko Takizawa"); +static const u8 gCreditsText_MakikoTakada[] = _("Makiko Takada"); +static const u8 gCreditsText_TakanaoKondo[] = _("Takanao Kondo"); +static const u8 gCreditsText_AiMashima[] = _("Ai Mashima"); +static const u8 gCreditsText_GakujiNomoto[] = _("Gakuji Nomoto"); +static const u8 gCreditsText_TakehiroIzushi[] = _("Takehiro Izushi"); +static const u8 gCreditsText_HitoshiYamagami[] = _("Hitoshi Yamagami"); +static const u8 gCreditsText_KyokoWatanabe[] = _("Kyoko Watanabe"); +static const u8 gCreditsText_TakaoNakano[] = _("Takao Nakano"); +static const u8 gCreditsText_HiroyukiJinnai[] = _("Hiroyuki Jinnai"); +static const u8 gCreditsText_HiroakiTsuru[] = _("Hiroaki Tsuru"); +static const u8 gCreditsText_TsunekazIshihara[] = _("Tsunekaz Ishihara"); +static const u8 gCreditsText_SatoruIwata[] = _("Satoru Iwata"); +static const u8 gCreditsText_KazuyaSuyama[] = _("Kazuya Suyama"); +static const u8 gCreditsText_SatoshiMitsuhara[] = _("Satoshi Mitsuhara"); +static const u8 gCreditsText_JapanBrailleLibrary[] = _("Japan Braille Library"); +static const u8 gCreditsText_TomotakaKomura[] = _("Tomotaka Komura"); +static const u8 gCreditsText_MikikoOhhashi[] = _("Mikiko Ohhashi"); +static const u8 gCreditsText_DaisukeHoshino[] = _("Daisuke Hoshino"); +static const u8 gCreditsText_KenjiroIto[] = _("Kenjiro Ito"); +static const u8 gCreditsText_RuiKawaguchi[] = _("Rui Kawaguchi"); +static const u8 gCreditsText_ShunsukeKohori[] = _("Shunsuke Kohori"); +static const u8 gCreditsText_SachikoNakamichi[] = _("Sachiko Nakamichi"); +static const u8 gCreditsText_FujikoNomura[] = _("Fujiko Nomura"); +static const u8 gCreditsText_KazukiYoshihara[] = _("Kazuki Yoshihara"); +static const u8 gCreditsText_RetsujiNomoto[] = _("Retsuji Nomoto"); +static const u8 gCreditsText_AzusaTajima[] = _("Azusa Tajima"); +static const u8 gCreditsText_ShusakuEgami[] = _("Shusaku Egami"); +static const u8 gCreditsText_PackageAndManual[] = _("Package & Manual Illustration"); +static const u8 gCreditsText_EnglishVersion[] = _("English Version Coordinators"); +static const u8 gCreditsText_Translator[] = _("Translator"); +static const u8 gCreditsText_TextEditor[] = _("Text Editor"); +static const u8 gCreditsText_NCLCoordinator[] = _("NCL Coordinator"); +static const u8 gCreditsText_GraphicDesigner[] = _("Graphic Designer"); +static const u8 gCreditsText_NOAProductTesting[] = _("NOA Product Testing"); +static const u8 gCreditsText_HideyukiNakajima[] = _("Hideyuki Nakajima"); +static const u8 gCreditsText_HidenoriSaeki[] = _("Hidenori Saeki"); +static const u8 gCreditsText_YokoWatanabe[] = _("Yoko Watanabe"); +static const u8 gCreditsText_SakaeKimura[] = _("Sakae Kimura"); +static const u8 gCreditsText_ChiakiShinkai[] = _("Chiaki Shinkai"); +static const u8 gCreditsText_SethMcMahill[] = _("Seth McMahill"); +static const u8 gCreditsText_NobOgasawara[] = _("Nob Ogasawara"); +static const u8 gCreditsText_TeresaLillygren[] = _("Teresa Lillygren"); +static const u8 gCreditsText_KimikoNakamichi[] = _("Kimiko Nakamichi"); +static const u8 gCreditsText_SouichiYamamoto[] = _("Souichi Yamamoto"); +static const u8 gCreditsText_YuichiroIto[] = _("Yuichiro Ito"); +static const u8 gCreditsText_ThomasHertzog[] = _("Thomas Hertzog"); +static const u8 gCreditsText_MikaKurosawa[] = _("Mika Kurosawa"); +static const u8 gCreditsText_NationalFederationBlind[] = _("National Federation of the Blind"); +static const u8 gCreditsText_PatriciaAMaurer[] = _("Patricia A. Maurer"); +static const u8 gCreditsText_EuropeanBlindUnion[] = _("European Blind Union"); +static const u8 gCreditsText_AustralianBrailleAuthority[] = _("Australian Braille Authority"); +static const u8 gCreditsText_RoyalNewZealandFederationBlind[] = _("Royal New Zealand Federation for the Blind"); +static const u8 gCreditsText_MotoyasuTojima[] = _("Motoyasu Tojima"); +static const u8 gCreditsText_NicolaPrattBarlow[] = _("Nicola Pratt-Barlow"); +static const u8 gCreditsText_ShellieDow[] = _("Shellie Dow"); +static const u8 gCreditsText_ErikJohnson[] = _("Erik Johnson"); +static const struct CreditsEntry gCreditsEntry_EmptyString[] = {0, 0, gCreditsText_EmptyString}; +static const struct CreditsEntry gCreditsEntry_PkmnEmeraldVersion[] = {7, 1, gCreditsText_PkmnEmeraldVersion}; +static const struct CreditsEntry gCreditsEntry_Credits[] = {11, 1, gCreditsText_Credits}; +static const struct CreditsEntry gCreditsEntry_ExecutiveDirector[] = {8, 1, gCreditsText_ExecutiveDirector}; +static const struct CreditsEntry gCreditsEntry_Director[] = {12, 1, gCreditsText_Director}; +static const struct CreditsEntry gCreditsEntry_ArtDirector[] = {10, 1, gCreditsText_ArtDirector}; +static const struct CreditsEntry gCreditsEntry_BattleDirector[] = {10, 1, gCreditsText_BattleDirector}; +static const struct CreditsEntry gCreditsEntry_MainProgrammer[] = {10, 1, gCreditsText_MainProgrammer}; +static const struct CreditsEntry gCreditsEntry_BattleSystemPgrms[] = {8, 1, gCreditsText_BattleSystemPgrms}; +static const struct CreditsEntry gCreditsEntry_FieldSystemPgrms[] = {7, 1, gCreditsText_FieldSystemPgrms}; +static const struct CreditsEntry gCreditsEntry_Programmers[] = {12, 1, gCreditsText_Programmers}; +static const struct CreditsEntry gCreditsEntry_MainGraphicDesigner[] = {7, 1, gCreditsText_MainGraphicDesigner}; +static const struct CreditsEntry gCreditsEntry_GraphicDesigners[] = {9, 1, gCreditsText_GraphicDesigners}; +static const struct CreditsEntry gCreditsEntry_PkmnDesigners[] = {10, 1, gCreditsText_PkmnDesigners}; +static const struct CreditsEntry gCreditsEntry_MusicComposition[] = {13, 1, gCreditsText_MusicComposition}; +static const struct CreditsEntry gCreditsEntry_SoundEffectsAndPkmnVoices[] = {4, 1, gCreditsText_SoundEffectsAndPkmnVoices}; +static const struct CreditsEntry gCreditsEntry_GameDesigners[] = {11, 1, gCreditsText_GameDesigners}; +static const struct CreditsEntry gCreditsEntry_ScenarioPlot[] = {11, 1, gCreditsText_ScenarioPlot}; +static const struct CreditsEntry gCreditsEntry_Scenario[] = {13, 1, gCreditsText_Scenario}; +static const struct CreditsEntry gCreditsEntry_ScriptDesigners[] = {10, 1, gCreditsText_ScriptDesigners}; +static const struct CreditsEntry gCreditsEntry_MapDesigners[] = {11, 1, gCreditsText_MapDesigners}; +static const struct CreditsEntry gCreditsEntry_MapDataDesigners[] = {9, 1, gCreditsText_MapDataDesigners}; +static const struct CreditsEntry gCreditsEntry_ParametricDesigners[] = {9, 1, gCreditsText_ParametricDesigners}; +static const struct CreditsEntry gCreditsEntry_PokedexText[] = {11, 1, gCreditsText_PokedexText}; +static const struct CreditsEntry gCreditsEntry_EnvAndToolPgrms[] = {6, 1, gCreditsText_EnvAndToolPgrms}; +static const struct CreditsEntry gCreditsEntry_NCLProductTesting[] = {11, 1, gCreditsText_NCLProductTesting}; +static const struct CreditsEntry gCreditsEntry_SpecialThanks[] = {10, 1, gCreditsText_SpecialThanks}; +static const struct CreditsEntry gCreditsEntry_Coordinators[] = {11, 1, gCreditsText_Coordinators}; +static const struct CreditsEntry gCreditsEntry_Producers[] = {11, 1, gCreditsText_Producers}; +static const struct CreditsEntry gCreditsEntry_ExecProducers[] = {7, 1, gCreditsText_ExecProducers}; +static const struct CreditsEntry gCreditsEntry_InfoSupervisors[] = {10, 1, gCreditsText_InfoSupervisors}; +static const struct CreditsEntry gCreditsEntry_TaskManagers[] = {8, 1, gCreditsText_TaskManagers}; +static const struct CreditsEntry gCreditsEntry_BrailleCodeCheck[] = {10, 1, gCreditsText_BrailleCodeCheck}; +static const struct CreditsEntry gCreditsEntry_WorldDirector[] = {10, 1, gCreditsText_WorldDirector}; +static const struct CreditsEntry gCreditsEntry_BattleFrontierData[] = {8, 1, gCreditsText_BattleFrontierData}; +static const struct CreditsEntry gCreditsEntry_SupportProgrammers[] = {10, 1, gCreditsText_SupportProgrammers}; +static const struct CreditsEntry gCreditsEntry_Artwork[] = {12, 1, gCreditsText_Artwork}; +static const struct CreditsEntry gCreditsEntry_LeadProgrammer[] = {10, 1, gCreditsText_LeadProgrammer}; +static const struct CreditsEntry gCreditsEntry_LeadGraphicArtist[] = {9, 1, gCreditsText_LeadGraphicArtist}; +static const struct CreditsEntry gCreditsEntry_SatoshiTajiri[] = {11, 0, gCreditsText_SatoshiTajiri}; +static const struct CreditsEntry gCreditsEntry_JunichiMasuda[] = {11, 0, gCreditsText_JunichiMasuda}; +static const struct CreditsEntry gCreditsEntry_KenSugimori[] = {11, 0, gCreditsText_KenSugimori}; +static const struct CreditsEntry gCreditsEntry_ShigekiMorimoto[] = {11, 0, gCreditsText_ShigekiMorimoto}; +static const struct CreditsEntry gCreditsEntry_TetsuyaWatanabe[] = {11, 0, gCreditsText_TetsuyaWatanabe}; +static const struct CreditsEntry gCreditsEntry_HisashiSogabe[] = {11, 0, gCreditsText_HisashiSogabe}; +static const struct CreditsEntry gCreditsEntry_SosukeTamada[] = {11, 0, gCreditsText_SosukeTamada}; +static const struct CreditsEntry gCreditsEntry_AkitoMori[] = {11, 0, gCreditsText_AkitoMori}; +static const struct CreditsEntry gCreditsEntry_KeitaKagaya[] = {11, 0, gCreditsText_KeitaKagaya}; +static const struct CreditsEntry gCreditsEntry_YoshinoriMatsuda[] = {11, 0, gCreditsText_YoshinoriMatsuda}; +static const struct CreditsEntry gCreditsEntry_HiroyukiNakamura[] = {11, 0, gCreditsText_HiroyukiNakamura}; +static const struct CreditsEntry gCreditsEntry_MasaoTaya[] = {11, 0, gCreditsText_MasaoTaya}; +static const struct CreditsEntry gCreditsEntry_SatoshiNohara[] = {11, 0, gCreditsText_SatoshiNohara}; +static const struct CreditsEntry gCreditsEntry_TomomichiOhta[] = {11, 0, gCreditsText_TomomichiOhta}; +static const struct CreditsEntry gCreditsEntry_MiyukiIwasawa[] = {11, 0, gCreditsText_MiyukiIwasawa}; +static const struct CreditsEntry gCreditsEntry_TakenoriOhta[] = {11, 0, gCreditsText_TakenoriOhta}; +static const struct CreditsEntry gCreditsEntry_HironobuYoshida[] = {11, 0, gCreditsText_HironobuYoshida}; +static const struct CreditsEntry gCreditsEntry_MotofumiFujiwara[] = {11, 0, gCreditsText_MotofumiFujiwara}; +static const struct CreditsEntry gCreditsEntry_SatoshiOhta[] = {11, 0, gCreditsText_SatoshiOhta}; +static const struct CreditsEntry gCreditsEntry_AsukaIwashita[] = {11, 0, gCreditsText_AsukaIwashita}; +static const struct CreditsEntry gCreditsEntry_AimiTomita[] = {11, 0, gCreditsText_AimiTomita}; +static const struct CreditsEntry gCreditsEntry_TakaoUnno[] = {11, 0, gCreditsText_TakaoUnno}; +static const struct CreditsEntry gCreditsEntry_KanakoEo[] = {11, 0, gCreditsText_KanakoEo}; +static const struct CreditsEntry gCreditsEntry_JunOkutani[] = {11, 0, gCreditsText_JunOkutani}; +static const struct CreditsEntry gCreditsEntry_AtsukoNishida[] = {11, 0, gCreditsText_AtsukoNishida}; +static const struct CreditsEntry gCreditsEntry_MuneoSaito[] = {11, 0, gCreditsText_MuneoSaito}; +static const struct CreditsEntry gCreditsEntry_RenaYoshikawa[] = {11, 0, gCreditsText_RenaYoshikawa}; +static const struct CreditsEntry gCreditsEntry_GoIchinose[] = {11, 0, gCreditsText_GoIchinose}; +static const struct CreditsEntry gCreditsEntry_MorikazuAoki[] = {11, 0, gCreditsText_MorikazuAoki}; +static const struct CreditsEntry gCreditsEntry_KojiNishino[] = {11, 0, gCreditsText_KojiNishino}; +static const struct CreditsEntry gCreditsEntry_KenjiMatsushima[] = {11, 0, gCreditsText_KenjiMatsushima}; +static const struct CreditsEntry gCreditsEntry_TetsujiOhta[] = {11, 0, gCreditsText_TetsujiOhta}; +static const struct CreditsEntry gCreditsEntry_HitomiSato[] = {11, 0, gCreditsText_HitomiSato}; +static const struct CreditsEntry gCreditsEntry_TakeshiKawachimaru[] = {11, 0, gCreditsText_TakeshiKawachimaru}; +static const struct CreditsEntry gCreditsEntry_TeruyukiShimoyamada[] = {11, 0, gCreditsText_TeruyukiShimoyamada}; +static const struct CreditsEntry gCreditsEntry_ShigeruOhmori[] = {11, 0, gCreditsText_ShigeruOhmori}; +static const struct CreditsEntry gCreditsEntry_TadashiTakahashi[] = {11, 0, gCreditsText_TadashiTakahashi}; +static const struct CreditsEntry gCreditsEntry_ToshinobuMatsumiya[] = {11, 0, gCreditsText_ToshinobuMatsumiya}; +static const struct CreditsEntry gCreditsEntry_AkihitoTomisawa[] = {11, 0, gCreditsText_AkihitoTomisawa}; +static const struct CreditsEntry gCreditsEntry_HirokiEnomoto[] = {11, 0, gCreditsText_HirokiEnomoto}; +static const struct CreditsEntry gCreditsEntry_KazuyukiTerada[] = {11, 0, gCreditsText_KazuyukiTerada}; +static const struct CreditsEntry gCreditsEntry_YuriSakurai[] = {11, 0, gCreditsText_YuriSakurai}; +static const struct CreditsEntry gCreditsEntry_HiromiSagawa[] = {11, 0, gCreditsText_HiromiSagawa}; +static const struct CreditsEntry gCreditsEntry_KenjiTominaga[] = {11, 0, gCreditsText_KenjiTominaga}; +static const struct CreditsEntry gCreditsEntry_YoshioTajiri[] = {11, 0, gCreditsText_YoshioTajiri}; +static const struct CreditsEntry gCreditsEntry_TeikoSasaki[] = {11, 0, gCreditsText_TeikoSasaki}; +static const struct CreditsEntry gCreditsEntry_SachikoHamano[] = {11, 0, gCreditsText_SachikoHamano}; +static const struct CreditsEntry gCreditsEntry_ChieMatsumiya[] = {11, 0, gCreditsText_ChieMatsumiya}; +static const struct CreditsEntry gCreditsEntry_AkikoShinozaki[] = {11, 0, gCreditsText_AkikoShinozaki}; +static const struct CreditsEntry gCreditsEntry_AstukoFujii[] = {11, 0, gCreditsText_AstukoFujii}; +static const struct CreditsEntry gCreditsEntry_NozomuSaito[] = {11, 0, gCreditsText_NozomuSaito}; +static const struct CreditsEntry gCreditsEntry_KenkichiToyama[] = {11, 0, gCreditsText_KenkichiToyama}; +static const struct CreditsEntry gCreditsEntry_SuguruNakatsui[] = {11, 0, gCreditsText_SuguruNakatsui}; +static const struct CreditsEntry gCreditsEntry_YumiFunasaka[] = {11, 0, gCreditsText_YumiFunasaka}; +static const struct CreditsEntry gCreditsEntry_NaokoYanase[] = {11, 0, gCreditsText_NaokoYanase}; +static const struct CreditsEntry gCreditsEntry_NCLSuperMarioClub[] = {11, 0, gCreditsText_NCLSuperMarioClub}; +static const struct CreditsEntry gCreditsEntry_AtsushiTada[] = {11, 0, gCreditsText_AtsushiTada}; +static const struct CreditsEntry gCreditsEntry_TakahiroOhnishi[] = {11, 0, gCreditsText_TakahiroOhnishi}; +static const struct CreditsEntry gCreditsEntry_NorihideOkamura[] = {11, 0, gCreditsText_NorihideOkamura}; +static const struct CreditsEntry gCreditsEntry_HiroNakamura[] = {11, 0, gCreditsText_HiroNakamura}; +static const struct CreditsEntry gCreditsEntry_HiroyukiUesugi[] = {11, 0, gCreditsText_HiroyukiUesugi}; +static const struct CreditsEntry gCreditsEntry_TerukiMurakawa[] = {11, 0, gCreditsText_TerukiMurakawa}; +static const struct CreditsEntry gCreditsEntry_AkiraKinashi[] = {11, 0, gCreditsText_AkiraKinashi}; +static const struct CreditsEntry gCreditsEntry_MichikoTakizawa[] = {11, 0, gCreditsText_MichikoTakizawa}; +static const struct CreditsEntry gCreditsEntry_MakikoTakada[] = {11, 0, gCreditsText_MakikoTakada}; +static const struct CreditsEntry gCreditsEntry_TakanaoKondo[] = {11, 0, gCreditsText_TakanaoKondo}; +static const struct CreditsEntry gCreditsEntry_AiMashima[] = {11, 0, gCreditsText_AiMashima}; +static const struct CreditsEntry gCreditsEntry_GakujiNomoto[] = {11, 0, gCreditsText_GakujiNomoto}; +static const struct CreditsEntry gCreditsEntry_TakehiroIzushi[] = {11, 0, gCreditsText_TakehiroIzushi}; +static const struct CreditsEntry gCreditsEntry_HitoshiYamagami[] = {11, 0, gCreditsText_HitoshiYamagami}; +static const struct CreditsEntry gCreditsEntry_KyokoWatanabe[] = {11, 0, gCreditsText_KyokoWatanabe}; +static const struct CreditsEntry gCreditsEntry_TakaoNakano[] = {11, 0, gCreditsText_TakaoNakano}; +static const struct CreditsEntry gCreditsEntry_HiroyukiJinnai[] = {11, 0, gCreditsText_HiroyukiJinnai}; +static const struct CreditsEntry gCreditsEntry_HiroakiTsuru[] = {11, 0, gCreditsText_HiroakiTsuru}; +static const struct CreditsEntry gCreditsEntry_TsunekazIshihara[] = {11, 0, gCreditsText_TsunekazIshihara}; +static const struct CreditsEntry gCreditsEntry_SatoruIwata[] = {11, 0, gCreditsText_SatoruIwata}; +static const struct CreditsEntry gCreditsEntry_KazuyaSuyama[] = {11, 0, gCreditsText_KazuyaSuyama}; +static const struct CreditsEntry gCreditsEntry_SatoshiMitsuhara[] = {11, 0, gCreditsText_SatoshiMitsuhara}; +static const struct CreditsEntry gCreditsEntry_JapanBrailleLibrary[] = {9, 0, gCreditsText_JapanBrailleLibrary}; +static const struct CreditsEntry gCreditsEntry_TomotakaKomura[] = {11, 0, gCreditsText_TomotakaKomura}; +static const struct CreditsEntry gCreditsEntry_MikikoOhhashi[] = {11, 0, gCreditsText_MikikoOhhashi}; +static const struct CreditsEntry gCreditsEntry_DaisukeHoshino[] = {11, 0, gCreditsText_DaisukeHoshino}; +static const struct CreditsEntry gCreditsEntry_KenjiroIto[] = {11, 0, gCreditsText_KenjiroIto}; +static const struct CreditsEntry gCreditsEntry_RuiKawaguchi[] = {11, 0, gCreditsText_RuiKawaguchi}; +static const struct CreditsEntry gCreditsEntry_ShunsukeKohori[] = {11, 0, gCreditsText_ShunsukeKohori}; +static const struct CreditsEntry gCreditsEntry_SachikoNakamichi[] = {11, 0, gCreditsText_SachikoNakamichi}; +static const struct CreditsEntry gCreditsEntry_FujikoNomura[] = {11, 0, gCreditsText_FujikoNomura}; +static const struct CreditsEntry gCreditsEntry_KazukiYoshihara[] = {11, 0, gCreditsText_KazukiYoshihara}; +static const struct CreditsEntry gCreditsEntry_RetsujiNomoto[] = {11, 0, gCreditsText_RetsujiNomoto}; +static const struct CreditsEntry gCreditsEntry_AzusaTajima[] = {11, 0, gCreditsText_AzusaTajima}; +static const struct CreditsEntry gCreditsEntry_ShusakuEgami[] = {11, 0, gCreditsText_ShusakuEgami}; +static const struct CreditsEntry gCreditsEntry_PackageAndManual[] = {0, 1, gCreditsText_PackageAndManual}; +static const struct CreditsEntry gCreditsEntry_EnglishVersion[] = {0, 1, gCreditsText_EnglishVersion}; +static const struct CreditsEntry gCreditsEntry_Translator[] = {0, 1, gCreditsText_Translator}; +static const struct CreditsEntry gCreditsEntry_TextEditor[] = {0, 1, gCreditsText_TextEditor}; +static const struct CreditsEntry gCreditsEntry_NCLCoordinator[] = {0, 1, gCreditsText_NCLCoordinator}; +static const struct CreditsEntry gCreditsEntry_GraphicDesigner[] = {0, 1, gCreditsText_GraphicDesigner}; +static const struct CreditsEntry gCreditsEntry_NOAProductTesting[] = {0, 1, gCreditsText_NOAProductTesting}; +static const struct CreditsEntry gCreditsEntry_HideyukiNakajima[] = {0, 0, gCreditsText_HideyukiNakajima}; +static const struct CreditsEntry gCreditsEntry_HidenoriSaeki[] = {0, 0, gCreditsText_HidenoriSaeki}; +static const struct CreditsEntry gCreditsEntry_YokoWatanabe[] = {0, 0, gCreditsText_YokoWatanabe}; +static const struct CreditsEntry gCreditsEntry_SakaeKimura[] = {0, 0, gCreditsText_SakaeKimura}; +static const struct CreditsEntry gCreditsEntry_ChiakiShinkai[] = {0, 0, gCreditsText_ChiakiShinkai}; +static const struct CreditsEntry gCreditsEntry_SethMcMahill[] = {0, 0, gCreditsText_SethMcMahill}; +static const struct CreditsEntry gCreditsEntry_NobOgasawara[] = {0, 0, gCreditsText_NobOgasawara}; +static const struct CreditsEntry gCreditsEntry_TeresaLillygren[] = {0, 0, gCreditsText_TeresaLillygren}; +static const struct CreditsEntry gCreditsEntry_KimikoNakamichi[] = {0, 0, gCreditsText_KimikoNakamichi}; +static const struct CreditsEntry gCreditsEntry_SouichiYamamoto[] = {0, 0, gCreditsText_SouichiYamamoto}; +static const struct CreditsEntry gCreditsEntry_YuichiroIto[] = {0, 0, gCreditsText_YuichiroIto}; +static const struct CreditsEntry gCreditsEntry_ThomasHertzog[] = {0, 0, gCreditsText_ThomasHertzog}; +static const struct CreditsEntry gCreditsEntry_MikaKurosawa[] = {0, 0, gCreditsText_MikaKurosawa}; +static const struct CreditsEntry gCreditsEntry_NationalFederationBlind[] = {0, 0, gCreditsText_NationalFederationBlind}; +static const struct CreditsEntry gCreditsEntry_PatriciaAMaurer[] = {0, 0, gCreditsText_PatriciaAMaurer}; +static const struct CreditsEntry gCreditsEntry_EuropeanBlindUnion[] = {0, 0, gCreditsText_EuropeanBlindUnion}; +static const struct CreditsEntry gCreditsEntry_AustralianBrailleAuthority[] = {0, 0, gCreditsText_AustralianBrailleAuthority}; +static const struct CreditsEntry gCreditsEntry_RoyalNewZealandFederationBlind[] = {0, 0, gCreditsText_RoyalNewZealandFederationBlind}; +static const struct CreditsEntry gCreditsEntry_MotoyasuTojima[] = {0, 0, gCreditsText_MotoyasuTojima}; +static const struct CreditsEntry gCreditsEntry_NicolaPrattBarlow[] = {0, 0, gCreditsText_NicolaPrattBarlow}; +static const struct CreditsEntry gCreditsEntry_ShellieDow[] = {0, 0, gCreditsText_ShellieDow}; +static const struct CreditsEntry gCreditsEntry_ErikJohnson[] = {0, 0, gCreditsText_ErikJohnson}; + +#define _ gCreditsEntry_EmptyString +static const struct CreditsEntry *const gCreditsEntryPointerTable[][5] = +{ + { + _, + gCreditsEntry_PkmnEmeraldVersion, + gCreditsEntry_Credits, + _, + _ + }, + { + _, + gCreditsEntry_Director, + gCreditsEntry_ShigekiMorimoto, + _, + _, + }, + { + _, + gCreditsEntry_ArtDirector, + gCreditsEntry_KenSugimori, + _, + _, + }, + { + _, + gCreditsEntry_WorldDirector, + gCreditsEntry_JunichiMasuda, + _, + _, + }, + { + gCreditsEntry_LeadProgrammer, + gCreditsEntry_HisashiSogabe, + gCreditsEntry_LeadGraphicArtist, + gCreditsEntry_MotofumiFujiwara, + _, + }, + { + gCreditsEntry_Programmers, + gCreditsEntry_HisashiSogabe, + gCreditsEntry_TomomichiOhta, + gCreditsEntry_NozomuSaito, + gCreditsEntry_EmptyString, + }, + { + gCreditsEntry_Programmers, + gCreditsEntry_AkitoMori, + gCreditsEntry_HiroyukiNakamura, + gCreditsEntry_MasaoTaya, + _, + }, + { + gCreditsEntry_Programmers, + gCreditsEntry_SatoshiNohara, + gCreditsEntry_MiyukiIwasawa, + gCreditsEntry_YoshinoriMatsuda, + gCreditsEntry_KeitaKagaya, + }, + { + gCreditsEntry_Programmers, + gCreditsEntry_TetsuyaWatanabe, + gCreditsEntry_SosukeTamada, + gCreditsEntry_TakenoriOhta, + _, + }, + { + _, + gCreditsEntry_GraphicDesigners, + gCreditsEntry_MotofumiFujiwara, + gCreditsEntry_SatoshiOhta, + _, + }, + { + gCreditsEntry_GraphicDesigners, + gCreditsEntry_KenkichiToyama, + gCreditsEntry_AsukaIwashita, + gCreditsEntry_TakaoUnno, + _, + }, + { + gCreditsEntry_GraphicDesigners, + gCreditsEntry_KenSugimori, + gCreditsEntry_HironobuYoshida, + gCreditsEntry_AimiTomita, + gCreditsEntry_KanakoEo, + }, + { + gCreditsEntry_MusicComposition, + gCreditsEntry_GoIchinose, + gCreditsEntry_JunichiMasuda, + gCreditsEntry_MorikazuAoki, + gCreditsEntry_HitomiSato, + }, + { + _, + gCreditsEntry_SoundEffectsAndPkmnVoices, + gCreditsEntry_GoIchinose, + gCreditsEntry_MorikazuAoki, + _, + }, + { + gCreditsEntry_GameDesigners, + gCreditsEntry_ShigekiMorimoto, + gCreditsEntry_TeruyukiShimoyamada, + gCreditsEntry_TakeshiKawachimaru, + gCreditsEntry_AkihitoTomisawa, + }, + { + gCreditsEntry_GameDesigners, + gCreditsEntry_SuguruNakatsui, + gCreditsEntry_TetsujiOhta, + gCreditsEntry_HitomiSato, + gCreditsEntry_KenjiMatsushima, + }, + { + gCreditsEntry_GameDesigners, + gCreditsEntry_JunichiMasuda, + gCreditsEntry_KojiNishino, + gCreditsEntry_ShigeruOhmori, + gCreditsEntry_TadashiTakahashi, + }, + { + gCreditsEntry_ScenarioPlot, + gCreditsEntry_AkihitoTomisawa, + gCreditsEntry_JunichiMasuda, + gCreditsEntry_KojiNishino, + _, + }, + { + gCreditsEntry_Scenario, + gCreditsEntry_AkihitoTomisawa, + gCreditsEntry_HitomiSato, + gCreditsEntry_ToshinobuMatsumiya, + _, + }, + { + gCreditsEntry_ScriptDesigners, + gCreditsEntry_TomomichiOhta, + gCreditsEntry_SatoshiNohara, + _, + _, + }, + { + gCreditsEntry_MapDesigners, + gCreditsEntry_SuguruNakatsui, + gCreditsEntry_TeruyukiShimoyamada, + gCreditsEntry_ShigeruOhmori, + gCreditsEntry_TetsujiOhta, + }, + { + _, + gCreditsEntry_BattleFrontierData, + gCreditsEntry_TetsujiOhta, + _, + _, + }, + { + gCreditsEntry_ParametricDesigners, + gCreditsEntry_TeruyukiShimoyamada, + gCreditsEntry_ShigekiMorimoto, + gCreditsEntry_TetsujiOhta, + gCreditsEntry_KojiNishino, + }, + { + _, + gCreditsEntry_PokedexText, + gCreditsEntry_KenjiMatsushima, + _, + _, + }, + { + gCreditsEntry_EnvAndToolPgrms, + gCreditsEntry_HisashiSogabe, + gCreditsEntry_SosukeTamada, + gCreditsEntry_HiroyukiNakamura, + gCreditsEntry_AkitoMori, + }, + { + gCreditsEntry_PkmnDesigners, + gCreditsEntry_KenSugimori, + gCreditsEntry_MotofumiFujiwara, + gCreditsEntry_ShigekiMorimoto, + _, + }, + { + gCreditsEntry_PkmnDesigners, + gCreditsEntry_HironobuYoshida, + gCreditsEntry_SatoshiOhta, + gCreditsEntry_AsukaIwashita, + _, + }, + { + gCreditsEntry_PkmnDesigners, + gCreditsEntry_TakaoUnno, + gCreditsEntry_KanakoEo, + gCreditsEntry_AimiTomita, + _, + }, + { + gCreditsEntry_PkmnDesigners, + gCreditsEntry_AtsukoNishida, + gCreditsEntry_MuneoSaito, + gCreditsEntry_RenaYoshikawa, + gCreditsEntry_JunOkutani, + }, + { + _, + gCreditsEntry_SupportProgrammers, + gCreditsEntry_SatoshiMitsuhara, + gCreditsEntry_DaisukeHoshino, + _, + }, + { + _, + gCreditsEntry_NCLProductTesting, + gCreditsEntry_NCLSuperMarioClub, + _, + _, + }, + { + _, + gCreditsEntry_PackageAndManual, + gCreditsEntry_KenSugimori, + _, + _, + }, + { + _, + gCreditsEntry_SpecialThanks, + gCreditsEntry_KenjiTominaga, + gCreditsEntry_HirokiEnomoto, + _, + }, + { + gCreditsEntry_SpecialThanks, + gCreditsEntry_KazuyaSuyama, + gCreditsEntry_KenjiroIto, + gCreditsEntry_MichikoTakizawa, + gCreditsEntry_MakikoTakada, + }, + { + gCreditsEntry_SpecialThanks, + gCreditsEntry_MikikoOhhashi, + gCreditsEntry_TakanaoKondo, + gCreditsEntry_RuiKawaguchi, + _, + }, + { + gCreditsEntry_SpecialThanks, + gCreditsEntry_TakahiroOhnishi, + gCreditsEntry_NorihideOkamura, + gCreditsEntry_ShunsukeKohori, + _, + }, + { + gCreditsEntry_InfoSupervisors, + gCreditsEntry_KazuyukiTerada, + gCreditsEntry_YuriSakurai, + gCreditsEntry_YumiFunasaka, + gCreditsEntry_NaokoYanase, + }, + { + _, + gCreditsEntry_Artwork, + gCreditsEntry_SachikoNakamichi, + gCreditsEntry_FujikoNomura, + _, + }, + { + _, + gCreditsEntry_Artwork, + gCreditsEntry_HideyukiNakajima, + gCreditsEntry_HidenoriSaeki, + _, + }, + { + gCreditsEntry_Artwork, + gCreditsEntry_YokoWatanabe, + gCreditsEntry_SakaeKimura, + gCreditsEntry_ChiakiShinkai, + _, + }, + { + gCreditsEntry_Coordinators, + gCreditsEntry_KazukiYoshihara, + gCreditsEntry_AkiraKinashi, + gCreditsEntry_RetsujiNomoto, + _, + }, + { + _, + gCreditsEntry_EnglishVersion, + gCreditsEntry_HiroNakamura, + gCreditsEntry_SethMcMahill, + _, + }, + { + _, + gCreditsEntry_Translator, + gCreditsEntry_NobOgasawara, + _, + _, + }, + { + _, + gCreditsEntry_TextEditor, + gCreditsEntry_TeresaLillygren, + _, + _, + }, + { + _, + gCreditsEntry_NCLCoordinator, + gCreditsEntry_KimikoNakamichi, + _, + _, + }, + { + gCreditsEntry_Programmers, + gCreditsEntry_TerukiMurakawa, + gCreditsEntry_SouichiYamamoto, + gCreditsEntry_YuichiroIto, + gCreditsEntry_AkiraKinashi, + }, + { + _, + gCreditsEntry_GraphicDesigner, + gCreditsEntry_AkiraKinashi, + _, + _, + }, + { + gCreditsEntry_EnvAndToolPgrms, + gCreditsEntry_TerukiMurakawa, + gCreditsEntry_SouichiYamamoto, + gCreditsEntry_KimikoNakamichi, + _, + }, + { + gCreditsEntry_NOAProductTesting, + gCreditsEntry_ThomasHertzog, + gCreditsEntry_ErikJohnson, + gCreditsEntry_MikaKurosawa, + _, + }, + { + gCreditsEntry_BrailleCodeCheck, + gCreditsEntry_NationalFederationBlind, + gCreditsEntry_PatriciaAMaurer, + gCreditsEntry_JapanBrailleLibrary, + gCreditsEntry_EuropeanBlindUnion, + }, + { + _, + gCreditsEntry_BrailleCodeCheck, + gCreditsEntry_AustralianBrailleAuthority, + gCreditsEntry_RoyalNewZealandFederationBlind, + _, + }, + { + gCreditsEntry_SpecialThanks, + gCreditsEntry_HiroyukiUesugi, + gCreditsEntry_MotoyasuTojima, + gCreditsEntry_NicolaPrattBarlow, + gCreditsEntry_ShellieDow, + }, + { + _, + gCreditsEntry_TaskManagers, + gCreditsEntry_AzusaTajima, + gCreditsEntry_ShusakuEgami, + _, + }, + { + gCreditsEntry_Producers, + gCreditsEntry_HiroyukiJinnai, + gCreditsEntry_HitoshiYamagami, + gCreditsEntry_GakujiNomoto, + gCreditsEntry_HiroakiTsuru, + }, + { + _, + gCreditsEntry_ExecutiveDirector, + gCreditsEntry_SatoshiTajiri, + _, + _, + }, + { + _, + gCreditsEntry_ExecProducers, + gCreditsEntry_SatoruIwata, + _, + _, + }, + { + _, + gCreditsEntry_ExecProducers, + gCreditsEntry_TsunekazIshihara, + _, + _, + }, +}; +#undef _ + +static const struct BgTemplate gUnknown_085E6F68[] = +{ + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 28, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, +}; +static const struct WindowTemplate gUnknown_085E6F6C[] = +{ + { 0x00, 0x00, 0x09, 0x1E, 0x0C, 0x08, 0x0001 }, + DUMMY_WIN_TEMPLATE, +}; +static const u8 gUnknown_085E6F7C[][2] = +{ + {104, 36}, + {120, 36}, + {136, 36}, +}; + +static const union AnimCmd gUnknown_085E6F84[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(64, 8), + ANIMCMD_FRAME(128, 8), + ANIMCMD_FRAME(192, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_085E6F98[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_FRAME(128, 4), + ANIMCMD_FRAME(192, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_085E6FAC[] = +{ + ANIMCMD_FRAME(256, 4), + ANIMCMD_FRAME(320, 4), + ANIMCMD_FRAME(384, 4), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_085E6FBC[] = +{ + ANIMCMD_FRAME(384, 30), + ANIMCMD_FRAME(320, 30), + ANIMCMD_FRAME(256, 30), + ANIMCMD_FRAME(256, 30), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_085E6FD0[] = +{ + gUnknown_085E6F84, + gUnknown_085E6F98, + gUnknown_085E6FAC, + gUnknown_085E6FBC, +}; + +static const union AnimCmd gUnknown_085E6FE0[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(64, 8), + ANIMCMD_FRAME(128, 8), + ANIMCMD_FRAME(192, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_085E6FF4[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_FRAME(128, 4), + ANIMCMD_FRAME(192, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_085E7008[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_085E7010[] = +{ + gUnknown_085E6FE0, + gUnknown_085E6FF4, + gUnknown_085E7008, +}; + +static const struct SpriteSheet gUnknown_085E701C[] = { + { gDecompressionBuffer, 6144, 1001 }, + { NULL }, +}; +static const struct SpritePalette gUnknown_085E702C[] = { + { (const u16 *)(gDecompressionBuffer + 0x1800), 1001 }, + { NULL }, +}; + +static const struct OamData gUnknown_085E703C = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_085E7044[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_085E704C[] = +{ + ANIMCMD_FRAME(64, 8), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_085E7054[] = +{ + ANIMCMD_FRAME(128, 8), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_085E705C[] = +{ + gUnknown_085E7044, + gUnknown_085E704C, + gUnknown_085E7054, +}; + +static const struct SpriteTemplate gUnknown_085E7068 = +{ + .tileTag = 1001, + .paletteTag = 1001, + .oam = &gUnknown_085E703C, + .anims = gUnknown_085E705C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_81772B8, +}; + +void sub_8175620(void); +static void sub_8175744(u8 taskIdA); +static void sub_8175774(u8 taskIdA); +static void sub_8175808(u8 taskIdA); +static void c2_080C9BFC(u8 taskIdA); +static void sub_81758E4(u8 taskIdA); +static void sub_81758A4(u8 taskIdA); +static void sub_8175A9C(u8 taskIdA); +static void sub_8175AE4(u8 taskIdA); +static void sub_8175B1C(u8 taskIdA); +static void sub_8175B90(u8 taskIdA); +static void sub_8175BD8(u8 taskIdA); +static void sub_8175C34(u8 taskIdA); +static void sub_8175CC8(u8 taskIdA); +static void sub_8175CE4(void); +static void sub_8175DA0(u8 taskIdB); +static u8 sub_817603C(u8 page, u8 taskIdA); +static void sub_81760FC(u8 taskIdA); +static void sub_817651C(u8 taskIdA); +static void sub_817624C(u8 taskIdA); +static bool8 sub_8176AB0(u8 data, u8 taskIdA); +static void sub_8176CA0(u8 taskIdA); +static void sub_8176D1C(u16, u16, u16); +static void sub_8176E40(u16 arg0, u16 palette); +static void sub_8176EE8(struct Sprite *sprite); +static void sub_8176F90(struct Sprite *sprite); +static u8 sub_8177224(u16 species, s16 x, s16 y, u16 position); +static void sub_8177388(void); + +static void sub_81754C8(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void sub_81754DC(void) +{ + RunTasks(); + AnimateSprites(); + + if ((gMain.heldKeys & B_BUTTON) + && gHasHallOfFameRecords != 0 + && gTasks[gUnknown_0203BCE2].func == sub_8175774) + { + sub_81754C8(); + RunTasks(); + AnimateSprites(); + gUnknown_0203BCE5 = 1; + } + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void sub_8175548(void) +{ + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, gUnknown_085E6F68, 1); + SetBgTilemapBuffer(0, AllocZeroed(0x800)); + LoadPalette(gUnknown_085E56F0, 0x80, 0x40); + InitWindows(gUnknown_085E6F6C); + DeactivateAllTextPrinters(); + PutWindowTilemap(0); + CopyWindowToVram(0, 3); + ShowBg(0); +} + +static void sub_81755A4(void) +{ + void *ptr; + FreeAllWindowBuffers(); + ptr = GetBgTilemapBuffer(0); + if (ptr) + Free(ptr); +} + +static void sub_81755BC(const u8 *string, u8 y, u8 a2) +{ + u8 x; + u8 color[3]; + + color[0] = 0; + + if (a2 == 1) + { + color[1] = 3; + color[2] = 4; + } + else + { + color[1] = 1; + color[2] = 2; + } + + x = GetStringCenterAlignXOffsetWithLetterSpacing(1, string, 0xF0, 1); + AddTextPrinterParameterized2(0, 1, x, y, 1, 0, color, -1, string); +} + +void sub_8175620(void) +{ + u8 taskIdA; + s16 taskIdC; + u8 taskIdB; + u16 savedIme; + + sub_8175CE4(); + SetVBlankCallback(NULL); + InitHeap(gHeap, HEAP_SIZE); + ResetPaletteFade(); + ResetTasks(); + sub_8175548(); + + taskIdA = CreateTask(sub_8175744, 0); + + gTasks[taskIdA].data[TDA_4] = 0; + gTasks[taskIdA].data[TDA_7] = 0; + gTasks[taskIdA].data[TDA_11] = 0; + gTasks[taskIdA].data[TDA_13] = 1; + + while (TRUE) + { + if (sub_8176AB0(0, taskIdA)) + break; + } + + taskIdC = gTasks[taskIdA].data[TDA_TASK_C_ID]; + gTasks[taskIdC].data[TDC_0] = 40; + + SetGpuReg(REG_OFFSET_BG0VOFS, 0xFFFC); + + taskIdB = CreateTask(sub_8175DA0, 0); + + gTasks[taskIdB].data[TDB_TASK_A_ID] = taskIdA; + gTasks[taskIdA].data[TDA_TASK_B_ID] = taskIdB; + + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + EnableInterrupts(INTR_FLAG_VBLANK); + SetVBlankCallback(sub_81754C8); + m4aSongNumStart(MUS_THANKFOR); + SetMainCallback2(sub_81754DC); + gUnknown_0203BCE5 = 0; + gUnknown_0203BCE8 = AllocZeroed(sizeof(struct Unk201C000)); + + sub_8177388(); + + gUnknown_0203BCE8->unk8E = 0; + gUnknown_0203BCE8->unk90 = 0; + gUnknown_0203BCE8->unk92 = 0; + + gUnknown_0203BCE2 = taskIdA; +} + +static void sub_8175744(u8 taskIdA) +{ + if (!gPaletteFade.active) + gTasks[taskIdA].func = sub_8175774; +} + +static void sub_8175774(u8 taskIdA) +{ + u16 data1; + + if (gTasks[taskIdA].data[TDA_4]) + { + s16 taskIdC; + + taskIdC = gTasks[taskIdA].data[TDA_TASK_C_ID]; + gTasks[taskIdC].data[TDC_0] = 30; + + gTasks[taskIdA].data[TDA_12] = 0x100; + gTasks[taskIdA].func = sub_8175A9C; + return; + } + + gUnknown_0203BCE0 = 0; + data1 = gTasks[taskIdA].data[TDA_11]; + + if (gTasks[taskIdA].data[TDA_11] == 1) + { + gTasks[taskIdA].data[TDA_13] = data1; + gTasks[taskIdA].data[TDA_11] = 0; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + gTasks[taskIdA].func = sub_8175808; + } + else if (gTasks[taskIdA].data[TDA_11] == 2) + { + gTasks[taskIdA].data[TDA_13] = data1; + gTasks[taskIdA].data[TDA_11] = 0; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + gTasks[taskIdA].func = sub_81758A4; + } +} + +static void sub_8175808(u8 taskIdA) +{ + if (!gPaletteFade.active) + { + SetGpuReg(REG_OFFSET_DISPCNT, 0); + sub_8176CA0(taskIdA); + gTasks[taskIdA].func = c2_080C9BFC; + } +} + +static void c2_080C9BFC(u8 taskIdA) +{ + u16 backup; + + SetVBlankCallback(NULL); + + if (sub_8176AB0(gTasks[taskIdA].data[TDA_7], taskIdA)) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + EnableInterrupts(INTR_FLAG_VBLANK); + SetVBlankCallback(sub_81754C8); + gTasks[taskIdA].func = sub_8175744; + } +} + +static void sub_81758A4(u8 taskIdA) +{ + if (!gPaletteFade.active) + { + SetGpuReg(REG_OFFSET_DISPCNT, 0); + sub_8176CA0(taskIdA); + gTasks[taskIdA].func = sub_81758E4; + } +} + +static void sub_81758E4(u8 taskIdA) +{ + switch (gMain.state) + { + default: + case 0: + { + u16 i; + u16 *temp; + + ResetSpriteData(); + dp13_810BB8C(); + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 8; + LZ77UnCompVram(&gBirchHelpGfx, (void *)VRAM); + LZ77UnCompVram(&gBirchGrassTilemap, (void *)(VRAM + 0x3800)); + LoadPalette(gBirchBagGrassPal[0] + 1, 1, 31 * 2); + + for (i = 0; i < 0x800; i++) + gDecompressionBuffer[i] = 0x11; + for (i = 0; i < 0x800; i++) + (gDecompressionBuffer + 0x800)[i] = 0x22; + for (i = 0; i < 0x800; i++) + (gDecompressionBuffer + 0x1000)[i] = 0x33; + + temp = (u16 *)(&gDecompressionBuffer[0x1800]); + temp[0] = RGB_BLACK; + temp[1] = RGB(31, 31, 20); // light yellow + temp[2] = RGB(31, 20, 20); // light red + temp[3] = RGB(20, 20, 31); // light blue + + LoadSpriteSheet(gUnknown_085E701C); + LoadSpritePalette(gUnknown_085E702C); + + gMain.state += 1; + break; + } + case 1: + gTasks[taskIdA].data[TDA_TASK_D_ID] = CreateTask(sub_81760FC, 0); + gTasks[gTasks[taskIdA].data[TDA_TASK_D_ID]].data[TDD_STATE] = 1; + gTasks[gTasks[taskIdA].data[TDA_TASK_D_ID]].data[TDD_TASK_A_ID] = taskIdA; + gTasks[gTasks[taskIdA].data[TDA_TASK_D_ID]].data[TDD_2] = gTasks[taskIdA].data[TDA_7]; + + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 32); + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) + | BGCNT_CHARBASE(0) + | BGCNT_SCREENBASE(7) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_BG3_ON + | DISPCNT_OBJ_ON); + + gMain.state = 0; + gUnknown_0203BD28 = 0; + gTasks[taskIdA].func = sub_8175744; + break; + } +} + +static void sub_8175A9C(u8 taskIdA) +{ + if (gTasks[taskIdA].data[TDA_12]) + { + gTasks[taskIdA].data[TDA_12] -= 1; + return; + } + + BeginNormalPaletteFade(0xFFFFFFFF, 12, 0, 16, RGB_BLACK); + gTasks[taskIdA].func = sub_8175AE4; +} + +static void sub_8175AE4(u8 taskIdA) +{ + if (!gPaletteFade.active) + { + sub_8176CA0(taskIdA); + gTasks[taskIdA].func = sub_8175B1C; + } +} + +static void sub_8175B1C(u8 taskIdA) +{ + sub_8175CE4(); + ResetPaletteFade(); + sub_8176D1C(0, 0x3800, 0); + ResetSpriteData(); + FreeAllSpritePalettes(); + BeginNormalPaletteFade(0xFFFFFFFF, 8, 16, 0, RGB_BLACK); + + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(0) + | BGCNT_SCREENBASE(7) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + EnableInterrupts(INTR_FLAG_VBLANK); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON); + + gTasks[taskIdA].data[TDA_0] = 0xEB; + gTasks[taskIdA].func = sub_8175B90; +} + +static void sub_8175B90(u8 taskIdA) +{ + if (gTasks[taskIdA].data[TDA_0]) + { + gTasks[taskIdA].data[TDA_0] -= 1; + return; + } + + BeginNormalPaletteFade(0xFFFFFFFF, 6, 0, 16, RGB_BLACK); + gTasks[taskIdA].func = sub_8175BD8; +} + +static void sub_8175BD8(u8 taskIdA) +{ + if (!gPaletteFade.active) + { + sub_8176E40(0x3800, 0); + + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0, RGB_BLACK); + gTasks[taskIdA].data[TDA_0] = 7200; + gTasks[taskIdA].func = sub_8175C34; + } +} + +static void sub_8175C34(u8 taskIdA) +{ + if (!gPaletteFade.active) + { + if (gTasks[taskIdA].data[TDA_0] == 0 || gMain.newKeys) + { + FadeOutBGM(4); + BeginNormalPaletteFade(0xFFFFFFFF, 8, 0, 16, RGB_WHITEALPHA); + gTasks[taskIdA].func = sub_8175CC8; + return; + } + + if (gTasks[taskIdA].data[TDA_0] == 7144) + FadeOutBGM(8); + + if (gTasks[taskIdA].data[TDA_0] == 6840) + m4aSongNumStart(MUS_END); + + gTasks[taskIdA].data[TDA_0] -= 1; + } +} + +static void sub_8175CC8(u8 taskIdA) +{ + if (!gPaletteFade.active) + SoftReset(0xFF); +} + +static void sub_8175CE4(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + + DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); + DmaFill32(3, 0, (void *)OAM, OAM_SIZE); + DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); +} + +static void sub_8175DA0(u8 taskIdB) +{ + int i; + + switch (gTasks[taskIdB].data[TDB_0]) + { + case 0: + case 6: + case 7: + case 8: + case 9: + default: + if (!gPaletteFade.active) + { + gTasks[taskIdB].data[TDB_0] = 1; + gTasks[taskIdB].data[TDB_3] = 0x48; + gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_14] = 0; + gUnknown_0203BCE0 = 0; + } + return; + case 1: + if (gTasks[taskIdB].data[TDB_3] != 0) + { + gTasks[taskIdB].data[TDB_3] -= 1; + return; + } + gTasks[taskIdB].data[TDB_0] += 1; + return; + case 2: + if (gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].func == sub_8175774) + { + if (gTasks[taskIdB].data[TDB_CURRENT_PAGE] < PAGE_COUNT) + { + for (i = 0; i < 5; i++) + sub_81755BC(gCreditsEntryPointerTable[gTasks[taskIdB].data[TDB_CURRENT_PAGE]][i]->text, 5 + i * 16, gCreditsEntryPointerTable[gTasks[taskIdB].data[TDB_CURRENT_PAGE]][i]->var_1); + + CopyWindowToVram(0, 2); + + gTasks[taskIdB].data[TDB_CURRENT_PAGE] += 1; + gTasks[taskIdB].data[TDB_0] += 1; + + gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_14] = 1; + + if (gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_13] == 1) + BeginNormalPaletteFade(0x00000300, 0, 16, 0, COLOR_LIGHT_GREEN); + else + BeginNormalPaletteFade(0x00000300, 0, 16, 0, COLOR_DARK_GREEN); + return; + } + gTasks[taskIdB].data[TDB_0] = 10; + return; + } + gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_14] = 0; + return; + case 3: + if (!gPaletteFade.active) + { + gTasks[taskIdB].data[TDB_3] = 0x73; + gTasks[taskIdB].data[TDB_0] += 1; + } + return; + case 4: + if (gTasks[taskIdB].data[TDB_3] != 0) + { + gTasks[taskIdB].data[TDB_3] -= 1; + return; + } + + if (sub_817603C((u8)gTasks[taskIdB].data[TDB_CURRENT_PAGE], (u8)gTasks[taskIdB].data[TDB_TASK_A_ID])) + { + gTasks[taskIdB].data[TDB_0] += 1; + return; + } + gTasks[taskIdB].data[TDB_0] += 1; + if (gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_13] == 1) + BeginNormalPaletteFade(0x00000300, 0, 0, 16, COLOR_LIGHT_GREEN); + else + BeginNormalPaletteFade(0x00000300, 0, 0, 16, COLOR_DARK_GREEN); + return; + case 5: + if (!gPaletteFade.active) + { + FillWindowPixelBuffer(0, 0); + CopyWindowToVram(0, 2); + gTasks[taskIdB].data[TDB_0] = 2; + } + return; + case 10: + gTasks[gTasks[taskIdB].data[TDB_TASK_A_ID]].data[TDA_4] = 1; + DestroyTask(taskIdB); + sub_81755A4(); + FREE_AND_SET_NULL(gUnknown_0203BCE8); + return; + } +} + +static u8 sub_817603C(u8 page, u8 taskIdA) +{ + // Starts with bike + ocean + morning + + if (page == 6) + { + // Grass patch + gTasks[taskIdA].data[TDA_11] = 2; + } + + if (page == 12) + { + // Bike + ocean + sunset + gTasks[taskIdA].data[TDA_7] = 1; + gTasks[taskIdA].data[TDA_11] = 1; + } + + if (page == 18) + { + // Grass patch + gTasks[taskIdA].data[TDA_11] = 2; + } + + if (page == 24) + { + // Bike + forest + sunset + gTasks[taskIdA].data[TDA_7] = 2; + gTasks[taskIdA].data[TDA_11] = 1; + } + + if (page == 30) + { + // Grass patch + gTasks[taskIdA].data[TDA_11] = 2; + } + + if (page == 36) + { + // Bike + forest + sunset + gTasks[taskIdA].data[TDA_7] = 3; + gTasks[taskIdA].data[TDA_11] = 1; + } + + if (page == 42) + { + // Grass patch + gTasks[taskIdA].data[TDA_11] = 2; + } + + if (page == 48) + { + // Bike + town + night + gTasks[taskIdA].data[TDA_7] = 4; + gTasks[taskIdA].data[TDA_11] = 1; + } + + if (gTasks[taskIdA].data[TDA_11] != 0) + { + // Returns true if changed? + return TRUE; + } + + return FALSE; +} + +static void sub_81760FC(u8 taskIdD) +{ + u8 r2; + + switch (gTasks[taskIdD].data[TDD_STATE]) + { + case 0: + break; + case 1: + if (gUnknown_0203BCE8->unk90 == 0 && gTasks[gTasks[taskIdD].data[TDD_TASK_A_ID]].data[TDA_14] == 0) + break; + gTasks[taskIdD].data[TDD_STATE]++; + break; + case 2: + if (gUnknown_0203BCE8->unk8E == 71 || gTasks[gTasks[taskIdD].data[TDD_TASK_A_ID]].func != sub_8175774) + break; + r2 = sub_8177224(gUnknown_0203BCE8->unk0[gUnknown_0203BCE8->unk92], gUnknown_085E6F7C[gUnknown_0203BCE8->unk90][0], gUnknown_085E6F7C[gUnknown_0203BCE8->unk90][1], gUnknown_0203BCE8->unk90); + if (gUnknown_0203BCE8->unk92 < gUnknown_0203BCE8->unk94 - 1) + { + gUnknown_0203BCE8->unk92++; + gSprites[r2].data[3] = 50; + } + else + { + gUnknown_0203BCE8->unk92 = 0; + gSprites[r2].data[3] = 512; + } + gUnknown_0203BCE8->unk8E++; + if (gUnknown_0203BCE8->unk90 == 2) + gUnknown_0203BCE8->unk90 = 0; + else + gUnknown_0203BCE8->unk90++; + gTasks[taskIdD].data[TDD_3] = 50; + gTasks[taskIdD].data[TDD_STATE]++; + break; + case 3: + if (gTasks[taskIdD].data[TDD_3] != 0) + gTasks[taskIdD].data[TDD_3]--; + else + gTasks[taskIdD].data[TDD_STATE] = 1; + break; + } +} + +static void sub_817624C(u8 taskIdC) +{ + switch (gTasks[taskIdC].data[TDC_0]) + { + case 0: + gUnknown_0203BD26 = Sin((gTasks[taskIdC].data[TDC_5] >> 1) & 0x7F, 12); + gTasks[taskIdC].data[TDC_5]++; + break; + case 1: + if (gUnknown_0203BD26 != 0) + { + gUnknown_0203BD26 = Sin((gTasks[taskIdC].data[TDC_5] >> 1) & 0x7F, 12); + gTasks[taskIdC].data[TDC_5]++; + } + else + { + gSprites[gTasks[taskIdC].data[TDC_2]].data[0] = 2; + gTasks[taskIdC].data[TDC_5] = 0; + gTasks[taskIdC].data[TDC_0]++; + } + break; + case 2: + if (gTasks[taskIdC].data[TDC_5] < 64) + { + gTasks[taskIdC].data[TDC_5]++; + gUnknown_0203BD26 = Sin(gTasks[taskIdC].data[TDC_5] & 0x7F, 20); + } + else + { + gTasks[taskIdC].data[TDC_0]++; + } + break; + case 3: + gSprites[gTasks[taskIdC].data[TDC_2]].data[0] = 3; + gSprites[gTasks[taskIdC].data[TDC_3]].data[0] = 1; + gTasks[taskIdC].data[TDC_4] = 120; + gTasks[taskIdC].data[TDC_0]++; + break; + case 4: + if (gTasks[taskIdC].data[TDC_4] != 0) + { + gTasks[taskIdC].data[TDC_4]--; + } + else + { + gTasks[taskIdC].data[TDC_5] = 64; + gTasks[taskIdC].data[TDC_0]++; + } + break; + case 5: + if (gTasks[taskIdC].data[TDC_5] > 0) + { + gTasks[taskIdC].data[TDC_5]--; + gUnknown_0203BD26 = Sin(gTasks[taskIdC].data[TDC_5] & 0x7F, 20); + } + else + { + gSprites[gTasks[taskIdC].data[TDC_2]].data[0] = 1; + gTasks[taskIdC].data[TDC_0]++; + } + break; + case 6: + gTasks[taskIdC].data[TDC_0] = 50; + break; + case 10: + gSprites[gTasks[taskIdC].data[TDC_3]].data[0] = 2; + gTasks[taskIdC].data[TDC_0] = 50; + break; + case 20: + gSprites[gTasks[taskIdC].data[TDC_2]].data[0] = 4; + gTasks[taskIdC].data[TDC_0] = 50; + break; + case 30: + gSprites[gTasks[taskIdC].data[TDC_2]].data[0] = 5; + gSprites[gTasks[taskIdC].data[TDC_3]].data[0] = 3; + gTasks[taskIdC].data[TDC_0] = 50; + break; + case 50: + gTasks[taskIdC].data[TDC_0] = 0; + break; + } +} + +static void sub_817651C(u8 taskIdE) +{ + s16 taskIdC; + + switch (gTasks[taskIdE].data[TDE_0]) + { + default: + case 0: + if (gTasks[taskIdE].data[TDE_1] != 0x7FFF) + { + + if (gTasks[gTasks[gTasks[taskIdE].data[TDE_TASK_A_ID]].data[TDA_TASK_B_ID]].data[TDB_CURRENT_PAGE] == 2) + { + gTasks[gTasks[gTasks[taskIdE].data[TDE_TASK_A_ID]].data[TDA_TASK_C_ID]].data[TDC_0] = 20; + gTasks[taskIdE].data[TDE_1] = 0x7FFF; + } + } + sub_817B540(0); + break; + case 1: + sub_817B540(0); + break; + case 2: + if (gTasks[taskIdE].data[TDE_1] != 0x7FFF) + { + taskIdC = gTasks[gTasks[taskIdE].data[TDE_TASK_A_ID]].data[TDA_TASK_C_ID]; + + // Floor to multiple of 128 + if ((gTasks[taskIdC].data[TDC_5] & -128) == 640) + { + gTasks[taskIdC].data[TDC_0] = 1; + gTasks[taskIdE].data[TDE_1] = 0x7FFF; + } + } + sub_817B540(1); + break; + case 3: + if (gTasks[taskIdE].data[TDE_1] != 0x7FFF) + { + + if (gTasks[taskIdE].data[TDE_1] == 0x248) + { + gTasks[gTasks[gTasks[taskIdE].data[TDE_TASK_A_ID]].data[TDA_TASK_C_ID]].data[TDC_0] = 10; + gTasks[taskIdE].data[TDE_1] = 0x7FFF; + } + else + { + gTasks[taskIdE].data[TDE_1] += 1; + } + } + sub_817B540(1); + break; + case 4: + sub_817B540(2); + break; + } +} + +static void sub_817664C(u8 data, u8 taskIdA) +{ + switch (data) + { + case 0: + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.x = 272; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.x = 272; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].data[0] = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].data[0] = 0; + gTasks[taskIdA].data[TDA_0] = sub_817B3DC(0, 0x2000, 0x20, 8); + break; + case 1: + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.x = 120; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.x = 272; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].data[0] = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].data[0] = 0; + gTasks[taskIdA].data[TDA_0] = sub_817B3DC(0, 0x2000, 0x20, 8); + break; + case 2: + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.x = 120; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.x = 272; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].data[0] = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].data[0] = 0; + gTasks[taskIdA].data[TDA_0] = sub_817B3DC(1, 0x2000, 0x200, 8); + break; + case 3: + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.x = 120; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.x = -32; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].data[0] = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].data[0] = 0; + gTasks[taskIdA].data[TDA_0] = sub_817B3DC(1, 0x2000, 0x200, 8); + break; + case 4: + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].invisible = 0; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.x = 88; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.x = 152; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].pos1.y = 46; + gSprites[gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]].data[0] = 0; + gSprites[gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]].data[0] = 0; + gTasks[taskIdA].data[TDA_0] = sub_817B3DC(2, 0x2000, 0x200, 8); + break; + } + + gTasks[taskIdA].data[TDA_TASK_E_ID] = CreateTask(sub_817651C, 0); + gTasks[gTasks[taskIdA].data[TDA_TASK_E_ID]].data[TDE_0] = data; + gTasks[gTasks[taskIdA].data[TDA_TASK_E_ID]].data[TDE_1] = 0; + gTasks[gTasks[taskIdA].data[TDA_TASK_E_ID]].data[TDE_TASK_A_ID] = taskIdA; + + gTasks[taskIdA].data[TDA_TASK_C_ID] = CreateTask(sub_817624C, 0); + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_0] = 0; + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_1] = taskIdA; + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_2] = gTasks[taskIdA].data[TDA_PLAYER_CYCLIST]; + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_3] = gTasks[taskIdA].data[TDA_RIVAL_CYCLIST]; + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_4] = 0; + + if (data == 2) + gTasks[gTasks[taskIdA].data[TDA_TASK_C_ID]].data[TDC_5] = 0x45; +} + +static bool8 sub_8176AB0(u8 data, u8 taskIdA) +{ + u8 spriteId; + + switch (gMain.state) + { + default: + case 0: + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 8); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + ResetSpriteData(); + FreeAllSpritePalettes(); + gMain.state = 1; + break; + case 1: + gUnknown_0203BD24 = 34; + gUnknown_0203BD26 = 0; + sub_817B1C8(data); + gMain.state += 1; + break; + case 2: + if (gSaveBlock2Ptr->playerGender == MALE) + { + LoadCompressedObjectPic(gUnknown_085F5334); + LoadCompressedObjectPic(gUnknown_085F53BC); + LoadCompressedObjectPic(gUnknown_085F5354); + LoadSpritePalettes(gUnknown_085F5384); + + spriteId = intro_create_brendan_sprite(120, 46); + gTasks[taskIdA].data[TDA_PLAYER_CYCLIST] = spriteId; + gSprites[spriteId].callback = sub_8176EE8; + gSprites[spriteId].anims = gUnknown_085E6FD0; + + spriteId = intro_create_may_sprite(272, 46); + gTasks[taskIdA].data[TDA_RIVAL_CYCLIST] = spriteId; + gSprites[spriteId].callback = sub_8176F90; + gSprites[spriteId].anims = gUnknown_085E7010; + } + else + { + LoadCompressedObjectPic(gUnknown_085F5344); + LoadCompressedObjectPic(gUnknown_085F53AC); + LoadCompressedObjectPic(gUnknown_085F5354); + LoadSpritePalettes(gUnknown_085F5384); + + spriteId = intro_create_may_sprite(120, 46); + gTasks[taskIdA].data[TDA_PLAYER_CYCLIST] = spriteId; + gSprites[spriteId].callback = sub_8176EE8; + gSprites[spriteId].anims = gUnknown_085E6FD0; + + spriteId = intro_create_brendan_sprite(272, 46); + gTasks[taskIdA].data[TDA_RIVAL_CYCLIST] = spriteId; + gSprites[spriteId].callback = sub_8176F90; + gSprites[spriteId].anims = gUnknown_085E7010; + }; + gMain.state += 1; + break; + case 3: + sub_817664C(data, taskIdA); + sub_817B3A8(data); + gMain.state = 0; + return TRUE; + } + return FALSE; +} + +static void sub_8176CA0(u8 taskIdA) +{ + if (gTasks[taskIdA].data[TDA_0] != 0) + { + DestroyTask(gTasks[taskIdA].data[TDA_0]); + gTasks[taskIdA].data[TDA_0] = 0; + } + + if (gTasks[taskIdA].data[TDA_TASK_C_ID] != 0) + { + DestroyTask(gTasks[taskIdA].data[TDA_TASK_C_ID]); + gTasks[taskIdA].data[TDA_TASK_C_ID] = 0; + } + + if (gTasks[taskIdA].data[TDA_TASK_E_ID] != 0) + { + DestroyTask(gTasks[taskIdA].data[TDA_TASK_E_ID]); + gTasks[taskIdA].data[TDA_TASK_E_ID] = 0; + } + + if (gTasks[taskIdA].data[TDA_TASK_D_ID] != 0) + { + DestroyTask(gTasks[taskIdA].data[TDA_TASK_D_ID]); + gTasks[taskIdA].data[TDA_TASK_D_ID] = 0; + } + + gUnknown_0203BD28 = 1; +} + +static void sub_8176D1C(u16 arg0, u16 arg1, u16 arg2) +{ + u16 baseTile; + u16 i; + + LZ77UnCompVram(gCreditsCopyrightEnd_Gfx, (void *)(VRAM + arg0)); + LoadPalette(gIntroCopyright_Pal, arg2, sizeof(gIntroCopyright_Pal)); + + baseTile = (arg2 / 16) << 12; + + for (i = 0; i < 32 * 32; i++) + ((u16 *) (VRAM + arg1))[i] = baseTile + 1; +} + +static u16 sub_8176D78(u8 arg0) +{ + u16 out = (arg0 & 0x3F) + 80; + + if (arg0 == 0xFF) + return 1; + + if (arg0 & (1 << 7)) + out |= 1 << 11; + if (arg0 & (1 << 6)) + out |= 1 << 10; + + return out; +} + +static void sub_8176DBC(const u8 arg0[], u8 baseX, u8 baseY, u16 arg3, u16 palette) +{ + u8 y, x; + const u16 tileOffset = (palette / 16) << 12; + + for (y = 0; y < 5; y++) + { + for (x = 0; x < 3; x++) + ((u16 *) (VRAM + arg3 + (baseY + y) * 64))[baseX + x] = tileOffset + sub_8176D78(arg0[y * 3 + x]); + } +} + +static void sub_8176E40(u16 arg0, u16 palette) +{ + u16 pos; + u16 baseTile = (palette / 16) << 12; + + for (pos = 0; pos < 32 * 32; pos++) + ((u16 *) (VRAM + arg0))[pos] = baseTile + 1; + + sub_8176DBC(gUnknown_085E5BAC, 3, 7, arg0, palette); + sub_8176DBC(gUnknown_085E5BBB, 7, 7, arg0, palette); + sub_8176DBC(gUnknown_085E5BCA, 11, 7, arg0, palette); + sub_8176DBC(gUnknown_085E5BCA, 16, 7, arg0, palette); + sub_8176DBC(gUnknown_085E5BD9, 20, 7, arg0, palette); + sub_8176DBC(gUnknown_085E5BE8, 24, 7, arg0, palette); +} + +static void sub_8176EE8(struct Sprite *sprite) +{ + if (gUnknown_0203BD28 != 0) + { + DestroySprite(sprite); + return; + } + + switch (sprite->data[0]) + { + case 0: + StartSpriteAnimIfDifferent(sprite, 0); + break; + case 1: + StartSpriteAnimIfDifferent(sprite, 1); + if (sprite->pos1.x > -32) + sprite->pos1.x -= 1; + break; + case 2: + StartSpriteAnimIfDifferent(sprite, 2); + break; + case 3: + StartSpriteAnimIfDifferent(sprite, 3); + break; + case 4: + StartSpriteAnimIfDifferent(sprite, 0); + if (sprite->pos1.x > 120) + sprite->pos1.x -= 1; + break; + case 5: + StartSpriteAnimIfDifferent(sprite, 0); + if (sprite->pos1.x > -32) + sprite->pos1.x -= 1; + break; + } +} + +static void sub_8176F90(struct Sprite *sprite) +{ + if (gUnknown_0203BD28 != 0) + { + DestroySprite(sprite); + return; + } + + switch (sprite->data[0]) + { + case 0: + sprite->pos2.y = 0; + StartSpriteAnimIfDifferent(sprite, 0); + break; + case 1: + if (sprite->pos1.x > 200) + StartSpriteAnimIfDifferent(sprite, 1); + else + StartSpriteAnimIfDifferent(sprite, 2); + if (sprite->pos1.x > -32) + sprite->pos1.x -= 2; + sprite->pos2.y = -gUnknown_0203BD26; + break; + case 2: + sprite->data[7] += 1; + StartSpriteAnimIfDifferent(sprite, 0); + if ((sprite->data[7] & 3) == 0) + sprite->pos1.x += 1; + break; + case 3: + StartSpriteAnimIfDifferent(sprite, 0); + if (sprite->pos1.x > -32) + sprite->pos1.x -= 1; + break; + } +} + +static void sub_8177050(struct Sprite *sprite) +{ + if (gUnknown_0203BD28) + { + sub_818D820(sprite->data[6]); + return; + } + + sprite->data[7] += 1; + switch (sprite->data[0]) + { + case 0: + default: + sprite->oam.affineMode = 1; + sprite->oam.matrixNum = sprite->data[1]; + sprite->data[2] = 16; + SetOamMatrix(sprite->data[1], 0x10000 / sprite->data[2], 0, 0, 0x10000 / sprite->data[2]); + sprite->invisible = FALSE; + sprite->data[0] = 1; + break; + case 1: + if (sprite->data[2] < 256) + { + sprite->data[2] += 8; + SetOamMatrix(sprite->data[1], 0x10000 / sprite->data[2], 0, 0, 0x10000 / sprite->data[2]); + } + else + { + sprite->data[0] += 1; + } + switch (sprite->data[1]) + { + case 1: + if ((sprite->data[7] & 3) == 0) + sprite->pos1.y += 1; + sprite->pos1.x -= 2; + break; + case 2: + break; + case 3: + if ((sprite->data[7] & 3) == 0) + sprite->pos1.y += 1; + sprite->pos1.x += 2; + break; + } + break; + case 2: + if (sprite->data[3] != 0) + { + sprite->data[3] -= 1; + } + else + { + SetGpuReg(REG_OFFSET_BLDCNT, 0xF40); + SetGpuReg(REG_OFFSET_BLDALPHA, 0x10); + sprite->oam.objMode = 1; + sprite->data[3] = 16; + sprite->data[0] += 1; + } + break; + case 3: + if (sprite->data[3] != 0) + { + int data3; + + sprite->data[3] -= 1; + + data3 = 16 - sprite->data[3]; + SetGpuReg(REG_OFFSET_BLDALPHA, (data3 << 8) + sprite->data[3]); + } + else + { + sprite->invisible = TRUE; + sprite->data[0] = 9; + } + break; + case 9: + sprite->data[0] += 1; + break; + case 10: + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + sub_818D820(sprite->data[6]); + break; + } +} + +static u8 sub_8177224(u16 species, s16 x, s16 y, u16 position) +{ + u8 spriteId; + u8 spriteId2; + + spriteId = sub_80C0E9C(species, x, y, position); + gSprites[spriteId].oam.priority = 1; + gSprites[spriteId].data[1] = position + 1; + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].callback = sub_8177050; + gSprites[spriteId].data[6] = spriteId; + + spriteId2 = CreateSprite(&gUnknown_085E7068, gSprites[spriteId].pos1.x, gSprites[spriteId].pos1.y, 1); + gSprites[spriteId2].data[0] = spriteId; + + StartSpriteAnimIfDifferent(&gSprites[spriteId2], position); + + return spriteId; +} + +static void sub_81772B8(struct Sprite *sprite) +{ + if (gSprites[sprite->data[0]].data[0] == 10 || gUnknown_0203BD28) + { + DestroySprite(sprite); + return; + } + + sprite->invisible = gSprites[sprite->data[0]].invisible; + sprite->oam.objMode = gSprites[sprite->data[0]].oam.objMode; + sprite->oam.affineMode = gSprites[sprite->data[0]].oam.affineMode; + sprite->oam.matrixNum = gSprites[sprite->data[0]].oam.matrixNum; + sprite->pos1.x = gSprites[sprite->data[0]].pos1.x; + sprite->pos1.y = gSprites[sprite->data[0]].pos1.y; +} + +static void sub_8177388(void) +{ + u16 starter = SpeciesToNationalPokedexNum(GetStarterPokemon(VarGet(VAR_FIRST_POKE))); + u16 page; + u16 dexNum; + u16 j; + + for (dexNum = 1, j = 0; dexNum < 386; dexNum++) + { + if (GetSetPokedexFlag(dexNum, 1)) + { + gUnknown_0203BCE8->unk96[j] = dexNum; + j++; + } + } + + for (dexNum = j; dexNum < 386; dexNum++) + gUnknown_0203BCE8->unk96[dexNum] = 0; + + gUnknown_0203BCE8->unk39A = j; + if (gUnknown_0203BCE8->unk39A < 71) + gUnknown_0203BCE8->unk94 = j; + else + gUnknown_0203BCE8->unk94 = 71; + + j = 0; + do + { + page = Random() % gUnknown_0203BCE8->unk39A; + gUnknown_0203BCE8->unk0[j] = gUnknown_0203BCE8->unk96[page]; + + j++; + gUnknown_0203BCE8->unk96[page] = 0; + gUnknown_0203BCE8->unk39A--; + if (page != gUnknown_0203BCE8->unk39A) + { + gUnknown_0203BCE8->unk96[page] = gUnknown_0203BCE8->unk96[gUnknown_0203BCE8->unk39A]; + gUnknown_0203BCE8->unk96[gUnknown_0203BCE8->unk39A] = 0; + } + } + while (gUnknown_0203BCE8->unk39A != 0 && j < 71); + + if (gUnknown_0203BCE8->unk94 < 71) + { + for (j = gUnknown_0203BCE8->unk94, page = 0; j < 71; j++) + { + gUnknown_0203BCE8->unk0[j] = gUnknown_0203BCE8->unk0[page]; + + page++; + if (page == gUnknown_0203BCE8->unk94) + page = 0; + } + gUnknown_0203BCE8->unk0[70] = starter; + } + else + { + for (dexNum = 0; gUnknown_0203BCE8->unk0[dexNum] != starter && dexNum < 71; dexNum++); + + if (dexNum < gUnknown_0203BCE8->unk94 - 1) + { + gUnknown_0203BCE8->unk0[dexNum] = gUnknown_0203BCE8->unk0[70]; + gUnknown_0203BCE8->unk0[70] = starter; + } + else + { + gUnknown_0203BCE8->unk0[70] = starter; + } + } + gUnknown_0203BCE8->unk94 = 71; +} diff --git a/src/daycare.c b/src/daycare.c index 89c0a48d8..d567ff79a 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -41,12 +41,11 @@ extern const u8 gDaycareText_PlayOther[]; extern u8 GetCursorSelectionMonId(void); extern u16 ItemIdToBattleMoveId(u16); extern s32 ListMenuHandleInputGetItemId(u8); -extern void sub_81AE6C8(u8, u16*, u16*); +extern void DestroyListMenuTask(u8, u16*, u16*); extern void sub_819746C(u8, bool8); extern void NewMenuHelpers_DrawStdWindowFrame(u8, bool8); extern void sub_81B9328(void); -extern void sub_81AF078(u32, bool8, struct ListMenu *); -extern void c2_exit_to_overworld_2_switch(void); +extern void CB2_ReturnToField(void); // this file's functions static void ClearDaycareMonMisc(struct DaycareMiscMon *misc); @@ -79,18 +78,18 @@ static const struct ListMenuTemplate sDaycareListMenuLevelTemplate = .unk_08 = DaycarePrintMonInfo, .totalItems = 3, .maxShowed = 3, - .unk_10 = 0, + .windowId = 0, .unk_11 = 0, .unk_12 = 8, - .cursor_Y = 0, + .cursor_X = 0, .upText_Y = 1, - .cursorColor = 2, - .fillColor = 1, - .cursorShadowColor = 3, - .unk_16_0 = TRUE, - .spaceBetweenItems = 0, - .unk_16_7 = FALSE, - .unk_17_0 = 1, + .cursorPal = 2, + .fillValue = 1, + .cursorShadowPal = 3, + .lettersSpacing = 1, + .unk_16_3 = 0, + .scrollMultiple = LIST_NO_MULTIPLE_SCROLL, + .fontId = 1, .cursorKind = 0 }; @@ -1271,7 +1270,7 @@ static void Task_HandleDaycareLevelMenuInput(u8 taskId) gSpecialVar_Result = 2; break; } - sub_81AE6C8(gTasks[taskId].tMenuListTaskId, NULL, NULL); + DestroyListMenuTask(gTasks[taskId].tMenuListTaskId, NULL, NULL); sub_819746C(gTasks[taskId].tWindowId, TRUE); RemoveWindow(gTasks[taskId].tWindowId); DestroyTask(taskId); @@ -1280,7 +1279,7 @@ static void Task_HandleDaycareLevelMenuInput(u8 taskId) else if (gMain.newKeys & B_BUTTON) { gSpecialVar_Result = 2; - sub_81AE6C8(gTasks[taskId].tMenuListTaskId, NULL, NULL); + DestroyListMenuTask(gTasks[taskId].tMenuListTaskId, NULL, NULL); sub_819746C(gTasks[taskId].tWindowId, TRUE); RemoveWindow(gTasks[taskId].tWindowId); DestroyTask(taskId); @@ -1299,7 +1298,7 @@ void ShowDaycareLevelMenu(void) NewMenuHelpers_DrawStdWindowFrame(windowId, FALSE); menuTemplate = sDaycareListMenuLevelTemplate; - menuTemplate.unk_10 = windowId; + menuTemplate.windowId = windowId; listMenuTaskId = ListMenuInit(&menuTemplate, 0, 0); CopyWindowToVram(windowId, 3); @@ -1315,5 +1314,5 @@ void ShowDaycareLevelMenu(void) void ChooseSendDaycareMon(void) { sub_81B9328(); - gMain.savedCallback = c2_exit_to_overworld_2_switch; + gMain.savedCallback = CB2_ReturnToField; } diff --git a/src/decompress.c b/src/decompress.c index 8e8827194..1d4165d75 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -117,7 +117,7 @@ void Unused_LZDecompressWramIndirect(const void **src, void *dest) } // This one (unused) function is really challenging, won't even try to decompile it. -__attribute__((naked)) +NAKED void sub_803471C() { asm(".syntax unified\n\ diff --git a/src/decoration.c b/src/decoration.c index db19ff4c6..1fc94c80e 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -111,7 +111,7 @@ void sub_812719C(u8 taskId); void sub_81271CC(u8 taskId); void sub_8127268(u8 taskId); void sub_8127454(u8 *dest, u16 decorId); -void sub_8127480(u32 a0, bool8 flag, struct ListMenu *menu); +void sub_8127480(s32 a0, bool8 flag, struct ListMenu *menu); void sub_81274A0(u8 a0, s32 a1, u8 a2); void sub_8127620(u8 taskId); void sub_812764C(u8 taskId); @@ -560,7 +560,7 @@ void SecretBasePC_Cancel(u8 taskId) } else { - sub_816B060(taskId); + ReshowPlayerPC(taskId); } } @@ -799,7 +799,7 @@ void sub_8127330(u8 taskId) sDecorPCBuffer->items[i].name = sDecorPCBuffer->names[i]; sDecorPCBuffer->items[i].id = -2; gMultiuseListMenuTemplate = gUnknown_085A6BD0; - gMultiuseListMenuTemplate.unk_10 = sDecorMenuWindowIndices[1]; + gMultiuseListMenuTemplate.windowId = sDecorMenuWindowIndices[1]; gMultiuseListMenuTemplate.totalItems = sDecorPCBuffer->unk_520; gMultiuseListMenuTemplate.items = sDecorPCBuffer->items; gMultiuseListMenuTemplate.maxShowed = sDecorPCBuffer->unk_521; @@ -811,7 +811,7 @@ void sub_8127454(u8 *dest, u16 decorId) StringAppend(dest, gDecorations[decorId].name); } -void sub_8127480(u32 a0, bool8 flag, struct ListMenu *menu) +void sub_8127480(s32 a0, bool8 flag, struct ListMenu *menu) { if (flag != TRUE) { @@ -890,7 +890,7 @@ void sub_812764C(u8 taskId) if (!gPaletteFade.active) { input = ListMenuHandleInputGetItemId(data[13]); - sub_81AE860(data[13], &sSecretBasePCSelectDecorPageNo, &sSecretBasePCSelectDecorLineNo); + ListMenuGetScrollAndRow(data[13], &sSecretBasePCSelectDecorPageNo, &sSecretBasePCSelectDecorLineNo); switch (input) { case -1: @@ -903,7 +903,7 @@ void sub_812764C(u8 taskId) PlaySE(SE_SELECT); gCurDecorationIndex = input; sub_8127554(); - sub_81AE6C8(data[13], &sSecretBasePCSelectDecorPageNo, &sSecretBasePCSelectDecorLineNo); + DestroyListMenuTask(data[13], &sSecretBasePCSelectDecorPageNo, &sSecretBasePCSelectDecorLineNo); sub_8126A58(1); sub_81277A8(); free(sDecorPCBuffer); @@ -1072,7 +1072,7 @@ void sub_8127A8C(u8 taskId) data = gTasks[taskId].data; sub_8127554(); sub_81277A8(); - sub_81AE6C8(data[13], NULL, NULL); + DestroyListMenuTask(data[13], NULL, NULL); free(sDecorPCBuffer); sub_8126E44(taskId); } @@ -1292,7 +1292,7 @@ void sub_8128060(u8 taskId) gTasks[taskId].data[2] = 2; break; case 2: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].data[12] = 0; sub_8128FD8(taskId); @@ -1303,12 +1303,12 @@ void sub_8128060(u8 taskId) void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor) { - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; - gUnknown_03005DD0.unk4 = gpu_pal_decompress_alloc_tag_and_upload(data, decor); - gSprites[gUnknown_03005DD0.unk4].oam.priority = 1; - gSprites[gUnknown_03005DD0.unk4].callback = sub_81292D0; - gSprites[gUnknown_03005DD0.unk4].pos1.x = gUnknown_085A7250[data->decoration->shape].x; - gSprites[gUnknown_03005DD0.unk4].pos1.y = gUnknown_085A7250[data->decoration->shape].y; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; + gUnknown_03005DD0.spriteId = gpu_pal_decompress_alloc_tag_and_upload(data, decor); + gSprites[gUnknown_03005DD0.spriteId].oam.priority = 1; + gSprites[gUnknown_03005DD0.spriteId].callback = sub_81292D0; + gSprites[gUnknown_03005DD0.spriteId].pos1.x = gUnknown_085A7250[data->decoration->shape].x; + gSprites[gUnknown_03005DD0.spriteId].pos1.y = gUnknown_085A7250[data->decoration->shape].y; } void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data) @@ -1330,7 +1330,7 @@ void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphic } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; } void sub_812826C(u8 taskId) @@ -1682,7 +1682,7 @@ void c1_overworld_prev_quest(u8 taskId) sub_812A3C8(); FreeSpritePaletteByTag(OVERWORLD_PLACE_DECOR_SELECTOR_PAL_TAG); gFieldCallback = sub_8128CD4; - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); DestroyTask(taskId); break; } @@ -1708,7 +1708,7 @@ void sub_8128C64(u8 taskId) data[2] ++; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].func = sub_812764C; } @@ -2218,7 +2218,7 @@ void sub_81298EC(u8 taskId) gTasks[taskId].data[2] = 3; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { StringExpandPlaceholders(gStringVar4, gText_DecorationReturnedToPC); DisplayItemMessageOnField(taskId, gStringVar4, sub_8129D64); @@ -2249,9 +2249,9 @@ bool8 sub_81299AC(u8 taskId) void SetUpPuttingAwayDecorationPlayerAvatar(void) { player_get_direction_lower_nybble(); - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; sub_812A39C(); - gUnknown_03005DD0.unk4 = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); + gUnknown_03005DD0.spriteId = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); if (gSaveBlock2Ptr->playerGender == MALE) { sDecor_CameraSpriteObjectIdx2 = AddPseudoFieldObject(0xC1, SpriteCallbackDummy, 0x88, 0x48, 0); @@ -2262,7 +2262,7 @@ void SetUpPuttingAwayDecorationPlayerAvatar(void) } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; gSprites[sDecor_CameraSpriteObjectIdx1].oam.priority = 1; } @@ -2288,7 +2288,7 @@ void sub_8129ABC(u8 taskId) data[2] = 2; break; case 2: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { data[12] = 1; sub_8129B34(taskId); @@ -2505,30 +2505,27 @@ void sub_812A040(u8 left, u8 top, u8 right, u8 bottom) } } -#ifdef NONMATCHING void sub_812A0E8(u8 taskId) { u8 i; u8 xOff; u8 yOff; - u8 decor; - register u8 decor asm("r1"); - struct DecorRearrangementDataBuffer *data; + u8 var1; + u32 var2; sCurDecorSelectedInRearrangement = 0; if (sub_8129FC8(taskId) != TRUE) { - for (i = 0; i < gUnknown_0203A17C.size; i ++) + for (i = 0; i < gUnknown_0203A17C.size; i++) { - decor = gUnknown_0203A17C.items[i]; - if (decor != DECOR_NONE) + var1 = gUnknown_0203A17C.items[i]; + if (var1 != DECOR_NONE) { - data = &sDecorRearrangementDataBuffer[0]; - sub_8129D8C(decor, data); - if (sub_8129E74(taskId, i, data) == TRUE) + sub_8129D8C(var1, &sDecorRearrangementDataBuffer[0]); + if (sub_8129E74(taskId, i, &sDecorRearrangementDataBuffer[0]) == TRUE) { - data->idx = i; - sCurDecorSelectedInRearrangement ++; + sDecorRearrangementDataBuffer[0].idx = i; + sCurDecorSelectedInRearrangement++; break; } } @@ -2537,95 +2534,13 @@ void sub_812A0E8(u8 taskId) { xOff = gUnknown_0203A17C.pos[sDecorRearrangementDataBuffer[0].idx] >> 4; yOff = gUnknown_0203A17C.pos[sDecorRearrangementDataBuffer[0].idx] & 0x0F; - sub_812A040(xOff, yOff - sDecorRearrangementDataBuffer[0].height + 1, xOff + sDecorRearrangementDataBuffer[0].width - 1, yOff); // Arithmetic register swap at the r2 argument: `add r2, r0, r2` instead of `add r2, r2, r0` + var1 = yOff - sDecorRearrangementDataBuffer[0].height + 1; + var2 = sDecorRearrangementDataBuffer[0].width + xOff - 1; + + sub_812A040(xOff, var1, var2, yOff); } } } -#else -__attribute__((naked)) void sub_812A0E8(u8 taskId) -{ - asm_unified("\tpush {r4-r7,lr}\n" - "\tlsls r0, 24\n" - "\tlsrs r6, r0, 24\n" - "\tldr r4, =sCurDecorSelectedInRearrangement\n" - "\tmovs r0, 0\n" - "\tstrb r0, [r4]\n" - "\tadds r0, r6, 0\n" - "\tbl sub_8129FC8\n" - "\tlsls r0, 24\n" - "\tlsrs r0, 24\n" - "\tcmp r0, 0x1\n" - "\tbeq _0812A18C\n" - "\tmovs r5, 0\n" - "\tldr r0, =gUnknown_0203A17C\n" - "\tldrb r1, [r0, 0x8]\n" - "\tcmp r5, r1\n" - "\tbcs _0812A15A\n" - "\tadds r7, r4, 0\n" - "_0812A10E:\n" - "\tldr r0, [r0]\n" - "\tadds r0, r5\n" - "\tldrb r1, [r0]\n" - "\tcmp r1, 0\n" - "\tbeq _0812A14C\n" - "\tldr r4, =sDecorRearrangementDataBuffer\n" - "\tadds r0, r1, 0\n" - "\tadds r1, r4, 0\n" - "\tbl sub_8129D8C\n" - "\tadds r0, r6, 0\n" - "\tadds r1, r5, 0\n" - "\tadds r2, r4, 0\n" - "\tbl sub_8129E74\n" - "\tlsls r0, 24\n" - "\tlsrs r0, 24\n" - "\tcmp r0, 0x1\n" - "\tbne _0812A14C\n" - "\tstrb r5, [r4]\n" - "\tldrb r0, [r7]\n" - "\tadds r0, 0x1\n" - "\tstrb r0, [r7]\n" - "\tb _0812A15A\n" - "\t.pool\n" - "_0812A14C:\n" - "\tadds r0, r5, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r5, r0, 24\n" - "\tldr r0, =gUnknown_0203A17C\n" - "\tldrb r1, [r0, 0x8]\n" - "\tcmp r5, r1\n" - "\tbcc _0812A10E\n" - "_0812A15A:\n" - "\tldr r0, =sCurDecorSelectedInRearrangement\n" - "\tldrb r0, [r0]\n" - "\tcmp r0, 0\n" - "\tbeq _0812A18C\n" - "\tldr r0, =gUnknown_0203A17C\n" - "\tldr r2, =sDecorRearrangementDataBuffer\n" - "\tldrb r1, [r2]\n" - "\tldr r0, [r0, 0x4]\n" - "\tadds r0, r1\n" - "\tldrb r1, [r0]\n" - "\tlsrs r0, r1, 4\n" - "\tmovs r3, 0xF\n" - "\tands r3, r1\n" - "\tldrb r1, [r2, 0x2]\n" - "\tsubs r1, r3, r1\n" - "\tadds r1, 0x1\n" - "\tlsls r1, 24\n" - "\tlsrs r1, 24\n" - "\tldrb r2, [r2, 0x1]\n" - "\tadds r2, r0\n" - "\tsubs r2, 0x1\n" - "\tlsls r2, 24\n" - "\tlsrs r2, 24\n" - "\tbl sub_812A040\n" - "_0812A18C:\n" - "\tpop {r4-r7}\n" - "\tpop {r0}\n" - "\tbx r0\n" - "\t.pool"); -} -#endif void sub_812A1A0(u8 taskId) { @@ -2673,7 +2588,7 @@ void sub_812A25C(u8 taskId) case 1: sub_812A3C8(); gFieldCallback = sub_812A334; - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); DestroyTask(taskId); break; } @@ -2699,7 +2614,7 @@ void sub_812A2C4(u8 taskId) data[2] ++; break; case 3: - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { gTasks[taskId].func = sub_8126B80; } diff --git a/src/dewford_trend.c b/src/dewford_trend.c new file mode 100644 index 000000000..3ceec6563 --- /dev/null +++ b/src/dewford_trend.c @@ -0,0 +1,340 @@ +#include "global.h" +#include "dewford_trend.h" +#include "easy_chat.h" +#include "constants/easy_chat.h" +#include "event_data.h" +#include "link.h" +#include "malloc.h" +#include "random.h" +#include "text.h" +#include "tv.h" + +// static functions +static void sub_8122804(struct EasyChatPair *s, u16 b, u8 c); +static bool8 sub_8122A58(struct EasyChatPair *a, struct EasyChatPair *b, u8 c); +static void sub_8122B28(struct EasyChatPair *s); +static bool8 SB1ContainsWords(u16 *a); +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2); +static s16 GetEqualEasyChatPairIndex(struct EasyChatPair *s, struct EasyChatPair *a, u16 b); + +// text +void InitDewfordTrend(void) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + gSaveBlock1Ptr->easyChatPairs[i].words[0] = sub_811EE38(EC_GROUP_CONDITIONS); + + if (Random() & 1) + gSaveBlock1Ptr->easyChatPairs[i].words[1] = sub_811EE38(EC_GROUP_LIFESTYLE); + else + gSaveBlock1Ptr->easyChatPairs[i].words[1] = sub_811EE38(EC_GROUP_HOBBIES); + + gSaveBlock1Ptr->easyChatPairs[i].unk1_6 = Random() & 1; + sub_8122B28(&(gSaveBlock1Ptr->easyChatPairs[i])); + } + sub_8122804(gSaveBlock1Ptr->easyChatPairs, 5, 0); +} + +void UpdateDewfordTrendPerDay(u16 a) +{ + u16 i; + + if (a != 0) + { + u32 sp0 = a * 5; + + for (i = 0; i < 5; i++) + { + u32 r4; + u32 r2 = sp0; + struct EasyChatPair *r5 = &(gSaveBlock1Ptr->easyChatPairs[i]); + + if (r5->unk1_6 == 0) + { + if (r5->unk0_0 >= (u16)r2) + { + r5->unk0_0 -= r2; + if (r5->unk0_0 == 0) + r5->unk1_6 = 1; + continue; + } + r2 -= r5->unk0_0; + r5->unk0_0 = 0; + r5->unk1_6 = 1; + } + r4 = r5->unk0_0 + r2; + if ((u16)r4 > r5->unk0_7) + { + u32 sp4 = r4 % r5->unk0_7; + r4 = r4 / r5->unk0_7; + + r5->unk1_6 = r4 ^ 1; + if (r5->unk1_6) + r5->unk0_0 = sp4; + else + r5->unk0_0 = r5->unk0_7 - sp4; + } + else + { + r5->unk0_0 = r4; + + if (r5->unk0_0 == r5->unk0_7) + r5->unk1_6 = 0; + } + } + sub_8122804(gSaveBlock1Ptr->easyChatPairs, 5, 0); + } +} + + +bool8 sub_81226D8(u16 *a) +{ + struct EasyChatPair s = {0}; + u16 i; + + if (!SB1ContainsWords(a)) + { + if (!FlagGet(FLAG_SYS_POPWORD_INPUT)) + { + FlagSet(FLAG_SYS_POPWORD_INPUT); + if (!FlagGet(FLAG_SYS_MIX_RECORD)) + { + gSaveBlock1Ptr->easyChatPairs[0].words[0] = a[0]; + gSaveBlock1Ptr->easyChatPairs[0].words[1] = a[1]; + return TRUE; + } + } + + s.words[0] = a[0]; + s.words[1] = a[1]; + s.unk1_6 = 1; + sub_8122B28(&s); + + for (i = 0; i < 5; i++) + { + if (sub_8122A58(&s, &(gSaveBlock1Ptr->easyChatPairs[i]), 0)) + { + u16 r3 = 4; + + while (r3 > i) + { + gSaveBlock1Ptr->easyChatPairs[r3] = gSaveBlock1Ptr->easyChatPairs[r3 - 1]; + r3--; + } + gSaveBlock1Ptr->easyChatPairs[i] = s; + if(i == 4) + sub_80EDC60(a); + return (i == 0); + } + } + gSaveBlock1Ptr->easyChatPairs[4] = s; + sub_80EDC60(a); + } + return FALSE; +} + + +static void sub_8122804(struct EasyChatPair *s, u16 b, u8 c) +{ + u16 h; + + for (h = 0; h < b; h++) + { + u16 i; + + for (i = h + 1; i < b; i++) + { + if (sub_8122A58(&s[i], &s[h], c)) + { + struct EasyChatPair temp; + + temp = s[i]; + s[i] = s[h]; + s[h] = temp; + } + } + } +} + +void sub_812287C(void *a, u32 b, u8 unused) +{ + u16 i, j, r3, players; + struct EasyChatPair *buffer1, *buffer2, *src, *dst, *foo_of_buffer2; + + buffer1 = Alloc(0x100); + if(buffer1 != NULL) + { + buffer2 = Alloc(0x100); + if(buffer2 == NULL) + { + Free(buffer1); + } + else + { + players = GetLinkPlayerCount(); + for (i = 0; i < players; i++) + memcpy(&(buffer1[i * 5]), (u8 *)a + i * b, 40); + src = buffer1; + dst = buffer2; + r3 = 0; + for (i = 0; i < players; i++) + { + for (j = 0; j < 5; j++) + { + s16 foo = GetEqualEasyChatPairIndex(buffer2, src, r3); + if (foo < 0) + { + *(dst++) = *src; + r3++; + } + else + { + foo_of_buffer2 = (struct EasyChatPair *)((u32)buffer2 + (foo * 8)); //required to do this to reverse the order of register operands in add ASM statement + if (foo_of_buffer2->unk0_0 < src->unk0_0) + { + *foo_of_buffer2 = *src; + } + } + src++; + } + } + sub_8122804(buffer2, r3, 2); + src = buffer2; + dst = gSaveBlock1Ptr->easyChatPairs; + for (i = 0; i < 5; i++) + *(dst++) = *(src++); + Free(buffer1); + Free(buffer2); + } + } +} + +void BufferTrendyPhraseString(void) +{ + struct EasyChatPair *s = &gSaveBlock1Ptr->easyChatPairs[gSpecialVar_0x8004]; + + ConvertEasyChatWordsToString(gStringVar1, s->words, 2, 1); +} + +void TrendyPhraseIsOld(void) +{ + u16 result = 0; + + if (gSaveBlock1Ptr->easyChatPairs[0].unk0_0 - gSaveBlock1Ptr->easyChatPairs[1].unk0_0 < 2) + { + asm("":::"r2"); //Force the compiler to store address of gSaveBlock1 in r3 instead of r2 + if (!gSaveBlock1Ptr->easyChatPairs[0].unk1_6 && gSaveBlock1Ptr->easyChatPairs[1].unk1_6) + result = 1; + } + gSpecialVar_Result = result; +} + +void GetDewfordHallPaintingNameIndex(void) +{ + gSpecialVar_Result = (gSaveBlock1Ptr->easyChatPairs[0].words[0] + gSaveBlock1Ptr->easyChatPairs[0].words[1]) & 7; +} + +static bool8 sub_8122A58(struct EasyChatPair *a, struct EasyChatPair *b, u8 c) +{ + switch (c) + { + case 0: + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + break; + case 1: + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + break; + case 2: + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + if (a->unk2 > b->unk2) + return 1; + if (a->unk2 < b->unk2) + return 0; + if (a->words[0] > b->words[0]) + return 1; + if (a->words[0] < b->words[0]) + return 0; + if (a->words[1] > b->words[1]) + return 1; + if (a->words[1] < b->words[1]) + return 0; + return 1; + } + return Random() & 1; +} + +static void sub_8122B28(struct EasyChatPair *s) +{ + u16 r4; + + r4 = Random() % 98; + if (r4 > 50) + { + r4 = Random() % 98; + if (r4 > 80) + r4 = Random() % 98; + } + s->unk0_7 = r4 + 30; + s->unk0_0 = (Random() % (r4 + 1)) + 30; + s->unk2 = Random(); +} + +static bool8 SB1ContainsWords(u16 *a) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + if (IsEasyChatPairEqual(a, gSaveBlock1Ptr->easyChatPairs[i].words) != 0) + return TRUE; + } + return FALSE; +} + +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + if (*(words1++) != *(words2++)) + return FALSE; + } + return TRUE; +} + +static s16 GetEqualEasyChatPairIndex(struct EasyChatPair*s, struct EasyChatPair *a, u16 b) +{ + s16 i; + + for (i = 0; i < b; i++) + { + if (IsEasyChatPairEqual(a->words, s->words)) + return i; + s++; + } + return -1; +} diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 5a2fe5ca2..8914d6ff3 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -25,6 +25,7 @@ #include "window.h" #include "constants/abilities.h" #include "daycare.h" +#include "overworld.h" #include "battle.h" // to get rid of later struct EggHatchData @@ -44,9 +45,6 @@ struct EggHatchData u8 textColor[3]; }; -extern struct SpriteTemplate gUnknown_0202499C; -extern void (*gFieldCallback)(void); - extern const struct CompressedSpriteSheet gMonFrontPicTable[]; extern const u8 gBattleTextboxTiles[]; extern const u8 gBattleTextboxTilemap[]; @@ -58,20 +56,14 @@ extern const u8 gText_HatchedFromEgg[]; extern const u8 gText_NickHatchPrompt[]; extern u8 sav1_map_get_name(void); -extern s8 ProcessMenuInputNoWrap_(void); extern void TVShowConvertInternationalString(u8* str1, u8* str2, u8); extern void sub_806A068(u16, u8); extern void FadeScreen(u8, u8); extern void overworld_free_bg_tilemaps(void); extern void sub_80AF168(void); -extern void AllocateMonSpritesGfx(void); -extern void FreeMonSpritesGfx(void); extern void ScanlineEffect_Stop(void); -extern void reset_temp_tile_data_buffers(void); -extern void c2_exit_to_overworld_2_switch(void); +extern void CB2_ReturnToField(void); extern void play_some_sound(void); -extern void copy_decompressed_tile_data_to_vram_autofree(u8 bg_id, const void* src, u16 size, u16 offset, u8 mode); -extern void CreateYesNoMenu(const struct WindowTemplate*, u16, u8, u8); extern void DoNamingScreen(u8, const u8*, u16, u8, u32, MainCallback); extern u16 sub_80D22D0(void); extern u8 CountPartyAliveNonEggMonsExcept(u8); @@ -440,12 +432,12 @@ static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], gMonSpritesGfxPtr->sprites[(a0 * 2) + 1], species, pid); - LoadCompressedObjectPalette(sub_806E794(mon)); + LoadCompressedObjectPalette(GetMonSpritePalStruct(mon)); *speciesLoc = species; } break; case 1: - sub_806A068(sub_806E794(mon)->tag, r5); + sub_806A068(GetMonSpritePalStruct(mon)->tag, r5); spriteID = CreateSprite(&gUnknown_0202499C, 120, 75, 6); gSprites[spriteID].invisible = 1; gSprites[spriteID].callback = SpriteCallbackDummy; @@ -571,7 +563,7 @@ static void EggHatchSetMonNickname(void) SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3); FreeMonSpritesGfx(); Free(sEggHatchData); - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); } static void Task_EggHatchPlayBGM(u8 taskID) @@ -582,10 +574,10 @@ static void Task_EggHatchPlayBGM(u8 taskID) play_some_sound(); } if (gTasks[taskID].data[0] == 1) - PlayBGM(376); + PlayBGM(MUS_ME_SHINKA); if (gTasks[taskID].data[0] > 60) { - PlayBGM(377); + PlayBGM(MUS_SHINKA); DestroyTask(taskID); // UB: task is destroyed, yet the value is incremented } @@ -695,7 +687,7 @@ static void CB2_EggHatch_1(void) UnsetBgTilemapBuffer(0); UnsetBgTilemapBuffer(1); Free(sEggHatchData); - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); } break; } diff --git a/src/evolution_scene.c b/src/evolution_scene.c index f38f9f19c..74eac32de 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -48,9 +48,7 @@ extern u16 gBattle_BG2_X; extern u16 gBattle_BG2_Y; extern u16 gBattle_BG3_X; extern u16 gBattle_BG3_Y; -extern struct SpriteTemplate gUnknown_0202499C; extern bool8 gAffineAnimsDisabled; -extern u16 gMoveToLearn; extern const u8 gSpeciesNames[][11]; #define sEvoCursorPos gBattleCommunication[1] // when learning a new move @@ -60,16 +58,8 @@ extern const struct WindowTemplate gUnknown_0833900C; extern const struct CompressedSpriteSheet gMonFrontPicTable[]; // strings -extern const u8 gText_PkmnIsEvolving[]; -extern const u8 gText_CongratsPkmnEvolved[]; -extern const u8 gText_BattleYesNoChoice[]; -extern const u8 gText_PkmnStoppedEvolving[]; -extern const u8 gText_EllipsisQuestionMark[]; extern const u8 gText_CommunicationStandby5[]; -extern void copy_decompressed_tile_data_to_vram_autofree(u8 arg0, const void *arg1, bool32 arg2, u16 arg3, u8 arg4); -extern u32 sub_80391E0(u8, u8); -extern void SpriteCallbackDummy_2(struct Sprite *sprite); extern void sub_80356D0(void); extern void sub_807B154(void); extern void sub_806A068(u16, u8); @@ -471,10 +461,10 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void) } break; case 6: - if (gLinkVSyncDisabled) + if (gWirelessCommType) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } BlendPalettes(-1,0x10, 0); gMain.state++; @@ -1255,7 +1245,7 @@ static void Task_TradeEvolutionScene(u8 taskID) case 5: if (!gPaletteFade.active) { - if (gLinkVSyncDisabled) + if (gWirelessCommType) sub_800E084(); Free(GetBgTilemapBuffer(3)); diff --git a/src/field_camera.c b/src/field_camera.c index 17ced6aa5..95167ee10 100644 --- a/src/field_camera.c +++ b/src/field_camera.c @@ -1,9 +1,20 @@ - -// Includes #include "global.h" +#include "berry.h" +#include "bike.h" +#include "field_camera.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "field_map_obj.h" +#include "gpu_regs.h" +#include "menu.h" +#include "overworld.h" +#include "rotating_gate.h" +#include "sprite.h" +#include "text.h" -// Static type declarations +EWRAM_DATA bool8 gUnusedBikeCameraAheadPanback = FALSE; +// Static type declarations struct FieldCameraUnknownStruct { u8 unk0; @@ -13,16 +24,478 @@ struct FieldCameraUnknownStruct bool8 unk4; }; -// Static RAM declarations +// static functions +static void RedrawMapSliceNorth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y); +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData); +static void DrawMetatileAt(const struct MapData *mapData, u16, int, int); +static void DrawMetatile(s32 a, u16 *b, u16 c); +static void CameraPanningCB_PanAhead(void); + +// IWRAM bss vars +static IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; +static IWRAM_DATA s16 gUnknown_03000E28; +static IWRAM_DATA s16 gUnknown_03000E2A; +static IWRAM_DATA u8 gUnknown_03000E2C; +static IWRAM_DATA void (*gUnknown_03000E30)(void); + +struct CameraObject gUnknown_03005DD0; +u16 gUnknown_03005DE8; +u16 gUnknown_03005DEC; + +// text +static void move_tilemap_camera_to_upper_left_corner_(struct FieldCameraUnknownStruct *a) +{ + a->unk2 = 0; + a->unk3 = 0; + a->unk0 = 0; + a->unk1 = 0; + a->unk4 = TRUE; +} + +static void tilemap_move_something(struct FieldCameraUnknownStruct *a, u32 b, u32 c) +{ + a->unk2 += b; + a->unk2 %= 32; + a->unk3 += c; + a->unk3 %= 32; +} + +static void coords8_add(struct FieldCameraUnknownStruct *a, u32 b, u32 c) +{ + a->unk0 += b; + a->unk1 += c; +} + +void move_tilemap_camera_to_upper_left_corner(void) +{ + move_tilemap_camera_to_upper_left_corner_(&gUnknown_03000E20); +} + +void FieldUpdateBgTilemapScroll(void) +{ + u32 r4, r5; + r5 = gUnknown_03000E20.unk0 + gUnknown_03000E28; + r4 = gUnknown_03000E2A + gUnknown_03000E20.unk1 + 8; + + SetGpuReg(REG_OFFSET_BG1HOFS, r5); + SetGpuReg(REG_OFFSET_BG1VOFS, r4); + SetGpuReg(REG_OFFSET_BG2HOFS, r5); + SetGpuReg(REG_OFFSET_BG2VOFS, r4); + SetGpuReg(REG_OFFSET_BG3HOFS, r5); + SetGpuReg(REG_OFFSET_BG3VOFS, r4); +} + +void sub_8089C08(s16 *a, s16 *b) +{ + *a = gUnknown_03000E20.unk0 + gUnknown_03000E28; + *b = gUnknown_03000E20.unk1 + gUnknown_03000E2A + 8; +} + +void DrawWholeMapView(void) +{ + DrawWholeMapViewInternal(gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y, gMapHeader.mapData); + gUnknown_03000E20.unk4 = TRUE; +} + +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData) +{ + u8 i; + u8 j; + u32 r6; + u8 temp; + + for (i = 0; i < 32; i += 2) + { + temp = gUnknown_03000E20.unk3 + i; + if (temp >= 32) + temp -= 32; + r6 = temp * 32; + for (j = 0; j < 32; j += 2) + { + temp = gUnknown_03000E20.unk2 + j; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2); + } + } +} + +static void RedrawMapSlicesForCameraUpdate(struct FieldCameraUnknownStruct *a, int x, int y) +{ + const struct MapData *mapData = gMapHeader.mapData; + + if (x > 0) + RedrawMapSliceWest(a, mapData); + if (x < 0) + RedrawMapSliceEast(a, mapData); + if (y > 0) + RedrawMapSliceNorth(a, mapData); + if (y < 0) + RedrawMapSliceSouth(a, mapData); + a->unk4 = TRUE; +} + +static void RedrawMapSliceNorth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7; + + temp = a->unk3 + 28; + if (temp >= 32) + temp -= 32; + r7 = temp * 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y + 14); + } +} + +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7 = a->unk3 * 32; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y); + } +} + +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r6 = a->unk2; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r6, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u8 r5 = a->unk2 + 28; + + if (r5 >= 32) + r5 -= 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r5, gSaveBlock1Ptr->pos.x + 14, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +void CurrentMapDrawMetatileAt(int a, int b) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, a, b); + + if (offset >= 0) + { + DrawMetatileAt(gMapHeader.mapData, offset, a, b); + gUnknown_03000E20.unk4 = TRUE; + } +} + +void DrawDoorMetatileAt(int x, int y, u16 *arr) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, x, y); + + if (offset >= 0) + { + DrawMetatile(1, arr, offset); + gUnknown_03000E20.unk4 = TRUE; + } +} + +static void DrawMetatileAt(const struct MapData *mapData, u16 b, int c, int d) +{ + u16 metatileId = MapGridGetMetatileIdAt(c, d); + u16 *metatiles; + + if (metatileId > 1024) + metatileId = 0; + if (metatileId < 512) + metatiles = mapData->primaryTileset->metatiles; + else + { + metatiles = mapData->secondaryTileset->metatiles; + metatileId -= 512; + } + DrawMetatile(MapGridGetMetatileLayerTypeAt(c, d), metatiles + metatileId * 8, b); +} + +static void DrawMetatile(s32 a, u16 *b, u16 c) +{ + switch (a) + { + case 2: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = 0; + gBGTilemapBuffers1[c + 1] = 0; + gBGTilemapBuffers1[c + 0x20] = 0; + gBGTilemapBuffers1[c + 0x21] = 0; + + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + case 1: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = b[4]; + gBGTilemapBuffers1[c + 1] = b[5]; + gBGTilemapBuffers1[c + 0x20] = b[6]; + gBGTilemapBuffers1[c + 0x21] = b[7]; + + gBGTilemapBuffers2[c] = 0; + gBGTilemapBuffers2[c + 1] = 0; + gBGTilemapBuffers2[c + 0x20] = 0; + gBGTilemapBuffers2[c + 0x21] = 0; + break; + case 0: + gBGTilemapBuffers3[c] = 0x3014; + gBGTilemapBuffers3[c + 1] = 0x3014; + gBGTilemapBuffers3[c + 0x20] = 0x3014; + gBGTilemapBuffers3[c + 0x21] = 0x3014; + + gBGTilemapBuffers1[c] = b[0]; + gBGTilemapBuffers1[c + 1] = b[1]; + gBGTilemapBuffers1[c + 0x20] = b[2]; + gBGTilemapBuffers1[c + 0x21] = b[3]; + + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + } + schedule_bg_copy_tilemap_to_vram(1); + schedule_bg_copy_tilemap_to_vram(2); + schedule_bg_copy_tilemap_to_vram(3); +} + +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y) +{ + x -= gSaveBlock1Ptr->pos.x; + x *= 2; + if (x >= 32 || x < 0) + return -1; + x = x + a->unk2; + if (x >= 32) + x -= 32; + + y = (y - gSaveBlock1Ptr->pos.y) * 2; + if (y >= 32 || y < 0) + return -1; + y = y + a->unk3; + if (y >= 32) + y -= 32; + + return y * 32 + x; +} + +static void CameraUpdateCallback(struct CameraObject *a) +{ + if (a->spriteId != 0) + { + a->unk8 = gSprites[a->spriteId].data[2]; + a->unkC = gSprites[a->spriteId].data[3]; + } +} + +void ResetCameraUpdateInfo(void) +{ + gUnknown_03005DD0.unk8 = 0; + gUnknown_03005DD0.unkC = 0; + gUnknown_03005DD0.x = 0; + gUnknown_03005DD0.y = 0; + gUnknown_03005DD0.spriteId = 0; + gUnknown_03005DD0.callback = NULL; +} -IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; -IWRAM_DATA s16 gUnknown_03000E28; -IWRAM_DATA s16 gUnknown_03000E2A; -IWRAM_DATA u8 gUnknown_03000E2C; -IWRAM_DATA void (*gUnknown_03000E30)(void); +u32 InitCameraUpdateCallback(u8 a) +{ + if (gUnknown_03005DD0.spriteId != 0) + DestroySprite(&gSprites[gUnknown_03005DD0.spriteId]); + gUnknown_03005DD0.spriteId = AddCameraObject(a); + gUnknown_03005DD0.callback = CameraUpdateCallback; + return 0; +} + +void CameraUpdate(void) +{ + int deltaX; + int deltaY; + int r0; + int r1; + int r7; + int r8; + + if (gUnknown_03005DD0.callback != NULL) + gUnknown_03005DD0.callback(&gUnknown_03005DD0); + r7 = gUnknown_03005DD0.unk8; + r8 = gUnknown_03005DD0.unkC; + deltaX = 0; + deltaY = 0; + r1 = gUnknown_03005DD0.x; + r0 = gUnknown_03005DD0.y; + + + if (r1 == 0 && r7 != 0) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 == 0 && r8 != 0) + { + if (r8 > 0) + deltaY = 1; + else + deltaY = -1; + } + if (r1 != 0 && r1 == -r7) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 != 0 && r0 == -r8) + { + if (r8 > 0) + deltaX = 1; + else + deltaX = -1; + } + + gUnknown_03005DD0.x += r7; + gUnknown_03005DD0.x = gUnknown_03005DD0.x - 16 * (gUnknown_03005DD0.x / 16); + gUnknown_03005DD0.y += r8; + gUnknown_03005DD0.y = gUnknown_03005DD0.y - 16 * (gUnknown_03005DD0.y / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + UpdateFieldObjectsForCameraUpdate(deltaX, deltaY); + RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + ResetBerryTreeSparkleFlags(); + tilemap_move_something(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + } + + coords8_add(&gUnknown_03000E20, r7, r8); + gUnknown_03005DEC -= r7; + gUnknown_03005DE8 -= r8; +} + +void camera_move_and_redraw(int a, int b) //unused +{ + CameraMove(a, b); + UpdateFieldObjectsForCameraUpdate(a, b); + DrawWholeMapView(); + gUnknown_03005DEC -= a * 16; + gUnknown_03005DE8 -= b * 16; +} + +void SetCameraPanningCallback(void (*a)(void)) +{ + gUnknown_03000E30 = a; +} + +void SetCameraPanning(s16 a, s16 b) +{ + gUnknown_03000E28 = a; + gUnknown_03000E2A = b + 32; +} + +void InstallCameraPanAheadCallback(void) +{ + gUnknown_03000E30 = CameraPanningCB_PanAhead; + gUnknown_03000E2C = 0; + gUnknown_03000E28 = 0; + gUnknown_03000E2A = 32; +} + +void UpdateCameraPanning(void) +{ + if (gUnknown_03000E30 != NULL) + gUnknown_03000E30(); + //Update sprite offset of overworld objects + gSpriteCoordOffsetX = gUnknown_03005DEC - gUnknown_03000E28; + gSpriteCoordOffsetY = gUnknown_03005DE8 - gUnknown_03000E2A - 8; +} + +static void CameraPanningCB_PanAhead(void) +{ + u8 var; -// Static ROM declarations + if (gUnusedBikeCameraAheadPanback == FALSE) + { + InstallCameraPanAheadCallback(); + } + else + { + // this code is never reached. + if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION) + { + gUnknown_03000E2C ^= 1; + if (gUnknown_03000E2C == 0) + return; + } + else + { + gUnknown_03000E2C = 0; + } -// .rodata + var = player_get_direction_upper_nybble(); + if (var == 2) + { + if (gUnknown_03000E2A > -8) + gUnknown_03000E2A -= 2; + } + else if (var == 1) + { + if (gUnknown_03000E2A < 72) + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A < 32) + { + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A > 32) + { + gUnknown_03000E2A -= 2; + } + } +} -// .text diff --git a/src/field_effect.c b/src/field_effect.c index 628dc776a..692090779 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -1,15 +1,3897 @@ // Includes #include "global.h" +#include "field_effect.h" +#include "battle_dome_cards.h" +#include "decompress.h" +#include "field_camera.h" +#include "field_effect_helpers.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_screen.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "fldeff_groundshake.h" +#include "gpu_regs.h" +#include "main.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "overworld.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "util.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +#define subsprite_table(ptr) {.subsprites = ptr, .subspriteCount = (sizeof ptr) / (sizeof(struct Subsprite))} + +EWRAM_DATA s32 gFieldEffectArguments[8] = {0}; // Static type declarations // Static RAM declarations -IWRAM_DATA u8 gUnknown_03000F58[32]; +static IWRAM_DATA u8 sActiveList[32]; // Static ROM declarations +extern u8 *gFieldEffectScriptPointers[]; + // .rodata +const u32 gNewGameBirchPic[] = INCBIN_U32("graphics/birch_speech/birch.4bpp"); +const u32 gUnusedBirchBeauty[] = INCBIN_U32("graphics/unused/intro_birch_beauty.4bpp"); +const u16 gNewGameBirchPalette[16] = INCBIN_U16("graphics/birch_speech/birch.gbapal"); +const u32 gSpriteImage_855A970[] = INCBIN_U32("graphics/misc/pokeball_glow.4bpp"); +const u16 gFieldEffectObjectPalette4[16] = INCBIN_U16("graphics/map_objects/palettes/field_effect_object_palette_04.gbapal"); +const u32 gSpriteImage_855A9B0[] = INCBIN_U32("graphics/misc/pokecenter_monitor/0.4bpp"); +const u32 gSpriteImage_855AA70[] = INCBIN_U32("graphics/misc/pokecenter_monitor/1.4bpp"); +const u32 gSpriteImage_855AB30[] = INCBIN_U32("graphics/misc/big_hof_monitor.4bpp"); +const u8 gSpriteImage_855AD30[] = INCBIN_U8("graphics/misc/small_hof_monitor.4bpp"); +const u16 gFieldEffectObjectPalette5[16] = INCBIN_U16("graphics/map_objects/palettes/field_effect_object_palette_05.gbapal"); + +// Graphics for the lights streaking past your Pokemon when it uses a field move. +const u32 gFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/field_move_streaks.4bpp"); +const u16 gFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/field_move_streaks.gbapal"); +const u16 gFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/field_move_streaks_map.bin"); + +// The following light streaks effect is used when the map is dark (e.g. a cave). +const u32 gDarknessFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/darkness_field_move_streaks.4bpp"); +const u16 gDarknessFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/darkness_field_move_streaks.gbapal"); +const u16 gDarknessFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/darkness_field_move_streaks_map.bin"); + +const u16 gUnknown_0855B610[16] = INCBIN_U16("graphics/misc/spotlight.gbapal"); +const u8 gUnknown_0855B630[] = INCBIN_U8("graphics/misc/spotlight.4bpp"); +const u8 gUnknown_0855C170[] = INCBIN_U8("graphics/unknown/unknown_55C170.4bpp"); +const u8 gUnknown_0855C190[] = INCBIN_U8("graphics/unknown/unknown_55C190.4bpp"); +const u8 gUnknown_0855C1B0[] = INCBIN_U8("graphics/unknown/unknown_55C1B0.4bpp"); +const u8 gUnknown_0855C1D0[] = INCBIN_U8("graphics/unknown/unknown_55C1D0.4bpp"); + +bool8 (*const gFieldEffectScriptFuncs[])(u8 **, u32 *) = { + FieldEffectCmd_loadtiles, + FieldEffectCmd_loadfadedpal, + FieldEffectCmd_loadpal, + FieldEffectCmd_callnative, + FieldEffectCmd_end, + FieldEffectCmd_loadgfx_callnative, + FieldEffectCmd_loadtiles_callnative, + FieldEffectCmd_loadfadedpal_callnative, +}; + +const struct OamData gNewGameBirchOamAttributes = {.size = 3}; +const struct OamData gOamData_855C218 = {.size = 0}; +const struct OamData gOamData_855C220 = {.size = 1}; + +const struct SpriteFrameImage gNewGameBirchPicTable[] = { + obj_frame_tiles(gNewGameBirchPic) +}; +const struct SpritePalette gNewGameBirchObjectPaletteInfo = {.data = gNewGameBirchPalette, .tag = 0x1006}; + +const union AnimCmd gNewGameBirchImageAnim[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_END +}; + +const union AnimCmd *const gNewGameBirchImageAnimTable[] = { + gNewGameBirchImageAnim +}; + +const struct SpriteTemplate gNewGameBirchObjectTemplate = { + .tileTag = 0xffff, + .paletteTag = 4102, + .oam = &gNewGameBirchOamAttributes, + .anims = gNewGameBirchImageAnimTable, + .images = gNewGameBirchPicTable, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +const struct SpritePalette gFieldEffectObjectPaletteInfo4 = {.data = gFieldEffectObjectPalette4, .tag = 0x1007}; +const struct SpritePalette gFieldEffectObjectPaletteInfo5 = {.data = gFieldEffectObjectPalette5, .tag = 0x1010}; +const struct OamData gOamData_855C26C = { + .shape = 1, + .size = 2 +}; + +const struct SpriteFrameImage gSpriteImageTable_855C274[] = { + obj_frame_tiles(gSpriteImage_855A970) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C27C[] = { + obj_frame_tiles(gSpriteImage_855A9B0), + obj_frame_tiles(gSpriteImage_855AA70) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C28C[] = { + obj_frame_tiles(gSpriteImage_855AB30) +}; + +const struct SpriteFrameImage gSpriteImageTable_855C294[] = { + {.data = gSpriteImage_855AD30, .size = 0x200} // the macro breaks down here +}; + +const struct Subsprite gSubspriteTable_855C29C[] = { + {.x = -12, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 0}, + {.x = 4, .y = -8, .priority = 2, .tileOffset = 2, .shape = 0, .size = 0}, + {.x = -12, .y = 0, .priority = 2, .tileOffset = 3, .shape = 1, .size = 0}, + {.x = 4, .y = 0, .priority = 2, .tileOffset = 5, .shape = 0, .size = 0} +}; + +const struct SubspriteTable gUnknown_0855C2AC = subsprite_table(gSubspriteTable_855C29C); + +const struct Subsprite gSubspriteTable_855C2B4[] = { + {.x = -32, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 1}, + {.x = 0, .y = -8, .priority = 2, .tileOffset = 4, .shape = 1, .size = 1}, + {.x = -32, .y = 0, .priority = 2, .tileOffset = 8, .shape = 1, .size = 1}, + {.x = 0, .y = 0, .priority = 2, .tileOffset = 12, .shape = 1, .size = 1} +}; + +const struct SubspriteTable gUnknown_0855C2C4 = subsprite_table(gSubspriteTable_855C2B4); + +const union AnimCmd gSpriteAnim_855C2CC[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_JUMP(0) +}; + +const union AnimCmd gSpriteAnim_855C2D4[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_855C2F8[] = { + gSpriteAnim_855C2CC, + gSpriteAnim_855C2D4 +}; + +const union AnimCmd *const gSpriteAnimTable_855C300[] = { + gSpriteAnim_855C2CC +}; + +const struct SpriteTemplate gSpriteTemplate_855C304 = { + .tileTag = 0xffff, + .paletteTag = 4103, + .oam = &gOamData_855C218, + .anims = gSpriteAnimTable_855C2F8, + .images = gSpriteImageTable_855C274, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokeballGlow +}; + +const struct SpriteTemplate gSpriteTemplate_855C31C = { + .tileTag = 0xffff, + .paletteTag = 4100, + .oam = &gOamData_855C220, + .anims = gSpriteAnimTable_855C2F8, + .images = gSpriteImageTable_855C27C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokecenterMonitor +}; + +const struct SpriteTemplate gSpriteTemplate_855C334 = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_855C220, + .anims = gSpriteAnimTable_855C300, + .images = gSpriteImageTable_855C28C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + +const struct SpriteTemplate gSpriteTemplate_855C34C = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_855C26C, + .anims = gSpriteAnimTable_855C300, + .images = gSpriteImageTable_855C294, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + +void (*const gUnknown_0855C364[])(struct Task *) = { + PokecenterHealEffect_0, + PokecenterHealEffect_1, + PokecenterHealEffect_2, + PokecenterHealEffect_3 +}; + +void (*const gUnknown_0855C374[])(struct Task *) = { + HallOfFameRecordEffect_0, + HallOfFameRecordEffect_1, + HallOfFameRecordEffect_2, + HallOfFameRecordEffect_3 +}; + +void (*const gUnknown_0855C384[])(struct Sprite *) = { + PokeballGlowEffect_0, + PokeballGlowEffect_1, + PokeballGlowEffect_2, + PokeballGlowEffect_3, + PokeballGlowEffect_4, + PokeballGlowEffect_5, + PokeballGlowEffect_6, + PokeballGlowEffect_7 +}; + +const struct Coords16 gUnknown_0855C3A4[] = { + {.x = 0, .y = 0}, + {.x = 6, .y = 0}, + {.x = 0, .y = 4}, + {.x = 6, .y = 4}, + {.x = 0, .y = 8}, + {.x = 6, .y = 8} +}; + +const u8 gUnknown_0855C3BC[] = {16, 12, 8, 0}; +const u8 gUnknown_0855C3C0[] = {16, 12, 8, 0}; +const u8 gUnknown_0855C3C4[] = { 0, 0, 0, 0}; + +bool8 (*const gUnknown_0855C3C8[])(struct Task *) = { + sub_80B6BCC, + sub_80B6C74, + sub_80B6C90, + sub_80B6D04, + sub_80B6DBC, + sub_80B6DD8, + sub_80B6E18, +}; + +bool8 (*const gUnknown_0855C3E4[])(struct Task *) = { + sub_80B6EC0, + sub_80B6EE0, + sub_80B6F50, + sub_80B6F74, + sub_80B6F84, + sub_80B6FA8, +}; + +bool8 (*const gUnknown_0855C3FC[])(struct Task *) = { + sub_80B7114, + sub_80B7190, + sub_80B71D0, + sub_80B7230, + sub_80B7270, + sub_80B72D0, + sub_80B72F4, +}; + +bool8 (*const gUnknown_0855C418[])(struct Task *, struct MapObject *) = { + sub_80B73D0, + waterfall_1_do_anim_probably, + waterfall_2_wait_anim_finish_probably, + sub_80B7450, + sub_80B7478, +}; + +bool8 (*const gUnknown_0855C42C[])(struct Task *) = { + dive_1_lock, + dive_2_unknown, + dive_3_unknown, +}; + +bool8 (*const gUnknown_0855C438[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B764C, + sub_80B7684, + sub_80B76B8, + sub_80B7704, + sub_80B77F8, + sub_80B7814, +}; + +bool8 (*const gUnknown_0855C450[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B78EC, + sub_80B791C, + sub_80B7968, + sub_80B79BC, +}; + +bool8 (*const gUnknown_0855C460[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80B7AE8, + sub_80B7B18, + sub_80B7B94, + sub_80B7BCC, + sub_80B7BF4, +}; + +void (*const gUnknown_0855C474[])(struct Task *) = { + sub_80B7D14, + sub_80B7D34, +}; // .text + +u32 FieldEffectStart(u8 id) +{ + u8 *script; + u32 val; + + FieldEffectActiveListAdd(id); + + script = gFieldEffectScriptPointers[id]; + + while (gFieldEffectScriptFuncs[*script](&script, &val)) + ; + + return val; +} + +bool8 FieldEffectCmd_loadtiles(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_end(u8 **script, u32 *val) +{ + return FALSE; +} + +bool8 FieldEffectCmd_loadgfx_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadtiles_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +u32 FieldEffectScript_ReadWord(u8 **script) +{ + return (*script)[0] + + ((*script)[1] << 8) + + ((*script)[2] << 16) + + ((*script)[3] << 24); +} + +void FieldEffectScript_LoadTiles(u8 **script) +{ + struct SpriteSheet *sheet = (struct SpriteSheet *)FieldEffectScript_ReadWord(script); + if (GetSpriteTileStartByTag(sheet->tag) == 0xFFFF) + LoadSpriteSheet(sheet); + (*script) += 4; +} + +void FieldEffectScript_LoadFadedPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + UpdateSpritePaletteWithWeather(IndexOfSpritePaletteTag(palette->tag)); + (*script) += 4; +} + +void FieldEffectScript_LoadPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + (*script) += 4; +} + +void FieldEffectScript_CallNative(u8 **script, u32 *val) +{ + u32 (*func)(void) = (u32 (*)(void))FieldEffectScript_ReadWord(script); + *val = func(); + (*script) += 4; +} + +void FieldEffectFreeGraphicsResources(struct Sprite *sprite) +{ + u16 sheetTileStart = sprite->sheetTileStart; + u32 paletteNum = sprite->oam.paletteNum; + DestroySprite(sprite); + FieldEffectFreeTilesIfUnused(sheetTileStart); + FieldEffectFreePaletteIfUnused(paletteNum); +} + +void FieldEffectStop(struct Sprite *sprite, u8 id) +{ + FieldEffectFreeGraphicsResources(sprite); + FieldEffectActiveListRemove(id); +} + +void FieldEffectFreeTilesIfUnused(u16 tileStart) +{ + u8 i; + u16 tag = GetSpriteTileTagByTileStart(tileStart); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].usingSheet && tileStart == gSprites[i].sheetTileStart) + return; + FreeSpriteTilesByTag(tag); + } +} + +void FieldEffectFreePaletteIfUnused(u8 paletteNum) +{ + u8 i; + u16 tag = GetSpritePaletteTagByPaletteNum(paletteNum); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].oam.paletteNum == paletteNum) + return; + FreeSpritePaletteByTag(tag); + } +} + +void FieldEffectActiveListClear(void) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + sActiveList[i] = 0xFF; +} + +void FieldEffectActiveListAdd(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == 0xFF) + { + sActiveList[i] = id; + return; + } + } +} + +void FieldEffectActiveListRemove(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == id) + { + sActiveList[i] = 0xFF; + return; + } + } +} + +bool8 FieldEffectActiveListContains(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + if (sActiveList[i] == id) + return TRUE; + return FALSE; +} + +u8 CreateTrainerSprite(u8 trainerSpriteID, s16 x, s16 y, u8 subpriority, u8 *buffer) +{ + struct SpriteTemplate spriteTemplate; + LoadCompressedObjectPaletteOverrideBuffer(&gTrainerFrontPicPaletteTable[trainerSpriteID], buffer); + LoadCompressedObjectPicOverrideBuffer(&gTrainerFrontPicTable[trainerSpriteID], buffer); + spriteTemplate.tileTag = gTrainerFrontPicTable[trainerSpriteID].tag; + spriteTemplate.paletteTag = gTrainerFrontPicPaletteTable[trainerSpriteID].tag; + spriteTemplate.oam = &gNewGameBirchOamAttributes; + spriteTemplate.anims = gDummySpriteAnimTable; + spriteTemplate.images = NULL; + spriteTemplate.affineAnims = gDummySpriteAffineAnimTable; + spriteTemplate.callback = SpriteCallbackDummy; + return CreateSprite(&spriteTemplate, x, y, subpriority); +} + +void LoadTrainerGfx_TrainerCard(u8 gender, u16 palOffset, u8 *dest) +{ + LZDecompressVram(gTrainerFrontPicTable[gender].data, dest); + LoadCompressedPalette(gTrainerFrontPicPaletteTable[gender].data, palOffset, 0x20); +} + +u8 AddNewGameBirchObject(s16 x, s16 y, u8 subpriority) +{ + LoadSpritePalette(&gNewGameBirchObjectPaletteInfo); + return CreateSprite(&gNewGameBirchObjectTemplate, x, y, subpriority); +} + +#ifdef NONMATCHING +u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y) +{ + u16 spriteId = sub_818D7D8(species, 0, 0x8000, 1, x, y, 0, gMonPaletteTable[species].tag); + PreservePaletteInWeather(IndexOfSpritePaletteTag(gMonPaletteTable[species].tag) + 0x10); + if (spriteId == 0xFFFF) + return 0x40; + + return spriteId; +} +#else +NAKED +u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y) +{ + asm_unified("push {r4,r5,lr}\n\ + sub sp, 0x10\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r3, 0x80\n\ + lsls r3, 8\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + str r1, [sp]\n\ + lsls r2, 16\n\ + asrs r2, 16\n\ + str r2, [sp, 0x4]\n\ + movs r1, 0\n\ + str r1, [sp, 0x8]\n\ + ldr r1, =gMonPaletteTable\n\ + lsls r4, r0, 3\n\ + adds r4, r1\n\ + ldrh r1, [r4, 0x4]\n\ + str r1, [sp, 0xC]\n\ + movs r1, 0\n\ + adds r2, r3, 0\n\ + movs r3, 0x1\n\ + bl sub_818D7D8\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + ldrh r0, [r4, 0x4]\n\ + bl IndexOfSpritePaletteTag\n\ + adds r0, 0x10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + bl PreservePaletteInWeather\n\ + ldr r0, =0x0000ffff\n\ + cmp r5, r0\n\ + beq _080B5FDC\n\ + lsls r0, r5, 24\n\ + lsrs r0, 24\n\ + b _080B5FDE\n\ + .pool\n\ +_080B5FDC:\n\ + movs r0, 0x40\n\ +_080B5FDE:\n\ + add sp, 0x10\n\ + pop {r4,r5}\n\ + pop {r1}\n\ + bx r1"); +} +#endif //NONMATCHING + +u8 CreateMonSprite_FieldMove(u16 species, u32 d, u32 g, s16 x, s16 y, u8 subpriority) +{ + const struct CompressedSpritePalette *spritePalette = GetMonSpritePalStructFromOtIdPersonality(species, d, g); + u16 spriteId = sub_818D7D8(species, d, g, 1, x, y, 0, spritePalette->tag); + PreservePaletteInWeather(IndexOfSpritePaletteTag(spritePalette->tag) + 0x10); + if (spriteId == 0xFFFF) + return 0x40; + + return spriteId; +} + +void FreeResourcesAndDestroySprite(struct Sprite *sprite, u8 spriteId) +{ + ResetPreservedPalettesInWeather(); + if (sprite->oam.affineMode != 0) + { + FreeOamMatrix(sprite->oam.matrixNum); + } + sub_818D820(spriteId); +} + +#ifdef NONMATCHING +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed += (((0x1f - curRed) * r) >> 4); + curGreen += (((0x1f - curGreen) * g) >> 4); + curBlue += (((0x1f - curBlue) * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} + +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed -= ((curRed * r) >> 4); + curGreen -= ((curGreen * g) >> 4); + curBlue -= ((curBlue * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} +#else +NAKED +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r7,lr}\n" + "\tmov r7, r9\n" + "\tmov r6, r8\n" + "\tpush {r6,r7}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D00 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r9, r5\n" + "\tmov r8, r4\n" + "\tmov r6, r8\n" + "\tands r6, r5\n" + "\tmov r8, r6\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 2\n" + "\tands r6, r4\n" + "\tlsrs r6, 5\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 7\n" + "\tands r4, r5\n" + "\tlsrs r4, 10\n" + "\tmov r7, r9\n" + "\tmov r5, r8\n" + "\tsubs r7, r5\n" + "\tmov r12, r7\n" + "\tmov r7, r12\n" + "\tmuls r7, r1\n" + "\tadds r1, r7, 0\n" + "\tasrs r1, 4\n" + "\tadd r8, r1\n" + "\tmov r5, r9\n" + "\tsubs r1, r5, r6\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tadds r6, r1\n" + "\tsubs r5, r4\n" + "\tmov r9, r5\n" + "\tmov r1, r9\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tadds r4, r1\n" + "\tmov r7, r8\n" + "\tlsls r7, 16\n" + "\tlsls r6, 21\n" + "\torrs r6, r7\n" + "\tlsls r4, 26\n" + "\torrs r4, r6\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D04 @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3,r4}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D00: .4byte gPlttBufferUnfaded\n" + "_08085D04: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} + +NAKED +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r6,lr}\n" + "\tmov r6, r8\n" + "\tpush {r6}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D78 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r8, r5\n" + "\tmov r6, r8\n" + "\tands r6, r4\n" + "\tmov r8, r6\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 2\n" + "\tands r5, r4\n" + "\tlsrs r5, 5\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 7\n" + "\tands r4, r6\n" + "\tlsrs r4, 10\n" + "\tmov r6, r8\n" + "\tmuls r6, r1\n" + "\tadds r1, r6, 0\n" + "\tasrs r1, 4\n" + "\tmov r6, r8\n" + "\tsubs r6, r1\n" + "\tadds r1, r5, 0\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tsubs r5, r1\n" + "\tadds r1, r4, 0\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tsubs r4, r1\n" + "\tlsls r6, 16\n" + "\tlsls r5, 21\n" + "\torrs r5, r6\n" + "\tlsls r4, 26\n" + "\torrs r4, r5\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D7C @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r6}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D78: .4byte gPlttBufferUnfaded\n" + "_08085D7C: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} +#endif + +void Task_PokecenterHeal(u8 taskId); +u8 CreatePokeballGlowSprite(s16, s16, s16, u16); +u8 PokecenterHealEffectHelper(s16, s16); + +bool8 FldEff_PokecenterHeal(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_PokecenterHeal, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x5d; + task->data[3] = 0x24; + task->data[4] = 0x7c; + task->data[5] = 0x18; + return FALSE; +} + +void Task_PokecenterHeal(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0855C364[task->data[0]](task); +} + +void PokecenterHealEffect_0(struct Task *task) +{ + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 1); + task->data[7] = PokecenterHealEffectHelper(task->data[4], task->data[5]); +} + +void PokecenterHealEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 1) + { + gSprites[task->data[7]].data[0]++; + task->data[0]++; + } +} + +void PokecenterHealEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 4) + { + task->data[0]++; + } +} + +void PokecenterHealEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_POKECENTER_HEAL); + DestroyTask(FindTaskIdByFunc(Task_PokecenterHeal)); + } +} + +void Task_HallOfFameRecord(u8 taskId); +void HallOfFameRecordEffectHelper(s16, s16, s16, u8); + +bool8 FldEff_HallOfFameRecord(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_HallOfFameRecord, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x75; + task->data[3] = 0x34; + return FALSE; +} + +void Task_HallOfFameRecord(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0855C374[task->data[0]](task); +} + +void HallOfFameRecordEffect_0(struct Task *task) +{ + u8 taskId; + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 0); + taskId = FindTaskIdByFunc(Task_HallOfFameRecord); + HallOfFameRecordEffectHelper(taskId, 0x78, 0x18, 0); + HallOfFameRecordEffectHelper(taskId, 0x28, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0x48, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xa8, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xc8, 0x08, 1); +} + +void HallOfFameRecordEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 1) + { + task->data[15]++; // was this ever initialized? is this ever used? + task->data[0]++; + } +} + +void HallOfFameRecordEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 4) + { + task->data[0]++; + } +} + +void HallOfFameRecordEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data[0] > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_HALL_OF_FAME_RECORD); + DestroyTask(FindTaskIdByFunc(Task_HallOfFameRecord)); + } +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *); + +u8 CreatePokeballGlowSprite(s16 data6, s16 x, s16 y, u16 data5) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateInvisibleSprite(SpriteCB_PokeballGlowEffect); + sprite = &gSprites[spriteId]; + sprite->pos2.x = x; + sprite->pos2.y = y; + sprite->data[5] = data5; + sprite->data[6] = data6; + sprite->data[7] = spriteId; + return spriteId; +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *sprite) +{ + gUnknown_0855C384[sprite->data[0]](sprite); +} + +void PokeballGlowEffect_0(struct Sprite *sprite) +{ + u8 endSpriteId; + if (sprite->data[1] == 0 || (--sprite->data[1]) == 0) + { + sprite->data[1] = 25; + endSpriteId = CreateSpriteAtEnd(&gSpriteTemplate_855C304, gUnknown_0855C3A4[sprite->data[2]].x + sprite->pos2.x, gUnknown_0855C3A4[sprite->data[2]].y + sprite->pos2.y, 0); + gSprites[endSpriteId].oam.priority = 2; + gSprites[endSpriteId].data[0] = sprite->data[7]; + sprite->data[2]++; + sprite->data[6]--; + PlaySE(SE_BOWA); + } + if (sprite->data[6] == 0) + { + sprite->data[1] = 32; + sprite->data[0]++; + } +} + +void PokeballGlowEffect_1(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->data[0]++; + sprite->data[1] = 8; + sprite->data[2] = 0; + sprite->data[3] = 0; + if (sprite->data[5]) + { + PlayFanfare(MUS_ME_ASA); + } + } +} + +void PokeballGlowEffect_2(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data[1]) == 0) + { + sprite->data[1] = 8; + sprite->data[2]++; + sprite->data[2] &= 3; + if (sprite->data[2] == 0) + { + sprite->data[3]++; + } + } + phase = (sprite->data[2] + 3) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = (sprite->data[2] + 2) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = (sprite->data[2] + 1) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + phase = sprite->data[2]; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + if (sprite->data[3] > 2) + { + sprite->data[0]++; + sprite->data[1] = 8; + sprite->data[2] = 0; + } +} + +void PokeballGlowEffect_3(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data[1]) == 0) + { + sprite->data[1] = 8; + sprite->data[2]++; + sprite->data[2] &= 3; + if (sprite->data[2] == 3) + { + sprite->data[0]++; + sprite->data[1] = 30; + } + } + phase = sprite->data[2]; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0855C3BC[phase], gUnknown_0855C3C0[phase], gUnknown_0855C3C4[phase]); +} + +void PokeballGlowEffect_4(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->data[0]++; + } +} + +void PokeballGlowEffect_5(struct Sprite *sprite) +{ + sprite->data[0]++; +} + +void PokeballGlowEffect_6(struct Sprite *sprite) +{ + if (sprite->data[5] == 0 || IsFanfareTaskInactive()) + { + sprite->data[0]++; + } +} + +void PokeballGlowEffect_7(struct Sprite *sprite) +{ +} + +void SpriteCB_PokeballGlow(struct Sprite *sprite) +{ + if (gSprites[sprite->data[0]].data[0] > 4) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +u8 PokecenterHealEffectHelper(s16 x, s16 y) +{ + u8 spriteIdAtEnd; + struct Sprite *sprite; + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C31C, x, y, 0); + sprite = &gSprites[spriteIdAtEnd]; + sprite->oam.priority = 2; + sprite->invisible = 1; + SetSubspriteTables(sprite, &gUnknown_0855C2AC); + return spriteIdAtEnd; +} + +void SpriteCB_PokecenterMonitor(struct Sprite *sprite) +{ + if (sprite->data[0] != 0) + { + sprite->data[0] = 0; + sprite->invisible = 0; + StartSpriteAnim(sprite, 1); + } + if (sprite->animEnded) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void HallOfFameRecordEffectHelper(s16 a0, s16 a1, s16 a2, u8 a3) +{ + u8 spriteIdAtEnd; + if (!a3) + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C334, a1, a2, 0); + SetSubspriteTables(&gSprites[spriteIdAtEnd], &gUnknown_0855C2C4); + } else + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_855C34C, a1, a2, 0); + } + gSprites[spriteIdAtEnd].invisible = 1; + gSprites[spriteIdAtEnd].data[0] = a0; +} + +void SpriteCB_HallOfFameMonitor(struct Sprite *sprite) +{ + if (gTasks[sprite->data[0]].data[15]) + { + if (sprite->data[1] == 0 || (--sprite->data[1]) == 0) + { + sprite->data[1] = 16; + sprite->invisible ^= 1; + } + sprite->data[2]++; + } + if (sprite->data[2] > 127) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void mapldr_080842E8(void); +void mapldr_08084390(void); +void task00_8084310(u8); +void c3_080843F8(u8); + +void sub_80B69DC(void) +{ + SetMainCallback2(CB2_ReturnToField); + gFieldCallback = mapldr_080842E8; +} + +void mapldr_080842E8(void) +{ + pal_fill_black(); + CreateTask(task00_8084310, 0); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void task00_8084310(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (!task->data[0]) + { + if (!IsWeatherNotFadingIn()) + { + return; + } + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + if ((int)gFieldEffectArguments[0] > 5) + { + gFieldEffectArguments[0] = 0; + } + FieldEffectStart(FLDEFF_USE_FLY); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_USE_FLY)) + { + Overworld_ResetStateAfterFly(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08084390; + DestroyTask(taskId); + } +} + +void mapldr_08084390(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + CreateTask(c3_080843F8, 0); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + if (gPlayerAvatar.flags & 0x08) + { + FieldObjectTurn(&gMapObjects[gPlayerAvatar.mapObjectId], DIR_WEST); + } + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void c3_080843F8(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (task->data[0] == 0) + { + if (gPaletteFade.active) + { + return; + } + FieldEffectStart(FLDEFF_FLY_IN); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_FLY_IN)) + { + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(taskId); + } +} + +extern void pal_fill_for_maplights(void); +void sub_80B6B94(u8); +extern void CameraObjectReset2(void); +extern void CameraObjectReset1(void); + +void sub_80B6B68(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_80B6B94, 0); + gFieldCallback = NULL; +} + +void sub_80B6B94(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3C8[task->data[0]](task)); // return code signifies whether to continue blocking here +} + +bool8 sub_80B6BCC(struct Task *task) // gUnknown_0855C3C8[0] +{ + struct MapObject *playerObject; + struct Sprite *playerSprite; + playerObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + playerSprite = &gSprites[gPlayerAvatar.spriteId]; + CameraObjectReset2(); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + gPlayerAvatar.preventStep = TRUE; + FieldObjectSetSpecialAnim(playerObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[4] = playerSprite->subspriteMode; + playerObject->mapobj_bit_26 = 1; + playerSprite->oam.priority = 1; + playerSprite->subspriteMode = 2; + task->data[0]++; + return TRUE; +} + +bool8 sub_80B6C74(struct Task *task) // gUnknown_0855C3C8[1] +{ + if (IsWeatherNotFadingIn()) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6C90(struct Task *task) // gUnknown_0855C3C8[2] +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + task->data[1] = 1; + task->data[2] = 0; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + PlaySE(SE_RU_HYUU); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B6D04(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y += task->data[1]; + if (task->data[1] < 8) + { + task->data[2] += task->data[1]; + if (task->data[2] & 0xf) + { + task->data[1] <<= 1; + } + } + if (task->data[3] == 0 && sprite->pos2.y >= -16) + { + task->data[3]++; + mapObject->mapobj_bit_26 = 0; + sprite->subspriteMode = task->data[4]; + mapObject->mapobj_bit_2 = 1; + } + if (sprite->pos2.y >= 0) + { + PlaySE(SE_W070); + mapObject->mapobj_bit_3 = 1; + mapObject->mapobj_bit_5 = 1; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6DBC(struct Task *task) +{ + task->data[0]++; + task->data[1] = 4; + task->data[2] = 0; + SetCameraPanningCallback(NULL); + return TRUE; +} + +bool8 sub_80B6DD8(struct Task *task) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if ((task->data[2] & 3) == 0) + { + task->data[1] >>= 1; + } + if (task->data[1] == 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6E18(struct Task *task) +{ + gPlayerAvatar.preventStep = FALSE; + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + InstallCameraPanAheadCallback(); + DestroyTask(FindTaskIdByFunc(sub_80B6B94)); + return FALSE; +} + +void sub_80B6E88(u8); +extern void sub_80E1558(u8); +extern void sub_80AF0B4(void); + +void sub_80B6FB8(struct Task *); +void sub_80B7004(struct Task *); +void sub_80B7050(void); +void sub_80B7060(void); +bool8 sub_80859A0(void); +void sub_80B70B4(void); +void sub_80E1570(void); +void sub_80B70DC(u8); + +void sub_80B6E4C(u8 a0, u8 priority) +{ + u8 taskId; + taskId = CreateTask(sub_80B6E88, priority); + gTasks[taskId].data[1] = 0; + if (a0 == 0x6a) + { + gTasks[taskId].data[1] = 1; + } +} + +void sub_80B6E88(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3E4[task->data[0]](task)); +} + +bool8 sub_80B6EC0(struct Task *task) +{ + FreezeMapObjects(); + CameraObjectReset2(); + sub_80E1558(task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B6EE0(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[0]++; + task->data[2] = 0; + task->data[3] = 0; + if ((u8)task->data[1] == 0) + { + task->data[0] = 4; + } + PlaySE(SE_ESUKA); + } + return FALSE; +} + +bool8 sub_80B6F50(struct Task *task) +{ + sub_80B6FB8(task); + if (task->data[2] > 3) + { + sub_80B7050(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6F74(struct Task *task) +{ + sub_80B6FB8(task); + sub_80B7060(); + return FALSE; +} + +bool8 sub_80B6F84(struct Task *task) +{ + sub_80B7004(task); + if (task->data[2] > 3) + { + sub_80B7050(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B6FA8(struct Task *task) +{ + sub_80B7004(task); + sub_80B7060(); + return FALSE; +} + +void sub_80B6FB8(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[2]); + sprite->pos2.y = Sin(0x94, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_80B7004(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[2]); + sprite->pos2.y = Sin(0x76, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_80B7050(void) +{ + music_something(); + sub_80AF0B4(); +} + +void sub_80B7060(void) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + sub_80E1570(); + warp_in(); + gFieldCallback = sub_80B70B4; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B6E88)); + } +} + +void sub_80B70B4(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + CreateTask(sub_80B70DC, 0); + gFieldCallback = NULL; +} + +void sub_80B70DC(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0855C3FC[task->data[0]](task)); +} + +bool8 sub_80B7114(struct Task *task) +{ + struct MapObject *mapObject; + s16 x; + s16 y; + u8 behavior; + CameraObjectReset2(); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(DIR_EAST)); + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + task->data[0]++; + task->data[1] = 16; + if (behavior == 0x6b) + { + behavior = 1; + task->data[0] = 3; + } else + { + behavior = 0; + } + sub_80E1558(behavior); + return TRUE; +} + +bool8 sub_80B7190(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B71D0(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0] = 5; + } + return FALSE; +} + +bool8 sub_80B7230(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7270(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +extern bool8 sub_80E1584(void); + +bool8 sub_80B72D0(struct Task *task) +{ + if (sub_80E1584()) + { + return FALSE; + } + sub_80E1570(); + task->data[0]++; + return TRUE; +} + +bool8 sub_80B72F4(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + CameraObjectReset1(); + ScriptContext2_Disable(); + FieldObjectSetSpecialAnim(mapObject, GetGoSpeed0AnimId(DIR_EAST)); + DestroyTask(FindTaskIdByFunc(sub_80B70DC)); + } + return FALSE; +} + +void sub_80B7384(u8); + +bool8 FldEff_UseWaterfall(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B7384, 0xff); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + sub_80B7384(taskId); + return FALSE; +} + +void sub_80B7384(u8 taskId) +{ + while (gUnknown_0855C418[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId])); +} + +bool8 sub_80B73D0(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + gPlayerAvatar.preventStep = TRUE; + task->data[0]++; + return FALSE; +} + +bool8 waterfall_1_do_anim_probably(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject)) + { + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } + return FALSE; +} + +bool8 waterfall_2_wait_anim_finish_probably(struct Task *task, struct MapObject *mapObject) +{ + if (FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + return FALSE; + } + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7450(struct Task *task, struct MapObject *mapObject) +{ + FieldObjectSetSpecialAnim(mapObject, GetSimpleGoAnimId(DIR_NORTH)); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7478(struct Task *task, struct MapObject *mapObject) +{ + if (!FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return FALSE; + } + if (MetatileBehavior_IsWaterfall(mapObject->mapobj_unk_1E)) + { + task->data[0] = 3; + return TRUE; + } + ScriptContext2_Disable(); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(FindTaskIdByFunc(sub_80B7384)); + FieldEffectActiveListRemove(FLDEFF_USE_WATERFALL); + return FALSE; +} + +void Task_Dive(u8); +extern int dive_warp(struct MapPosition *, u16); + +bool8 FldEff_UseDive(void) +{ + u8 taskId; + taskId = CreateTask(Task_Dive, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + gTasks[taskId].data[14] = gFieldEffectArguments[1]; + Task_Dive(taskId); + return FALSE; +} + +void Task_Dive(u8 taskId) +{ + while (gUnknown_0855C42C[gTasks[taskId].data[0]](&gTasks[taskId])); +} + +bool8 dive_1_lock(struct Task *task) +{ + gPlayerAvatar.preventStep = TRUE; + task->data[0]++; + return FALSE; +} + +bool8 dive_2_unknown(struct Task *task) +{ + ScriptContext2_Enable(); + gFieldEffectArguments[0] = task->data[15]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + return FALSE; +} + +bool8 dive_3_unknown(struct Task *task) +{ + struct MapPosition mapPosition; + PlayerGetDestCoords(&mapPosition.x, &mapPosition.y); + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + dive_warp(&mapPosition, gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E); + DestroyTask(FindTaskIdByFunc(Task_Dive)); + FieldEffectActiveListRemove(FLDEFF_USE_DIVE); + } + return FALSE; +} + +void sub_80B75F0(u8); +void mapldr_080851BC(void); + +void sub_80B75D8(u8 priority) +{ + CreateTask(sub_80B75F0, priority); +} + +void sub_80B75F0(u8 taskId) +{ + while (gUnknown_0855C438[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B764C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + SetCameraPanningCallback(NULL); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_26 = 1; + task->data[1] = 1; + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7684(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if (task->data[2] > 7) + { + task->data[2] = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B76B8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->pos2.y = 0; + task->data[3] = 1; + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_LAVARIDGE_GYM_WARP); + PlaySE(SE_W153); + task->data[0]++; + return TRUE; +} + +bool8 sub_80B7704(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + s16 centerToCornerVecY; + SetCameraPanning(0, task->data[1]); + if (task->data[1] = -task->data[1], ++task->data[2] <= 17) + { + if (!(task->data[2] & 1) && (task->data[1] <= 3)) + { + task->data[1] <<= 1; + } + } else if (!(task->data[2] & 4) && (task->data[1] > 0)) + { + task->data[1] >>= 1; + } + if (task->data[2] > 6) + { + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + if (sprite->pos2.y > -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY)) + { + sprite->pos2.y -= task->data[3]; + if (task->data[3] <= 7) + { + task->data[3]++; + } + } else + { + task->data[4] = 1; + } + } + if (task->data[5] == 0 && sprite->pos2.y < -0x10) + { + task->data[5]++; + mapObject->mapobj_bit_26 = 1; + sprite->oam.priority = 1; + sprite->subspriteMode = 2; + } + if (task->data[1] == 0 && task->data[4] != 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B77F8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + music_something(); + sub_80AF0B4(); + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7814(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + warp_in(); + gFieldCallback = mapldr_080851BC; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B75F0)); + } + return FALSE; +} + +void sub_80B7890(u8); + +void mapldr_080851BC(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + gFieldCallback = NULL; + CreateTask(sub_80B7890, 0); +} + +void sub_80B7890(u8 taskId) +{ + while (gUnknown_0855C450[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B78EC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + CameraObjectReset2(); + FreezeMapObjects(); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80B791C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (IsWeatherNotFadingIn()) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B7968(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite = &gSprites[task->data[1]]; + if (sprite->animCmdIndex > 1) + { + task->data[0]++; + mapObject->mapobj_bit_13 = 0; + CameraObjectReset1(); + PlaySE(SE_W091); + FieldObjectSetSpecialAnim(mapObject, sub_8093514(DIR_EAST)); + } + return FALSE; +} + +bool8 sub_80B79BC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.preventStep = FALSE; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B7890)); + } + return FALSE; +} + +extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[36]; + +u8 FldEff_LavaridgeGymWarp(void) +{ + u8 spriteId; + sub_80930E0((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[33], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_80B7A58(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_LAVARIDGE_GYM_WARP); + } +} + +void sub_80B7A8C(u8); + +void sub_80B7A74(u8 priority) +{ + CreateTask(sub_80B7A8C, priority); +} + +void sub_80B7A8C(u8 taskId) +{ + while(gUnknown_0855C460[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80B7AE8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + gPlayerAvatar.preventStep = TRUE; + mapObject->mapobj_bit_26 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80B7B18(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[1] > 3) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } else + { + task->data[1]++; + FieldObjectSetSpecialAnim(mapObject, GetStepInPlaceDelay4AnimId(mapObject->mapobj_unk_18)); + PlaySE(SE_FU_ZUZUZU); + } + } + return FALSE; +} + +bool8 sub_80B7B94(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gSprites[task->data[1]].animCmdIndex == 2) + { + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80B7BCC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH)) + { + music_something(); + sub_80AF0B4(); + task->data[0]++; + } + return FALSE; +} + +void sub_80B7CE4(u8); +void mapldr_080859D4(void); + +bool8 sub_80B7BF4(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_80859A0() == TRUE) + { + warp_in(); + gFieldCallback = sub_80B6B68; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B7A8C)); + } + return FALSE; +} + +u8 FldEff_PopOutOfAsh(void) +{ + u8 spriteId; + sub_80930E0((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[32], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_80B7CAC(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_POP_OUT_OF_ASH); + } +} + +void sub_80B7CC8(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_80B7CE4, 0x50); +} + +void sub_80B7CE4(u8 taskId) +{ + gUnknown_0855C474[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B7D14(struct Task *task) +{ + task->data[0]++; + task->data[14] = 64; + task->data[15] = player_get_direction_lower_nybble(); +} + +void sub_80B7D34(struct Task *task) +{ + struct MapObject *mapObject; + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + if (task->data[14] != 0 && (--task->data[14]) == 0) + { + music_something(); + sub_80AF0B4(); + } + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[14] == 0 && !gPaletteFade.active && sub_80859A0() == TRUE) + { + FieldObjectSetDirection(mapObject, task->data[15]); + sub_8084E14(); + warp_in(); + gFieldCallback = mapldr_080859D4; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80B7CE4)); + } else if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(spinDirections[mapObject->mapobj_unk_18])); + if (task->data[2] < 12) + { + task->data[2]++; + } + task->data[1] = 8 >> (task->data[2] >> 2); + } + } +} + +void (*const gUnknown_0855C484[])(struct Task *) = { + sub_80B7EC4, + sub_80B7EE8 +}; + +void sub_80B7E94(u8); + +void mapldr_080859D4(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CreateTask(sub_80B7E94, 0); +} + +void sub_80B7E94(u8 taskId) +{ + gUnknown_0855C484[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B7EC4(struct Task *task) +{ + if (IsWeatherNotFadingIn()) + { + task->data[0]++; + task->data[15] = player_get_direction_lower_nybble(); + } +} + +void sub_80B7EE8(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) && !FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return; + } + if (task->data[2] >= 32 && task->data[15] == player_get_direction_lower_nybble()) + { + mapObject->mapobj_bit_13 = 0; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B7E94)); + return; + } + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(spinDirections[mapObject->mapobj_unk_18])); + if (task->data[2] < 32) + { + task->data[2]++; + } + task->data[1] = task->data[2] >> 2; + } + mapObject->mapobj_bit_13 ^= 1; +} + +static void ExecuteTeleportFieldEffectTask(u8); +static void TeleportFieldEffectTask1(struct Task*); +static void TeleportFieldEffectTask2(struct Task*); +static void TeleportFieldEffectTask3(struct Task*); +static void TeleportFieldEffectTask4(struct Task*); +static void mapldr_08085D88(void); + +void CreateTeleportFieldEffectTask(void) +{ + CreateTask(ExecuteTeleportFieldEffectTask, 0); +} + +static void (*const sTeleportFieldEffectTasks[])(struct Task *) = { + TeleportFieldEffectTask1, + TeleportFieldEffectTask2, + TeleportFieldEffectTask3, + TeleportFieldEffectTask4 +}; + +static void ExecuteTeleportFieldEffectTask(u8 taskId) +{ + sTeleportFieldEffectTasks[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +static void TeleportFieldEffectTask1(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CameraObjectReset2(); + task->data[15] = player_get_direction_lower_nybble(); + task->data[0]++; +} + +static void TeleportFieldEffectTask2(struct Task *task) +{ + u8 spinDirections[5] = {DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + task->data[1] = 8; + task->data[2]++; + } + if (task->data[2] > 7 && task->data[15] == mapObject->mapobj_unk_18) + { + task->data[0]++; + task->data[1] = 4; + task->data[2] = 8; + task->data[3] = 1; + PlaySE(SE_TK_WARPIN); + } +} + +static void TeleportFieldEffectTask3(struct Task *task) +{ + u8 spinDirections[5] = {DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((--task->data[1]) <= 0) + { + task->data[1] = 4; + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + } + sprite->pos1.y -= task->data[3]; + task->data[4] += task->data[3]; + if ((--task->data[2]) <= 0 && (task->data[2] = 4, task->data[3] < 8)) + { + task->data[3] <<= 1; + } + if (task->data[4] > 8 && (sprite->oam.priority = 1, sprite->subspriteMode != 0)) + { + sprite->subspriteMode = 2; + } + if (task->data[4] >= 0xa8) + { + task->data[0]++; + music_something(); + sub_80AF0B4(); + } +} + +static void TeleportFieldEffectTask4(struct Task *task) +{ + if (!gPaletteFade.active) + { + if (task->data[5] == FALSE) + { + sub_81BE72C(); + task->data[5] = TRUE; + } + + if (sub_80859A0() == TRUE) + { + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08085D88; + DestroyTask(FindTaskIdByFunc(ExecuteTeleportFieldEffectTask)); + } + } +} + +void sub_80B8250(u8); + +static void mapldr_08085D88(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_maplights(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CameraObjectReset2(); + CreateTask(sub_80B8250, 0); +} + +void (*const gUnknown_0855C49C[])(struct Task *) = { + sub_80B8280, + sub_80B830C, + sub_80B8410 +}; + +void sub_80B8250(u8 taskId) +{ + gUnknown_0855C49C[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8280(struct Task *task) +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + if (IsWeatherNotFadingIn()) + { + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + task->data[0]++; + task->data[1] = 8; + task->data[2] = 1; + task->data[14] = sprite->subspriteMode; + task->data[15] = player_get_direction_lower_nybble(); + PlaySE(SE_TK_WARPIN); + } +} + +void sub_80B830C(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((sprite->pos2.y += task->data[1]) >= -8) + { + if (task->data[13] == 0) + { + task->data[13]++; + mapObject->mapobj_bit_2 = 1; + sprite->subspriteMode = task->data[14]; + } + } else + { + sprite->oam.priority = 1; + if (sprite->subspriteMode != 0) + { + sprite->subspriteMode = 2; + } + } + if (sprite->pos2.y >= -0x30 && task->data[1] > 1 && !(sprite->pos2.y & 1)) + { + task->data[1]--; + } + if ((--task->data[2]) == 0) + { + task->data[2] = 4; + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + } + if (sprite->pos2.y >= 0) + { + sprite->pos2.y = 0; + task->data[0]++; + task->data[1] = 1; + task->data[2] = 0; + } +} + +void sub_80B8410(struct Task *task) +{ + u8 spinDirections[5] = {1, 3, 4, 2, 1}; + struct MapObject *mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, spinDirections[mapObject->mapobj_unk_18]); + task->data[1] = 8; + if ((++task->data[2]) > 4 && task->data[14] == mapObject->mapobj_unk_18) + { + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_80B8250)); + } + } +} + +void sub_80B8554(u8); +void sub_80B88B4(u8); +u8 sub_80B8C60(u32, u32, u32); +void sub_80B880C(void); +void sub_80B8874(u16); +void sub_80B8CC0(struct Sprite *); + +bool8 FldEff_FieldMoveShowMon(void) +{ + u8 taskId; + if (is_map_type_1_2_3_5_or_6(Overworld_GetMapTypeOfSaveblockLocation()) == TRUE) + { + taskId = CreateTask(sub_80B8554, 0xff); + } else + { + taskId = CreateTask(sub_80B88B4, 0xff); + } + gTasks[taskId].data[15] = sub_80B8C60(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + return FALSE; +} + +bool8 FldEff_FieldMoveShowMonInit(void) +{ + struct Pokemon *pokemon; + u32 flag = gFieldEffectArguments[0] & 0x80000000; + pokemon = &gPlayerParty[(u8)gFieldEffectArguments[0]]; + gFieldEffectArguments[0] = GetMonData(pokemon, MON_DATA_SPECIES); + gFieldEffectArguments[1] = GetMonData(pokemon, MON_DATA_OT_ID); + gFieldEffectArguments[2] = GetMonData(pokemon, MON_DATA_PERSONALITY); + gFieldEffectArguments[0] |= flag; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + return FALSE; +} + +void (*const gUnknown_0855C4A8[])(struct Task *) = { + sub_80B8584, + sub_80B85F8, + sub_80B8660, + sub_80B86EC, + sub_80B871C, + sub_80B8770, + overworld_bg_setup_2, +}; + +void sub_80B8554(u8 taskId) +{ + gUnknown_0855C4A8[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8584(struct Task *task) +{ + task->data[11] = REG_WININ; + task->data[12] = REG_WINOUT; + StoreWordInTwoHalfwords(&task->data[13], (u32)gMain.vblankCallback); + task->data[1] = 0xf0f1; + task->data[2] = 0x5051; + task->data[3] = 0x3f; + task->data[4] = 0x3e; + SetGpuReg(REG_OFFSET_WIN0H, task->data[1]); + SetGpuReg(REG_OFFSET_WIN0V, task->data[2]); + SetGpuReg(REG_OFFSET_WININ, task->data[3]); + SetGpuReg(REG_OFFSET_WINOUT, task->data[4]); + SetVBlankCallback(sub_80B880C); + task->data[0]++; +} + +void sub_80B85F8(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + CpuCopy16(gFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x200); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gFieldMoveStreaksPalette, 0xf0, 0x20); + sub_80B8874(delta); + task->data[0]++; +} + +void sub_80B8660(struct Task *task) +{ + s16 v0; + s16 v2; + s16 v3; + task->data[5] -= 16; + v0 = ((u16)task->data[1] >> 8); + v2 = ((u16)task->data[2] >> 8); + v3 = ((u16)task->data[2] & 0xff); + v0 -= 16; + v2 -= 2; + v3 += 2; + if (v0 < 0) + { + v0 = 0; + } + if (v2 < 0x28) + { + v2 = 0x28; + } + if (v3 > 0x78) + { + v3 = 0x78; + } + task->data[1] = (v0 << 8) | (task->data[1] & 0xff); + task->data[2] = (v2 << 8) | v3; + if (v0 == 0 && v2 == 0x28 && v3 == 0x78) + { + gSprites[task->data[15]].callback = sub_80B8CC0; + task->data[0]++; + } +} + +void sub_80B86EC(struct Task *task) +{ + task->data[5] -= 16; + if (gSprites[task->data[15]].data[7]) + { + task->data[0]++; + } +} + +void sub_80B871C(struct Task *task) +{ + s16 v2; + s16 v3; + task->data[5] -= 16; + v2 = (task->data[2] >> 8); + v3 = (task->data[2] & 0xff); + v2 += 6; + v3 -= 6; + if (v2 > 0x50) + { + v2 = 0x50; + } + if (v3 < 0x51) + { + v3 = 0x51; + } + task->data[2] = (v2 << 8) | v3; + if (v2 == 0x50 && v3 == 0x51) + { + task->data[0]++; + } +} + +void sub_80B8770(struct Task *task) +{ + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + task->data[1] = 0xf1; + task->data[2] = 0xa1; + task->data[3] = task->data[11]; + task->data[4] = task->data[12]; + task->data[0]++; +} + +void overworld_bg_setup_2(struct Task *task) +{ + IntrCallback callback; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + SetVBlankCallback(callback); + sub_8197200(); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]], task->data[15]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_80B8554)); +} + +void sub_80B880C(void) +{ + struct Task *task; + IntrCallback callback; + task = &gTasks[FindTaskIdByFunc(sub_80B8554)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + callback(); + SetGpuReg(REG_OFFSET_WIN0H, task->data[1]); + SetGpuReg(REG_OFFSET_WIN0V, task->data[2]); + SetGpuReg(REG_OFFSET_WININ, task->data[3]); + SetGpuReg(REG_OFFSET_WINOUT, task->data[4]); + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[5]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[6]); +} + +void sub_80B8874(u16 offs) +{ + u16 i; + u16 *dest; + dest = (u16 *)(VRAM + 0x140 + offs); + for (i = 0; i < 0x140; i++, dest++) + { + *dest = gFieldMoveStreaksTilemap[i] | 0xf000; + } +} + +void sub_80B8AE0(void); +bool8 sub_80B8B38(struct Task *); +void sub_80B8B28(struct Task *); +bool8 sub_80B8BF0(struct Task *); + +void (*const gUnknown_0855C4C4[])(struct Task *) = { + sub_80B88E4, + sub_80B8920, + sub_80B898C, + sub_80B89DC, + sub_80B8A0C, + sub_80B8A44, + sub_80B8A64, +}; + +void sub_80B88B4(u8 taskId) +{ + gUnknown_0855C4C4[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B88E4(struct Task *task) +{ + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[1]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); + StoreWordInTwoHalfwords((u16 *)&task->data[13], (u32)gMain.vblankCallback); + SetVBlankCallback(sub_80B8AE0); + task->data[0]++; +} + +void sub_80B8920(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + task->data[12] = delta; + CpuCopy16(gDarknessFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x80); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gDarknessFieldMoveStreaksPalette, 0xf0, 0x20); + task->data[0]++; +} + +void sub_80B898C(struct Task *task) +{ + if (sub_80B8B38(task)) + { + SetGpuReg(REG_OFFSET_WIN1H, 0x00f0); + SetGpuReg(REG_OFFSET_WIN1V, 0x2878); + gSprites[task->data[15]].callback = sub_80B8CC0; + task->data[0]++; + } + sub_80B8B28(task); +} + +void sub_80B89DC(struct Task *task) +{ + sub_80B8B28(task); + if (gSprites[task->data[15]].data[7]) + { + task->data[0]++; + } +} + +void sub_80B8A0C(struct Task *task) +{ + sub_80B8B28(task); + task->data[3] = task->data[1] & 7; + task->data[4] = 0; + SetGpuReg(REG_OFFSET_WIN1H, 0xffff); + SetGpuReg(REG_OFFSET_WIN1V, 0xffff); + task->data[0]++; +} + +void sub_80B8A44(struct Task *task) +{ + sub_80B8B28(task); + if (sub_80B8BF0(task)) + { + task->data[0]++; + } +} + +void sub_80B8A64(struct Task *task) +{ + IntrCallback intrCallback; + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + SetVBlankCallback(intrCallback); + sub_8197200(); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]], task->data[15]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_80B88B4)); +} + +void sub_80B8AE0(void) +{ + IntrCallback intrCallback; + struct Task *task; + task = &gTasks[FindTaskIdByFunc(sub_80B88B4)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + intrCallback(); + SetGpuReg(REG_OFFSET_BG0HOFS, task->data[1]); + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); +} + +void sub_80B8B28(struct Task *task) +{ + task->data[1] -= 16; + task->data[3] += 16; +} + +#ifdef NONMATCHING +bool8 sub_80B8B38(struct Task *task) +{ + u16 i; + u16 srcOffs; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = (task->data[3] >> 3) & 0x1f; + if (dstOffs >= task->data[4]) + { + dstOffs = (32 - dstOffs) & 0x1f; + srcOffs = (32 - task->data[4]) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = gDarknessFieldMoveStreaksTilemap[srcOffs + i * 32] | 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = gDarknessFieldMoveStreaksTilemap[((srcOffs + 1) & 0x1f) + i * 32] | 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} +#else +NAKED +bool8 sub_80B8B38(struct Task *task) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x4\n" + "\tadds r5, r0, 0\n" + "\tldrh r2, [r5, 0x10]\n" + "\tmovs r1, 0x10\n" + "\tldrsh r0, [r5, r1]\n" + "\tcmp r0, 0x1F\n" + "\tble _08088724\n" + "\tmovs r0, 0x1\n" + "\tb _080887A8\n" + "_08088724:\n" + "\tldrh r0, [r5, 0xE]\n" + "\tlsls r0, 16\n" + "\tasrs r3, r0, 19\n" + "\tmovs r1, 0x1F\n" + "\tands r3, r1\n" + "\tmovs r4, 0x10\n" + "\tldrsh r0, [r5, r4]\n" + "\tcmp r3, r0\n" + "\tblt _080887A6\n" + "\tmovs r0, 0x20\n" + "\tsubs r3, r0, r3\n" + "\tands r3, r1\n" + "\tsubs r0, r2\n" + "\tmov r12, r0\n" + "\tmov r7, r12\n" + "\tands r7, r1\n" + "\tmov r12, r7\n" + "\tldrh r0, [r5, 0x20]\n" + "\tldr r1, _080887B8 @ =0x06000140\n" + "\tadds r1, r0\n" + "\tmov r8, r1\n" + "\tmovs r4, 0\n" + "\tldr r7, _080887BC @ =gDarknessFieldMoveStreaksTilemap\n" + "\tmov r10, r7\n" + "\tmovs r0, 0xF0\n" + "\tlsls r0, 8\n" + "\tmov r9, r0\n" + "\tadds r1, r3, 0x1\n" + "\tmovs r0, 0x1F\n" + "\tands r1, r0\n" + "\tstr r1, [sp]\n" + "\tmov r6, r12\n" + "\tadds r6, 0x1\n" + "\tands r6, r0\n" + "_08088768:\n" + "\tlsls r1, r4, 5\n" + "\tadds r2, r1, r3\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tmov r7, r12\n" + "\tadds r0, r7, r1\n" + "\tlsls r0, 1\n" + "\tadd r0, r10\n" + "\tldrh r0, [r0]\n" + "\tmov r7, r9\n" + "\torrs r0, r7\n" + "\tstrh r0, [r2]\n" + "\tldr r0, [sp]\n" + "\tadds r2, r1, r0\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tadds r1, r6, r1\n" + "\tlsls r1, 1\n" + "\tadd r1, r10\n" + "\tldrh r0, [r1]\n" + "\tmov r1, r9\n" + "\torrs r0, r1\n" + "\tstrh r0, [r2]\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r4, r0, 16\n" + "\tcmp r4, 0x9\n" + "\tbls _08088768\n" + "\tldrh r0, [r5, 0x10]\n" + "\tadds r0, 0x2\n" + "\tstrh r0, [r5, 0x10]\n" + "_080887A6:\n" + "\tmovs r0, 0\n" + "_080887A8:\n" + "\tadd sp, 0x4\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_080887B8: .4byte 0x06000140\n" + "_080887BC: .4byte gDarknessFieldMoveStreaksTilemap"); +} +#endif + +bool8 sub_80B8BF0(struct Task *task) +{ + u16 i; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = task->data[3] >> 3; + if (dstOffs >= task->data[4]) + { + dstOffs = (task->data[1] >> 3) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} + +u8 sub_80B8C60(u32 a0, u32 a1, u32 a2) +{ + u16 v0; + u8 monSprite; + struct Sprite *sprite; + v0 = (a0 & 0x80000000) >> 16; + a0 &= 0x7fffffff; + monSprite = CreateMonSprite_FieldMove(a0, a1, a2, 0x140, 0x50, 0); + sprite = &gSprites[monSprite]; + sprite->callback = SpriteCallbackDummy; + sprite->oam.priority = 0; + sprite->data[0] = a0; + sprite->data[6] = v0; + return monSprite; +} + +void sub_80B8D04(struct Sprite *); + +void sub_80B8CC0(struct Sprite *sprite) +{ + if ((sprite->pos1.x -= 20) <= 0x78) + { + sprite->pos1.x = 0x78; + sprite->data[1] = 30; + sprite->callback = sub_80B8D04; + if (sprite->data[6]) + { + PlayCry2(sprite->data[0], 0, 0x7d, 0xa); + } else + { + PlayCry1(sprite->data[0], 0); + } + } +} + +void sub_80B8D20(struct Sprite *); + +void sub_80B8D04(struct Sprite *sprite) +{ + if ((--sprite->data[1]) == 0) + { + sprite->callback = sub_80B8D20; + } +} + +void sub_80B8D20(struct Sprite *sprite) +{ + if (sprite->pos1.x < -0x40) + { + sprite->data[7] = 1; + } else + { + sprite->pos1.x -= 20; + } +} + +void sub_80B8D84(u8); + +u8 FldEff_UseSurf(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B8D84, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + Overworld_ClearSavedMusic(); + Overworld_ChangeMusicTo(MUS_NAMINORI); + return FALSE; +} + +void (*const gUnknown_0855C4E0[])(struct Task *) = { + sub_80B8DB4, + sub_80B8E14, + sub_80B8E60, + sub_80B8EA8, + sub_80B8F24, +}; + +void sub_80B8D84(u8 taskId) +{ + gUnknown_0855C4E0[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B8DB4(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(8); + PlayerGetDestCoords(&task->data[1], &task->data[2]); + MoveCoords(gMapObjects[gPlayerAvatar.mapObjectId].placeholder18, &task->data[1], &task->data[2]); + task->data[0]++; +} + +void sub_80B8E14(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B8E60(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(mapObject)) + { + gFieldEffectArguments[0] = task->data[15] | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } +} + +void sub_80B8EA8(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(3)); + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + FieldObjectSetSpecialAnim(mapObject, sub_8093540(mapObject->placeholder18)); + gFieldEffectArguments[0] = task->data[1]; + gFieldEffectArguments[1] = task->data[2]; + gFieldEffectArguments[2] = gPlayerAvatar.mapObjectId; + mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_SURF_BLOB); + task->data[0]++; + } +} + +void sub_80B8F24(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.preventStep = FALSE; + gPlayerAvatar.flags &= 0xdf; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(mapObject->placeholder18)); + sub_81555AC(mapObject->mapobj_unk_1A, 1); + UnfreezeMapObjects(); + ScriptContext2_Disable(); + FieldEffectActiveListRemove(FLDEFF_USE_SURF); + DestroyTask(FindTaskIdByFunc(sub_80B8D84)); + } +} + +#ifdef NONMATCHING +u8 sub_80B8F98(void) +{ + u8 spriteId, i, j, k, l; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[36], 0x78, -0x18, 1); + sprite = &gSprites[spriteId]; + sprite->oam.priority = 1; + sprite->oam.paletteNum = 4; + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 0; + sprite->data[3] = -1; + sprite->data[4] = sprite->pos1.y; + sprite->data[5] = 0; + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(14, 14)); + SetGpuReg(REG_OFFSET_WININ, 0x3F3F); + LoadPalette(gUnknown_0855B610, 0xC0, sizeof(gUnknown_0855B610)); + SetGpuReg(REG_OFFSET_BG0VOFS, 120); + for (i = 3; i < 15; i++) + { + for (j = 12; j < 18; j++) + { + ((u16*)(VRAM + 0xF800))[i * 32 + j] = 0xBFF4 + i * 6 + j + 1; + } + } + for (k = 0; k < 90; k++) + { + for (l = 0; l < 8; l++) + { + *(u16*)(VRAM + 0x8000 + (k + 1) * 32 + l * 4) = (gUnknown_0855B630[k * 32 + l * 4 + 1] << 8) + gUnknown_0855B630[k * 32 + l * 4]; + *(u16*)(VRAM + 0x8000 + (k + 1) * 32 + l * 4 + 2) = (gUnknown_0855B630[k * 32 + l * 4 + 3] << 8) + gUnknown_0855B630[k * 32 + l * 4 + 2]; + } + } + return spriteId; +} +#else +NAKED +u8 sub_80B8F98(void) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + ldr r0, =gFieldEffectObjectTemplatePointers\n\ + adds r0, 0x90\n\ + ldr r0, [r0]\n\ + movs r2, 0x18\n\ + negs r2, r2\n\ + movs r1, 0x78\n\ + movs r3, 0x1\n\ + bl CreateSprite\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + lsls r1, r0, 4\n\ + add r1, r8\n\ + lsls r1, 2\n\ + ldr r0, =gSprites\n\ + adds r1, r0\n\ + ldrb r2, [r1, 0x5]\n\ + movs r0, 0xD\n\ + negs r0, r0\n\ + ands r0, r2\n\ + movs r2, 0x4\n\ + orrs r0, r2\n\ + movs r2, 0xF\n\ + ands r0, r2\n\ + movs r2, 0x40\n\ + orrs r0, r2\n\ + strb r0, [r1, 0x5]\n\ + movs r2, 0\n\ + strh r2, [r1, 0x2E]\n\ + strh r2, [r1, 0x30]\n\ + strh r2, [r1, 0x32]\n\ + ldr r0, =0x0000ffff\n\ + strh r0, [r1, 0x34]\n\ + ldrh r0, [r1, 0x22]\n\ + strh r0, [r1, 0x36]\n\ + strh r2, [r1, 0x38]\n\ + ldr r1, =0x00003e41\n\ + movs r0, 0x50\n\ + bl SetGpuReg\n\ + ldr r1, =0x00000e0e\n\ + movs r0, 0x52\n\ + bl SetGpuReg\n\ + ldr r1, =0x00003f3f\n\ + movs r0, 0x48\n\ + bl SetGpuReg\n\ + ldr r0, =gUnknown_0855B610\n\ + movs r1, 0xC0\n\ + movs r2, 0x20\n\ + bl LoadPalette\n\ + movs r0, 0x12\n\ + movs r1, 0x78\n\ + bl SetGpuReg\n\ + movs r4, 0x3\n\ + ldr r7, =0x0600f800\n\ + ldr r0, =0x0000bff4\n\ + adds r6, r0, 0\n\ +_080B901A:\n\ + movs r2, 0xC\n\ + lsls r0, r4, 1\n\ + lsls r5, r4, 5\n\ + adds r0, r4\n\ + lsls r3, r0, 1\n\ +_080B9024:\n\ + adds r0, r5, r2\n\ + lsls r0, 1\n\ + adds r0, r7\n\ + adds r1, r2, r6\n\ + adds r1, r3, r1\n\ + adds r1, 0x1\n\ + strh r1, [r0]\n\ + adds r0, r2, 0x1\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + cmp r2, 0x11\n\ + bls _080B9024\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0xE\n\ + bls _080B901A\n\ + movs r0, 0\n\ + ldr r5, =gUnknown_0855B630\n\ +_080B904A:\n\ + movs r4, 0\n\ + adds r7, r0, 0x1\n\ + lsls r6, r0, 5\n\ +_080B9050:\n\ + lsls r1, r4, 2\n\ + adds r1, r6, r1\n\ + ldr r0, =0x06008020\n\ + adds r3, r1, r0\n\ + adds r0, r1, 0x1\n\ + adds r0, r5\n\ + ldrb r2, [r0]\n\ + lsls r2, 8\n\ + adds r0, r1, r5\n\ + ldrb r0, [r0]\n\ + adds r0, r2\n\ + strh r0, [r3]\n\ + ldr r0, =0x06008022\n\ + adds r3, r1, r0\n\ + adds r0, r1, 0x3\n\ + adds r0, r5\n\ + ldrb r2, [r0]\n\ + lsls r2, 8\n\ + adds r1, 0x2\n\ + adds r1, r5\n\ + ldrb r0, [r1]\n\ + adds r0, r2\n\ + strh r0, [r3]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r4, 0x7\n\ + bls _080B9050\n\ + lsls r0, r7, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x59\n\ + bls _080B904A\n\ + mov r0, r8\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool"); +} +#endif // NONMATCHING + +void sub_80B9128(struct Sprite *); + +u8 FldEff_NPCFlyOut(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0x78, 0, 1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_80B9128; + sprite->data[1] = gFieldEffectArguments[0]; + PlaySE(SE_W019); + return spriteId; +} + +void sub_80B9128(struct Sprite *sprite) +{ + struct Sprite *npcSprite; + sprite->pos2.x = Cos(sprite->data[2], 0x8c); + sprite->pos2.y = Sin(sprite->data[2], 0x48); + sprite->data[2] = (sprite->data[2] + 4) & 0xff; + if (sprite->data[0]) + { + npcSprite = &gSprites[sprite->data[1]]; + npcSprite->coordOffsetEnabled = 0; + npcSprite->pos1.x = sprite->pos1.x + sprite->pos2.x; + npcSprite->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + npcSprite->pos2.x = 0; + npcSprite->pos2.y = 0; + } + if (sprite->data[2] >= 0x80) + { + FieldEffectStop(sprite, FLDEFF_NPCFLY_OUT); + } +} + +void sub_80B91D4(u8); +extern void sub_81555D8(u8, u8); +u8 sub_80B94C4(void); +bool8 sub_80B9508(u8); +void sub_80B9524(u8); +void sub_80B9560(u8, u8); +void sub_80B957C(struct Sprite *); +void sub_80B963C(struct Sprite *); + +u8 FldEff_UseFly(void) +{ + u8 taskId; + taskId = CreateTask(sub_80B91D4, 0xfe); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + return 0; +} + +void (*const gUnknown_0855C4F4[])(struct Task *) = { + sub_80B9204, + sub_80B925C, + sub_80B92A0, + sub_80B92F8, + sub_80B933C, + sub_80B9390, + sub_80B9418, + sub_80B9474, + sub_80B9494, +}; + +void sub_80B91D4(u8 taskId) +{ + gUnknown_0855C4F4[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B9204(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(1); + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B925C(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + } +} + +void sub_80B92A0(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[15] & 0x08) + { + sub_81555AC(mapObject->mapobj_unk_1A, 2); + sub_81555D8(mapObject->mapobj_unk_1A, 0); + } + task->data[1] = sub_80B94C4(); + task->data[0]++; + } +} + +void sub_80B92F8(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + task->data[0]++; + task->data[2] = 16; + SetPlayerAvatarTransitionFlags(PLAYER_AVATAR_FLAG_ON_FOOT); + FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], 0x02); + } +} + +void sub_80B933C(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((task->data[2] == 0 || (--task->data[2]) == 0) && FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + PlaySE(SE_W019); + sub_80B9524(task->data[1]); + } +} + +void sub_80B9390(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 8) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x03)); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_12 = 1; + FieldObjectSetSpecialAnim(mapObject, 0x48); + if (task->data[15] & 0x08) + { + DestroySprite(&gSprites[mapObject->mapobj_unk_1A]); + } + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_80B9418(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 10) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectClearAnimIfSpecialAnimActive(mapObject); + mapObject->mapobj_bit_12 = 0; + mapObject->mapobj_bit_22 = 0; + sub_80B9560(task->data[1], mapObject->spriteId); + CameraObjectReset2(); + task->data[0]++; + } +} + +void sub_80B9474(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + sub_80AF0B4(); + task->data[0]++; + } +} + +void sub_80B9494(struct Task *task) +{ + if (!gPaletteFade.active) + { + FieldEffectActiveListRemove(FLDEFF_USE_FLY); + DestroyTask(FindTaskIdByFunc(sub_80B91D4)); + } +} + +u8 sub_80B94C4(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0xff, 0xb4, 0x1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_80B957C; + return spriteId; +} + +u8 sub_80B9508(u8 spriteId) +{ + return gSprites[spriteId].data[7]; +} + +void sub_80B9524(u8 spriteId) +{ + struct Sprite *sprite; + sprite = &gSprites[spriteId]; + sprite->callback = sub_80B963C; + sprite->pos1.x = 0x78; + sprite->pos1.y = 0x00; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + memset(&sprite->data[0], 0, 8 * sizeof(u16) /* zero all data cells */); + sprite->data[6] = 0x40; +} + +void sub_80B9560(u8 a0, u8 a1) +{ + gSprites[a0].data[6] = a1; +} + +const union AffineAnimCmd SpriteAffineAnim_855C518[] = { + AFFINEANIMCMD_FRAME(8, 8, -30, 0), + AFFINEANIMCMD_FRAME(28, 28, 0, 30), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd SpriteAffineAnim_855C530[] = { + AFFINEANIMCMD_FRAME(256, 256, 64, 0), + AFFINEANIMCMD_FRAME(-10, -10, 0, 22), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd *const gSpriteAffineAnimTable_0855C548[] = { + SpriteAffineAnim_855C518, + SpriteAffineAnim_855C530 +}; + +void sub_80B957C(struct Sprite *sprite) +{ + if (sprite->data[7] == 0) + { + if (sprite->data[0] == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0855C548; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 0); + sprite->pos1.x = 0x76; + sprite->pos1.y = -0x30; + sprite->data[0]++; + sprite->data[1] = 0x40; + sprite->data[2] = 0x100; + } + sprite->data[1] += (sprite->data[2] >> 8); + sprite->pos2.x = Cos(sprite->data[1], 0x78); + sprite->pos2.y = Sin(sprite->data[1], 0x78); + if (sprite->data[2] < 0x800) + { + sprite->data[2] += 0x60; + } + if (sprite->data[1] > 0x81) + { + sprite->data[7]++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, 0); + } + } +} + +void sub_80B963C(struct Sprite *sprite) +{ + struct Sprite *sprite1; + sprite->pos2.x = Cos(sprite->data[2], 0x8c); + sprite->pos2.y = Sin(sprite->data[2], 0x48); + sprite->data[2] = (sprite->data[2] + 4) & 0xff; + if (sprite->data[6] != 0x40) + { + sprite1 = &gSprites[sprite->data[6]]; + sprite1->coordOffsetEnabled = 0; + sprite1->pos1.x = sprite->pos1.x + sprite->pos2.x; + sprite1->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + sprite1->pos2.x = 0; + sprite1->pos2.y = 0; + } + if (sprite->data[2] >= 0x80) + { + sprite->data[7] = 1; + } +} + +void sub_80B96B0(struct Sprite *sprite) +{ + if (sprite->data[7] == 0) + { + if (sprite->data[0] == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0855C548; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 1); + sprite->pos1.x = 0x5e; + sprite->pos1.y = -0x20; + sprite->data[0]++; + sprite->data[1] = 0xf0; + sprite->data[2] = 0x800; + sprite->data[4] = 0x80; + } + sprite->data[1] += sprite->data[2] >> 8; + sprite->data[3] += sprite->data[2] >> 8; + sprite->data[1] &= 0xff; + sprite->pos2.x = Cos(sprite->data[1], 0x20); + sprite->pos2.y = Sin(sprite->data[1], 0x78); + if (sprite->data[2] > 0x100) + { + sprite->data[2] -= sprite->data[4]; + } + if (sprite->data[4] < 0x100) + { + sprite->data[4] += 24; + } + if (sprite->data[2] < 0x100) + { + sprite->data[2] = 0x100; + } + if (sprite->data[3] >= 60) + { + sprite->data[7]++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + sprite->invisible = 1; + } + } +} + +void sub_80B9794(u8 spriteId) +{ + sub_80B9524(spriteId); + gSprites[spriteId].callback = sub_80B96B0; +} + +void sub_80B97D4(u8); + +u8 FldEff_FlyIn(void) +{ + CreateTask(sub_80B97D4, 0xfe); + return 0; +} + +void (*const gUnknown_0855C550[])(struct Task *) = { + sub_80B9804, + sub_80B98B8, + sub_80B9924, + sub_80B9978, + sub_80B99F0, + sub_80B9A28, + sub_80B9A60, +}; + +void sub_80B97D4(u8 taskId) +{ + gUnknown_0855C550[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80B9804(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + task->data[2] = 17; + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.preventStep = TRUE; + SetPlayerAvatarStateMask(0x01); + if (task->data[15] & 0x08) + { + sub_81555AC(mapObject->mapobj_unk_1A, 0); + } + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x3)); + CameraObjectReset2(); + FieldObjectTurn(mapObject, DIR_WEST); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_13 = 0; + task->data[1] = sub_80B94C4(); + sub_80B9524(task->data[1]); + sub_80B9560(task->data[1], mapObject->spriteId); + } +} + +void sub_80B98B8(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (task->data[2] == 0 || (--task->data[2]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + sub_80B9560(task->data[1], 0x40); + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_80B9924(struct Task *task) +{ + s16 unknown_0855C56C[18] = { + -2, + -4, + -5, + -6, + -7, + -8, + -8, + -8, + -7, + -7, + -6, + -5, + -3, + -2, + 0, + 2, + 4, + 8 + }; + struct Sprite *sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y = unknown_0855C56C[task->data[2]]; + if ((++task->data[2]) >= 18) + { + task->data[0]++; + } +} + +void sub_80B9978(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (sub_80B9508(task->data[1])) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + mapObject->mapobj_bit_12 = 0; + sub_808EB08(mapObject, mapObject->coords2.x, mapObject->coords2.y); + sprite->pos2.x = 0; + sprite->pos2.y = 0; + sprite->coordOffsetEnabled = 1; + sub_808C114(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_80B99F0(struct Task *task) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gPlayerAvatar.mapObjectId])) + { + task->data[0]++; + sub_80B9794(task->data[1]); + } +} + +void sub_80B9A28(struct Task *task) +{ + if (sub_80B9508(task->data[1])) + { + DestroySprite(&gSprites[task->data[1]]); + task->data[0]++; + task->data[1] = 0x10; + } +} + +void sub_80B9A60(struct Task *task) +{ + u8 state; + struct MapObject *mapObject; + if ((--task->data[1]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + state = 0; + if (task->data[15] & 0x08) + { + state = 3; + sub_81555AC(mapObject->mapobj_unk_1A, 1); + } + FieldObjectSetGraphicsId(mapObject, GetPlayerAvatarGraphicsIdByStateId(state)); + FieldObjectTurn(mapObject, DIR_SOUTH); + gPlayerAvatar.flags = task->data[15]; + gPlayerAvatar.preventStep = FALSE; + FieldEffectActiveListRemove(FLDEFF_FLY_IN); + DestroyTask(FindTaskIdByFunc(sub_80B97D4)); + } +} + +void sub_80B9BE8(u8 taskId); + +bool8 sub_80B9ADC(void) +{ + u8 taskId; + u8 mapObjectIdBuffer; + if (!TryGetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &mapObjectIdBuffer)) + { + taskId = CreateTask(sub_80B9BE8, 0x50); + gTasks[taskId].data[2] = mapObjectIdBuffer; + gTasks[taskId].data[6] = gFieldEffectArguments[0]; + gTasks[taskId].data[7] = gFieldEffectArguments[1]; + gTasks[taskId].data[8] = gFieldEffectArguments[2]; + } + else + { + FieldEffectActiveListRemove(0x41); + } + return FALSE; +} + +void sub_80B9B3C(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + if (data[7] != 0) + { + if (++data[6] > 20) + { + data[6] = 0; + if (data[5] != 0) + data[5]--; + } + } + else + { + data[5] = 4; + } + + if (++data[0] > 1) + { + data[0] = 0; + if (++data[1] & 1) + { + SetCameraPanning(0, -data[5]); + } + else + { + SetCameraPanning(0, data[5]); + } + } + UpdateCameraPanning(); + if (data[5] == 0) + DestroyTask(taskId); +} + +void sub_80B9BD0(u8 taskId) +{ + gTasks[taskId].data[7] = 1; +} + +void (*const gUnknown_0855C590[])(s16*, u8) = { + sub_80B9C28, + sub_80B9C54, + sub_80B9CDC, +}; + +void sub_80B9BE8(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + InstallCameraPanAheadCallback(); + SetCameraPanningCallback(0); + gUnknown_0855C590[data[1]](data, taskId); +} + +void sub_80B9C28(s16* data, u8 taskId) +{ + u8 newTaskId = CreateTask(sub_80B9B3C, 0x5A); + PlaySE(SE_T_KAMI2); + data[5] = newTaskId; + data[1]++; +} + +void sub_80B9D24(struct Sprite*); + +void sub_80B9C54(s16* data, u8 taskId) +{ + if (++data[3] > 0x78) + { + struct Sprite *sprite = &gSprites[gMapObjects[data[2]].spriteId]; + gMapObjects[data[2]].mapobj_bit_13 = TRUE; + BlendPalettes(0x0000FFFF, 0x10, RGB_WHITE); + BeginNormalPaletteFade(0x0000FFFF, 0, 0x10, 0, RGB_WHITE); + sub_80B9D24(sprite); + PlaySE(SE_T_KAMI); + sub_80B9BD0(data[5]); + data[3] = 0; + data[1]++; + } +} + +void sub_80B9CDC(s16* a0, u8 taskId) +{ + if (!gPaletteFade.active && !FuncIsActiveTask(sub_80B9B3C)) + { + InstallCameraPanAheadCallback(); + RemoveFieldObjectByLocalIdAndMap(a0[6], a0[7], a0[8]); + FieldEffectActiveListRemove(0x41); + DestroyTask(taskId); + } +} + +void sub_80B9DB8(struct Sprite* sprite); + +const struct SpriteFrameImage gSpriteImageTable_855C59C[] = { + obj_frame_tiles(gUnknown_0855C170), + obj_frame_tiles(gUnknown_0855C190), + obj_frame_tiles(gUnknown_0855C1B0), + obj_frame_tiles(gUnknown_0855C1D0), +}; + +const union AnimCmd gSpriteAnim_855C5BC[] = { + ANIMCMD_FRAME(.imageValue = 0), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5C4[] = { + ANIMCMD_FRAME(.imageValue = 1), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5CC[] = { + ANIMCMD_FRAME(.imageValue = 2), + ANIMCMD_END +}; + +const union AnimCmd gSpriteAnim_855C5D4[] = { + ANIMCMD_FRAME(.imageValue = 3), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_855C5DC[] = { + gSpriteAnim_855C5BC, + gSpriteAnim_855C5C4, + gSpriteAnim_855C5CC, + gSpriteAnim_855C5D4, +}; + +const struct SpriteTemplate gUnknown_0855C5EC = { + .tileTag = 0xffff, + .paletteTag = 4378, + .oam = &gOamData_855C218, + .anims = gSpriteAnimTable_855C5DC, + .images = gSpriteImageTable_855C59C, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B9DB8 +}; + +void sub_80B9D24(struct Sprite* sprite) +{ + int i; + int xPos = (s16)gUnknown_03005DEC + sprite->pos1.x + sprite->pos2.x; + int yPos = (s16)gUnknown_03005DE8 + sprite->pos1.y + sprite->pos2.y - 4; + + for (i = 0; i < 4; i++) + { + u8 spriteId = CreateSprite(&gUnknown_0855C5EC, xPos, yPos, 0); + if (spriteId != 0x40) + { + StartSpriteAnim(&gSprites[spriteId], i); + gSprites[spriteId].data[0] = i; + gSprites[spriteId].oam.paletteNum = sprite->oam.paletteNum; + } + } +} + +void sub_80B9DB8(struct Sprite* sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.x -= 16; + sprite->pos1.y -= 12; + break; + case 1: + sprite->pos1.x += 16; + sprite->pos1.y -= 12; + break; + case 2: + sprite->pos1.x -= 16; + sprite->pos1.y += 12; + break; + case 3: + sprite->pos1.x += 16; + sprite->pos1.y += 12; + break; + } + if ((u16)(sprite->pos1.x + 4) > 0xF8 || sprite->pos1.y < -4 || sprite->pos1.y > 0xA4) + DestroySprite(sprite); +} + +void sub_80B9EDC(u8 taskId); + +bool8 sub_80B9E28(struct Sprite* sprite) +{ + u8 mapObjectIdBuffer; + if (!TryGetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &mapObjectIdBuffer)) + { + struct MapObject *object; + int xPos, yPos; + u8 taskId; + object = &gMapObjects[mapObjectIdBuffer]; + xPos = object->coords2.x - 7; + yPos = object->coords2.y - 7; + xPos = (gFieldEffectArguments[3] - xPos) * 16; + yPos = (gFieldEffectArguments[4] - yPos) * 16; + npc_coords_shift(object, gFieldEffectArguments[3] + 7, gFieldEffectArguments[4] + 7); + taskId = CreateTask(sub_80B9EDC, 0x50); + gTasks[taskId].data[1] = object->spriteId; + gTasks[taskId].data[2] = gSprites[object->spriteId].pos1.x + xPos; + gTasks[taskId].data[3] = gSprites[object->spriteId].pos1.y + yPos; + gTasks[taskId].data[8] = gFieldEffectArguments[5]; + gTasks[taskId].data[9] = mapObjectIdBuffer; + } + return FALSE; +} + +void sub_80B9EDC(u8 taskId) +{ + // BUG: Possible divide by zero + s16 *data = gTasks[taskId].data; + struct Sprite *sprite = &gSprites[data[1]]; + switch (data[0]) + { + case 0: + data[4] = sprite->pos1.x << 4; + data[5] = sprite->pos1.y << 4; + data[6] = (data[2] * 16 - data[4]) / data[8]; + data[7] = (data[3] * 16 - data[5]) / data[8]; + data[0]++; + case 1: + if (data[8] != 0) + { + data[8]--; + data[4] += data[6]; + data[5] += data[7]; + sprite->pos1.x = data[4] >> 4; + sprite->pos1.y = data[5] >> 4; + } + else + { + struct MapObject *object = &gMapObjects[data[9]]; + sprite->pos1.x = data[2]; + sprite->pos1.y = data[3]; + npc_coords_shift_still(object); + object->mapobj_bit_3 = TRUE; + FieldEffectActiveListRemove(0x42); + DestroyTask(taskId); + } + break; + } +} diff --git a/src/field_map_obj.c b/src/field_map_obj.c index 906eff4b7..af018eb16 100644 --- a/src/field_map_obj.c +++ b/src/field_map_obj.c @@ -198,7 +198,7 @@ static void npcs_clear_ids_and_state(void) void sub_808D438(void) { - strange_npc_table_clear(); + ZeroAllLinkPlayerMapObjects(); npcs_clear_ids_and_state(); ClearPlayerAvatarInfo(); sub_808D450(); @@ -353,7 +353,7 @@ static u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u return slot; } #else -static __attribute__((naked)) u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapId, u8 mapGroupId) +static NAKED u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapId, u8 mapGroupId) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r9\n" @@ -1146,7 +1146,7 @@ const struct MapObjectGraphicsInfo *GetFieldObjectGraphicsInfo(u8 graphicsId) } if (graphicsId == 0x45) { - bard = sub_81201C8(); + bard = GetCurrentMauvilleOldMan(); return gMauvilleOldManGraphicsInfoPointers[bard]; } if (graphicsId >= NUM_OBJECT_GRAPHICS_INFO) @@ -1673,7 +1673,7 @@ struct MapObjectTemplate *GetFieldObjectTemplateByLocalIdAndMap(u8 localId, u8 m } else { - mapHeader = get_mapheader_by_bank_and_number(mapGroup, mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum); templates = mapHeader->events->mapObjects; count = mapHeader->events->mapObjectCount; } diff --git a/src/field_map_obj_helpers.c b/src/field_map_obj_helpers.c index de26cb034..b8efcfe72 100755 --- a/src/field_map_obj_helpers.c +++ b/src/field_map_obj_helpers.c @@ -529,16 +529,17 @@ void DoRippleFieldEffect(struct MapObject *mapObject, struct Sprite *sprite) FieldEffectStart(FLDEFF_RIPPLE); } -#ifdef NONMATCHING bool32 sub_8097E50(struct MapObject *mapObject, struct Sprite *sprite) { + u32 one; bool32 ableToStore = FALSE; if (gUnknown_020375B8 == NULL) { gUnknown_020375B8 = AllocZeroed(0x14); gUnknown_020375B8[0] = mapObject->localId; - gUnknown_020375B8[16] = 1; - ableToStore = TRUE; + // needed to match + gUnknown_020375B8[16] = (one = 1); + ableToStore = one; } else { @@ -561,7 +562,7 @@ bool32 sub_8097E50(struct MapObject *mapObject, struct Sprite *sprite) { gUnknown_020375B8[firstFreeSlot] = mapObject->localId; gUnknown_020375B8[16]++; - ableToStore = TRUE; // the nonmatching problem is that ableToStore == TRUE isnt being merged with the above ableToStore = TRUE assignment. + ableToStore = TRUE; } } @@ -574,174 +575,34 @@ bool32 sub_8097E50(struct MapObject *mapObject, struct Sprite *sprite) sprite->data[2] = 1; return TRUE; } -#else -__attribute__((naked)) -bool32 sub_8097E50(struct MapObject *mapObject, struct Sprite *sprite) -{ - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r8\n\ - push {r7}\n\ - adds r4, r0, 0\n\ - mov r8, r1\n\ - movs r0, 0\n\ - mov r12, r0\n\ - ldr r0, =gUnknown_020375B8\n\ - ldr r1, [r0]\n\ - adds r6, r0, 0\n\ - cmp r1, 0\n\ - bne _08097E80\n\ - movs r0, 0x14\n\ - bl AllocZeroed\n\ - str r0, [r6]\n\ - ldrb r1, [r4, 0x8]\n\ - strb r1, [r0]\n\ - ldr r1, [r6]\n\ - movs r0, 0x1\n\ - strb r0, [r1, 0x10]\n\ - b _08097ECC\n\ - .pool\n\ -_08097E80:\n\ - movs r2, 0x10\n\ - movs r5, 0\n\ - movs r1, 0\n\ - adds r3, r6, 0\n\ - b _08097E90\n\ -_08097E8A:\n\ - adds r0, r1, 0x1\n\ - lsls r0, 24\n\ - lsrs r1, r0, 24\n\ -_08097E90:\n\ - cmp r1, 0xF\n\ - bhi _08097EB2\n\ - cmp r2, 0x10\n\ - bne _08097EA4\n\ - ldr r0, [r3]\n\ - adds r0, r1\n\ - ldrb r0, [r0]\n\ - cmp r0, 0\n\ - bne _08097EA4\n\ - adds r2, r1, 0\n\ -_08097EA4:\n\ - ldr r0, [r3]\n\ - adds r0, r1\n\ - ldrb r0, [r0]\n\ - ldrb r7, [r4, 0x8]\n\ - cmp r0, r7\n\ - bne _08097E8A\n\ - movs r5, 0x1\n\ -_08097EB2:\n\ - cmp r5, 0\n\ - bne _08097ECE\n\ - cmp r2, 0x10\n\ - beq _08097ECE\n\ - ldr r0, [r6]\n\ - adds r0, r2\n\ - ldrb r1, [r4, 0x8]\n\ - strb r1, [r0]\n\ - ldr r1, [r6]\n\ - ldrb r0, [r1, 0x10]\n\ - adds r0, 0x1\n\ - strb r0, [r1, 0x10]\n\ - movs r0, 0x1\n\ -_08097ECC:\n\ - mov r12, r0\n\ -_08097ECE:\n\ - mov r1, r12\n\ - cmp r1, 0x1\n\ - bne _08097EE0\n\ - ldrb r0, [r4, 0x1]\n\ - movs r1, 0x10\n\ - orrs r0, r1\n\ - movs r1, 0x2\n\ - orrs r0, r1\n\ - strb r0, [r4, 0x1]\n\ -_08097EE0:\n\ - movs r0, 0x1\n\ - mov r7, r8\n\ - strh r0, [r7, 0x32]\n\ - pop {r3}\n\ - mov r8, r3\n\ - pop {r4-r7}\n\ - pop {r1}\n\ - bx r1\n\ - .syntax divided"); -} -#endif - -// this function is very similar to the above one and I don't want to decompile this one until the above is matching. -__attribute__((naked)) + bool32 sub_8097EF0(struct MapObject *mapObject, struct Sprite *sprite) { - asm(".syntax unified\n\ - push {r4-r7,lr}\n\ - mov r7, r8\n\ - push {r7}\n\ - adds r6, r0, 0\n\ - mov r8, r1\n\ - movs r0, 0x1\n\ - strh r0, [r1, 0x32]\n\ - ldr r5, =gUnknown_020375B8\n\ - ldr r0, [r5]\n\ - cmp r0, 0\n\ - beq _08097F68\n\ - movs r7, 0\n\ - adds r0, r6, 0\n\ - bl sub_8097F78\n\ - lsls r0, 24\n\ - lsrs r1, r0, 24\n\ - cmp r1, 0x10\n\ - beq _08097F28\n\ - ldr r0, [r5]\n\ - adds r0, r1\n\ - movs r1, 0\n\ - strb r1, [r0]\n\ - ldr r1, [r5]\n\ - ldrb r0, [r1, 0x10]\n\ - subs r0, 0x1\n\ - strb r0, [r1, 0x10]\n\ - movs r7, 0x1\n\ -_08097F28:\n\ - ldr r0, [r5]\n\ - ldrb r4, [r0, 0x10]\n\ - cmp r4, 0\n\ - bne _08097F36\n\ - bl Free\n\ - str r4, [r5]\n\ -_08097F36:\n\ - cmp r7, 0x1\n\ - bne _08097F68\n\ - ldrb r0, [r6, 0x5]\n\ - bl GetFieldObjectGraphicsInfo\n\ - ldrb r1, [r0, 0xC]\n\ - lsls r1, 25\n\ - lsrs r1, 31\n\ - lsls r1, 4\n\ - ldrb r2, [r6, 0x1]\n\ - movs r0, 0x11\n\ - negs r0, r0\n\ - ands r0, r2\n\ - orrs r0, r1\n\ - movs r1, 0x3\n\ - negs r1, r1\n\ - ands r0, r1\n\ - strb r0, [r6, 0x1]\n\ - mov r2, r8\n\ - adds r2, 0x2C\n\ - ldrb r1, [r2]\n\ - movs r0, 0x41\n\ - negs r0, r0\n\ - ands r0, r1\n\ - strb r0, [r2]\n\ -_08097F68:\n\ - movs r0, 0x1\n\ - pop {r3}\n\ - mov r8, r3\n\ - pop {r4-r7}\n\ - pop {r1}\n\ - bx r1\n\ - .pool\n\ - .syntax divided"); + bool32 ableToStore; + u8 id; + + sprite->data[2] = 1; + if (gUnknown_020375B8 != NULL) + { + ableToStore = FALSE; + id = sub_8097F78(mapObject); + if (id != 16) + { + gUnknown_020375B8[id] = 0; + gUnknown_020375B8[16]--; + ableToStore = TRUE; + } + if (gUnknown_020375B8[16] == 0) + FREE_AND_SET_NULL(gUnknown_020375B8); + if (ableToStore == TRUE) + { + mapObject->mapobj_bit_12 = GetFieldObjectGraphicsInfo(mapObject->graphicsId)->inanimate; + mapObject->mapobj_bit_9 = 0; + sprite->animPaused = 0; + } + } + + return TRUE; } u8 sub_8097F78(struct MapObject *mapObject) diff --git a/src/fieldmap.c b/src/fieldmap.c new file mode 100644 index 000000000..245c88327 --- /dev/null +++ b/src/fieldmap.c @@ -0,0 +1,1034 @@ +#include "global.h" +#include "overworld.h" +#include "bg.h" +#include "battle_frontier_2.h" +#include "constants/rgb.h" +#include "fieldmap.h" +#include "fldeff_80F9BCC.h" +#include "fldeff_cut.h" +#include "fldeff_groundshake.h" +#include "menu.h" +#include "palette.h" +#include "pokenav.h" +#include "script.h" +#include "secret_base.h" +#include "tv.h" + +struct ConnectionFlags +{ + u8 south:1; + u8 north:1; + u8 west:1; + u8 east:1; +}; + +EWRAM_DATA static u16 gUnknown_02032318[0x2800] = {0}; +EWRAM_DATA struct MapHeader gMapHeader = {0}; +EWRAM_DATA struct Camera gCamera = {0}; +EWRAM_DATA static struct ConnectionFlags gUnknown_02037340 = {0}; +EWRAM_DATA static u32 sFiller_02037344 = 0; // without this, the next file won't align properly + +struct BackupMapData gUnknown_03005DC0; + +static const struct ConnectionFlags sDummyConnectionFlags = {0}; + +struct MapHeader const *const mapconnection_get_mapheader(struct MapConnection *connection) +{ + return Overworld_GetMapHeaderByGroupAndId(connection->mapGroup, connection->mapNum); +} + +void not_trainer_hill_battle_pyramid(void) +{ + mapheader_copy_mapdata_with_padding(&gMapHeader); + sub_80E8EE0(gMapHeader.events); + mapheader_run_script_with_tag_x1(); +} + +void sub_8087D74(void) +{ + mapheader_copy_mapdata_with_padding(&gMapHeader); + sub_80E9238(0); + sub_80E8EE0(gMapHeader.events); + mapdata_from_sav2(); + mapheader_run_script_with_tag_x1(); + UpdateTVScreensOnMap(gUnknown_03005DC0.width, gUnknown_03005DC0.height); +} + +void battle_pyramid_map_load_related(u8 a0) +{ + CpuFastFill(0x03ff03ff, gUnknown_02032318, sizeof(gUnknown_02032318)); + sub_81AA078(gUnknown_02032318, a0); +} + +void trainer_hill_map_load_related(void) +{ + CpuFastFill(0x03ff03ff, gUnknown_02032318, sizeof(gUnknown_02032318)); + sub_81D5FB4(gUnknown_02032318); +} + +void mapheader_copy_mapdata_with_padding(struct MapHeader *mapHeader) +{ + struct MapData const *mapData; + int width; + int height; + mapData = mapHeader->mapData; + CpuFastFill16(0x03ff, gUnknown_02032318, sizeof(gUnknown_02032318)); + gUnknown_03005DC0.map = gUnknown_02032318; + width = mapData->width + 15; + gUnknown_03005DC0.width = width; + height = mapData->height + 14; + gUnknown_03005DC0.height = height; + if (width * height <= 0x2800) + { + map_copy_with_padding(mapData->map, mapData->width, mapData->height); + mapheader_copy_mapdata_of_adjacent_maps(mapHeader); + } +} + +void map_copy_with_padding(u16 *map, u16 width, u16 height) +{ + u16 *dest; + int y; + dest = gUnknown_03005DC0.map; + dest += gUnknown_03005DC0.width * 7 + 7; + for (y = 0; y < height; y++) + { + CpuCopy16(map, dest, width * 2); + dest += width + 0xf; + map += width; + } +} + +void mapheader_copy_mapdata_of_adjacent_maps(struct MapHeader *mapHeader) +{ + int count; + struct MapConnection *connection; + int i; + + if (mapHeader->connections) + { + count = mapHeader->connections->count; + connection = mapHeader->connections->connections; + + gUnknown_02037340 = sDummyConnectionFlags; + for (i = 0; i < count; i++, connection++) + { + struct MapHeader const *cMap = mapconnection_get_mapheader(connection); + u32 offset = connection->offset; + + switch (connection->direction) + { + case CONNECTION_SOUTH: + fillSouthConnection(mapHeader, cMap, offset); + gUnknown_02037340.south = 1; + break; + case CONNECTION_NORTH: + fillNorthConnection(mapHeader, cMap, offset); + gUnknown_02037340.north = 1; + break; + case CONNECTION_WEST: + fillWestConnection(mapHeader, cMap, offset); + gUnknown_02037340.west = 1; + break; + case CONNECTION_EAST: + fillEastConnection(mapHeader, cMap, offset); + gUnknown_02037340.east = 1; + break; + } + } + } +} + +void sub_8087F54(int x, int y, struct MapHeader const *mapHeader, int x2, int y2, int width, int height) +{ + int i; + u16 *src; + u16 *dest; + int mapWidth; + + mapWidth = mapHeader->mapData->width; + src = &mapHeader->mapData->map[mapWidth * y2 + x2]; + dest = &gUnknown_03005DC0.map[gUnknown_03005DC0.width * y + x]; + + for (i = 0; i < height; i++) + { + CpuCopy16(src, dest, width * 2); + dest += gUnknown_03005DC0.width; + src += mapWidth; + } +} + +void fillSouthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset) +{ + int x, y; + int x2; + int width; + int cWidth; + + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + x = offset + 7; + y = mapHeader->mapData->height + 7; + if (x < 0) + { + x2 = -x; + x += cWidth; + if (x < gUnknown_03005DC0.width) + { + width = x; + } + else + { + width = gUnknown_03005DC0.width; + } + x = 0; + } + else + { + x2 = 0; + if (x + cWidth < gUnknown_03005DC0.width) + { + width = cWidth; + } + else + { + width = gUnknown_03005DC0.width - x; + } + } + + sub_8087F54( + x, y, + connectedMapHeader, + x2, /*y2*/ 0, + width, /*height*/ 7); + } +} + +void fillNorthConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset) +{ + int x; + int x2, y2; + int width; + int cWidth, cHeight; + + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + cHeight = connectedMapHeader->mapData->height; + x = offset + 7; + y2 = cHeight - 7; + if (x < 0) + { + x2 = -x; + x += cWidth; + if (x < gUnknown_03005DC0.width) + { + width = x; + } + else + { + width = gUnknown_03005DC0.width; + } + x = 0; + } + else + { + x2 = 0; + if (x + cWidth < gUnknown_03005DC0.width) + { + width = cWidth; + } + else + { + width = gUnknown_03005DC0.width - x; + } + } + + sub_8087F54( + x, /*y*/ 0, + connectedMapHeader, + x2, y2, + width, /*height*/ 7); + + } +} + +void fillWestConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset) +{ + int y; + int x2, y2; + int height; + int cWidth, cHeight; + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + cHeight = connectedMapHeader->mapData->height; + y = offset + 7; + x2 = cWidth - 7; + if (y < 0) + { + y2 = -y; + if (y + cHeight < gUnknown_03005DC0.height) + { + height = y + cHeight; + } + else + { + height = gUnknown_03005DC0.height; + } + y = 0; + } + else + { + y2 = 0; + if (y + cHeight < gUnknown_03005DC0.height) + { + height = cHeight; + } + else + { + height = gUnknown_03005DC0.height - y; + } + } + + sub_8087F54( + /*x*/ 0, y, + connectedMapHeader, + x2, y2, + /*width*/ 7, height); + } +} + +void fillEastConnection(struct MapHeader const *mapHeader, struct MapHeader const *connectedMapHeader, s32 offset) +{ + int x, y; + int y2; + int height; + int cHeight; + if (connectedMapHeader) + { + cHeight = connectedMapHeader->mapData->height; + x = mapHeader->mapData->width + 7; + y = offset + 7; + if (y < 0) + { + y2 = -y; + if (y + cHeight < gUnknown_03005DC0.height) + { + height = y + cHeight; + } + else + { + height = gUnknown_03005DC0.height; + } + y = 0; + } + else + { + y2 = 0; + if (y + cHeight < gUnknown_03005DC0.height) + { + height = cHeight; + } + else + { + height = gUnknown_03005DC0.height - y; + } + } + + sub_8087F54( + x, y, + connectedMapHeader, + /*x2*/ 0, y2, + /*width*/ 8, height); + } +} + +union Block +{ + struct + { + u16 block:10; + u16 collision:2; + u16 elevation:4; + } block; + u16 value; +}; + +u8 MapGridGetZCoordAt(int x, int y) +{ + u16 block; + int i; + u16 *border; + + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + block = gUnknown_03005DC0.map[x + gUnknown_03005DC0.width * y]; + } + else + { + border = gMapHeader.mapData->border; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = gMapHeader.mapData->border[i]; + block |= 0xc00; + } + + if (block == 0x3ff) + { + return 0; + } + + return block >> 12; +} + +u8 MapGridIsImpassableAt(int x, int y) +{ + u16 block; + int i; + u16 *border; + + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + block = gUnknown_03005DC0.map[x + gUnknown_03005DC0.width * y]; + } + else + { + border = gMapHeader.mapData->border; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = gMapHeader.mapData->border[i]; + block |= 0xc00; + } + if (block == 0x3ff) + { + return 1; + } + return (block & 0xc00) >> 10; +} + +u32 MapGridGetMetatileIdAt(int x, int y) +{ + u16 block; + int i; + int j; + struct MapData const *mapData; + u16 *border; + u16 block2; + + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + block = gUnknown_03005DC0.map[x + gUnknown_03005DC0.width * y]; + } + else + { + mapData = gMapHeader.mapData; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = mapData->border[i] | 0xc00; + } + if (block == 0x3ff) + { + border = gMapHeader.mapData->border; + j = (x + 1) & 1; + j += ((y + 1) & 1) * 2; + block2 = gMapHeader.mapData->border[j]; + block2 |= 0xc00; + return block2 & block; + } + return block & 0x3ff; +} + +u32 MapGridGetMetatileBehaviorAt(int x, int y) +{ + u16 metatile; + metatile = MapGridGetMetatileIdAt(x, y); + return GetBehaviorByMetatileId(metatile) & 0xff; +} + +u8 MapGridGetMetatileLayerTypeAt(int x, int y) +{ + u16 metatile; + metatile = MapGridGetMetatileIdAt(x, y); + return (GetBehaviorByMetatileId(metatile) & 0xf000) >> 12; +} + +void MapGridSetMetatileIdAt(int x, int y, u16 metatile) +{ + int i; + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + i = x + y * gUnknown_03005DC0.width; + gUnknown_03005DC0.map[i] = (gUnknown_03005DC0.map[i] & 0xf000) | (metatile & 0xfff); + } +} + +void MapGridSetMetatileEntryAt(int x, int y, u16 metatile) +{ + int i; + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + i = x + gUnknown_03005DC0.width * y; + gUnknown_03005DC0.map[i] = metatile; + } +} + +u16 GetBehaviorByMetatileId(u16 metatile) +{ + u16 *attributes; + if (metatile <= 0x1ff) + { + attributes = gMapHeader.mapData->primaryTileset->metatileAttributes; + return attributes[metatile]; + } + else if (metatile <= 0x3ff) + { + attributes = gMapHeader.mapData->secondaryTileset->metatileAttributes; + return attributes[metatile - 0x200]; + } + else + { + return 0xff; + } +} + +void save_serialize_map(void) +{ + int i, j; + int x, y; + u16 *mapView; + int width; + mapView = gSaveBlock1Ptr->mapView; + width = gUnknown_03005DC0.width; + x = gSaveBlock1Ptr->pos.x; + y = gSaveBlock1Ptr->pos.y; + for (i = y; i < y + 14; i++) + { + for (j = x; j < x + 15; j++) + { + *mapView++ = gUnknown_02032318[width * i + j]; + } + } +} + +int sub_8088438(void) +{ + u16 i; + u32 r2; + r2 = 0; + for (i = 0; i < 0x200; i++) + { + r2 |= gSaveBlock1Ptr->mapView[i]; + } + if (r2 == 0) + { + return 1; + } + return 0; +} + +void sav2_mapdata_clear(void) +{ + CpuFill16(0, gSaveBlock1Ptr->mapView, sizeof(gSaveBlock1Ptr->mapView)); +} + +void mapdata_from_sav2(void) +{ + u8 a0; + int i, j; + int x, y; + u16 *mapView; + int width; + mapView = gSaveBlock1Ptr->mapView; + if (!sub_8088438()) + { + width = gUnknown_03005DC0.width; + x = gSaveBlock1Ptr->pos.x; + y = gSaveBlock1Ptr->pos.y; + for (i = y; i < y + 14; i++) + { + if (i == y && i != 0) + a0 = 0; + else if (i == y + 13 && i != gMapHeader.mapData->height - 1) + a0 = 1; + else + a0 = -1; + + for (j = x; j < x + 15; j++) + { + if (!sub_8088BF0(&gUnknown_02032318[j + width * i], width, a0)) + gUnknown_02032318[j + width * i] = *mapView; + mapView++; + } + } + for (j = x; j < x + 15; j++) + { + if (y != 0) + sub_80D423C(j, y - 1); + if (i < gMapHeader.mapData->height - 1) + sub_80D42B8(j, y + 13); + } + sav2_mapdata_clear(); + } +} + +void sub_80885C4(u8 a1) +{ + int width; + u16 *mapView; + int x0, y0; + int x2, y2; + u16 *src, *dest; + int srci, desti; + int r9, r8; + int x, y; + int i, j; + mapView = gSaveBlock1Ptr->mapView; + width = gUnknown_03005DC0.width; + r9 = 0; + r8 = 0; + x0 = gSaveBlock1Ptr->pos.x; + y0 = gSaveBlock1Ptr->pos.y; + x2 = 15; + y2 = 14; + switch (a1) + { + case CONNECTION_NORTH: + y0 += 1; + y2 = 13; + break; + case CONNECTION_SOUTH: + r8 = 1; + y2 = 13; + break; + case CONNECTION_WEST: + x0 += 1; + x2 = 14; + break; + case CONNECTION_EAST: + r9 = 1; + x2 = 14; + break; + } + for (y = 0; y < y2; y++) + { + i = 0; + j = 0; + for (x = 0; x < x2; x++) + { + desti = width * (y + y0); + srci = (y + r8) * 15 + r9; + src = &mapView[srci + i]; + dest = &gUnknown_02032318[x0 + desti + j]; + *dest = *src; + i++; + j++; + } + } + sav2_mapdata_clear(); +} + +int GetMapBorderIdAt(int x, int y) +{ + struct MapData const *mapData; + u16 block, block2; + int i, j; + if (x >= 0 && x < gUnknown_03005DC0.width + && y >= 0 && y < gUnknown_03005DC0.height) + { + i = gUnknown_03005DC0.width; + i *= y; + block = gUnknown_03005DC0.map[x + i]; + if (block == 0x3ff) + { + goto fail; + } + } + else + { + mapData = gMapHeader.mapData; + j = (x + 1) & 1; + j += ((y + 1) & 1) * 2; + block2 = 0xc00 | mapData->border[j]; + if (block2 == 0x3ff) + { + goto fail; + } + } + goto success; +fail: + return -1; +success: + + if (x >= (gUnknown_03005DC0.width - 8)) + { + if (!gUnknown_02037340.east) + { + return -1; + } + return CONNECTION_EAST; + } + else if (x < 7) + { + if (!gUnknown_02037340.west) + { + return -1; + } + return CONNECTION_WEST; + } + else if (y >= (gUnknown_03005DC0.height - 7)) + { + if (!gUnknown_02037340.south) + { + return -1; + } + return CONNECTION_SOUTH; + } + else if (y < 7) + { + if (!gUnknown_02037340.north) + { + return -1; + } + return CONNECTION_NORTH; + } + else + { + return 0; + } +} + +int GetPostCameraMoveMapBorderId(int x, int y) +{ + return GetMapBorderIdAt(gSaveBlock1Ptr->pos.x + 7 + x, gSaveBlock1Ptr->pos.y + 7 + y); +} + +int CanCameraMoveInDirection(int direction) +{ + int x, y; + x = gSaveBlock1Ptr->pos.x + 7 + gUnknown_08339D64[direction].x; + y = gSaveBlock1Ptr->pos.y + 7 + gUnknown_08339D64[direction].y; + if (GetMapBorderIdAt(x, y) == -1) + { + return 0; + } + return 1; +} + +void sub_80887F8(struct MapConnection *connection, int direction, int x, int y) +{ + struct MapHeader const *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (direction) + { + case CONNECTION_EAST: + gSaveBlock1Ptr->pos.x = -x; + gSaveBlock1Ptr->pos.y -= connection->offset; + break; + case CONNECTION_WEST: + gSaveBlock1Ptr->pos.x = mapHeader->mapData->width; + gSaveBlock1Ptr->pos.y -= connection->offset; + break; + case CONNECTION_SOUTH: + gSaveBlock1Ptr->pos.x -= connection->offset; + gSaveBlock1Ptr->pos.y = -y; + break; + case CONNECTION_NORTH: + gSaveBlock1Ptr->pos.x -= connection->offset; + gSaveBlock1Ptr->pos.y = mapHeader->mapData->height; + break; + } +} + +bool8 CameraMove(int x, int y) +{ + unsigned int direction; + struct MapConnection *connection; + int old_x, old_y; + gCamera.active = FALSE; + direction = GetPostCameraMoveMapBorderId(x, y); + if (direction + 1 <= 1) + { + gSaveBlock1Ptr->pos.x += x; + gSaveBlock1Ptr->pos.y += y; + } + else + { + save_serialize_map(); + sub_81BE72C(); + old_x = gSaveBlock1Ptr->pos.x; + old_y = gSaveBlock1Ptr->pos.y; + connection = sub_8088950(direction, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y); + sub_80887F8(connection, direction, x, y); + mliX_load_map(connection->mapGroup, connection->mapNum); + gCamera.active = TRUE; + gCamera.x = old_x - gSaveBlock1Ptr->pos.x; + gCamera.y = old_y - gSaveBlock1Ptr->pos.y; + gSaveBlock1Ptr->pos.x += x; + gSaveBlock1Ptr->pos.y += y; + sub_80885C4(direction); + } + return gCamera.active; +} + +struct MapConnection *sub_8088950(u8 direction, int x, int y) +{ + int count; + struct MapConnection *connection; + int i; + count = gMapHeader.connections->count; + connection = gMapHeader.connections->connections; + for (i = 0; i < count; i++, connection++) + { + if (connection->direction == direction && sub_80889A8(direction, x, y, connection) == TRUE) + return connection; + } + return NULL; +} + +bool8 sub_80889A8(u8 direction, int x, int y, struct MapConnection *connection) +{ + struct MapHeader const *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (direction) + { + case CONNECTION_SOUTH: + case CONNECTION_NORTH: + return sub_8088A0C(x, gMapHeader.mapData->width, mapHeader->mapData->width, connection->offset); + case CONNECTION_WEST: + case CONNECTION_EAST: + return sub_8088A0C(y, gMapHeader.mapData->height, mapHeader->mapData->height, connection->offset); + } + return FALSE; +} + +bool8 sub_8088A0C(int x, int src_width, int dest_width, int offset) +{ + int offset2; + offset2 = offset; + + if (offset2 < 0) + offset2 = 0; + + if (dest_width + offset < src_width) + src_width = dest_width + offset; + + if (offset2 <= x && x <= src_width) + return TRUE; + + return FALSE; +} + +int sub_8088A38(int x, int width) +{ + if (x >= 0 && x < width) + return TRUE; + + return FALSE; +} + +int sub_8088A4C(struct MapConnection *connection, int x, int y) +{ + struct MapHeader const *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (connection->direction) + { + case CONNECTION_SOUTH: + case CONNECTION_NORTH: + return sub_8088A38(x - connection->offset, mapHeader->mapData->width); + case CONNECTION_WEST: + case CONNECTION_EAST: + return sub_8088A38(y - connection->offset, mapHeader->mapData->height); + } + return FALSE; +} + +struct MapConnection *sub_8088A8C(s16 x, s16 y) +{ + int count; + struct MapConnection *connection; + int i; + u8 direction; + if (!gMapHeader.connections) + { + return NULL; + } + else + { + count = gMapHeader.connections->count; + connection = gMapHeader.connections->connections; + for (i = 0; i < count; i++, connection++) + { + direction = connection->direction; + if ((direction == CONNECTION_DIVE || direction == CONNECTION_EMERGE) + || (direction == CONNECTION_NORTH && y > 6) + || (direction == CONNECTION_SOUTH && y < gMapHeader.mapData->height + 7) + || (direction == CONNECTION_WEST && x > 6) + || (direction == CONNECTION_EAST && x < gMapHeader.mapData->width + 7)) + { + continue; + } + if (sub_8088A4C(connection, x - 7, y - 7) == TRUE) + { + return connection; + } + } + } + return NULL; +} + +void sub_8088B3C(u16 x, u16 y) +{ + gSaveBlock1Ptr->pos.x = x - 7; + gSaveBlock1Ptr->pos.y = y - 7; +} + +void sav1_camera_get_focus_coords(u16 *x, u16 *y) +{ + *x = gSaveBlock1Ptr->pos.x + 7; + *y = gSaveBlock1Ptr->pos.y + 7; +} + +void SetCameraCoords(u16 x, u16 y) +{ + gSaveBlock1Ptr->pos.x = x; + gSaveBlock1Ptr->pos.y = y; +} + +void GetCameraCoords(u16 *x, u16 *y) +{ + *x = gSaveBlock1Ptr->pos.x; + *y = gSaveBlock1Ptr->pos.y; +} + +void sub_8088B94(int x, int y, int a2) +{ + if (x >= 0 && x < gUnknown_03005DC0.width && y >= 0 && y < gUnknown_03005DC0.height) + { + if (a2 != 0) + gUnknown_03005DC0.map[x + gUnknown_03005DC0.width * y] |= 0xC00; + else + gUnknown_03005DC0.map[x + gUnknown_03005DC0.width * y] &= 0xF3FF; + } +} + +bool8 sub_8088BF0(u16* a0, u16 a1, u8 a2) +{ + if (a2 == 0xFF) + return FALSE; + + if (a2 == 0) + a0 -= a1; + else + a0 += a1; + + if (sub_80FADE4(*a0 & 0x3FF, a2) == 1) + return TRUE; + return FALSE; +} + +void copy_tileset_patterns_to_vram(struct Tileset const *tileset, u16 numTiles, u16 offset) +{ + if (tileset) + { + if (!tileset->isCompressed) + LoadBgTiles(2, tileset->tiles, numTiles * 32, offset); + else + decompress_and_copy_tile_data_to_vram(2, tileset->tiles, numTiles * 32, offset, 0); + } +} + +void copy_tileset_patterns_to_vram2(struct Tileset const *tileset, u16 numTiles, u16 offset) +{ + if (tileset) + { + if (!tileset->isCompressed) + LoadBgTiles(2, tileset->tiles, numTiles * 32, offset); + else + copy_decompressed_tile_data_to_vram_autofree(2, tileset->tiles, numTiles * 32, offset, 0); + } +} + +void nullsub_3(u16 a0, u16 a1) +{ + +} + +void nullsub_90(void) +{ + +} + +void apply_map_tileset_palette(struct Tileset const *tileset, u16 destOffset, u16 size) +{ + u16 black = RGB_BLACK; + + if (tileset) + { + if (tileset->isSecondary == FALSE) + { + LoadPalette(&black, destOffset, 2); + LoadPalette(((u16*)tileset->palettes) + 1, destOffset + 1, size - 2); + nullsub_3(destOffset + 1, (size - 2) >> 1); + } + else if (tileset->isSecondary == TRUE) + { + LoadPalette(((u16*)tileset->palettes) + 0x60, destOffset, size); + nullsub_3(destOffset, size >> 1); + } + else + { + LoadCompressedPalette((u16*)tileset->palettes, destOffset, size); + nullsub_3(destOffset, size >> 1); + } + } +} + +void copy_map_tileset1_to_vram(struct MapData const *mapData) +{ + copy_tileset_patterns_to_vram(mapData->primaryTileset, 0x200, 0); +} + +void copy_map_tileset2_to_vram(struct MapData const *mapData) +{ + copy_tileset_patterns_to_vram(mapData->secondaryTileset, 0x200, 0x200); +} + +void copy_map_tileset2_to_vram_2(struct MapData const *mapData) +{ + copy_tileset_patterns_to_vram2(mapData->secondaryTileset, 0x200, 0x200); +} + +void apply_map_tileset1_palette(struct MapData const *mapData) +{ + apply_map_tileset_palette(mapData->primaryTileset, 0, 0xC0); +} + +void apply_map_tileset2_palette(struct MapData const *mapData) +{ + apply_map_tileset_palette(mapData->secondaryTileset, 0x60, 0xE0); +} + +void copy_map_tileset1_tileset2_to_vram(struct MapData const *mapData) +{ + if (mapData) + { + copy_tileset_patterns_to_vram2(mapData->primaryTileset, 0x200, 0); + copy_tileset_patterns_to_vram2(mapData->secondaryTileset, 0x200, 0x200); + } +} + +void apply_map_tileset1_tileset2_palette(struct MapData const *mapData) +{ + if (mapData) + { + apply_map_tileset1_palette(mapData); + apply_map_tileset2_palette(mapData); + } +} diff --git a/src/fldeff_flash.c b/src/fldeff_flash.c new file mode 100644 index 000000000..4f3a091ce --- /dev/null +++ b/src/fldeff_flash.c @@ -0,0 +1,367 @@ +#include "global.h" +#include "constants/songs.h" +#include "braille_puzzles.h" +#include "event_data.h" +#include "event_scripts.h" +#include "field_effect.h" +#include "gpu_regs.h" +#include "gba/io_reg.h" +#include "main.h" +#include "palette.h" +#include "party_menu.h" +#include "overworld.h" +#include "rom6.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +// structures +struct FlashStruct +{ + u8 unk0; + u8 unk1; + bool8 unk2; + bool8 unk3; + void (*func)(void); +}; + +// static functions +static void hm2_flash(void); +static void sub_81371B4(void); +static bool8 sub_8137304(void); +static void sub_81373F0(void); +static void sub_8137404(u8 taskId); +static void sub_8137420(u8 taskId); +static void sub_81374C4(u8 taskId); +static void sub_813750C(u8 taskId); +static void sub_8137574(u8 taskId); +static void sub_81375A8(void); +static void sub_81375BC(u8 taskId); +static void sub_81375D8(u8 taskId); +static void sub_8137678(u8 taskId); +static void sub_81376DC(u8 taskId); + +// rodata +static const struct FlashStruct gUnknown_085B27C8[] = +{ + {1, 4, 1, 0, sub_81375A8}, + {2, 4, 1, 0, sub_81375A8}, + {3, 4, 1, 0, sub_81375A8}, + {5, 4, 1, 0, sub_81375A8}, + {6, 4, 1, 0, sub_81375A8}, + {7, 4, 1, 0, sub_81375A8}, + {8, 4, 1, 0, sub_81375A8}, + {9, 4, 1, 0, sub_81375A8}, + {4, 1, 0, 1, sub_81373F0}, + {4, 2, 0, 1, sub_81373F0}, + {4, 3, 0, 1, sub_81373F0}, + {4, 5, 0, 1, sub_81373F0}, + {4, 6, 0, 1, sub_81373F0}, + {4, 7, 0, 1, sub_81373F0}, + {4, 8, 0, 1, sub_81373F0}, + {4, 9, 0, 1, sub_81373F0}, + {0, 0, 0, 0, NULL}, +}; + +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 gUnknown_085B2890[] = INCBIN_U16("graphics/misc/85B2890.gbapal"); +static const u16 gUnknown_085B28A0[] = INCBIN_U16("graphics/misc/85B28A0.gbapal"); +static const u16 gCaveTransitionTilemap[] = INCBIN_U16("graphics/misc/cave_transition_map.bin.lz"); +static const u8 gCaveTransitionTiles[] = INCBIN_U8("graphics/misc/cave_transition.4bpp.lz"); + +// text +bool8 SetUpFieldMove_Flash(void) +{ + if (ShouldDoBrailleFlyEffect()) + { + gSpecialVar_Result = GetCursorSelectionMonId(); + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = sub_8179918; + return TRUE; + } + else if (gMapHeader.cave == TRUE && !FlagGet(FLAG_SYS_USE_FLASH)) + { + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = hm2_flash; + return TRUE; + } + + return FALSE; +} + +static void hm2_flash(void) +{ + u8 taskId = oei_task_add(); + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + gTasks[taskId].data[8] = (uintptr_t)sub_81371B4 >> 16; + gTasks[taskId].data[9] = (uintptr_t)sub_81371B4; +} + +static void sub_81371B4(void) +{ + PlaySE(SE_W115); + FlagSet(FLAG_SYS_USE_FLASH); + ScriptContext1_SetupScript(EventScript_2926F8); +} + +static void sub_81371D4(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void sub_81371EC(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void c2_change_map(void) +{ + u16 ime; + + SetVBlankCallback(NULL); + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); + DmaFill32(3, 0, (void *)OAM, OAM_SIZE); + DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); + ResetPaletteFade(); + ResetTasks(); + ResetSpriteData(); + ime = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = ime; + SetVBlankCallback(sub_81371EC); + SetMainCallback2(sub_81371D4); + if (!sub_8137304()) + SetMainCallback2(gMain.savedCallback); +} + +static bool8 sub_8137304(void) +{ + u8 i; + u8 v0 = get_map_light_from_warp0(); + u8 v1 = Overworld_GetMapTypeOfSaveblockLocation(); + + for (i = 0; gUnknown_085B27C8[i].unk0; i++) + { + if (gUnknown_085B27C8[i].unk0 == v0 && gUnknown_085B27C8[i].unk1 == v1) + { + gUnknown_085B27C8[i].func(); + return TRUE; + } + } + + return FALSE; +} + +bool8 sub_8137360(u8 a1, u8 a2) +{ + u8 i; + u8 v0 = a1; + u8 v1 = a2; + + for (i = 0; gUnknown_085B27C8[i].unk0; i++) + { + if (gUnknown_085B27C8[i].unk0 == v0 && gUnknown_085B27C8[i].unk1 == v1) + { + return gUnknown_085B27C8[i].unk2; + } + } + + return FALSE; +} + +bool8 fade_type_for_given_maplight_pair(u8 a1, u8 a2) +{ + u8 i; + u8 v0 = a1; + u8 v1 = a2; + + for (i = 0; gUnknown_085B27C8[i].unk0; i++) + { + if (gUnknown_085B27C8[i].unk0 == v0 && gUnknown_085B27C8[i].unk1 == v1) + { + return gUnknown_085B27C8[i].unk3; + } + } + + return FALSE; +} + +static void sub_81373F0(void) +{ + CreateTask(sub_8137404, 0); +} + +static void sub_8137404(u8 taskId) +{ + gTasks[taskId].func = sub_8137420; +} + +static void sub_8137420(u8 taskId) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + LZ77UnCompVram(gCaveTransitionTiles, (void *)0x600C000); + LZ77UnCompVram(gCaveTransitionTilemap, (void *)0x600F800); + LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(gUnknown_085B28A0, 0xE0, 0x10); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 + | BLDCNT_EFFECT_BLEND + | BLDCNT_TGT2_BG1 + | BLDCNT_TGT2_BG2 + | BLDCNT_TGT2_BG3 + | BLDCNT_TGT2_OBJ + | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(3) + | BGCNT_SCREENBASE(31) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_OBJ_ON); + gTasks[taskId].func = sub_81374C4; + gTasks[taskId].data[0] = 16; + gTasks[taskId].data[1] = 0; +} + +static void sub_81374C4(u8 taskId) +{ + u16 count = gTasks[taskId].data[1]; + u16 blend = count + 0x1000; + + SetGpuReg(REG_OFFSET_BLDALPHA, blend); + if (count <= 0x10) + { + gTasks[taskId].data[1]++; + } + else + { + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_813750C; + } +} + +static void sub_813750C(u8 taskId) +{ + u16 count; + + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 16)); + count = gTasks[taskId].data[2]; + + if (count < 8) + { + gTasks[taskId].data[2]++; + LoadPalette(&gUnknown_085B28A0[count], 0xE0, 16 - 2 * count); + } + else + { + LoadPalette(gCaveTransitionPalette_White, 0, 0x20); + gTasks[taskId].func = sub_8137574; + gTasks[taskId].data[2] = 8; + } +} + +static void sub_8137574(u8 taskId) +{ + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2]--; + else + SetMainCallback2(gMain.savedCallback); +} + +static void sub_81375A8(void) +{ + CreateTask(sub_81375BC, 0); +} + +static void sub_81375BC(u8 taskId) +{ + gTasks[taskId].func = sub_81375D8; +} + +static void sub_81375D8(u8 taskId) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + LZ77UnCompVram(gCaveTransitionTiles, (void *)0x600C000); + LZ77UnCompVram(gCaveTransitionTilemap, (void *)0x600F800); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(3) + | BGCNT_SCREENBASE(31) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_OBJ_ON); + LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + gTasks[taskId].func = sub_8137678; + gTasks[taskId].data[0] = 16; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; +} + +static void sub_8137678(u8 taskId) +{ + u16 count = gTasks[taskId].data[2]; + + if (count < 16) + { + gTasks[taskId].data[2]++; + gTasks[taskId].data[2]++; + LoadPalette(&gUnknown_085B2890[15 - count], 0xE0, 2 * (count + 1)); + } + else + { + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 16)); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 + | BLDCNT_EFFECT_BLEND + | BLDCNT_TGT2_BG1 + | BLDCNT_TGT2_BG2 + | BLDCNT_TGT2_BG3 + | BLDCNT_TGT2_OBJ + | BLDCNT_TGT2_BD); + gTasks[taskId].func = sub_81376DC; + } +} + +static void sub_81376DC(u8 taskId) +{ + u16 count = 16 - gTasks[taskId].data[1]; + u16 blend = count + 0x1000; + + SetGpuReg(REG_OFFSET_BLDALPHA, blend); + if (count) + { + gTasks[taskId].data[1]++; + } + else + { + LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + SetMainCallback2(gMain.savedCallback); + } +} diff --git a/src/fldeff_groundshake.c b/src/fldeff_groundshake.c new file mode 100644 index 000000000..bee4d2c4b --- /dev/null +++ b/src/fldeff_groundshake.c @@ -0,0 +1,299 @@ +#include "global.h" +#include "global.fieldmap.h" +#include "constants/flags.h" +#include "constants/songs.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_map_obj.h" +#include "malloc.h" +#include "random.h" +#include "roulette_util.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +// structures +struct Struct203CF18 { + u8 taskId; + struct InnerStruct203CF18 unk4; +}; //size = 0xC8 + +// extern data +extern const struct SpriteSheet gUnknown_08617D94[]; +extern const s16 gUnknown_08617D64[][3]; + +// static functions +static void sub_81BE808(u8 taskId); +static void sub_81BE900(u8 taskId); +static void sub_81BE968(void); +static void sub_81BE9C0(u8 taskId); +static void sub_81BEA00(u8 taskId); +static void sub_81BEA20(void); +static void sub_81BEAD8(struct Sprite* sprite); + +// rodata +static const u8 gUnknown_08617E18[] = {0x3b, 0x43, 0x61, 0x00, 0x0f, 0x05, 0xff, 0x9b}; + +static const union AnimCmd gSpriteAnim_8617E20[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gSpriteAnimTable_8617E28[] = +{ + gSpriteAnim_8617E20, +}; + +static const struct OamData gUnknown_08617E2C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate gUnknown_08617E34 = { + 0x0FA0, 0xFFFF, &gUnknown_08617E2C, gSpriteAnimTable_8617E28, NULL, gDummySpriteAffineAnimTable, sub_81BEAD8 +}; + +static const union AnimCmd gSpriteAnim_8617E4C[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gSpriteAnim_8617E54[] = +{ + gSpriteAnim_8617E4C, +}; + +static const struct OamData gSpriteAnim_8617E58 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate gUnknown_08617E60 = { + 0x0FA0, 0xFFFF, &gSpriteAnim_8617E58, gSpriteAnim_8617E54, NULL, gDummySpriteAffineAnimTable, sub_81BEAD8 +}; + +// ewram +EWRAM_DATA struct Struct203CF18 *gUnknown_0203CF18 = NULL; + +// text +bool8 sub_81BE66C(void) +{ + if (!(gSaveBlock1Ptr->location.mapGroup == 0x0 && gSaveBlock1Ptr->location.mapNum == 0x1A)) + return 0; + return FlagGet(FLAG_0x14E); +} + +void sub_81BE698(u8 taskId) +{ + sub_8151E50(&(gUnknown_0203CF18->unk4)); +} + +void sub_81BE6AC(void) +{ + gUnknown_0203CF18 = NULL; +} + +void sub_81BE6B8(void) +{ + if(gUnknown_0203CF18 != NULL) + { + gUnknown_0203CF18 = NULL; + return; + } + if(!(gSaveBlock1Ptr->location.mapGroup == 0x0 && gSaveBlock1Ptr->location.mapNum == 0x1A) || !FlagGet(FLAG_0x14E)) + return; + + gUnknown_0203CF18 = (struct Struct203CF18 *)AllocZeroed(sizeof(struct Struct203CF18)); + sub_8151B3C(&(gUnknown_0203CF18->unk4)); + sub_8151B68(&(gUnknown_0203CF18->unk4), gUnknown_08617E18); + sub_8151CA8(&(gUnknown_0203CF18->unk4), 1, 1); + gUnknown_0203CF18->taskId = CreateTask(sub_81BE698, 0xFF); +} + +void sub_81BE72C(void) +{ + if(!(gSaveBlock1Ptr->location.mapGroup == 0x0 && gSaveBlock1Ptr->location.mapNum == 0x1A) || !FlagGet(FLAG_0x14E) || gUnknown_0203CF18 == NULL) + return; + if(FuncIsActiveTask(sub_81BE698)) + DestroyTask(gUnknown_0203CF18->taskId); + sub_8151D28(&(gUnknown_0203CF18->unk4), 1, 1); + sub_8151C50(&(gUnknown_0203CF18->unk4), 1, 1); + Free(gUnknown_0203CF18); + gUnknown_0203CF18 = NULL; +} + +void sub_81BE79C(void) +{ + u16 rand; + bool8 chance; + + if(VarGet(VAR_0x40CB) != 0) + { + FlagClear(FLAG_0x14E); + return; + } + rand = Random(); + chance = rand & 1; + if(FlagGet(FLAG_0x09D) == TRUE) + chance = TRUE; + if(chance) + { + FlagSet(FLAG_0x14E); + sub_81BE6B8(); + return; + } + FlagClear(FLAG_0x14E); +} + +void sub_81BE7F4(void) +{ + CreateTask(sub_81BE808, 0x8); +} + +static void sub_81BE808(u8 taskId) +{ + u8 mapObjectIdBuffer; + struct MapObject *fieldMapObject; + struct MapObject *playerAvatarMapObject; + + TryGetFieldObjectIdByLocalIdAndMap(0x2D, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &mapObjectIdBuffer); + fieldMapObject = &(gMapObjects[mapObjectIdBuffer]); + gSprites[fieldMapObject->spriteId].pos2.y += 4; + playerAvatarMapObject = &(gMapObjects[gPlayerAvatar.mapObjectId]); + + if((gSprites[fieldMapObject->spriteId].pos1.y + gSprites[fieldMapObject->spriteId].pos2.y) >= + (gSprites[playerAvatarMapObject->spriteId].pos1.y + gSprites[playerAvatarMapObject->spriteId].pos2.y)) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} + +static void sp136_strengh_sound(u8 a, u8 b, u8 c, u8 d) +{ + u8 taskId; + + taskId = CreateTask(sub_81BE900, 0x9); + gTasks[taskId].data[0] = b; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = c; + gTasks[taskId].data[3] = d; + gTasks[taskId].data[4] = a; + SetCameraPanningCallback(NULL); + PlaySE(SE_W070); +} + +static void sub_81BE900(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + data[1]++; + if((data[1] % data[3]) == 0) + { + data[1] = 0; + data[2]--; + data[0] = -data[0]; + data[4] = -data[4]; + SetCameraPanning(data[0], data[4]); + if(!data[2]) + { + sub_81BE968(); + DestroyTask(taskId); + InstallCameraPanAheadCallback(); + } + } +} + +static void sub_81BE968(void) +{ + u8 taskId; + + taskId = FindTaskIdByFunc(sub_81BE9C0); + if(taskId != 0xFF) + gTasks[taskId].data[0]++; +} + +void sub_81BE994(void) +{ + LoadSpriteSheets(gUnknown_08617D94); + sub_81BEA20(); + CreateTask(sub_81BE9C0, 0x8); + sp136_strengh_sound(2, 1, 16, 3); +} + +static void sub_81BE9C0(u8 taskId) +{ + u16 *data; + + data = gTasks[taskId].data; + data[1]++; + if(data[1] == 1000 || data[0] == 17) + gTasks[taskId].func = sub_81BEA00; +} + +static void sub_81BEA00(u8 taskId) +{ + FreeSpriteTilesByTag(4000); + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +static void sub_81BEA20(void) +{ + u8 i; + u8 spriteId; + + for(i = 0; i < 8; i++) + { + spriteId = CreateSprite(&gUnknown_08617E60, gUnknown_08617D64[i][0] + 120, gUnknown_08617D64[i][1], 8); + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].oam.paletteNum = 0; + gSprites[spriteId].data[0] = i; + } + for(i = 0; i < 8; i++) + { + spriteId = CreateSprite(&gUnknown_08617E34, gUnknown_08617D64[i][0] + 115, gUnknown_08617D64[i][1] - 3, 8); + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].oam.paletteNum = 0; + gSprites[spriteId].data[0] = i; + } +} + +static void sub_81BEAD8(struct Sprite* sprite) +{ + sprite->data[1] += 2; + sprite->pos2.y = (sprite->data[1] / 2); + if(((sprite->pos1.y) + (sprite->pos2.y)) > gUnknown_08617D64[sprite->data[0]][2]) + { + DestroySprite(sprite); + sub_81BE968(); + } +} diff --git a/src/fldeff_softboiled.c b/src/fldeff_softboiled.c new file mode 100644 index 000000000..d0a40a9a9 --- /dev/null +++ b/src/fldeff_softboiled.c @@ -0,0 +1,109 @@ +#include "global.h" +#include "menu.h" +#include "party_menu.h" +#include "pokemon.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" + +static void sub_816166C(u8 taskId); +static void sub_81616C0(u8 taskId); +static void sub_8161724(u8 taskId); +static void sub_81617B8(u8 taskId); + +bool8 SetUpFieldMove_SoftBoiled(void) +{ + u16 maxHp; + u16 hp; + u16 minHp; + + maxHp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_MAX_HP); + hp = GetMonData(&gPlayerParty[GetCursorSelectionMonId()], MON_DATA_HP); + + minHp = (maxHp / 5); + if (hp > minHp) + return TRUE; + return FALSE; +} + +void sub_8161560(u8 taskId) +{ + gUnknown_0203CEC8.unkB = 0xA; + gUnknown_0203CEC8.unkA = gUnknown_0203CEC8.unk9; + sub_81B0FCC(GetCursorSelectionMonId(), 0x1); + display_pokemon_menu_message(0x5); + gTasks[taskId].func = sub_81B1370; +} + +void sub_81615A8(u8 taskId) +{ + u16 hp; + + u8 unk9 = gUnknown_0203CEC8.unk9; + u8 pokemonIndex = gUnknown_0203CEC8.unkA; + if(pokemonIndex > 6) + { + gUnknown_0203CEC8.unkB = 0; + display_pokemon_menu_message(0x0); + gTasks[taskId].func = sub_81B1370; + return; + } + + hp = GetMonData(&gPlayerParty[pokemonIndex], MON_DATA_HP); + if(hp == 0 || unk9 == pokemonIndex || GetMonData(&gPlayerParty[pokemonIndex], MON_DATA_MAX_HP) == hp) + { + sub_81617B8(taskId); + return; + } + + PlaySE(SE_KAIFUKU); + sub_81B1F18(taskId, unk9, -1, GetMonData(&gPlayerParty[unk9], MON_DATA_MAX_HP)/5, sub_816166C); +} + +static void sub_816166C(u8 taskId) +{ + PlaySE(SE_KAIFUKU); + sub_81B1F18(taskId, gUnknown_0203CEC8.unkA, 1, GetMonData(&gPlayerParty[gUnknown_0203CEC8.unk9], MON_DATA_MAX_HP)/5, sub_81616C0); +} + +static void sub_81616C0(u8 taskId) +{ + GetMonNickname(&gPlayerParty[gUnknown_0203CEC8.unkA], gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_PkmnHPRestoredByVar2); + sub_81B1B5C(gStringVar4, 0); + schedule_bg_copy_tilemap_to_vram(2); + gTasks[taskId].func = sub_8161724; +} + +static void sub_8161724(u8 taskId) +{ + if(sub_81B1BD4() == 1) + return; + gUnknown_0203CEC8.unkB = 0x0; + sub_81B0FCC(gUnknown_0203CEC8.unk9, 0); + gUnknown_0203CEC8.unk9 = gUnknown_0203CEC8.unkA; + sub_81B0FCC(gUnknown_0203CEC8.unkA, 1); + sub_8198070(0x6, FALSE); + ClearWindowTilemap(0x6); + display_pokemon_menu_message(0); + gTasks[taskId].func = sub_81B1370; +} + +static void sub_8161784(u8 taskId) +{ + if(sub_81B1BD4() == 1) + return; + display_pokemon_menu_message(0x5); + gTasks[taskId].func = sub_81B1370; +} + +static void sub_81617B8(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_81B1B5C(&gText_CantBeUsedOnPkmn, 0); + schedule_bg_copy_tilemap_to_vram(2); + gTasks[taskId].func = sub_8161784; +} diff --git a/src/fldeff_strength.c b/src/fldeff_strength.c new file mode 100644 index 000000000..162479c73 --- /dev/null +++ b/src/fldeff_strength.c @@ -0,0 +1,46 @@ +#include "global.h" +#include "event_data.h" +#include "event_scripts.h" +#include "field_effect.h" +#include "party_menu.h" +#include "rom6.h" +#include "script.h" +#include "task.h" + +// static functions +static void FldEff_UseStrength(void); +static void sub_8145E74(void); + +// text +bool8 SetUpFieldMove_Strength(void) +{ + if (npc_before_player_of_type(87) == TRUE) + { + gSpecialVar_Result = GetCursorSelectionMonId(); + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = FldEff_UseStrength; + return TRUE; + } + return FALSE; +} + +static void FldEff_UseStrength(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + ScriptContext1_SetupScript(FieryPath_EventScript_2908FD); +} + +bool8 sub_8145E2C(void) +{ + u8 taskId = oei_task_add(); + gTasks[taskId].data[8] = (u32)sub_8145E74 >> 16; + gTasks[taskId].data[9] = (u32)sub_8145E74; + GetMonNickname(&gPlayerParty[gFieldEffectArguments[0]], gStringVar1); + return FALSE; +} + +static void sub_8145E74(void) +{ + FieldEffectActiveListRemove(FLDEFF_USE_STRENGTH); + EnableBothScriptContexts(); +} diff --git a/src/fldeff_sweetscent.c b/src/fldeff_sweetscent.c new file mode 100644 index 000000000..100e440a5 --- /dev/null +++ b/src/fldeff_sweetscent.c @@ -0,0 +1,98 @@ +#include "global.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "event_data.h" +#include "event_scripts.h" +#include "field_effect.h" +#include "field_player_avatar.h" +#include "field_screen.h" +#include "palette.h" +#include "party_menu.h" +#include "rom6.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "wild_encounter.h" + +void hm2_sweet_scent(void); +void sub_8159F5C(void); +void sub_8159FEC(u8 taskId); +void sub_815A090(u8 taskId); +void sub_81BE6B8(void); +void sub_81BE72C(void); + +bool8 SetUpFieldMove_SweetScent(void) +{ + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = hm2_sweet_scent; + return TRUE; +} + +void hm2_sweet_scent(void) +{ + FieldEffectStart(FLDEFF_SWEET_SCENT); + gFieldEffectArguments[0] = GetCursorSelectionMonId(); +} + +bool8 FldEff_SweetScent() +{ + u8 taskId; + + sub_80AC3D0(); + taskId = oei_task_add(); + gTasks[taskId].data[8] = (u32)sub_8159F5C >> 16; + gTasks[taskId].data[9] = (u32)sub_8159F5C; + return FALSE; +} + +void sub_8159F5C(void) +{ + u8 taskId; + + PlaySE(SE_W230); + CpuFastSet(gPlttBufferUnfaded, gPaletteDecompressionBuffer, 0x100); + CpuFastSet(gPlttBufferFaded, gPlttBufferUnfaded, 0x100); + BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarObjectId()].oam.paletteNum + 16)), 4, 0, 8, RGB_RED); + taskId = CreateTask(sub_8159FEC, 0); + gTasks[taskId].data[0] = 0; + FieldEffectActiveListRemove(FLDEFF_SWEET_SCENT); +} + +void sub_8159FEC(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_81BE72C(); + BlendPalettes(0x00000040, 8, RGB_RED); + if (gTasks[taskId].data[0] == 64) + { + gTasks[taskId].data[0] = 0; + if (SweetScentWildEncounter() == TRUE) + { + DestroyTask(taskId); + } + else + { + gTasks[taskId].func = sub_815A090; + BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarObjectId()].oam.paletteNum + 16)), 4, 8, 0, RGB_RED); + sub_81BE6B8(); + } + } + else + { + gTasks[taskId].data[0]++; + } + } +} + +void sub_815A090(u8 taskId) +{ + if (!gPaletteFade.active) + { + CpuFastSet(gPaletteDecompressionBuffer, gPlttBufferUnfaded, 0x100); + sub_80AC3E4(); + ScriptContext1_SetupScript(EventScript_290CAE); + DestroyTask(taskId); + } +} diff --git a/src/fldeff_teleport.c b/src/fldeff_teleport.c index 5b3492db0..1b88b42d7 100644 --- a/src/fldeff_teleport.c +++ b/src/fldeff_teleport.c @@ -7,17 +7,14 @@ #include "rom6.h" #include "task.h" -extern bool8 (*gUnknown_03005DB0)(void); -extern void (*gUnknown_0203CEEC)(void); - bool8 SetUpFieldMove_Teleport(void) { if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) { gUnknown_03005DB0 = FieldCallback_Teleport; - gUnknown_0203CEEC = hm_teleport_run_dp02scr; + gUnknown_0203CEEC = hm_teleport_run_dp02scr; return TRUE; - } + } return FALSE; } @@ -40,7 +37,7 @@ bool8 FldEff_UseTeleport(void) void sub_817C94C(void) { FieldEffectActiveListRemove(FLDEFF_USE_TELEPORT); - sub_80B7FC8(); + CreateTeleportFieldEffectTask(); } diff --git a/src/fossil_specials.c b/src/fossil_specials.c new file mode 100644 index 000000000..060915fa6 --- /dev/null +++ b/src/fossil_specials.c @@ -0,0 +1,770 @@ +#include "global.h" +#include "constants/flags.h" +#include "constants/songs.h" +#include "bg.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_map_obj.h" +#include "fieldmap.h" +#include "global.fieldmap.h" +#include "gpu_regs.h" +#include "malloc.h" +#include "menu.h" +#include "random.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "window.h" + +#define MIRAGE_TOWER_GFX_LENGTH (sizeof(gUnknown_08617274) + sizeof(gMirageTower_Gfx)) +#define MIRAGE_TOWER_PALETTE_LENGTH 0x800 +#define ROOT_FOSSIL_GFX_LENGTH sizeof(gRootFossil_Gfx) +#define ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH 0x100 + +//struct +struct Struct8617DA4 { + u8 x; + u8 y; + u16 tileId; +}; + +struct Struct203CF10 { + u8 *buffer; + u8 curr_buffer_index; +}; + +struct DynamicSpriteFrameImage{ + u8 *data; + u16 size; +}; + +struct Struct203CF0C { + u8 *frameImageTiles; + struct DynamicSpriteFrameImage *frameImage; + u8 spriteId; + u16 *unkC; + u16 unk10; +}; + +// static functions +static void sub_81BED50(u8 taskId); +static void sub_81BEBF4(u8 taskId); +static void sub_81BF028(u8 taskId); +static void sub_81BF248(struct Sprite *); +/*static*/ void sub_81BF2B8(u8* a, u16 b, u8 c, u8 d, u8 e); + +// .rodata +static const u8 gUnknown_08617274[] = {00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}; +static const u8 gMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp"); +static const u16 gUnknown_08617B94[] = INCBIN_U16("graphics/misc/mirage_tower.bin"); +static const u16 gRootFossil_Pal[] = INCBIN_U16("graphics/misc/fossil.gbapal"); +static const u8 gRootFossil_Gfx[] = INCBIN_U8("graphics/misc/fossil.4bpp"); +static const u8 gMirageTowerCrumbles_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower_crumbles.4bpp"); +static const u16 gMirageTowerCrumbles_Palette[] = INCBIN_U16("graphics/misc/mirage_tower_crumbles.gbapal"); + +const s16 gUnknown_08617D64[][3] = + { + { 0, 10, 65}, + { 17, 3, 50}, + {-12, 0, 75}, + { 10, 15, 90}, + { 7, 8, 65}, + {-18, 5, 75}, + { 22, -10, 55}, + {-24, -4, 65}, + }; + +const struct SpriteSheet gUnknown_08617D94[] = +{ + {gMirageTowerCrumbles_Gfx, 0x0080, 0x0fa0}, + {NULL} +}; + +static const struct Struct8617DA4 gUnknown_08617DA4[] = + { + {0x12, 0x35, 0x251}, + {0x13, 0x35, 0x251}, + {0x14, 0x35, 0x251}, + {0x12, 0x36, 0x251}, + {0x13, 0x36, 0x251}, + {0x14, 0x36, 0x251}, + {0x12, 0x37, 0x251}, + {0x13, 0x37, 0x251}, + {0x14, 0x37, 0x251}, + {0x12, 0x38, 0x251}, + {0x13, 0x38, 0x251}, + {0x14, 0x38, 0x251}, + {0x12, 0x39, 0x259}, + {0x13, 0x39, 0x259}, + {0x14, 0x39, 0x259}, + {0x12, 0x3A, 0x121}, + {0x13, 0x3A, 0x121}, + {0x14, 0x3A, 0x121}, + }; + +static const union AnimCmd gSpriteAnim_8617DEC[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const struct OamData gOamData_8617DF4 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 3, + .affineParam = 0, +}; + +static const union AnimCmd *const gSpriteAnimTable_8617DFC[] = +{ + gSpriteAnim_8617DEC, +}; + +static const struct SpriteTemplate gUnknown_08617E00 = { + 0xFFFF, 0xFFFF, &gOamData_8617DF4, gSpriteAnimTable_8617DFC, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy +}; + +// ewram +EWRAM_DATA u8* gUnknown_0203CF04 = NULL; +EWRAM_DATA u8* gUnknown_0203CF08 = NULL; +EWRAM_DATA struct Struct203CF0C *gUnknown_0203CF0C = NULL; +EWRAM_DATA struct Struct203CF10 *gUnknown_0203CF10 = NULL; +EWRAM_DATA u16 *gUnknown_0203CF14 = NULL; + +// iwram +IWRAM_DATA u16 gUnknown_030012A8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + +// text +void sub_81BEB24(void) +{ + u8 i; + for(i = 0; i < (sizeof(gUnknown_08617DA4)/sizeof(gUnknown_08617DA4[0])); i++) + MapGridSetMetatileIdAt(gUnknown_08617DA4[i].x + 7, gUnknown_08617DA4[i].y + 7, gUnknown_08617DA4[i].tileId); + DrawWholeMapView(); +} + +void sub_81BEB54(void) +{ + CreateTask(sub_81BED50, 0x9); +} + +void sub_81BEB68(void) +{ + CreateTask(sub_81BEBF4, 0x9); +} + +void sub_81BEB7C(void) +{ + CreateTask(sub_81BF028, 0x9); +} + +void sub_81BEB90(void) +{ + SetGpuReg(REG_OFFSET_BG0HOFS, gUnknown_0203CF14[0]); + SetGpuReg(REG_OFFSET_BG0VOFS, gUnknown_0203CF14[1]); +} + +void sub_81BEBB4(u8 taskId) +{ + if(!(gTasks[taskId].data[0])) + { + gUnknown_0203CF14[0] = -gUnknown_0203CF14[0]; + gTasks[taskId].data[0] = 2; + sub_81BEB90(); + } + else + gTasks[taskId].data[0]--; +} + +static void sub_81BEBF4(u8 taskId) +{ + u8 zero; + + switch(gTasks[taskId].data[0]) + { + case 0: + FreeAllWindowBuffers(); + SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 2); + gTasks[taskId].data[0]++; + break; + case 1: + gUnknown_0203CF04 = (u8 *)AllocZeroed(MIRAGE_TOWER_GFX_LENGTH); + gUnknown_0203CF08 = (u8 *)AllocZeroed(MIRAGE_TOWER_PALETTE_LENGTH); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + gTasks[taskId].data[0]++; + break; + case 2: + CpuSet(gUnknown_08617274, gUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH / 2); + LoadBgTiles(0, gUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH, 0); + gTasks[taskId].data[0]++; + break; + case 3: + SetBgTilemapBuffer(0, gUnknown_0203CF08); + CopyToBgTilemapBufferRect_ChangePalette(0, &gUnknown_08617B94, 12, 29, 6, 12, 17); + CopyBgTilemapBufferToVram(0); + gTasks[taskId].data[0]++; + break; + case 4: + ShowBg(0); + gTasks[taskId].data[0]++; + break; + case 5: + sub_81BEB24(); + gTasks[taskId].data[0]++; + break; + case 6: + gUnknown_0203CF14 = (u16 *)Alloc(4); + zero = 0; + gUnknown_0203CF14[0] = 2; + gUnknown_0203CF14[1] = zero; + CreateTask(sub_81BEBB4, 0xA); + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } +} + +#ifdef NONMATCHING +#define OUTER_BUFFER_LENGTH 0x60 +#define INNER_BUFFER_LENGTH 0x30 +static void sub_81BED50(u8 taskId) +{ + u8 anotherTaskId, j; + + + switch(gTasks[taskId].data[0]) + { + case 1: + gUnknown_0203CF10 = (struct Struct203CF10 *)AllocZeroed(OUTER_BUFFER_LENGTH * sizeof(struct Struct203CF10)); + break; + case 3: + { + u16 i; + u16 left; + u32 index, next; + + index = (u16)gTasks[taskId].data[3]; + if(gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1)) + { + if(gTasks[taskId].data[1] > 1) + { + index = (u8)index; + gUnknown_0203CF10[index].buffer = (u8 *)Alloc(INNER_BUFFER_LENGTH); + for(i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++) + gUnknown_0203CF10[index].buffer[i] = i; + for(i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++) + { + u16 rand1, rand2, temp; + + rand1 = Random() % 0x30; + rand2 = Random() % 0x30; + temp = gUnknown_0203CF10[index].buffer[rand2]; + gUnknown_0203CF10[index].buffer[rand2] = gUnknown_0203CF10[index].buffer[rand1]; + gUnknown_0203CF10[index].buffer[rand1] = temp; + } + if(gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1)) + gTasks[taskId].data[3]++; + gTasks[taskId].data[1] = 0; + } + gTasks[taskId].data[1]++; + } + index = (u8)gTasks[taskId].data[3]; + for(left = (u8)gTasks[taskId].data[2]; left < (u16)index; left = next) + { + j = 0; + next = left + 1; + while(!j) + { + sub_81BF2B8(gUnknown_0203CF04, ((((OUTER_BUFFER_LENGTH - 1) - left) * INNER_BUFFER_LENGTH) + gUnknown_0203CF10[left].buffer[(gUnknown_0203CF10[left].curr_buffer_index)++]), 0, INNER_BUFFER_LENGTH, 1); + j++; + } + if(gUnknown_0203CF10[left].curr_buffer_index > (INNER_BUFFER_LENGTH - 1)) + { + FREE_AND_SET_NULL(gUnknown_0203CF10[left].buffer); + gTasks[taskId].data[2]++; + if((left % 2) == 1) + gUnknown_0203CF14[1]--; + } + } + LoadBgTiles(0, gUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH, 0); + if(gUnknown_0203CF10[OUTER_BUFFER_LENGTH - 1].curr_buffer_index > (INNER_BUFFER_LENGTH - 1)) + break; + return; + } + case 4: + UnsetBgTilemapBuffer(0); + anotherTaskId = FindTaskIdByFunc(sub_81BEBB4); + if(anotherTaskId != 0xFF) + DestroyTask(anotherTaskId); + gUnknown_0203CF14[1] = gUnknown_0203CF14[0] = 0; + sub_81BEB90(); + break; + case 5: + FREE_AND_SET_NULL(gUnknown_0203CF14); + FREE_AND_SET_NULL(gUnknown_0203CF10); + FREE_AND_SET_NULL(gUnknown_0203CF04); + FREE_AND_SET_NULL(gUnknown_0203CF08); + break; + case 6: + SetGpuRegBits(REG_OFFSET_BG2CNT, 0x2); + SetGpuRegBits(REG_OFFSET_BG0CNT, 0x0); + SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 0); + sub_81971D0(); + break; + case 7: + ShowBg(0); + break; + case 8: + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } + gTasks[taskId].data[0]++; +} + +#else +NAKED +static void sub_81BED50(u8 taskId) +{ + asm("\n\ + .syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ + ldr r1, =gTasks\n\ + lsls r0, 2\n\ + add r0, r10\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x8]\n\ + subs r0, 0x1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + adds r6, r1, 0\n\ + cmp r0, 0x7\n\ + bls _081BED7C\n\ + b _081BF002\n\ + _081BED7C:\n\ + lsls r0, 2\n\ + ldr r1, =_081BED90\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .pool\n\ + .align 2, 0\n\ + _081BED90:\n\ + .4byte _081BEDB0\n\ + .4byte _081BF002\n\ + .4byte _081BEDC4\n\ + .4byte _081BEF64\n\ + .4byte _081BEF94\n\ + .4byte _081BEFD0\n\ + .4byte _081BEFF0\n\ + .4byte _081BEFF8\n\ + _081BEDB0:\n\ + ldr r4, =gUnknown_0203CF10\n\ + movs r0, 0xC0\n\ + lsls r0, 2\n\ + bl AllocZeroed\n\ + str r0, [r4]\n\ + b _081BF002\n\ + .pool\n\ + _081BEDC4:\n\ + mov r1, r10\n\ + lsls r0, r1, 2\n\ + adds r1, r0, r1\n\ + lsls r1, 3\n\ + adds r2, r1, r6\n\ + ldrh r3, [r2, 0xE]\n\ + movs r4, 0xE\n\ + ldrsh r1, [r2, r4]\n\ + str r0, [sp, 0x8]\n\ + cmp r1, 0x5F\n\ + bgt _081BEE8A\n\ + movs r1, 0xA\n\ + ldrsh r0, [r2, r1]\n\ + cmp r0, 0x1\n\ + ble _081BEE7C\n\ + lsls r0, r3, 24\n\ + lsrs r4, r0, 24\n\ + movs r0, 0x30\n\ + bl Alloc\n\ + ldr r3, =gUnknown_0203CF10\n\ + ldr r1, [r3]\n\ + lsls r2, r4, 3\n\ + adds r1, r2, r1\n\ + str r0, [r1]\n\ + movs r5, 0\n\ + adds r4, r2, 0\n\ + _081BEDFA:\n\ + ldr r0, [r3]\n\ + adds r0, r4, r0\n\ + ldr r0, [r0]\n\ + adds r0, r5\n\ + strb r5, [r0]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0x2F\n\ + bls _081BEDFA\n\ + movs r5, 0\n\ + ldr r7, =gUnknown_0203CF10\n\ + adds r6, r2, 0\n\ + _081BEE14:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x30\n\ + bl __umodsi3\n\ + adds r4, r0, 0\n\ + lsls r4, 16\n\ + lsrs r4, 16\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0x30\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + ldr r1, [r7]\n\ + adds r1, r6, r1\n\ + ldr r1, [r1]\n\ + adds r0, r1, r0\n\ + ldrb r2, [r0]\n\ + adds r1, r4 \n\ + ldrb r1, [r1]\n\ + strb r1, [r0]\n\ + ldr r0, [r7]\n\ + adds r0, r6, r0\n\ + ldr r0, [r0]\n\ + adds r0, r4\n\ + strb r2, [r0]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0x2F\n\ + bls _081BEE14\n\ + ldr r0, =gTasks\n\ + ldr r1, [sp, 0x8]\n\ + add r1, r10\n\ + lsls r1, 3\n\ + adds r2, r1, r0\n\ + ldrh r3, [r2, 0xE]\n\ + movs r4, 0xE\n\ + ldrsh r1, [r2, r4]\n\ + adds r6, r0, 0\n\ + cmp r1, 0x5F\n\ + bgt _081BEE78\n\ + adds r0, r3, 0x1\n\ + strh r0, [r2, 0xE]\n\ + _081BEE78:\n\ + movs r0, 0\n\ + strh r0, [r2, 0xA]\n\ + _081BEE7C:\n\ + ldr r1, [sp, 0x8]\n\ + add r1, r10\n\ + lsls r1, 3\n\ + adds r1, r6\n\ + ldrh r0, [r1, 0xA]\n\ + adds r0, 0x1\n\ + strh r0, [r1, 0xA]\n\ + _081BEE8A:\n\ + ldr r0, [sp, 0x8]\n\ + add r0, r10\n\ + lsls r0, 3\n\ + adds r0, r6\n\ + ldrb r4, [r0, 0xE]\n\ + ldrb r5, [r0, 0xC]\n\ + lsls r0, r4, 16\n\ + cmp r5, r4\n\ + bcs _081BEF32\n\ + str r0, [sp, 0xC]\n\ + _081BEE9E:\n\ + movs r6, 0\n\ + adds r0, r5, 0x1\n\ + str r0, [sp, 0x4]\n\ + lsls r4, r5, 3\n\ + movs r2, 0x5F\n\ + subs r1, r2, r5\n\ + lsls r0, r1, 1\n\ + adds r0, r1\n\ + lsls r0, 4\n\ + mov r9, r0\n\ + _081BEEB2:\n\ + ldr r0, =gUnknown_0203CF04\n\ + ldr r0, [r0]\n\ + ldr r7, =gUnknown_0203CF10\n\ + ldr r3, [r7]\n\ + adds r3, r4, r3\n\ + ldrb r2, [r3, 0x4]\n\ + adds r1, r2, 0x1\n\ + strb r1, [r3, 0x4]\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + ldr r1, [r3]\n\ + adds r1, r2\n\ + ldrb r1, [r1]\n\ + add r1, r9\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + movs r2, 0x1\n\ + mov r8, r2\n\ + str r2, [sp]\n\ + movs r2, 0\n\ + movs r3, 0x30\n\ + bl sub_81BF2B8\n\ + adds r0, r6, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + cmp r6, 0\n\ + beq _081BEEB2\n\ + ldr r0, [r7]\n\ + adds r1, r4, r0\n\ + ldrb r0, [r1, 0x4]\n\ + cmp r0, 0x2F\n\ + bls _081BEF24\n\ + ldr r0, [r1]\n\ + bl Free\n\ + ldr r0, [r7]\n\ + adds r0, r4, r0\n\ + movs r1, 0\n\ + str r1, [r0]\n\ + ldr r1, [sp, 0x8]\n\ + add r1, r10\n\ + lsls r1, 3\n\ + ldr r4, =gTasks\n\ + adds r1, r4\n\ + ldrh r0, [r1, 0xC]\n\ + adds r0, 0x1\n\ + strh r0, [r1, 0xC]\n\ + mov r0, r8\n\ + ands r5, r0\n\ + cmp r5, 0x1\n\ + bne _081BEF24\n\ + ldr r0, =gUnknown_0203CF14\n\ + ldr r1, [r0]\n\ + ldrh r0, [r1, 0x2]\n\ + subs r0, 0x1\n\ + strh r0, [r1, 0x2]\n\ + _081BEF24:\n\ + ldr r1, [sp, 0x4]\n\ + lsls r0, r1, 16\n\ + lsrs r5, r0, 16\n\ + ldr r2, [sp, 0xC]\n\ + lsrs r0, r2, 16\n\ + cmp r5, r0\n\ + bcc _081BEE9E\n\ + _081BEF32:\n\ + ldr r0, =gUnknown_0203CF04\n\ + ldr r1, [r0]\n\ + movs r2, 0x92\n\ + lsls r2, 4\n\ + movs r0, 0\n\ + movs r3, 0\n\ + bl LoadBgTiles\n\ + ldr r0, =gUnknown_0203CF10\n\ + ldr r0, [r0]\n\ + movs r4, 0xBE\n\ + lsls r4, 2\n\ + adds r0, r4\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r0, 0x2F\n\ + bhi _081BF002\n\ + b _081BF014\n\ + .pool\n\ + _081BEF64:\n\ + movs r0, 0\n\ + bl UnsetBgTilemapBuffer\n\ + ldr r0, =sub_81BEBB4\n\ + bl FindTaskIdByFunc\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0xFF\n\ + beq _081BEF7C\n\ + bl DestroyTask\n\ + _081BEF7C:\n\ + ldr r0, =gUnknown_0203CF14\n\ + ldr r1, [r0]\n\ + movs r0, 0\n\ + strh r0, [r1]\n\ + strh r0, [r1, 0x2]\n\ + bl sub_81BEB90\n\ + b _081BF002\n\ + .pool\n\ + _081BEF94:\n\ + ldr r4, =gUnknown_0203CF14\n\ + ldr r0, [r4]\n\ + bl Free\n\ + movs r5, 0\n\ + str r5, [r4]\n\ + ldr r4, =gUnknown_0203CF10\n\ + ldr r0, [r4]\n\ + bl Free\n\ + str r5, [r4]\n\ + ldr r4, =gUnknown_0203CF04\n\ + ldr r0, [r4]\n\ + bl Free\n\ + str r5, [r4]\n\ + ldr r4, =gUnknown_0203CF08\n\ + ldr r0, [r4]\n\ + bl Free\n\ + str r5, [r4]\n\ + b _081BF002\n\ + .pool\n\ + _081BEFD0:\n\ + movs r0, 0xC\n\ + movs r1, 0x2\n\ + bl SetGpuRegBits\n\ + movs r0, 0x8\n\ + movs r1, 0\n\ + bl SetGpuRegBits\n\ + movs r0, 0\n\ + movs r1, 0x7\n\ + movs r2, 0\n\ + bl SetBgAttribute\n\ + bl sub_81971D0\n\ + b _081BF002\n\ + _081BEFF0:\n\ + movs r0, 0\n\ + bl ShowBg\n\ + b _081BF002\n\ + _081BEFF8:\n\ + mov r0, r10\n\ + bl DestroyTask\n\ + bl EnableBothScriptContexts\n\ + _081BF002:\n\ + ldr r0, =gTasks\n\ + mov r2, r10\n\ + lsls r1, r2, 2\n\ + add r1, r10\n\ + lsls r1, 3\n\ + adds r1, r0\n\ + ldrh r0, [r1, 0x8]\n\ + adds r0, 0x1\n\ + strh r0, [r1, 0x8]\n\ + _081BF014:\n\ + add sp, 0x10\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void sub_81BF028(u8 taskId) +{ + u16 i; + + switch(gTasks[taskId].data[0]) + { + case 1: + gUnknown_0203CF0C = (struct Struct203CF0C *)AllocZeroed(sizeof(struct Struct203CF0C)); + gUnknown_0203CF0C->frameImageTiles = (u8 *)AllocZeroed(ROOT_FOSSIL_GFX_LENGTH); + gUnknown_0203CF0C->frameImage = (struct DynamicSpriteFrameImage *) AllocZeroed(sizeof(struct DynamicSpriteFrameImage)); + gUnknown_0203CF0C->unkC = (u16 *)AllocZeroed(ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH * sizeof(u16)); + gUnknown_0203CF0C->unk10 = 0; + break; + case 2: + { + u8 *buffer; + buffer = gUnknown_0203CF0C->frameImageTiles; + for(i = 0; i < ROOT_FOSSIL_GFX_LENGTH; i++, buffer++) + *buffer = gRootFossil_Gfx[i]; + } + break; + case 3: + gUnknown_0203CF0C->frameImage->data = gUnknown_0203CF0C->frameImageTiles; + gUnknown_0203CF0C->frameImage->size = ROOT_FOSSIL_GFX_LENGTH; + break; + case 4: + { + u8 spriteId, zero; + struct SpriteTemplate fossilTemplate; + + fossilTemplate = gUnknown_08617E00; + fossilTemplate.images = (struct SpriteFrameImage *)(gUnknown_0203CF0C->frameImage); + spriteId = CreateSprite(&fossilTemplate, 128, -16, 1); + gUnknown_0203CF0C->spriteId = spriteId; + zero = 0; + gSprites[gUnknown_0203CF0C->spriteId].centerToCornerVecX = zero; + gSprites[gUnknown_0203CF0C->spriteId].data[0] = gSprites[gUnknown_0203CF0C->spriteId].pos1.x; + gSprites[gUnknown_0203CF0C->spriteId].data[1] = 1; + } + case 5: + for(i = 0; i < ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH; i++) + gUnknown_0203CF0C->unkC[i] = i; + break; + case 6: + { + u16 rand1, rand2, temp, j; + j = (ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH * sizeof(u16)) - 1; + for(i = 0; i <= j; i++) + { + rand1 = Random() % 0x100; + rand2 = Random() % 0x100; + j = (ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH * sizeof(u16)) - 1; + temp = gUnknown_0203CF0C->unkC[rand2]; + gUnknown_0203CF0C->unkC[rand2] = gUnknown_0203CF0C->unkC[rand1]; + gUnknown_0203CF0C->unkC[rand1] = temp; + } + gSprites[gUnknown_0203CF0C->spriteId].callback = sub_81BF248; + break; + } + case 7: + if(gSprites[gUnknown_0203CF0C->spriteId].callback != SpriteCallbackDummy) + return; + DestroySprite(&gSprites[gUnknown_0203CF0C->spriteId]); + FREE_AND_SET_NULL(gUnknown_0203CF0C->unkC);; + FREE_AND_SET_NULL(gUnknown_0203CF0C->frameImage); + FREE_AND_SET_NULL(gUnknown_0203CF0C->frameImageTiles); + FREE_AND_SET_NULL(gUnknown_0203CF0C); + break; + case 8: + EnableBothScriptContexts(); + } + ++gTasks[taskId].data[0]; +} + +static void sub_81BF248(struct Sprite *sprite) +{ + if (gUnknown_0203CF0C->unk10 >= (ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH)) + { + sprite->callback = SpriteCallbackDummy; + } + else if (sprite->pos1.y >= 0x60) + { + u8 i; + for (i = 0; i < 2; i++) + { + sub_81BF2B8(gUnknown_0203CF0C->frameImageTiles, gUnknown_0203CF0C->unkC[gUnknown_0203CF0C->unk10++], 0, 16, 0); + } + StartSpriteAnim(sprite, 0); + } + else + { + sprite->pos1.y++; + } +} diff --git a/src/gym_leader_rematch.c b/src/gym_leader_rematch.c new file mode 100644 index 000000000..355ae5534 --- /dev/null +++ b/src/gym_leader_rematch.c @@ -0,0 +1,106 @@ +#include "global.h" +#include "constants/flags.h" +#include "random.h" +#include "event_data.h" +#include "battle_setup.h" +#include "gym_leader_rematch.h" + +static void UpdateGymLeaderRematchFromArray(const u16 *data, size_t size, u32 maxRematch); +static s32 GetRematchIndex(u32 trainerIdx); + +static const u16 GymLeaderRematches_AfterNewMauville[] = { + REMATCH_ROXANNE, + REMATCH_BRAWLY, + REMATCH_WATTSON, + REMATCH_FLANNERY, + REMATCH_NORMAN, + REMATCH_WINONA, + REMATCH_TATE_AND_LIZA, + REMATCH_JUAN +}; + +static const u16 GymLeaderRematches_BeforeNewMauville[] = { + REMATCH_ROXANNE, + REMATCH_BRAWLY, + // Wattson isn't available at this time + REMATCH_FLANNERY, + REMATCH_NORMAN, + REMATCH_WINONA, + REMATCH_TATE_AND_LIZA, + REMATCH_JUAN +}; + +void UpdateGymLeaderRematch(void) +{ + if (FlagGet(FLAG_SYS_GAME_CLEAR) && (Random() % 100) <= 30) + { + if (FlagGet(FLAG_WATTSON_REMATCH_AVAILABLE)) + UpdateGymLeaderRematchFromArray(GymLeaderRematches_AfterNewMauville, ARRAY_COUNT(GymLeaderRematches_AfterNewMauville), 5); + else + UpdateGymLeaderRematchFromArray(GymLeaderRematches_BeforeNewMauville, ARRAY_COUNT(GymLeaderRematches_BeforeNewMauville), 1); + } +} + +static void UpdateGymLeaderRematchFromArray(const u16 *data, size_t size, u32 maxRematch) +{ + s32 whichLeader = 0; + s32 lowestRematchIndex = 5; + u32 i; + s32 rematchIndex; + for (i = 0; i < size; i++) + { + if (!gSaveBlock1Ptr->trainerRematches[data[i]]) + { + rematchIndex = GetRematchIndex(data[i]); + if (lowestRematchIndex > rematchIndex) + lowestRematchIndex = rematchIndex; + whichLeader++; + } + } + if (whichLeader != 0 && lowestRematchIndex <= maxRematch) + { + whichLeader = 0; + for (i = 0; i < size; i++) + { + if (!gSaveBlock1Ptr->trainerRematches[data[i]]) + { + rematchIndex = GetRematchIndex(data[i]); + if (rematchIndex == lowestRematchIndex) + whichLeader++; + } + } + if (whichLeader != 0) + { + whichLeader = Random() % whichLeader; + for (i = 0; i < size; i++) + { + if (!gSaveBlock1Ptr->trainerRematches[data[i]]) + { + rematchIndex = GetRematchIndex(data[i]); + if (rematchIndex == lowestRematchIndex) + { + if (whichLeader == 0) + { + gSaveBlock1Ptr->trainerRematches[data[i]] = lowestRematchIndex; + break; + } + whichLeader--; + } + } + } + } + } +} + +static s32 GetRematchIndex(u32 trainerIdx) +{ + s32 i; + for (i = 0; i < 5; i++) + { + if (!HasTrainerBeenFought(gRematchTable[trainerIdx].trainerIds[i])) + { + return i; + } + } + return 5; +} diff --git a/src/hall_of_fame.c b/src/hall_of_fame.c index 6dda6ad9c..83df30d05 100644 --- a/src/hall_of_fame.c +++ b/src/hall_of_fame.c @@ -369,7 +369,7 @@ static const struct HallofFameMon sDummyFameMon = 0x3EA03EA, 0, 0, 0, {0} }; -static const u8 sUnused2[6] = {2, 1, 3, 6, 4, 5}; +static const u8 sUnused2[] = {2, 1, 3, 6, 4, 5, 0, 0}; // code static void VBlankCB_HallOfFame(void) @@ -516,7 +516,7 @@ static void Task_Hof_InitTeamSaveData(u8 taskId) } else { - if (sub_81534D0(3) != TRUE) + if (Save_LoadGameData(3) != TRUE) memset(gDecompressionBuffer, 0, 0x2000); } @@ -885,7 +885,7 @@ void CB2_DoHallOfFamePC(void) static void Task_HofPC_CopySaveData(u8 taskId) { sub_81980F0(0, 0x1E, 0, 0xC, 0x226); - if (sub_81534D0(3) != 1) + if (Save_LoadGameData(3) != 1) { gTasks[taskId].func = Task_HofPC_PrintDataIsCorrupted; } diff --git a/src/hof_pc.c b/src/hof_pc.c index e772f04e8..44b929337 100644 --- a/src/hof_pc.c +++ b/src/hof_pc.c @@ -7,7 +7,6 @@ #include "script_menu.h" #include "task.h" -extern void (*gFieldCallback)(void); extern void (*gUnknown_0300485C)(void); extern void Overworld_PlaySpecialMapMusic(void); @@ -25,7 +24,7 @@ void AccessHallOfFamePC(void) void ReturnFromHallOfFamePC(void) { - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); gFieldCallback = ReshowPCMenuAfterHallOfFamePC; } diff --git a/src/international_string_util.c b/src/international_string_util.c index 89b4a7a69..9de338c59 100644 --- a/src/international_string_util.c +++ b/src/international_string_util.c @@ -42,7 +42,7 @@ s32 GetMaxWidthInMenuTable(const struct MenuAction *str, s32 arg1) return convert_pixel_width_to_tile_width(var); } -s32 sub_81DB3D8(const struct MenuAction *str, u8* arg1, s32 arg2) +s32 sub_81DB3D8(const struct MenuAction *str, const u8* arg1, s32 arg2) { s32 i, var; diff --git a/src/intro.c b/src/intro.c new file mode 100644 index 000000000..f21ad348d --- /dev/null +++ b/src/intro.c @@ -0,0 +1,3020 @@ +#include "global.h" +#include "main.h" +#include "palette.h" +#include "scanline_effect.h" +#include "task.h" +#include "title_screen.h" +#include "libgcnmultiboot.h" +#include "malloc.h" +#include "gpu_regs.h" +#include "link.h" +#include "multiboot_pokemon_colosseum.h" +#include "load_save.h" +#include "save.h" +#include "new_game.h" +#include "m4a.h" +#include "random.h" +#include "decompress.h" +#include "constants/songs.h" +#include "intro_credits_graphics.h" +#include "trig.h" +#include "intro.h" +#include "graphics.h" +#include "sound.h" +#include "constants/species.h" +#include "blend_palette.h" +#include "title_screen.h" +#include "constants/rgb.h" + +extern const struct CompressedSpriteSheet gBattleAnimPicTable[]; +extern const struct CompressedSpritePalette gBattleAnimPaletteTable[]; +extern const struct SpriteTemplate gUnknown_08596C10[]; + +//ewram +EWRAM_DATA u16 gUnknown_0203BCC8 = 0; +EWRAM_DATA u16 gUnknown_0203BCCA = 0; +EWRAM_DATA u16 gUnknown_0203BCCC = 0; + +//iwram +u32 gIntroFrameCounter; +struct GcmbStruct gMultibootProgramStruct; + +//.rodata +static const u16 gIntro1DropsPal[] = INCBIN_U16("graphics/intro/intro1_drops.gbapal"); +static const u16 gIntro1GFLogoPal[] = INCBIN_U16("graphics/intro/intro1_gflogo.gbapal"); +static const u8 gIntroTiles[] = INCBIN_U8("graphics/intro/intro.4bpp.lz"); +static const u16 gIntro1BGPals[16][16] = INCBIN_U16("graphics/intro/intro1_bgpal.gbapal"); +static const u8 gIntro1BG0_Tilemap[] = INCBIN_U8("graphics/intro/intro1_bg0_map.bin.lz"); +static const u8 gIntro1BG1_Tilemap[] = INCBIN_U8("graphics/intro/intro1_bg1_map.bin.lz"); +static const u8 gIntro1BG2_Tilemap[] = INCBIN_U8("graphics/intro/intro1_bg2_map.bin.lz"); +static const u8 gIntro1BG3_Tilemap[] = INCBIN_U8("graphics/intro/intro1_bg3_map.bin.lz"); +static const u8 gIntro1BGLeavesGfx[] = INCBIN_U8("graphics/intro/introgfx.4bpp.lz"); +static const u16 gIntro3PokeballPal[] = INCBIN_U16("graphics/intro/intro3_pokeball.gbapal"); +static const u8 gIntro3Pokeball_Tilemap[] = INCBIN_U8("graphics/intro/intro3_pokeball_map.bin.lz"); +static const u8 gIntro3Pokeball_Gfx[] = INCBIN_U8("graphics/intro/intro3_pokeball.8bpp.lz"); +static const u16 gIntro3Streaks_Pal_Unused[] = INCBIN_U16("graphics/intro/intro3_streaks.gbapal"); +static const u8 gIntro3Streaks_Gfx_Unused[] = INCBIN_U8("graphics/intro/intro3_streaks.4bpp.lz"); +static const u8 gIntro3Streaks_Tilemap_Unused[] = INCBIN_U8("graphics/intro/intro3_streaks_map.bin.lz"); +static const u16 gIntro3Misc1Palette[] = INCBIN_U16("graphics/intro/intro3_misc1.gbapal"); +static const u16 gIntro3Misc2Palette_Unused[] = INCBIN_U16("graphics/intro/intro3_misc2.gbapal"); +static const u8 gIntro3MiscTiles[] = INCBIN_U8("graphics/intro/intro3_misc.4bpp.lz"); +static const u16 gIntro1FlygonPalette[] = INCBIN_U16("graphics/intro/intro1_flygon.gbapal"); +static const u8 gIntro1EonTiles_Unused[] = INCBIN_U8("graphics/intro/intro1_eon.4bpp.lz"); +static const u8 sUnknownBytes[] = { + 0x02, 0x03, 0x04, 0x05, 0x01, 0x01, 0x01, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x02, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x02, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x02, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x00 +}; +static const struct CompressedSpriteSheet gUnknown_085E4A74[] = +{ + {gIntro1SparkleGfx, 0x400, 1505}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E4A84[] = +{ + {gIntro3LightningPal, 1505}, + {NULL}, +}; +static const struct OamData gUnknown_085E4A94 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4A9C[] = +{ + ANIMCMD_FRAME(0, 2), + ANIMCMD_FRAME(4, 2), + ANIMCMD_FRAME(8, 2), + ANIMCMD_FRAME(12, 2), + ANIMCMD_FRAME(16, 2), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd *const gUnknown_085E4AB4[] = +{ + gUnknown_085E4A9C, +}; +static void sub_816D338(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4AB8 = +{ + .tileTag = 1505, + .paletteTag = 1505, + .oam = &gUnknown_085E4A94, + .anims = gUnknown_085E4AB4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816D338, +}; +static const u8 gUnknown_085E4AD0[][2] = +{ + {0x7C, 0x28}, + {0x66, 0x1E}, + {0x4D, 0x1E}, + {0x36, 0x0F}, + {0x94, 0x09}, + {0x3F, 0x1C}, + {0x5D, 0x28}, + {0x94, 0x20}, + {0xAD, 0x29}, + {0x5E, 0x14}, + {0xD0, 0x26}, + {0x00, 0x00}, +}; +static const struct CompressedSpriteSheet gUnknown_085E4AE8[] = +{ + {gIntro2VolbeatGfx, 0x400, 1500}, + {gIntro2TorchicGfx, 0xC00, 1501}, + {gIntro2ManectricGfx, 0x2000, 1502}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E4B08[] = +{ + {gIntro2VolbeatPal, 1500}, + {gIntro2TorchicPal, 1501}, + {gIntro2ManectricPal, 1502}, + {NULL}, +}; +static const struct OamData gUnknown_085E4B28 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4B30[] = +{ + ANIMCMD_FRAME(0, 2), + ANIMCMD_FRAME(16, 2), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd *const gUnknown_085E4B3C[] = +{ + gUnknown_085E4B30, +}; +static void sub_816D81C(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4B40 = +{ + .tileTag = 1500, + .paletteTag = 1500, + .oam = &gUnknown_085E4B28, + .anims = gUnknown_085E4B3C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816D81C, +}; +static const struct OamData gUnknown_085E4B58 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4B60[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd gUnknown_085E4B74[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd gUnknown_085E4B88[] = +{ + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 6), + ANIMCMD_FRAME(80, 0), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4B98[] = +{ + gUnknown_085E4B60, + gUnknown_085E4B74, + gUnknown_085E4B88, +}; +static void sub_816D9C0(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4BA4 = +{ + .tileTag = 1501, + .paletteTag = 1501, + .oam = &gUnknown_085E4B58, + .anims = gUnknown_085E4B98, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816D9C0, +}; +static const struct OamData gUnknown_085E4BBC = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4BC4[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_FRAME(128, 4), + ANIMCMD_FRAME(192, 4), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd *const gUnknown_085E4BD8[] = +{ + gUnknown_085E4BC4, +}; +static void sub_816DAE8(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4BDC = +{ + .tileTag = 1502, + .paletteTag = 1502, + .oam = &gUnknown_085E4BBC, + .anims = gUnknown_085E4BD8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816DAE8, +}; +static const struct CompressedSpriteSheet gUnknown_085E4BF4[] = +{ + {gIntro3LightningGfx, 0xC00, 1503}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E4C04[] = +{ + {gIntro3LightningPal, 1503}, + {NULL}, +}; +static const struct OamData gUnknown_085E4C14 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4C1C[] = +{ + ANIMCMD_FRAME(0, 2), + ANIMCMD_FRAME(48, 2), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4C28[] = +{ + ANIMCMD_FRAME(16, 2), + ANIMCMD_FRAME(64, 2), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4C34[] = +{ + ANIMCMD_FRAME(32, 2), + ANIMCMD_FRAME(80, 2), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4C40[] = +{ + gUnknown_085E4C1C, + gUnknown_085E4C28, + gUnknown_085E4C34, +}; +static void sub_816EC6C(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4C4C = +{ + .tileTag = 1503, + .paletteTag = 1503, + .oam = &gUnknown_085E4C14, + .anims = gUnknown_085E4C40, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816EC6C, +}; +static const s16 gUnknown_085E4C64[][3] = +{ + {0x68, 0x00, 0x0C0}, + {0x8E, 0x03, 0x280}, + {0x53, 0x01, 0x180}, + {0x9B, 0x00, 0x080}, + {0x38, 0x02, 0x200}, + {0xAE, 0x01, 0x100}, +}; +static const struct CompressedSpriteSheet gUnknown_085E4C88[] = +{ + {gIntro2BubblesGfx, 0x600, 1504}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E4C98[] = +{ + {gIntro2BubblesPal, 1504}, + {NULL}, +}; +static const s16 gUnknown_085E4CA8[][3] = +{ + {0x42, 0x40, 0x1}, + {0x60, 0x60, 0x8}, + {0x80, 0x40, 0x1}, + {0x90, 0x30, 0x8}, + {0xA0, 0x48, 0x1}, + {0xB0, 0x60, 0x8}, + {0x60, 0x60, 0x4}, + {0x70, 0x68, 0x8}, + {0x80, 0x60, 0x4}, + {0x58, 0x20, 0x4}, + {0x68, 0x18, 0x8}, + {0x78, 0x20, 0x4}, +}; +static const struct OamData gUnknown_085E4CF0 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 2, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4CF8[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(8, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(24, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4D10[] = +{ + gUnknown_085E4CF8, +}; +static void sub_816E7B4(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4D14 = +{ + .tileTag = 1504, + .paletteTag = 1504, + .oam = &gUnknown_085E4CF0, + .anims = gUnknown_085E4D10, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816E7B4, +}; +static const struct OamData gUnknown_085E4D2C = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4D34[] = +{ + ANIMCMD_FRAME(16, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4D3C[] = +{ + ANIMCMD_FRAME(24, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4D44[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4D4C[] = +{ + ANIMCMD_FRAME(48, 8), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4D54[] = +{ + gUnknown_085E4D34, + gUnknown_085E4D3C, + gUnknown_085E4D44, + gUnknown_085E4D4C, +}; +static void sub_816F454(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4D64 = +{ + .tileTag = 2000, + .paletteTag = 2000, + .oam = &gUnknown_085E4D2C, + .anims = gUnknown_085E4D54, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816F454, +}; +static const union AnimCmd gUnknown_085E4D7C[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_FRAME(128, 4), + ANIMCMD_FRAME(192, 4), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd gUnknown_085E4D90[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(64, 8), + ANIMCMD_FRAME(128, 8), + ANIMCMD_FRAME(192, 8), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd gUnknown_085E4DA4[] = +{ + ANIMCMD_FRAME(256, 4), + ANIMCMD_FRAME(0x140, 4), + ANIMCMD_FRAME(0x180, 4), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4DB4[] = +{ + ANIMCMD_FRAME(0x180, 16), + ANIMCMD_FRAME(0x140, 16), + ANIMCMD_FRAME(256, 16), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4DC4[] = +{ + gUnknown_085E4D7C, + gUnknown_085E4D90, + gUnknown_085E4DA4, + gUnknown_085E4DB4, +}; +static const struct OamData gUnknown_085E4DD4 = +{ + .y = 160, + .affineMode = 3, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const struct OamData gUnknown_085E4DDC = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const struct OamData gUnknown_085E4DE4 = +{ + .y = 160, + .affineMode = 3, + .objMode = 1, + .mosaic = 0, + .bpp = 0, + .shape = 2, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4DEC[] = +{ + ANIMCMD_FRAME(80, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4DF4[] = +{ + ANIMCMD_FRAME(84, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4DFC[] = +{ + ANIMCMD_FRAME(88, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E04[] = +{ + ANIMCMD_FRAME(92, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E0C[] = +{ + ANIMCMD_FRAME(96, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E14[] = +{ + ANIMCMD_FRAME(100, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E1C[] = +{ + ANIMCMD_FRAME(104, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E24[] = +{ + ANIMCMD_FRAME(112, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E2C[] = +{ + ANIMCMD_FRAME(113, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E34[] = +{ + ANIMCMD_FRAME(114, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E3C[] = +{ + ANIMCMD_FRAME(115, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E44[] = +{ + ANIMCMD_FRAME(116, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E4C[] = +{ + ANIMCMD_FRAME(117, 8), + ANIMCMD_END, +}; +static const union AnimCmd gUnknown_085E4E54[] = +{ + ANIMCMD_FRAME(128, 8), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E4E5C[] = +{ + gUnknown_085E4DEC, + gUnknown_085E4DF4, + gUnknown_085E4DFC, + gUnknown_085E4E04, + gUnknown_085E4E0C, + gUnknown_085E4E14, + gUnknown_085E4E1C, +}; +static const union AnimCmd *const gUnknown_085E4E78[] = +{ + gUnknown_085E4E24, + gUnknown_085E4E2C, + gUnknown_085E4E34, + gUnknown_085E4E3C, + gUnknown_085E4E44, + gUnknown_085E4E4C, +}; +static const union AnimCmd *const gUnknown_085E4E90[] = +{ + gUnknown_085E4E54, +}; +static const s16 gUnknown_085E4E94[][2] = +{ + {0, -72}, + {1, -56}, + {2, -40}, + {3, -24}, + {4, 8}, + {5, 24}, + {3, 40}, + {1, 56}, + {6, 72}, + {0, -28}, + {1, -20}, + {2, -12}, + {3, -4}, + {2, 4}, + {4, 12}, + {5, 20}, + {3, 28}, +}; +static const union AffineAnimCmd gUnknown_085E4ED8[] = +{ + AFFINEANIMCMD_FRAME(128, 128, 0, 0), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd gUnknown_085E4EE8[] = +{ + AFFINEANIMCMD_FRAME(128, 128, 0, 0), + AFFINEANIMCMD_FRAME(16, 16, 0, 16), + AFFINEANIMCMD_FRAME(-16, -16, 0, 8), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd gUnknown_085E4F08[] = +{ + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_FRAME(8, 8, 0, 48), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd gUnknown_085E4F20[] = +{ + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_FRAME(2, 2, 0, 48), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd *const gUnknown_085E4F38[] = +{ + gUnknown_085E4ED8, + gUnknown_085E4EE8, + gUnknown_085E4F08, + gUnknown_085E4F20, +}; +static const u16 gUnknown_085E4F48[] = +{ + 0x100, 0xC0, 0x80, 0x40, 0x00, 0x40, 0x80, 0xC0, 0x100 +}; +static void sub_816FB38(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4F5C = +{ + .tileTag = 2000, + .paletteTag = 2001, + .oam = &gUnknown_085E4DD4, + .anims = gUnknown_085E4E5C, + .images = NULL, + .affineAnims = gUnknown_085E4F38, + .callback = sub_816FB38, +}; +static const struct SpriteTemplate gUnknown_085E4F74 = +{ + .tileTag = 2000, + .paletteTag = 2001, + .oam = &gUnknown_085E4DDC, + .anims = gUnknown_085E4E78, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816FB38, +}; +static void sub_816FD44(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4F8C = +{ + .tileTag = 2000, + .paletteTag = 2001, + .oam = &gUnknown_085E4DE4, + .anims = gUnknown_085E4E90, + .images = NULL, + .affineAnims = gUnknown_085E4F38, + .callback = sub_816FD44, +}; +static const u8 gUnknown_085E4FA4[] = +{ + 0x00, 0x17, 0x17, 0x31, 0x3E, 0x24, 0x24, 0x0A, 0x0A +}; +static const struct OamData gUnknown_085E4FB0 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 1, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E4FB8[] = +{ + ANIMCMD_FRAME(0, 10), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd *const gUnknown_085E4FC0[] = +{ + gUnknown_085E4FB8, +}; +static void sub_816FEDC(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E4FC4 = +{ + .tileTag = 2002, + .paletteTag = 2002, + .oam = &gUnknown_085E4FB0, + .anims = gUnknown_085E4FC0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_816FEDC, +}; +static const struct CompressedSpriteSheet gUnknown_085E4FDC[] = +{ + {gIntroTiles, 0x1400, 2000}, + {NULL}, +}; +static const struct CompressedSpriteSheet gUnknown_085E4FEC[] = +{ + {gIntro1FlygonGfx, 0x400, 2002}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E4FFC[] = +{ + {gIntro1DropsPal, 2000}, + {gIntro1GFLogoPal, 2001}, + {gIntro1FlygonPalette, 2002}, + {NULL}, +}; +static const struct OamData gUnknown_085E501C = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gUnknown_085E5024[] = +{ + ANIMCMD_FRAME(16, 8), + ANIMCMD_END, +}; +static const union AnimCmd *const gUnknown_085E502C[] = +{ + gUnknown_085E5024, +}; +static void sub_8170040(struct Sprite *sprite); +static const struct SpriteTemplate gUnknown_085E5030 = +{ + .tileTag = 2003, + .paletteTag = 2003, + .oam = &gUnknown_085E501C, + .anims = gUnknown_085E502C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_8170040, +}; +static const struct CompressedSpriteSheet gUnknown_085E5048[] = +{ + {gIntro3MiscTiles, 0xA00, 2003}, + {NULL}, +}; +static const struct SpritePalette gUnknown_085E5058[] = +{ + {gIntro3Misc1Palette, 2003}, + {NULL}, +}; + +// this file's functions +static void MainCB2_EndIntro(void); +static void Task_IntroLoadPart1Graphics(u8); +static u8 CreateWaterDrop(s16, s16, u16, u16, u16, u8); +static void Task_IntroFadeIn(u8); +static void intro_reset_and_hide_bgs(void); +static void Task_IntroWaterDrops(u8); +static void Task_IntroWaterDrops_1(u8); +static void Task_IntroWaterDrops_2(u8); +static void Task_IntroWaterDrops_3(u8); +static void Task_IntroScrollDownAndShowFlygon(u8); +static void Task_IntroWaitToSetupPart2(u8); +static void Task_IntroLoadPart2Graphics(u8); +static void Task_IntroStartBikeRide(u8); +static void Task_IntroHandleBikeAndFlygonMovement(u8); +static void Task_IntroWaitToSetupPart3(u8); +static void Task_IntroLoadPart3Graphics(u8); +static void Task_IntroSpinAndZoomPokeball(u8); +static void Task_IntroWaitToSetupPart3LegendsFight(u8); +static void Task_IntroLoadPart1Graphics3(u8); +static void Task_IntroLoadPart1Graphics4(u8); +static void Task_IntroLoadPart1Graphics5(u8); +static void Task_IntroLoadPart1Graphics6(u8); +static void Task_IntroLoadPart1Graphics7(u8); +static void Task_IntroLoadPart1Graphics8(u8); +static void Task_IntroLoadPart1Graphics9(u8); +static void Task_IntroFadeIn0(u8); +static void Task_IntroFadeIn1(u8); +static void Task_IntroFadeIn2(u8); +static void Task_IntroFadeIn3(u8); +static void Task_IntroFadeIn4(u8); +static void Task_IntroFadeIn5(u8); +static void Task_IntroFadeIn6(u8); +static void Task_IntroFadeIn7(u8); +static void Task_IntroFadeIn8(u8); +static void Task_IntroFadeIn9(u8); +static void sub_816E190(u8); +static void sub_816E1F8(struct Sprite *); +static void sub_816E6D4(u8); +static void sub_816E74C(void); +static void sub_816EEA8(u8); +static void sub_816F46C(struct Sprite *); +static void sub_816F5B4(struct Sprite *); +static void sub_816F660(struct Sprite *); +static void SpriteCB_WaterDropFall(struct Sprite *); +static void sub_816F318(struct Sprite *); +static void sub_816F9D4(struct Sprite *); +static void sub_816FAB0(struct Sprite *); +static u8 sub_816FDB8(s16, s16, s16); + +static void VBlankCB_Intro(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + ScanlineEffect_InitHBlankDmaTransfer(); +} + +static void MainCB2_Intro(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + if (gMain.newKeys && !gPaletteFade.active) + SetMainCallback2(MainCB2_EndIntro); + else if (gIntroFrameCounter != -1) + gIntroFrameCounter++; +} + +static void MainCB2_EndIntro(void) +{ + if (!UpdatePaletteFade()) + SetMainCallback2(CB2_InitTitleScreen); +} + +static void LoadCopyrightGraphics(u16 tilesetAddress, u16 tilemapAddress, u16 paletteAddress) +{ + LZ77UnCompVram(gIntroCopyright_Gfx, (void *)(VRAM + tilesetAddress)); + LZ77UnCompVram(gIntroCopyright_Tilemap, (void *)(VRAM + tilemapAddress)); + LoadPalette(gIntroCopyright_Pal, paletteAddress, 0x20); +} + +static void SerialCB_CopyrightScreen(void) +{ + GameCubeMultiBoot_HandleSerialInterrupt(&gMultibootProgramStruct); +} + +static u8 SetUpCopyrightScreen(void) +{ + u16 ime; + + switch (gMain.state) + { + case 0: + SetVBlankCallback(NULL); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + *(u16 *)PLTT = 0x7FFF; + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + CpuFill32(0, (void *)VRAM, VRAM_SIZE); + CpuFill32(0, (void *)OAM, OAM_SIZE); + CpuFill16(0, (void *)(PLTT + 2), PLTT_SIZE - 2); + ResetPaletteFade(); + LoadCopyrightGraphics(0, 0x3800, 0); + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + FreeAllSpritePalettes(); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_WHITEALPHA); + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(0) + | BGCNT_SCREENBASE(7) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + EnableInterrupts(INTR_FLAG_VBLANK); + SetVBlankCallback(VBlankCB_Intro); + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON; + SetSerialCallback(SerialCB_CopyrightScreen); + GameCubeMultiBoot_Init(&gMultibootProgramStruct); + default: + UpdatePaletteFade(); + gMain.state++; + GameCubeMultiBoot_Main(&gMultibootProgramStruct); + break; + case 140: + GameCubeMultiBoot_Main(&gMultibootProgramStruct); + if (gMultibootProgramStruct.gcmb_field_2 != 1) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK); + gMain.state++; + } + break; + case 141: + if (UpdatePaletteFade()) + break; + CreateTask(Task_IntroLoadPart1Graphics, 0); + SetMainCallback2(MainCB2_Intro); + if (gMultibootProgramStruct.gcmb_field_2 != 0) + { + if (gMultibootProgramStruct.gcmb_field_2 == 2) + { + // check the multiboot ROM header game code to see if we already did this + if (*(u32 *)(EWRAM_START + 0xAC) == 0x65366347) // "Gc6e" in ASCII + { + CpuCopy16(&gMultiBootProgram_PokemonColosseum_Start, (void *)EWRAM_START, sizeof(gMultiBootProgram_PokemonColosseum_Start)); + *(u32 *)(EWRAM_START + 0xAC) = 0x65366347; + } + GameCubeMultiBoot_ExecuteProgram(&gMultibootProgramStruct); + } + } + else + { + GameCubeMultiBoot_Quit(); + SetSerialCallback(SerialCB); + } + return 0; + } + + return 1; +} + +void CB2_InitCopyrightScreenAfterBootup(void) +{ + if (!SetUpCopyrightScreen()) + { + SetSaveBlocksPointers(sub_815355C()); + sub_808447C(); + Save_ResetSaveCounters(); + Save_LoadGameData(SAVE_NORMAL); + if (gSaveFileStatus == 0 || gSaveFileStatus == 2) + Sav2_ClearSetDefault(); + SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound); + InitHeap(gHeap, HEAP_SIZE); + } +} + +void CB2_InitCopyrightScreenAfterTitleScreen(void) +{ + SetUpCopyrightScreen(); +} + +static void Task_IntroLoadPart1Graphics(u8 taskId) +{ + SetVBlankCallback(NULL); + gUnknown_0203BCC8 = Random() & 1; + intro_reset_and_hide_bgs(); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0x50); + SetGpuReg(REG_OFFSET_BG1VOFS, 0x18); + SetGpuReg(REG_OFFSET_BG0VOFS, 0x28); + LZ77UnCompVram(gIntro1BGLeavesGfx, (void *)VRAM); + LZ77UnCompVram(gIntro1BG0_Tilemap, (void *)(VRAM + 0x8000)); + DmaClear16(3, VRAM + 0x8800, 0x800); + LZ77UnCompVram(gIntro1BG1_Tilemap, (void *)(VRAM + 0x9000)); + DmaClear16(3, VRAM + 0x9800, 0x800); + LZ77UnCompVram(gIntro1BG2_Tilemap, (void *)(VRAM + 0xA000)); + DmaClear16(3, VRAM + 0xA800, 0x800); + LZ77UnCompVram(gIntro1BG3_Tilemap, (void *)(VRAM + 0xB000)); + DmaClear16(3, VRAM + 0xB800, 0x800); + LoadPalette(gIntro1BGPals, 0, sizeof(gIntro1BGPals)); + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(22) | BGCNT_16COLOR | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(20) | BGCNT_16COLOR | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(18) | BGCNT_16COLOR | BGCNT_TXT256x512); + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(16) | BGCNT_16COLOR | BGCNT_TXT256x512); + LoadCompressedObjectPic(gUnknown_085E4FDC); + LoadCompressedObjectPic(gUnknown_085E4FEC); + LoadSpritePalettes(gUnknown_085E4FFC); + LoadCompressedObjectPic(gUnknown_085E4A74); + LoadSpritePalettes(gUnknown_085E4A84); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1F0, 0x20); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1E1, 0x1E); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1D2, 0x1C); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1C3, 0x1A); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1B4, 0x18); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x1A5, 0x16); + CpuCopy16(gPlttBufferUnfaded + 0x100, gPlttBufferUnfaded + 0x196, 0x14); + sub_816FDB8(0x78, 0x50, 0); + gTasks[taskId].data[0] = CreateWaterDrop(236, -14, 0x200, 1, 0x78, FALSE); + gTasks[taskId].func = Task_IntroFadeIn; +} + +static void Task_IntroFadeIn(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + SetVBlankCallback(VBlankCB_Intro); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON); + gTasks[taskId].func = Task_IntroWaterDrops; + gIntroFrameCounter = 0; + m4aSongNumStart(MUS_DEMO1); + ResetSerial(); +} + +static void Task_IntroWaterDrops(u8 taskId) +{ + //start moving rock + if (gIntroFrameCounter == 76) + gSprites[gTasks[taskId].data[0]].data[0] = 1; + + if (gIntroFrameCounter == 128) + CreateTask(Task_IntroWaterDrops_1, 0); + + //drop rock + if (gIntroFrameCounter == 251) + gSprites[gTasks[taskId].data[0]].data[0] = 2; + + if (gIntroFrameCounter == 256) + CreateTask(Task_IntroWaterDrops_2, 0); + + if (gIntroFrameCounter == 368) + CreateWaterDrop(48, 0, 0x400, 5, 0x70, TRUE); + + if (gIntroFrameCounter == 384) + CreateWaterDrop(200, 60, 0x400, 9, 0x80, TRUE); + + if (gIntroFrameCounter == 560) + CreateTask(Task_IntroWaterDrops_3, 0); + + if (gIntroFrameCounter > 560) + { + gTasks[taskId].data[1] = 0x50; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0x18; + gTasks[taskId].data[4] = 0; + gTasks[taskId].data[5] = 0x28; + gTasks[taskId].data[6] = 0; + gTasks[taskId].func = Task_IntroScrollDownAndShowFlygon; + } +} + +static void Task_IntroWaterDrops_3(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + if (++data[2] & 1) + data[3]++; + + switch (data[0]) + { + case 0: + CreateSprite(&gUnknown_085E4AB8, gUnknown_085E4AD0[data[4]][0], gUnknown_085E4AD0[data[4]][1] + data[3], 0); + data[0]++; + data[1] = 0xC; + data[4]++; + break; + case 1: + if (!--data[1]) + data[0] = 0; + break; + } + + if (data[3] > 0x3C) + DestroyTask(taskId); +} + +static void sub_816D338(struct Sprite *sprite) +{ + if (++sprite->data[0] == 0xC) + DestroySprite(sprite); +} + +static void Task_IntroScrollDownAndShowFlygon(u8 taskId) +{ + if (gIntroFrameCounter < 904) + { + s32 r2; + + //slide backgrounds downward + r2 = (gTasks[taskId].data[1] << 16) + (u16)gTasks[taskId].data[2]; + r2 -= 0x6000; + gTasks[taskId].data[1] = r2 >> 16; + gTasks[taskId].data[2] = r2; + SetGpuReg(REG_OFFSET_BG2VOFS, gTasks[taskId].data[1]); + r2 = (gTasks[taskId].data[3] << 16) + (u16)gTasks[taskId].data[4]; + r2 -= 0x8000; + gTasks[taskId].data[3] = r2 >> 16; + gTasks[taskId].data[4] = r2; + SetGpuReg(REG_OFFSET_BG1VOFS, gTasks[taskId].data[3]); + r2 = (gTasks[taskId].data[5] << 16) + (u16)gTasks[taskId].data[6]; + r2 -= 0xC000; + gTasks[taskId].data[5] = r2 >> 16; + gTasks[taskId].data[6] = r2; + SetGpuReg(REG_OFFSET_BG0VOFS, gTasks[taskId].data[5]); + + //show Flygon sprite + if (gIntroFrameCounter == 832) + { + u8 spriteId = CreateSprite(&gUnknown_085E4FC4, 120, 160, 10); + gSprites[spriteId].invisible = TRUE; + } + } + else + { + //fade to white + if (gIntroFrameCounter > 1007) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_WHITEALPHA); + gTasks[taskId].func = Task_IntroWaitToSetupPart2; + } + } +} + +static void Task_IntroWaitToSetupPart2(u8 taskId) +{ + if (gIntroFrameCounter > 1026) + gTasks[taskId].func = Task_IntroLoadPart2Graphics; +} + +static void Task_IntroLoadPart2Graphics(u8 taskId) +{ + intro_reset_and_hide_bgs(); + SetVBlankCallback(NULL); + ResetSpriteData(); + FreeAllSpritePalettes(); + gUnknown_0203BD24 = 0; + gUnknown_0203BD26 = 0; + gUnknown_0203BCCC = 0; + load_intro_part2_graphics(1); + gTasks[taskId].func = Task_IntroStartBikeRide; +} + +static void Task_IntroStartBikeRide(u8 taskId) +{ + u8 spriteId; + + if (gUnknown_0203BCC8 == 0) + LoadCompressedObjectPic(gIntro2BrendanSpriteSheet); + else + LoadCompressedObjectPic(gIntro2MaySpriteSheet); + + LoadCompressedObjectPic(gIntro2BicycleSpriteSheet); + LoadCompressedObjectPic(gIntro2FlygonSpriteSheet); + + for (spriteId = 0; spriteId < 3; spriteId++) + { + LoadCompressedObjectPic(&gUnknown_085E4AE8[spriteId]); + } + + LoadSpritePalettes(gUnknown_085F530C); + LoadSpritePalettes(gUnknown_085E4B08); + CreateSprite(&gUnknown_085E4BDC, 0x110, 0x80, 0); + CreateSprite(&gUnknown_085E4BA4, 0x120, 0x6E, 1); + + if (gUnknown_0203BCC8 == 0) + spriteId = intro_create_brendan_sprite(0x110, 100); + else + spriteId = intro_create_may_sprite(0x110, 100); + + gSprites[spriteId].callback = sub_816F9D4; + gSprites[spriteId].anims = gUnknown_085E4DC4; + gTasks[taskId].data[1] = spriteId; + CreateSprite(&gUnknown_085E4B40, 0x110, 0x50, 0x4); + spriteId = intro_create_flygon_sprite(-0x40, 0x3C); + gSprites[spriteId].callback = sub_816FAB0; + gTasks[taskId].data[2] = spriteId; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_WHITEALPHA); + SetVBlankCallback(VBlankCB_Intro); + gTasks[taskId].data[0] = sub_817B3DC(1, 0x4000, 0x400, 0x10); + sub_817B150(1); + gTasks[taskId].func = Task_IntroHandleBikeAndFlygonMovement; +} + +static void Task_IntroHandleBikeAndFlygonMovement(u8 taskId) +{ + s16 a; + u16 sine; + + if (gIntroFrameCounter == 1856) + { + gUnknown_0203BD28 = 2; + DestroyTask(gTasks[taskId].data[0]); + } + if (gIntroFrameCounter > 1946) + { + BeginNormalPaletteFade(0xFFFFFFFF, 8, 0, 16, RGB_WHITEALPHA); + gTasks[taskId].func = Task_IntroWaitToSetupPart3; + } + if (gIntroFrameCounter == 1109) + gSprites[gTasks[taskId].data[1]].data[0] = 1; + if (gIntroFrameCounter == 1214) + gSprites[gTasks[taskId].data[1]].data[0] = 0; + if (gIntroFrameCounter == 1394) + gSprites[gTasks[taskId].data[2]].data[0] = 1; + if (gIntroFrameCounter == 1398) + gSprites[gTasks[taskId].data[1]].data[0] = 2; + if (gIntroFrameCounter == 1576) + gSprites[gTasks[taskId].data[1]].data[0] = 3; + if (gIntroFrameCounter == 1727) + gSprites[gTasks[taskId].data[1]].data[0] = 4; + + sine = Sin(gTasks[taskId].data[3] >> 2 & 0x7F, 48); + gUnknown_0203BCCC = sine; + if (gTasks[taskId].data[3] < 512) + gTasks[taskId].data[3]++; + sub_817B540(0); +} + +static void Task_IntroWaitToSetupPart3(u8 taskId) +{ + if (gIntroFrameCounter > 2068) + gTasks[taskId].func = Task_IntroLoadPart3Graphics; +} + +static void sub_816D81C(struct Sprite *sprite) +{ + sprite->data[3] += 4; + switch (sprite->data[0]) + { + case 0: + if (++sprite->data[1] < 180) + break; + ++sprite->data[0]; + case 1: + sprite->pos1.x -= 4; + if (sprite->pos1.x == 0x3C) + { + sprite->data[0] = 8; + sprite->data[1] = 20; + sprite->data[2] = 2; + } + break; + case 2: + sprite->pos1.x += 8; + sprite->pos1.y -= 2; + if (sprite->pos1.x == 0x7C) + { + sprite->data[0] = 8; + sprite->data[1] = 20; + sprite->data[2] = 3; + } + break; + case 3: + sprite->pos1.y += 4; + if (sprite->pos1.y == 0x50) + { + sprite->data[0] = 8; + sprite->data[1] = 10; + sprite->data[2] = 4; + } + break; + case 4: + sprite->pos1.x -= 8; + sprite->pos1.y -= 2; + if (sprite->pos1.x == 0x3C) + { + sprite->data[0] = 8; + sprite->data[1] = 10; + sprite->data[2] = 5; + } + break; + case 5: + sprite->pos1.x += 0x3C; + sprite->data[4] = 0xC0; + sprite->data[5] = 0x80; + sprite->data[6] = 0x3; + sprite->data[0]++; + case 6: + sprite->pos2.x = Sin((u8)sprite->data[4], 0x3C); + sprite->pos2.y = Sin((u8)sprite->data[5], 0x14); + sprite->data[4] += 2; + sprite->data[5] += 4; + if ((sprite->data[4] & 0xFF) == 0x40) + { + sprite->hFlip = FALSE; + if (!--sprite->data[6]) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos2.x = 0; + sprite->data[0]++; + } + } + break; + case 7: + sprite->pos1.x -= 2; + sprite->pos2.y = Sin((u8)sprite->data[5], 0x14); + sprite->data[5] += 4; + if (sprite->pos1.x < -16) + DestroySprite(sprite); + break; + case 8: + sprite->pos2.y = Cos((u8)sprite->data[3], 2); + if (!--sprite->data[1]) + sprite->data[0] = sprite->data[2]; + break; + } +} + +static void sub_816D9C0(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (gIntroFrameCounter == 1224) + { + StartSpriteAnim(sprite, 1); + sprite->data[0]++; + } + break; + case 1: + if (gIntroFrameCounter == 1576) + { + StartSpriteAnim(sprite, 0); + sprite->data[0]++; + } + else + { + sprite->data[1] += 0x40; + if (sprite->data[1] & 0xFF00) + { + sprite->pos1.x--; + sprite->data[1] &= 0xFF; + } + } + break; + case 2: + if (gIntroFrameCounter != 1735) + { + sprite->data[1] += 0x20; + if (sprite->data[1] & 0xFF00) + { + sprite->pos1.x++; + sprite->data[1] &= 0xFF; + } + } + else + { + StartSpriteAnim(sprite, 1); + sprite->data[0]++; + sprite->data[2] = 0x50; + } + break; + case 3: + if (--sprite->data[2]) + { + sprite->data[1] += 0x40; + if (sprite->data[1] & 0xFF00) + { + sprite->pos1.x--; + sprite->data[1] &= 0xFF; + } + } + else + { + StartSpriteAnim(sprite, 2); + sprite->data[0]++; + } + break; + case 4: + if (sprite->animEnded) + sprite->pos1.x += 4; + + if (sprite->pos1.x > 336) + { + StartSpriteAnim(sprite, 1); + sprite->data[0]++; + } + break; + case 5: + if (gIntroFrameCounter > 1855) + sprite->pos1.x -= 2; + break; + } +} + +static void sub_816DAE8(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (gIntroFrameCounter == 1088) + sprite->data[0]++; + break; + case 1: + sprite->pos1.x -= 2; + if (gIntroFrameCounter != 1168) + break; + sprite->pos1.y -= 12; + sprite->data[1] = 0x80; + sprite->data[2] = 0; + sprite->data[0]++; + case 2: + if (sprite->pos1.x + sprite->pos2.x <= -0x20) + { + DestroySprite(sprite); + } + else + { + if ((sprite->data[1] & 0xFF) < 0x40) + { + sprite->pos2.x = Sin((u8)sprite->data[1], 0x10); + } + else + { + if ((sprite->data[1] & 0xFF) == 0x40) + sprite->pos1.x -= 0x30; + sprite->pos2.x = Sin((u8)sprite->data[1], 0x40); + } + sprite->data[1]++; + sprite->pos2.y = Cos((u8)sprite->data[2], 0xC); + sprite->data[2]++; + } + break; + } +} + +static void Task_IntroLoadPart3Graphics(u8 taskId) +{ + intro_reset_and_hide_bgs(); + LZ77UnCompVram(gIntro3Pokeball_Gfx, (void *)VRAM); + LZ77UnCompVram(gIntro3Pokeball_Tilemap, (void *)(VRAM + 0x4000)); + LoadPalette(gIntro3PokeballPal, 0, 0x200); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + sub_816F2A8(0x78, 0x50, 0, 0); + ResetSpriteData(); + FreeAllSpritePalettes(); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_WHITEALPHA); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(8) | BGCNT_256COLOR | BGCNT_AFF256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_OBJ_ON); + gTasks[taskId].func = Task_IntroSpinAndZoomPokeball; + gIntroFrameCounter = 0; + m4aSongNumStart(MUS_T_BATTLE); +} + +static void Task_IntroSpinAndZoomPokeball(u8 taskId) +{ + gTasks[taskId].data[0] += 0x400; + + if (gTasks[taskId].data[1] <= 0x6BF) + { + gTasks[taskId].data[1] += gTasks[taskId].data[2]; + gTasks[taskId].data[2] += 2; + } + else + { + gTasks[taskId].func = Task_IntroWaitToSetupPart3LegendsFight; + } + + sub_816F2A8(0x78, 0x50, 0x10000 / gTasks[taskId].data[1], gTasks[taskId].data[0]); + + if (gIntroFrameCounter == 28) + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_WHITEALPHA); +} + +static void Task_IntroWaitToSetupPart3LegendsFight(u8 taskId) +{ + if (gIntroFrameCounter > 43) + gTasks[taskId].func = Task_IntroLoadPart1Graphics3; +} + +static void Task_IntroLoadPart1Graphics3(u8 taskId) +{ + u16 i; + + if (!gPaletteFade.active) + { + intro_reset_and_hide_bgs(); + ResetSpriteData(); + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 8; + LZDecompressVram(gIntro3GroudonGfx, (void *)VRAM); + LZDecompressVram(gIntro3GroudonTilemap, (void *)(VRAM + 0xC000)); + LZDecompressVram(gIntro3LegendBgGfx, (void *)(VRAM + 0x4000)); + LZDecompressVram(gIntro3GroudonBgTilemap, (void *)(VRAM + 0xE000)); + LoadCompressedObjectPicUsingHeap(&gBattleAnimPicTable[0x3A]); + LoadCompressedObjectPaletteUsingHeap(&gBattleAnimPaletteTable[0x3A]); + CpuCopy16(gIntro3BgPal, gPlttBufferUnfaded, sizeof(gIntro3BgPal)); + gTasks[taskId].func = Task_IntroLoadPart1Graphics4; + } +} + +static void Task_IntroLoadPart1Graphics4(u8 taskId) +{ + SetGpuReg(REG_OFFSET_WIN0H, 0xF0); + SetGpuReg(REG_OFFSET_WIN0V, 0xA0); + SetGpuReg(REG_OFFSET_WININ, 0x3F); + SetGpuReg(REG_OFFSET_WINOUT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(0) + | BGCNT_SCREENBASE(24) + | BGCNT_256COLOR + | BGCNT_WRAP + | BGCNT_AFF512x512); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) + | BGCNT_CHARBASE(1) + | BGCNT_SCREENBASE(28) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG1_ON + | DISPCNT_BG2_ON + | DISPCNT_OBJ_ON + | DISPCNT_WIN0_ON); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_WHITEALPHA); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = 0xFFA0; + gTasks[taskId].data[2] = 0xFF51; + gTasks[taskId].data[3] = 0x100; + sub_816F2A8(0xFFA0, 0xFF51, 0x100, 0); + gTasks[taskId].func = Task_IntroLoadPart1Graphics5; +} + +static void Task_IntroLoadPart1Graphics5(u8 taskId) +{ + u16 foo = gTasks[taskId].data[0]; + + if (gTasks[taskId].data[0] != 32) + { + gTasks[taskId].data[0] += 4; + SetGpuReg(REG_OFFSET_WIN0V, (gTasks[taskId].data[0] * 256) - (foo -= 0x9C)); + } + else + { + SetGpuReg(REG_OFFSET_WIN0V, 0x2080); + gTasks[taskId].func = Task_IntroLoadPart1Graphics6; + } +} + +static void Task_IntroLoadPart1Graphics6(u8 taskId) +{ + gTasks[taskId].func = Task_IntroLoadPart1Graphics7; +} + +static void Task_IntroLoadPart1Graphics7(u8 taskId) +{ + gTasks[taskId].data[0] = 0; + gTasks[taskId].func = Task_IntroLoadPart1Graphics8; + ScanlineEffect_InitWave(0, 0xA0, 0x4, 4, 1, 4, 0); +} + +static void Task_IntroLoadPart1Graphics8(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + data[5]++; + if ((u16)(data[0] - 1) < 7 && data[5] % 2 == 0) + data[4] ^= 3; + sub_816F2A8(data[1], data[2] + data[4], data[3], 0); + switch (data[0]) + { + case 0: + data[1] += 0x10; + if (data[1] == 0xA0) + { + data[0]++; + data[6] = 2; + data[7] = 0x1E2; + sub_816E190(taskId); + } + break; + case 1: + if (--data[6] == 0) + { + data[6] = 2; + CpuCopy16(&gIntro3BgPal[data[7]], &gPlttBufferFaded[31], sizeof(u16)); + data[7] += 2; + if (data[7] == 0x1EC) + data[0]++; + } + break; + case 2: + if (--data[6] == 0) + { + data[6] = 2; + data[0]++; + } + break; + case 3: + if (--data[6] == 0) + { + data[6] = 2; + CpuCopy16(&gIntro3BgPal[data[7]], &gPlttBufferFaded[31], sizeof(u16)); + data[7] -= 2; + if (data[7] == 0x1E0) + { + data[6] = 8; + data[0]++; + } + } + break; + case 4: + if (--data[6] == 0) + { + data[1] = -0x60; + data[2] = 0xA9; + data[6] = 3; + data[0]++; + } + break; + case 5: + if (--data[6] == 0) + { + data[1] = 0x50; + data[2] = 0x29; + data[6] = 0x10; + PlayCryInternal(SPECIES_GROUDON, 0, 100, 10, 0); + data[0]++; + } + break; + case 6: + if (--data[6] == 0) + { + data[1] = 0x50; + data[2] = 0x28; + data[0]++; + } + break; + case 7: + data[1] += 4; + data[2] += 4; + data[6] += 0x666; + data[3] = Sin((data[6] & 0xFF00) >> 8, 0x40) + 0x100; + if (data[1] == 0x78) + { + BeginNormalPaletteFade(0xFFFFFFFE, 3, 0, 16, RGB_WHITE); + data[3] = 0x100; + data[4] = 0; + data[0]++; + } + break; + case 8: + if (data[3]) + data[3] -= 8; + else + data[0]++; + break; + case 9: + if (!gPaletteFade.active) + { + gTasks[taskId].func = Task_IntroLoadPart1Graphics9; + gScanlineEffect.state = 3; + } + break; + } +} + +static void sub_816E190(u8 a0) +{ + int i; + u8 spriteId; + + for (i = 0; i < 6; i++) + { + spriteId = CreateSprite(gUnknown_08596C10, gUnknown_085E4C64[i][0], 0xA0, i); + gSprites[spriteId].callback = sub_816E1F8; + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].data[1] = i; + gSprites[spriteId].data[4] = a0; + StartSpriteAnim(&gSprites[spriteId], gUnknown_085E4C64[i][1]); + } +} + +static void sub_816E1F8(struct Sprite *sprite) +{ + sprite->data[3]++; + if (sprite->data[3] % 2 == 0) + sprite->pos2.y ^= 3; + + switch(sprite->data[0]) + { + case 0: + sprite->data[2] += gUnknown_085E4C64[sprite->data[1]][2]; + sprite->pos1.y -= (sprite->data[2] & 0xFF00) >> 8; + sprite->data[2] &= 0xFF; + if (gTasks[sprite->data[4]].data[0] > 7) + sprite->data[0]++; + break; + case 1: + if (sprite->pos1.x < 0x78) + sprite->pos1.x -= 2; + else + sprite->pos1.x += 2; + + if (sprite->pos1.y < 0x50) + sprite->pos1.y -= 2; + else + sprite->pos1.y += 2; + break; + } +} + +static void Task_IntroLoadPart1Graphics9(u8 taskId) +{ + ResetSpriteData(); + LZDecompressVram(gIntro3KyogreGfx, (void *)VRAM); + LZDecompressVram(gIntro3KyogreTilemap, (void *)(VRAM + 0xC000)); + LZDecompressVram(gIntro3KyogreBgTilemap, (void *)(VRAM + 0xE000)); + LoadCompressedObjectPic(gUnknown_085E4C88); + LoadSpritePalette(gUnknown_085E4C98); + BeginNormalPaletteFade(0xFFFFFFFE, 0, 0x10, 0, RGB_WHITEALPHA); + gTasks[taskId].func = Task_IntroFadeIn0; + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = 0x150; + gTasks[taskId].data[2] = 0x50; + gTasks[taskId].data[6] = 0x10; + gTasks[taskId].data[3] = 0x100; + sub_816F2A8(0x150, 0x50, 0x100, 0); + ScanlineEffect_InitWave(0, 0xA0, 4, 4, 1, 6, 0); +} + +static void Task_IntroFadeIn0(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + sub_816F2A8(data[1], data[2], data[3], 0); + + switch (data[0]) + { + case 0: + if (--data[6] != 0) + break; + data[0]++; + case 1: + data[6] += 4; + gTasks[taskId].data[1] = 0x158 - Sin(data[6], 0x100); + gTasks[taskId].data[2] = 0x54 - Cos(data[6], 0x40); + if (data[6] == 0x40) + { + data[6] = 0x19; + data[7] = 1; + data[0]++; + sub_816E6D4(0); + } + break; + case 2: + if (--data[6] == 0) + { + gTasks[taskId].data[1] += 0x100; + gTasks[taskId].data[2] -= 0x102; + data[6] = 8; + data[0]++; + sub_816E6D4(0); + sub_816E74C(); + } + break; + case 3: + if (--data[6] == 0) + { + gTasks[taskId].data[1] -= 0x100; + gTasks[taskId].data[2] += 0x102; + data[6] = 8; + data[0]++; + } + break; + case 4: + if (--data[6] == 0) + { + gTasks[taskId].data[2] -= 0xFC; + data[6] = 8; + data[0]++; + } + break; + case 5: + if (--data[6] == 0) + { + gTasks[taskId].data[2] += 0xFC; + if (data[7] != 0) + { + data[6] = 12; + data[7]--; + data[0] = 2; + } + else + { + data[6] = 1; + data[0]++; + PlayCryInternal(SPECIES_KYOGRE, 0, 120, 10, 0); + } + } + break; + case 6: + if (--data[6] == 0) + { + data[6] = 4; + data[7] = 0x1EA; + data[0]++; + } + break; + case 7: + if (--data[6] == 0) + { + data[6] = 4; + CpuCopy16(&gIntro3BgPal[data[7]], &gPlttBufferFaded[47], sizeof(u16)); + data[7] -= 2; + if (data[7] == 0x1E0) + data[0]++; + } + break; + case 8: + if (--data[6] == 0) + { + data[6] = 4; + data[7] = 0x1E2; + data[0]++; + } + break; + case 9: + if (--data[6] == 0) + { + data[6] = 4; + CpuCopy16(&gIntro3BgPal[data[7]], &gPlttBufferFaded[47], sizeof(u16)); + data[7] += 2; + if (data[7] == 0x1EE) + { + data[6] = 0x10; + data[0]++; + } + } + break; + case 10: + if (--data[6] == 0) + { + data[6] = 0; + data[0]++; + sub_816E6D4(taskId); + } + break; + case 11: + data[6] += 4; + data[3] -= 8; + gTasks[taskId].data[1] = Sin(data[6], 0x3C) + 0x58; + if (data[6] == 0x40) + { + BeginNormalPaletteFade(0xFFFFFFFE, 3, 0, 16, RGB_WHITE); + data[0]++; + } + break; + case 12: + data[6] += 4; + data[3] -= 8; + gTasks[taskId].data[1] = Sin(data[6], 0x14) + 0x80; + if (data[6] == 0x80) + data[0]++; + break; + case 13: + if (!gPaletteFade.active) + { + gTasks[taskId].func = Task_IntroFadeIn1; + gScanlineEffect.state = 3; + } + break; + } +} + +static void sub_816E6D4(u8 a0) +{ + int i; + u8 spriteId; + + for (i = 0; i < 6; i++) + { + spriteId = CreateSprite(&gUnknown_085E4D14, gUnknown_085E4CA8[i][0], gUnknown_085E4CA8[i][1], i); + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].data[5] = a0; + gSprites[spriteId].data[6] = gUnknown_085E4CA8[i][2]; + gSprites[spriteId].data[7] = 0x40; + } +} + +static void sub_816E74C(void) +{ + int i; + u8 spriteId; + + for (i = 0; i < 6; i++) + { + spriteId = CreateSprite(&gUnknown_085E4D14, gUnknown_085E4CA8[i + 6][0], gUnknown_085E4CA8[i + 6][1], i); + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].data[6] = gUnknown_085E4CA8[i][2]; + gSprites[spriteId].data[7] = 0x40; + } +} + +static void sub_816E7B4(struct Sprite *sprite) +{ + switch(sprite->data[0]) + { + case 0: + if (sprite->data[6] == 0) + { + sprite->data[1] = (sprite->data[1] + 11) & 0xFF; + sprite->pos2.x = Sin(sprite->data[1], 4); + sprite->data[2] += 0x30; + sprite->pos2.y = -(sprite->data[2] >> 8); + if (sprite->animEnded) + DestroySprite(sprite); + } + else if (--sprite->data[6] == 0) + { + StartSpriteAnim(sprite, 0); + sprite->invisible = FALSE; + } + if (gTasks[sprite->data[5]].data[0] > 11) + sprite->data[0]++; + break; + case 1: + if (sprite->pos1.x < 120) + sprite->pos1.x -= 3; + else + sprite->pos1.x += 3; + + if (sprite->pos1.y < 80) + sprite->pos1.y -= 3; + else + sprite->pos1.y += 3; + if ((u16)(sprite->pos1.y - 20) > 140) + DestroySprite(sprite); + break; + } +} + +static void Task_IntroFadeIn1(u8 taskId) +{ + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 + | BLDCNT_TGT1_BG1 + | BLDCNT_TGT1_BG2 + | BLDCNT_EFFECT_LIGHTEN); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(31, 31)); + SetGpuReg(REG_OFFSET_BLDY, 31); + SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(0) + | BGCNT_SCREENBASE(24) + | BGCNT_16COLOR + | BGCNT_TXT512x256); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(0) + | BGCNT_CHARBASE(1) + | BGCNT_SCREENBASE(26) + | BGCNT_16COLOR + | BGCNT_TXT512x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) + | BGCNT_CHARBASE(1) + | BGCNT_SCREENBASE(28) + | BGCNT_16COLOR + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_BG1_ON + | DISPCNT_BG2_ON + | DISPCNT_OBJ_ON + | DISPCNT_WIN0_ON); + SetGpuReg(REG_OFFSET_BG0HOFS, 80); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, -80); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + LZDecompressVram(gIntro3CloudsGfx, (void *)VRAM); + LZDecompressVram(gIntro3CloudsGfx, (void *)(VRAM + 0x4000)); + LZDecompressVram(gIntro3Clouds3Tilemap, (void *)(VRAM + 0xE000)); + gTasks[taskId].func = Task_IntroFadeIn2; +} + +static void Task_IntroFadeIn2(u8 taskId) +{ + LZDecompressVram(gIntro3Clouds1Tilemap, (void *)(VRAM + 0xC000)); + LZDecompressVram(gIntro3Clouds2Tilemap, (void *)(VRAM + 0xD000)); + gTasks[taskId].func = Task_IntroFadeIn3; +} + +static void Task_IntroFadeIn3(u8 taskId) +{ + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].func = Task_IntroFadeIn4; + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[6] = 16; +} + +static void Task_IntroFadeIn4(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + SetGpuReg(REG_OFFSET_BG0HOFS, (data[6] >> 8)); + SetGpuReg(REG_OFFSET_BG1HOFS, -(data[6] >> 8)); + + switch (data[0]) + { + case 0: + if (--data[6] == 0) + { + BeginNormalPaletteFade(0xFFFFFFFE, 0, 16, 0, RGB_WHITEALPHA); + data[6] = 0x5000; + data[0]++; + } + break; + case 1: + if (data[6] == 0x2800) + BeginNormalPaletteFade(0x0000FFFE, 3, 0, 16, RGB(9, 10, 10)); + + if (data[6] != 0) + data[6] -= 0x80; + else if (!gPaletteFade.active) + gTasks[taskId].func = Task_IntroFadeIn5; + break; + } +} + +static void Task_IntroFadeIn5(u8 taskId) +{ + LZDecompressVram(gIntro3RayquazaTilemap, (void *)(VRAM + 0xE000)); + LZDecompressVram(gIntro3Clouds4Tilemap, (void *)(VRAM + 0xC000)); + LZDecompressVram(gIntro3RayquazaGfx, (void *)(VRAM + 0x4000)); + LZDecompressVram(gIntro3Clouds2Gfx, (void *)VRAM); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_BG2_ON + | DISPCNT_OBJ_ON + | DISPCNT_WIN0_ON); + gTasks[taskId].func = Task_IntroFadeIn6; + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[6] = 1; + gTasks[taskId].data[7] = 0; + LoadCompressedObjectPicUsingHeap(gUnknown_085E4BF4); + LoadSpritePalettes(gUnknown_085E4C04); +} + +static void Task_IntroFadeIn6(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u8 spriteId; + + switch (data[0]) + { + case 0: + if (--data[6] == 0) + { + CreateSprite(&gUnknown_085E4C4C, 200, 48, 0); + spriteId = CreateSprite(&gUnknown_085E4C4C, 200, 80, 1); + StartSpriteAnim(&gSprites[spriteId], 1); + spriteId = CreateSprite(&gUnknown_085E4C4C, 200, 112, 2); + StartSpriteAnim(&gSprites[spriteId], 2); + data[0]++; + data[6] = 72; + } + break; + case 1: + if (--data[6] == 0) + { + CreateSprite(&gUnknown_085E4C4C, 40, 48, 0); + spriteId = CreateSprite(&gUnknown_085E4C4C, 40, 80, 1); + StartSpriteAnim(&gSprites[spriteId], 1); + spriteId = CreateSprite(&gUnknown_085E4C4C, 40, 112, 2); + StartSpriteAnim(&gSprites[spriteId], 2); + data[0]++; + data[6] = 48; + } + break; + case 2: + if (--data[6] == 0) + gTasks[taskId].func = Task_IntroFadeIn7; + break; + } +} + +static void sub_816EC6C(struct Sprite *sprite) +{ + if (sprite->animEnded) + sprite->invisible = TRUE; + + switch(sprite->data[0]) + { + case 0: + sprite->data[1] = 0x1C2; + sprite->data[0]++; + case 1: + CpuCopy16(&gIntro3BgPal[sprite->data[1]], &gPlttBufferFaded[93], 2); + sprite->data[1] += 2; + if (sprite->data[1] != 0x1CE) + break; + sprite->data[1] = 0x1CC; + sprite->data[2] = 4; + sprite->data[0]++; + case 2: + if (--sprite->data[2] == 0) + { + sprite->data[2] = 4; + CpuCopy16(&gIntro3BgPal[sprite->data[1]], &gPlttBufferFaded[93], 2); + sprite->data[1] -= 2; + if (sprite->data[1] == 0x1C0) + DestroySprite(sprite); + } + break; + } +} + +static void Task_IntroFadeIn7(u8 taskId) +{ + u8 newTaskId; + + LoadCompressedObjectPic(gUnknown_085E5048); + LoadSpritePalettes(gUnknown_085E5058); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG0_ON + | DISPCNT_BG2_ON + | DISPCNT_OBJ_ON + | DISPCNT_WIN0_ON); + gTasks[taskId].func = Task_IntroFadeIn8; + BeginNormalPaletteFade(0x0000FFDE, 0, 16, 0, RGB(9, 10, 10)); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = 0xA8; + gTasks[taskId].data[2] = -0x10; + gTasks[taskId].data[3] = -0x88; + gTasks[taskId].data[4] = -0x10; + newTaskId = CreateTask(sub_816EEA8, 0); + gTasks[newTaskId].data[4] = taskId; +} + +static void Task_IntroFadeIn8(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (data[7] % 2 == 0) + data[6] ^= 2; + + data[7]++; + + switch(data[0]) + { + case 0: + if ((data[7] & 1) != 0) + { + data[1] -= 2; + data[2]++; + data[3] += 2; + data[4]++; + } + if (data[1] == 0x68) + { + data[0]++; + data[5] = 1; + } + break; + case 1: + data[0]++; + data[5] = 4; + break; + case 2: + data[1] += 4; + data[2] -= 2; + data[3] -= 4; + data[4] -= 2; + if (!gPaletteFade.active) + { + data[5] = 0x8C; + data[0]++; + } + break; + case 3: + if (--data[5] == 0) + gTasks[taskId].func = Task_IntroFadeIn9; + break; + } +} + +static void Task_IntroFadeIn9(u8 taskId) +{ + DestroyTask(taskId); + SetMainCallback2(MainCB2_EndIntro); +} + +static void sub_816EEA8(u8 taskId) +{ + u8 spriteId; + s16 *data = gTasks[taskId].data; + + data[2]++; + + switch(data[0]) + { + case 0: + if ((data[2] & 1) != 0) + { + CpuCopy16(&gIntro3BgPal[0x1A2 + data[1] * 2], &gPlttBufferFaded[94], 2); + data[1]++; + } + if (data[1] == 6) + { + data[0]++; + data[1] = 0; + data[3] = 10; + } + break; + case 1: + if (data[3] == 0) + { + if ((data[2] & 1) != 0) + { + CpuCopy16(&gIntro3BgPal[0x1A2 + data[1] * 2], &gPlttBufferFaded[88], 2); + data[1]++; + } + if (data[1] == 6) + { + data[0]++; + data[3] = 10; + } + } + else + { + data[3]--; + } + break; + case 2: + if (data[3] == 0) + { + if ((data[2] & 1) != 0) + { + CpuCopy16(&gIntro3BgPal[0x182 + data[1] * 2], &gPlttBufferFaded[92], 2); + data[1]++; + } + if (data[1] == 6) + { + spriteId = CreateSprite(&gUnknown_085E5030, 120, 88, 15); + PlaySE(SE_OP_BASYU); + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].data[3] = data[4]; + data[0]++; + data[3] = 16; + } + } + else + { + data[3]--; + } + break; + case 3: + if ((data[2] & 1) != 0) + { + if (--data[3] != 0) + { + BlendPalette(0x50, 16, data[3], RGB(9, 10, 10)); + CpuCopy16(&gIntro3BgPal[0x1AC], &gPlttBufferFaded[94], 2); + CpuCopy16(&gIntro3BgPal[0x1AC], &gPlttBufferFaded[88], 2); + CpuCopy16(&gIntro3BgPal[0x18C], &gPlttBufferFaded[92], 2); + } + else + { + data[0]++; + data[3] = 53; + } + } + break; + case 4: + if (--data[3] == 0) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_WHITE); + data[0]++; + } + break; + case 5: + if (!gPaletteFade.active) + DestroyTask(taskId); + break; + } +} + +static void intro_reset_and_hide_bgs(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); +} + +static void Task_IntroWaterDrops_1(u8 taskId) +{ + switch (gTasks[taskId].data[0]) + { + case 0: + default: + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND + | BLDCNT_TGT2_BG0 + | BLDCNT_TGT2_BG1 + | BLDCNT_TGT2_BG2 + | BLDCNT_TGT2_BG3 + | BLDCNT_TGT2_OBJ + | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[31]); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[1] = 0x40; + gTasks[taskId].data[0]++; + break; + case 1: + if (gTasks[taskId].data[1] != 0) + { + u8 tmp; + + gTasks[taskId].data[1]--; + tmp = gTasks[taskId].data[1] / 2; + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[tmp]); + } + else + { + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[0]); + gTasks[taskId].data[1] = 0x10; + gTasks[taskId].data[0]++; + } + break; + case 2: + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + DestroyTask(taskId); + break; + } +} + +static void Task_IntroWaterDrops_2(u8 taskId) +{ + switch (gTasks[taskId].data[0]) + { + case 0: + default: + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND + | BLDCNT_TGT2_BG0 + | BLDCNT_TGT2_BG1 + | BLDCNT_TGT2_BG2 + | BLDCNT_TGT2_BG3 + | BLDCNT_TGT2_OBJ + | BLDCNT_TGT2_BD); + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[0]); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[0]++; + break; + case 1: + if (gTasks[taskId].data[1] < 62) + { + u8 tmp; + + gTasks[taskId].data[1]++; + tmp = gTasks[taskId].data[1] / 2; + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[tmp]); + } + else + { + SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[31]); + gTasks[taskId].data[1] = 0x10; + gTasks[taskId].data[0]++; + } + break; + case 2: + if (gTasks[taskId].data[1] != 0) + { + gTasks[taskId].data[1]--; + } + else + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + DestroyTask(taskId); + } + break; + } +} + +void sub_816F2A8(u16 scrX, u16 scrY, u16 zoom, u16 alpha) +{ + struct BgAffineSrcData src; + struct BgAffineDstData dest; + + src.texX = 0x8000; + src.texY = 0x8000; + src.scrX = scrX; + src.scrY = scrY; + src.sx = zoom; + src.sy = zoom; + src.alpha = alpha; + BgAffineSet(&src, &dest, 1); + SetGpuReg(REG_OFFSET_BG2PA, dest.pa); + SetGpuReg(REG_OFFSET_BG2PB, dest.pb); + SetGpuReg(REG_OFFSET_BG2PC, dest.pc); + SetGpuReg(REG_OFFSET_BG2PD, dest.pd); + SetGpuReg(REG_OFFSET_BG2X_L, dest.dx); + SetGpuReg(REG_OFFSET_BG2X_H, dest.dx >> 16); + SetGpuReg(REG_OFFSET_BG2Y_L, dest.dy); + SetGpuReg(REG_OFFSET_BG2Y_H, dest.dy >> 16); +} + +static void sub_816F318(struct Sprite *sprite) +{ + u8 r0; + + if (sprite->data[2] >= 192) + { + if (sprite->data[3] != 0) + { + sprite->data[3]--; + } + else + { + sprite->invisible = FALSE; + SetOamMatrix(sprite->data[1], sprite->data[2], 0, 0, sprite->data[2]); + sprite->data[2] = (sprite->data[2] * 95) / 100; + r0 = (sprite->data[2] - 192) / 128 + 9; + if (r0 > 15) + r0 = 15; + sprite->oam.paletteNum = r0; + } + } + else + { + DestroySprite(sprite); + } +} + +static void sub_816F3A4(struct Sprite *sprite) +{ + if (gSprites[sprite->data[7]].data[7] != 0) + { + sprite->invisible = TRUE; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + StartSpriteAnim(sprite, 3); + sprite->data[2] = 1024; + sprite->data[3] = 8 * (sprite->data[1] & 3); + sprite->callback = sub_816F318; + sprite->oam.shape = 1; + sprite->oam.size = 3; + CalcCenterToCornerVec(sprite, 1, 3, 2); + } + else + { + sprite->pos2.x = gSprites[sprite->data[7]].pos2.x; + sprite->pos2.y = gSprites[sprite->data[7]].pos2.y; + sprite->pos1.x = gSprites[sprite->data[7]].pos1.x; + sprite->pos1.y = gSprites[sprite->data[7]].pos1.y; + } +} + +static void sub_816F454(struct Sprite *sprite) +{ + if (sprite->data[0] != 0) + sprite->callback = sub_816F46C; +} + +static void sub_816F46C(struct Sprite *sprite) +{ + if (sprite->pos1.x <= 116) + { + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos1.x += 4; + sprite->pos2.x = -4; + sprite->data[4] = 128; + sprite->callback = sub_816F5B4; + } + else + { + u16 data2; + u16 data3; + u16 data4; + s16 sin1; + s16 sin2; + s16 sin3; + s16 sin4; + s16 var1; + s16 var2; + s16 var3; + s16 var4; + s16 temp; + + data4 = sprite->data[4]; + sin1 = gSineTable[(u8)data4]; + sin2 = gSineTable[(u8)(data4 + 64)]; + sprite->data[4] += 2; + sprite->pos2.y = sin1 / 32; + sprite->pos1.x--; + if (sprite->pos1.x & 1) + sprite->pos1.y++; + temp = -sin2 / 16; + data2 = sprite->data[2]; + data3 = sprite->data[3]; + sin3 = gSineTable[(u8)(temp - 16)]; + sin4 = gSineTable[(u8)(temp + 48)]; + var1 = sin4 * data2 / 256; + var2 = -sin3 * data3 / 256; + var3 = sin3 * data2 / 256; + var4 = sin4 * data3 / 256; + SetOamMatrix(sprite->data[1], data2, 0, 0, data3); + SetOamMatrix(sprite->data[1] + 1, var1, var3, var2, var4); + SetOamMatrix(sprite->data[1] + 2, var1, var3, var2 * 2, var4 * 2); + } +} + +static void sub_816F5B4(struct Sprite *sprite) +{ + SetOamMatrix(sprite->data[1], sprite->data[6] + 64, 0, 0, sprite->data[6] + 64); + SetOamMatrix(sprite->data[1] + 1, sprite->data[6] + 64, 0, 0, sprite->data[6] + 64); + SetOamMatrix(sprite->data[1] + 2, sprite->data[6] + 64, 0, 0, sprite->data[6] + 64); + if (sprite->data[4] != 64) + { + u16 data4; + + sprite->data[4] -= 8; + data4 = sprite->data[4]; + sprite->pos2.x = gSineTable[(u8)(data4 + 64)] / 64; + sprite->pos2.y = gSineTable[(u8)data4] / 64; + } + else + { + sprite->data[4] = 0; + sprite->callback = sub_816F660; + } +} + +static void sub_816F660(struct Sprite *sprite) +{ + if (sprite->data[0] != 2) + { + s16 r2; + + sprite->data[4] += 8; + r2 = gSineTable[(u8)sprite->data[4]] / 16 + 64; + sprite->pos2.x = gSineTable[(u8)(r2 + 64)] / 64; + sprite->pos2.y = gSineTable[(u8)r2] / 64; + } + else + { + sprite->callback = SpriteCB_WaterDropFall; + } +} + +static void SpriteCB_WaterDropFall(struct Sprite *sprite) +{ + if (sprite->pos1.y < sprite->data[5]) + { + sprite->pos1.y += 4; + } + else + { + sprite->data[7] = 1; + sprite->invisible = TRUE; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + StartSpriteAnim(sprite, 3); + sprite->data[2] = 1024; + sprite->data[3] = 8 * (sprite->data[1] & 3); + sprite->callback = sub_816F318; + sprite->oam.shape = 1; + sprite->oam.size = 3; + CalcCenterToCornerVec(sprite, 1, 3, 2); + } +} + +//Duplicate function +static void SpriteCB_WaterDropFall_2(struct Sprite *sprite) +{ + if (sprite->pos1.y < sprite->data[5]) + { + sprite->pos1.y += 4; + } + else + { + sprite->data[7] = 1; + sprite->invisible = TRUE; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + StartSpriteAnim(sprite, 3); + sprite->data[2] = 1024; + sprite->data[3] = 8 * (sprite->data[1] & 3); + sprite->callback = sub_816F318; + sprite->oam.shape = 1; + sprite->oam.size = 3; + CalcCenterToCornerVec(sprite, 1, 3, 2); + } +} + +static u8 CreateWaterDrop(s16 x, s16 y, u16 c, u16 d, u16 e, u8 fallImmediately) +{ + u8 spriteId; + u8 oldSpriteId; + + spriteId = CreateSprite(&gUnknown_085E4D64, x, y, 1); + gSprites[spriteId].data[0] = 0; + gSprites[spriteId].data[7] = 0; + gSprites[spriteId].data[1] = d; + gSprites[spriteId].data[2] = c; + gSprites[spriteId].data[3] = c; + gSprites[spriteId].data[5] = e; + gSprites[spriteId].data[6] = c; + gSprites[spriteId].oam.affineMode = 3; + gSprites[spriteId].oam.matrixNum = d; + CalcCenterToCornerVec(&gSprites[spriteId], 0, 2, 2); + StartSpriteAnim(&gSprites[spriteId], 2); + if (!fallImmediately) + gSprites[spriteId].callback = sub_816F454; + else + gSprites[spriteId].callback = SpriteCB_WaterDropFall_2; + oldSpriteId = spriteId; + + spriteId = CreateSprite(&gUnknown_085E4D64, x, y, 1); + gSprites[spriteId].data[7] = oldSpriteId; + gSprites[spriteId].data[1] = d + 1; + gSprites[spriteId].oam.affineMode = 3; + gSprites[spriteId].oam.matrixNum = d + 1; + CalcCenterToCornerVec(&gSprites[spriteId], 0, 2, 2); + gSprites[spriteId].callback = sub_816F3A4; + + spriteId = CreateSprite(&gUnknown_085E4D64, x, y, 1); + gSprites[spriteId].data[7] = oldSpriteId; + gSprites[spriteId].data[1] = d + 2; + StartSpriteAnim(&gSprites[spriteId], 1); + gSprites[spriteId].oam.affineMode = 3; + gSprites[spriteId].oam.matrixNum = d + 2; + CalcCenterToCornerVec(&gSprites[spriteId], 0, 2, 2); + gSprites[spriteId].callback = sub_816F3A4; + + SetOamMatrix(d, c + 32, 0, 0, c + 32); + SetOamMatrix(d + 1, c + 32, 0, 0, c + 32); + SetOamMatrix(d + 2, c + 32, 0, 0, 2 * (c + 32)); + + return oldSpriteId; +} + +static void sub_816F9D4(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + StartSpriteAnimIfDifferent(sprite, 0); + sprite->pos1.x--; + break; + case 1: + StartSpriteAnimIfDifferent(sprite, 0); + if (gIntroFrameCounter & 7) + return; + sprite->pos1.x++; + break; + case 2: + if (sprite->pos1.x <= 120 || gIntroFrameCounter & 7) + sprite->pos1.x++; + break; + case 3: + break; + case 4: + if (sprite->pos1.x > -32) + sprite->pos1.x -= 2; + break; + } + if (gIntroFrameCounter & 7) + return; + if (sprite->pos2.y != 0) + { + sprite->pos2.y = 0; + } + else + { + switch (Random() & 3) + { + case 0: + sprite->pos2.y = -1; + break; + case 1: + sprite->pos2.y = 1; + break; + case 2: + case 3: + sprite->pos2.y = 0; + break; + } + } +} + +static void sub_816FAB0(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + break; + case 1: + if (sprite->pos2.x + sprite->pos1.x < 304) + sprite->pos2.x += 8; + else + sprite->data[0] = 2; + break; + case 2: + if (sprite->pos2.x + sprite->pos1.x > 120) + sprite->pos2.x -= 1; + else + sprite->data[0] = 3; + break; + case 3: + if (sprite->pos2.x > 0) + sprite->pos2.x -= 2; + break; + } + sprite->pos2.y = Sin((u8)sprite->data[1], 8) - gUnknown_0203BCCC; + sprite->data[1] += 4; +} + +static void sub_816FB38(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (sprite->data[1] != 0) + { + sprite->data[1]--; + } + else + { + sprite->invisible = FALSE; + StartSpriteAffineAnim(sprite, 1); + sprite->data[0]++; + } + break; + case 1: + if (gIntroFrameCounter == 0x90) + { + sprite->data[0]++; + sprite->data[1] = 9; + sprite->data[3] = 2; + } + break; + case 2: + if (sprite->data[3] == 0) + { + sprite->data[3] = 2; + if (sprite->data[1] != 0) + { + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1]], &gPlttBufferFaded[0x11F], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x10], &gPlttBufferFaded[0x114], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x20], &gPlttBufferFaded[0x11A], 2); + sprite->data[1]--; + } + else + { + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1]], &gPlttBufferFaded[0x11F], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x10], &gPlttBufferFaded[0x114], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x20], &gPlttBufferFaded[0x11A], 2); + sprite->data[0]++; + } + } + else + { + sprite->data[3]--; + } + break; + case 3: + if (sprite->data[3] != 0) + { + sprite->data[3]--; + } + else + { + sprite->data[3] = 2; + if (sprite->data[1] < 10) + { + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1]], &gPlttBufferFaded[0x11F], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x10], &gPlttBufferFaded[0x114], 2); + CpuCopy16(&gIntro1GameFreakTextFadePal[sprite->data[1] + 0x20], &gPlttBufferFaded[0x11A], 2); + sprite->data[1]++; + } + else + { + sprite->data[0]++; + } + } + break; + case 4: + if (gIntroFrameCounter == 0x110) + { + StartSpriteAffineAnim(sprite, 2); + sprite->oam.objMode = 1; + sprite->data[0]++; + } + break; + case 5: + sprite->data[3] += gUnknown_085E4F48[sprite->data[2]]; + sprite->pos2.x = (sprite->data[3] & 0xFF00) >> 8; + if (sprite->data[2] < 4) + { + s16 temp = sprite->pos2.x; + sprite->pos2.x = -temp; + } + if (sprite->affineAnimEnded) + DestroySprite(sprite); + break; + } +} + +static void sub_816FD44(struct Sprite *sprite) +{ + switch(sprite->data[0]) + { + case 0: + if (gIntroFrameCounter == 0x80) + { + sprite->invisible = FALSE; + sprite->data[0]++; + } + break; + case 1: + if (gIntroFrameCounter == 0x110) + { + StartSpriteAffineAnim(sprite, 3); + sprite->data[0]++; + } + break; + case 2: + if (sprite->affineAnimEnded) + DestroySprite(sprite); + break; + } +} + +static u8 sub_816FDB8(s16 a0, s16 a1, s16 a2) +{ + u16 i; + u8 spriteId; + + for (i = 0; i < 9; i++) + { + spriteId = CreateSprite(&gUnknown_085E4F5C, gUnknown_085E4E94[i][1] + a0, a1 - 4, 0); + gSprites[spriteId].data[0] = 0; + gSprites[spriteId].data[1] = gUnknown_085E4FA4[i]; + gSprites[spriteId].data[2] = i; + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].oam.matrixNum = i + 12; + StartSpriteAnim(&gSprites[spriteId], gUnknown_085E4E94[i][0]); + StartSpriteAffineAnim(&gSprites[spriteId], 0); + } + spriteId = CreateSprite(&gUnknown_085E4F8C, 120, a1 - 6, 0); + gSprites[spriteId].data[0] = 0; + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].oam.matrixNum = i + 12; + StartSpriteAffineAnim(&gSprites[spriteId], 1); + return spriteId; +} + +static void sub_816FEDC(struct Sprite *sprite) +{ + sprite->data[7]++; + + if (sprite->data[0] != 0) + { + s16 sin1; + s16 sin2; + + s16 a, b, c, d; + + sin1 = gSineTable[(u8)sprite->data[2]]; + sin2 = gSineTable[(u8)(sprite->data[2] + 64)]; + + d = Q_8_8_TO_INT(sin2 * sprite->data[1]); + c = Q_8_8_TO_INT(-sin1 * sprite->data[1]); + b = Q_8_8_TO_INT(sin1 * sprite->data[1]); + a = Q_8_8_TO_INT(sin2 * sprite->data[1]); + + SetOamMatrix(1, a, b, c, d); + } + + switch (sprite->data[0]) + { + case 0: + default: + sprite->oam.affineMode = 3; + sprite->oam.matrixNum = 1; + CalcCenterToCornerVec(sprite, 1, 3, 3); + sprite->invisible = FALSE; + sprite->data[0] = 1; + sprite->data[1] = 0x80; + sprite->data[2] = 0; + sprite->data[3] = 0; + break; + case 1: + sprite->pos2.x = -Sin((u8)sprite->data[3], 140); + sprite->pos2.y = -Sin((u8)sprite->data[3], 120); + sprite->data[1] += 7; + sprite->data[3] += 3; + if (sprite->pos1.x + sprite->pos2.x <= -16) + { + sprite->oam.priority = 3; + sprite->data[0]++; + sprite->pos1.x = 20; + sprite->pos1.y = 40; + sprite->data[1] = 0x200; + sprite->data[2] = 0; + sprite->data[3] = 0x10; + } + break; + case 2: + sprite->pos2.x = Sin((u8)sprite->data[3], 34); + sprite->pos2.y = -Cos((u8)sprite->data[3], 60); + sprite->data[1] += 2; + if (sprite->data[7] % 5 == 0) + sprite->data[3]++; + break; + } +} + +static void sub_8170040(struct Sprite *sprite) +{ + u16 foo; + + //I'm not sure why a switch statement was used here. + //if (sprite->data[0] != 1) would have been more appropriate. + switch (sprite->data[0]) + { + case 0: + default: + sprite->invisible = FALSE; + sprite->oam.affineMode = 3; + sprite->oam.matrixNum = 18; + CalcCenterToCornerVec(sprite, 0, 3, 3); + sprite->data[1] = 0; + sprite->data[0] = 1; + //fall through + case 1: + sprite->data[7]++; + if (sprite->data[7] & 1) + { + sprite->invisible = TRUE; + } + else + { + sprite->invisible = FALSE; + if (sprite->data[1] < 64) + sprite->data[1]++; + } + foo = 256 - gSineTable[(u8)sprite->data[1]] / 2; + SetOamMatrix(18, foo, 0, 0, foo); + break; + } +} diff --git a/src/intro_credits_graphics.c b/src/intro_credits_graphics.c new file mode 100644 index 000000000..d570b2992 --- /dev/null +++ b/src/intro_credits_graphics.c @@ -0,0 +1,740 @@ +#include "global.h" +#include "intro_credits_graphics.h" +#include "palette.h" +#include "decompress.h" +#include "gpu_regs.h" +#include "task.h" +#include "main.h" +#include "graphics.h" + +struct IntroCreditsSpriteMetadata +{ + u8 animNum:4; + u8 shape:2; + u8 size:2; + u8 x; + u8 y; + u8 subpriority; + u16 xOff; +}; + +static const u16 gUnknown_085F06E0[] = INCBIN_U16("graphics/intro/intro2_grass.gbapal"); +static const u16 gUnknown_085F0700[] = INCBIN_U16("graphics/intro/intro2_grass_afternoon.gbapal"); +static const u16 gUnknown_085F0720[] = INCBIN_U16("graphics/intro/intro2_grass_night.gbapal"); +static const u8 gUnknown_085F0740[] = INCBIN_U8("graphics/intro/intro2_grass.4bpp.lz"); +static const u8 gUnknown_085F0BC0[] = INCBIN_U8("graphics/intro/intro2_grass_map.bin.lz"); +static const u16 gUnknown_085F0CFC[] = INCBIN_U16("graphics/intro/85F0CFC.gbapal"); +static const u16 gUnknown_085F0D5C[] = INCBIN_U16("graphics/intro/85F0D5C.gbapal"); +static const u8 gUnknown_085F0DBC[] = INCBIN_U8("graphics/intro/intro2_bgclouds.4bpp.lz"); +static const u8 gUnknown_085F1398[] = INCBIN_U8("graphics/intro/intro2_bgclouds_map.bin.lz"); +static const u16 gUnknown_085F1668[] = INCBIN_U16("graphics/intro/intro2_bgclouds.gbapal"); +static const u16 gUnknown_085F1688[] = INCBIN_U16("graphics/intro/intro2_bgclouds_afternoon.gbapal"); +static const u8 gUnknown_085F16A8[] = INCBIN_U8("graphics/intro/intro2_bgclouds2.4bpp.lz"); +static const u16 gUnknown_085F17E4[] = INCBIN_U16("graphics/intro/intro2_bgtrees2.gbapal"); +static const u16 gUnknown_085F1804[] = INCBIN_U16("graphics/intro/intro2_bgtrees2_afternoon.gbapal"); +static const u8 gUnknown_085F1824[] = INCBIN_U8("graphics/intro/intro2_bgtrees.4bpp.lz"); +static const u8 gUnknown_085F1EAC[] = INCBIN_U8("graphics/intro/intro2_bgtrees_map.bin.lz"); +static const u16 gUnknown_085F21B0[] = INCBIN_U16("graphics/intro/intro2_bgtrees.gbapal"); +static const u8 gIntro2TreeTiles[] = INCBIN_U8("graphics/intro/intro2_bgtreessmall.4bpp.lz"); +static const u16 gUnknown_085F231C[] = INCBIN_U16("graphics/intro/85F231C.gbapal"); +static const u8 gUnknown_085F235C[] = INCBIN_U8("graphics/intro/intro2_bgnight.4bpp.lz"); +static const u16 gUnknown_085F2548[] = INCBIN_U16("graphics/intro/intro2_bgnight.gbapal"); +static const u8 gUnknown_085F2568[] = INCBIN_U8("graphics/intro/intro2_bgnight_map.bin.lz"); +static const u8 gIntro2NightTiles[] = INCBIN_U8("graphics/intro/intro2_night.4bpp.lz"); +static const u16 gIntro2BrendanPalette[] = INCBIN_U16("graphics/intro/intro2_brendan.gbapal"); +static const u8 gIntro2BrendanTiles[] = INCBIN_U8("graphics/intro/intro2_brendan.4bpp.lz"); +static const u16 gIntro2MayPalette[] = INCBIN_U16("graphics/intro/intro2_may.gbapal"); +static const u16 gUnknown_085F3490[0xF0] = {0}; +static const u8 gIntro2MayTiles[] = INCBIN_U8("graphics/intro/intro2_may.4bpp.lz"); +static const u8 gIntro2BicycleTiles[] = INCBIN_U8("graphics/intro/intro2_bicycle.4bpp.lz"); +static const u16 gIntro2LatiosPalette[] = INCBIN_U16("graphics/intro/intro2_latios.gbapal"); +static const u8 gIntro2LatiosTiles[] = INCBIN_U8("graphics/intro/intro2_latios.4bpp.lz"); +static const u16 gIntro2LatiasPalette[] = INCBIN_U16("graphics/intro/intro2_latias.gbapal"); +static const u8 gIntro2LatiasTiles[] = INCBIN_U8("graphics/intro/intro2_latias.4bpp.lz"); + +static void sub_817B62C(struct Sprite *sprite); +static void nullsub_65(struct Sprite *sprite); +static void sub_817B7C4(struct Sprite *sprite); +static void nullsub_66(struct Sprite *sprite); + +static const struct SpriteTemplate gUnknown_085F504C = { + 2000, 0xFFFF, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_817B62C +}; + +static const struct CompressedSpriteSheet gUnknown_085F5064[] = { + { gUnknown_085F16A8, 0x400, 2000 }, + { NULL } +}; + +static const union AnimCmd gUnknown_085F5074[] = { + ANIMCMD_FRAME( 0, 30), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F507C[] = { + ANIMCMD_FRAME(16, 30), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F5084[] = { + ANIMCMD_FRAME(20, 30), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F508C[] = { + ANIMCMD_FRAME(22, 30), + ANIMCMD_END +}; + +static const union AnimCmd *const gUnknown_085F5094[] = { + gUnknown_085F5074, + gUnknown_085F507C, + gUnknown_085F5084, + gUnknown_085F508C +}; + +static const struct IntroCreditsSpriteMetadata gUnknown_085F50A4[] = { + { 0, ST_OAM_SQUARE, 2, 72, 32, 100, 0xc00 }, + { 0, ST_OAM_SQUARE, 2, 158, 32, 100, 0xc00 }, + { 1, ST_OAM_SQUARE, 1, 192, 40, 101, 0x800 }, + { 1, ST_OAM_SQUARE, 1, 56, 40, 101, 0x800 }, + { 2, ST_OAM_H_RECTANGLE, 0, 100, 44, 102, 0x400 }, + { 2, ST_OAM_H_RECTANGLE, 0, 152, 44, 102, 0x400 }, + { 3, ST_OAM_H_RECTANGLE, 0, 8, 46, 103, 0x100 }, + { 3, ST_OAM_H_RECTANGLE, 0, 56, 46, 103, 0x100 }, + { 3, ST_OAM_H_RECTANGLE, 0, 240, 46, 103, 0x100 }, +}; + +static const struct CompressedSpriteSheet gUnknown_085F50EC[] = { + { gIntro2TreeTiles, 0x400, 2000 }, + { NULL } +}; + +static const union AnimCmd gUnknown_085F50FC[] = { + ANIMCMD_FRAME( 0, 30), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F5104[] = { + ANIMCMD_FRAME(16, 30), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F510C[] = { + ANIMCMD_FRAME(24, 30), + ANIMCMD_END +}; + +static const union AnimCmd *const gUnknown_085F5114[] = { + gUnknown_085F50FC, + gUnknown_085F5104, + gUnknown_085F510C +}; + +static const struct IntroCreditsSpriteMetadata gUnknown_085F5120[] = { + { 0, ST_OAM_SQUARE, 2, 16, 88, 100, 0x2000 }, + { 0, ST_OAM_SQUARE, 2, 80, 88, 100, 0x2000 }, + { 0, ST_OAM_SQUARE, 2, 144, 88, 100, 0x2000 }, + { 0, ST_OAM_SQUARE, 2, 208, 88, 100, 0x2000 }, + { 1, ST_OAM_V_RECTANGLE, 2, 40, 88, 101, 0x1000 }, + { 1, ST_OAM_V_RECTANGLE, 2, 104, 88, 101, 0x1000 }, + { 1, ST_OAM_V_RECTANGLE, 2, 168, 88, 101, 0x1000 }, + { 1, ST_OAM_V_RECTANGLE, 2, 232, 88, 101, 0x1000 }, + { 2, ST_OAM_V_RECTANGLE, 2, 56, 88, 102, 0x800 }, + { 2, ST_OAM_V_RECTANGLE, 2, 120, 88, 102, 0x800 }, + { 2, ST_OAM_V_RECTANGLE, 2, 184, 88, 102, 0x800 }, + { 2, ST_OAM_V_RECTANGLE, 2, 248, 88, 102, 0x800 }, +}; + +static const struct CompressedSpriteSheet gUnknown_085F5180[] = { + { gIntro2NightTiles, 0x400, 2000 }, + { NULL } +}; + +static const union AnimCmd gUnknown_085F5190[] = { + ANIMCMD_FRAME(0, 30), + ANIMCMD_END +}; + +static const union AnimCmd *const gUnknown_085F5198[] = { + gUnknown_085F5190 +}; + +static const struct IntroCreditsSpriteMetadata gUnknown_085F519C[] = { + { 0, ST_OAM_SQUARE, 2, 24, 88, 100, 0x1000 }, + { 0, ST_OAM_SQUARE, 2, 64, 88, 100, 0x1000 }, + { 0, ST_OAM_SQUARE, 2, 104, 88, 100, 0x1000 }, + { 0, ST_OAM_SQUARE, 2, 144, 88, 100, 0x1000 }, + { 0, ST_OAM_SQUARE, 2, 184, 88, 100, 0x1000 }, + { 0, ST_OAM_SQUARE, 2, 224, 88, 100, 0x1000 }, +}; + +static const struct OamData gOamData_85F51CC = { + .y = 160, .shape = ST_OAM_SQUARE, .size = 3, .priority = 1 +}; + +static const union AnimCmd gUnknown_085F51D4[] = { + ANIMCMD_FRAME( 0, 8), + ANIMCMD_FRAME( 64, 8), + ANIMCMD_FRAME(128, 8), + ANIMCMD_FRAME(192, 8), + ANIMCMD_JUMP(0) +}; + +static const union AnimCmd *const gUnknown_085F51E8[] = { + gUnknown_085F51D4 +}; + +static const struct SpriteTemplate gUnknown_085F51EC = { + 1002, 1002, &gOamData_85F51CC, gUnknown_085F51E8, NULL, gDummySpriteAffineAnimTable, nullsub_65 +}; + +static const struct SpriteTemplate gUnknown_085F5204 = { + 1003, 1003, &gOamData_85F51CC, gUnknown_085F51E8, NULL, gDummySpriteAffineAnimTable, nullsub_65 +}; + +static const struct OamData gUnknown_085F521C = { + .y = 160, .shape = ST_OAM_H_RECTANGLE, .size = 3, .priority = 1 +}; + +static const union AnimCmd gUnknown_085F5224[] = { + ANIMCMD_FRAME( 0, 8), + ANIMCMD_FRAME( 32, 8), + ANIMCMD_FRAME( 64, 8), + ANIMCMD_FRAME( 96, 8), + ANIMCMD_JUMP(0) +}; + +static const union AnimCmd *const gUnknown_085F5238[] = { + gUnknown_085F5224 +}; + +static const struct SpriteTemplate gUnknown_085F523C = { + 1001, 1002, &gUnknown_085F521C, gUnknown_085F5238, NULL, gDummySpriteAffineAnimTable, sub_817B7C4 +}; + +static const struct SpriteTemplate gUnknown_085F5254 = { + 1001, 1003, &gUnknown_085F521C, gUnknown_085F5238, NULL, gDummySpriteAffineAnimTable, sub_817B7C4 +}; + +static const struct OamData gUnknown_085F526C = { + .y = 160, .shape = ST_OAM_SQUARE, .size = 3, .priority = 1 +}; + +static const union AnimCmd gUnknown_085F5274[] = { + ANIMCMD_FRAME( 0, 16), + ANIMCMD_END +}; + +static const union AnimCmd gUnknown_085F527C[] = { + ANIMCMD_FRAME( 64, 16), + ANIMCMD_END +}; + +static const union AnimCmd *const gUnknown_085F5284[] = { + gUnknown_085F5274, + gUnknown_085F527C +}; + +static const struct SpriteTemplate gUnknown_085F528C = { + 1004, 1004, &gUnknown_085F526C, gUnknown_085F5284, NULL, gDummySpriteAffineAnimTable, nullsub_66 +}; + +static const struct SpriteTemplate gUnknown_085F52A4 = { + 1005, 1005, &gUnknown_085F526C, gUnknown_085F5284, NULL, gDummySpriteAffineAnimTable, nullsub_66 +}; + +const struct CompressedSpriteSheet gIntro2BrendanSpriteSheet[] = { + { gIntro2BrendanNoTurnGfx, 0x2000, 1002 }, + { NULL } +}; + +const struct CompressedSpriteSheet gIntro2MaySpriteSheet[] = { + { gIntro2MayNoTurnGfx, 0x2000, 1003 }, + { NULL } +}; + +const struct CompressedSpriteSheet gIntro2BicycleSpriteSheet[] = { + { gIntro2BicycleTiles, 0x1000, 1001 }, + { NULL } +}; + +static const struct CompressedSpriteSheet gUnknown_085F52EC[] = { + { gIntro2FlygonGfx, 0x1000, 1004 }, + { NULL } +}; + +const struct CompressedSpriteSheet gIntro2FlygonSpriteSheet[] = { + { gIntro2FlygonGfx, 0x1000, 1005 }, + { NULL } +}; + +const struct SpritePalette gUnknown_085F530C[] = { + { gIntro2BrendanNoTurnPal, 1002 }, + { gIntro2BrendanNoTurnPal, 1003 }, + { gIntro2FlygonPal, 1004 }, + { gIntro2FlygonPal, 1005 }, + { NULL } +}; + +const struct CompressedSpriteSheet gUnknown_085F5334[] = { + { gIntro2BrendanTiles, 0x3800, 1002 }, + { NULL } +}; + +const struct CompressedSpriteSheet gUnknown_085F5344[] = { + { gIntro2MayTiles, 0x3800, 1003 }, + { NULL } +}; + +const struct CompressedSpriteSheet gUnknown_085F5354[] = { + { gIntro2BicycleTiles, 0x1000, 1001 }, + { NULL } +}; + +static const struct CompressedSpriteSheet gUnknown_085F5364[] = { + { gIntro2LatiosTiles, 0x1000, 1004 }, + { NULL } +}; + +static const struct CompressedSpriteSheet gUnknown_085F5374[] = { + { gIntro2LatiasTiles, 0x1000, 1005 }, + { NULL } +}; + +const struct SpritePalette gUnknown_085F5384[] = { + { gIntro2BrendanPalette, 1002 }, + { gIntro2MayPalette, 1003 }, + { gIntro2LatiosPalette, 1004 }, + { gIntro2LatiasPalette, 1005 }, + { NULL } +}; + +const struct CompressedSpriteSheet gUnknown_085F53AC[] = { + { gIntro2BrendanTiles, 0x2000, 1002}, + { NULL } +}; + +const struct CompressedSpriteSheet gUnknown_085F53BC[] = { + { gIntro2MayTiles, 0x2000, 1003}, + { NULL } +}; + +EWRAM_DATA u16 gUnknown_0203BD24 = 0; +EWRAM_DATA s16 gUnknown_0203BD26 = 0; +EWRAM_DATA s16 gUnknown_0203BD28 = 0; + +static void sub_817B76C(void); +static void sub_817B788(void); +static void sub_817B7A4(void); +static void sub_817B458(u8); + +void load_intro_part2_graphics(u8 a) +{ + LZ77UnCompVram(&gUnknown_085F0740, (void *)(VRAM + 0x4000)); + LZ77UnCompVram(&gUnknown_085F0BC0, (void *)(VRAM + 0x7800)); + LoadPalette(&gUnknown_085F06E0, 240, 32); + switch (a) + { + case 0: + default: + LZ77UnCompVram(&gUnknown_085F0DBC, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F1398, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F0CFC, 0, 96); + LoadCompressedObjectPic(gUnknown_085F5064); + LoadPalette(&gUnknown_085F1668, 256, 32); + sub_817B76C(); + break; + case 1: + LZ77UnCompVram(&gUnknown_085F1824, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F1EAC, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F17E4, 0, 32); + LoadCompressedObjectPic(gUnknown_085F50EC); + LoadPalette(&gUnknown_085F21B0, 256, 32); + sub_817B788(); + break; + } + gUnknown_0203BD28 = 0; + gReservedSpritePaletteCount = 8; +} + +void sub_817B150(u8 a) +{ + switch (a) + { + default: + case 0: + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(6) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(7) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) + | BGCNT_CHARBASE(1) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(15) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG1_ON + | DISPCNT_BG2_ON + | DISPCNT_BG3_ON + | DISPCNT_OBJ_ON); + break; + case 1: + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(6) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(7) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) + | BGCNT_CHARBASE(1) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(15) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG1_ON + | DISPCNT_BG2_ON + | DISPCNT_BG3_ON + | DISPCNT_OBJ_ON); + break; + case 2: + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(6) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(7) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) + | BGCNT_CHARBASE(1) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(15) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG1_ON + | DISPCNT_BG2_ON + | DISPCNT_BG3_ON + | DISPCNT_OBJ_ON); + break; + } +} + +void sub_817B1C8(u8 a) +{ + LZ77UnCompVram(&gUnknown_085F0740, (void *)(VRAM + 0x4000)); + LZ77UnCompVram(&gUnknown_085F0BC0, (void *)(VRAM + 0x7800)); + switch (a) + { + case 0: + default: + LoadPalette(&gUnknown_085F06E0, 240, 32); + LZ77UnCompVram(&gUnknown_085F0DBC, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F1398, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F0CFC, 0, 96); + LoadCompressedObjectPic(gUnknown_085F5064); + LZ77UnCompVram(&gUnknown_085F16A8, (void *)(VRAM + 0x10000)); + LoadPalette(&gUnknown_085F1668, 256, 32); + sub_817B76C(); + break; + case 1: + LoadPalette(&gUnknown_085F0700, 240, 32); + LZ77UnCompVram(&gUnknown_085F0DBC, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F1398, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F0D5C, 0, 96); + LoadCompressedObjectPic(gUnknown_085F5064); + LZ77UnCompVram(&gUnknown_085F16A8, (void *)(VRAM + 0x10000)); + LoadPalette(&gUnknown_085F1688, 256, 32); + sub_817B76C(); + break; + case 2: + case 3: + LoadPalette(&gUnknown_085F0700, 240, 32); + LZ77UnCompVram(&gUnknown_085F1824, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F1EAC, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F1804, 0, 32); + LoadCompressedObjectPic(gUnknown_085F50EC); + LoadPalette(&gUnknown_085F1804, 256, 32); + sub_817B788(); + break; + case 4: + LoadPalette(&gUnknown_085F0720, 240, 32); + LZ77UnCompVram(&gUnknown_085F235C, (void *)(VRAM)); + LZ77UnCompVram(&gUnknown_085F2568, (void *)(VRAM + 0x3000)); + LoadPalette(&gUnknown_085F231C, 0, 64); + LoadCompressedObjectPic(gUnknown_085F5180); + LoadPalette(&gUnknown_085F2548, 256, 32); + sub_817B7A4(); + break; + } + gReservedSpritePaletteCount = 8; + gUnknown_0203BD28 = 0; +} + +void sub_817B3A8(u8 a) +{ + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(6) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2) + | BGCNT_CHARBASE(0) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(7) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(1) + | BGCNT_CHARBASE(1) + | BGCNT_16COLOR + | BGCNT_SCREENBASE(15) + | BGCNT_TXT256x256); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 + | DISPCNT_OBJ_1D_MAP + | DISPCNT_BG_ALL_ON + | DISPCNT_OBJ_ON); +} + +u8 sub_817B3DC(u8 a, u16 b, u16 c, u16 d) +{ + u8 taskId = CreateTask(&sub_817B458, 0); + + gTasks[taskId].data[0] = a; + gTasks[taskId].data[1] = b; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = c; + gTasks[taskId].data[5] = 0; + gTasks[taskId].data[6] = 0; + gTasks[taskId].data[7] = d; + gTasks[taskId].data[8] = 8; + gTasks[taskId].data[9] = 0; + sub_817B458(taskId); + return taskId; +} + +static void sub_817B458(u8 taskId) +{ + s16 data1; + s16 data4; + s16 data7; + s32 r2; + + data1 = gTasks[taskId].data[1]; + if (data1 != 0) + { + r2 = (gTasks[taskId].data[2] << 16) + (u16)gTasks[taskId].data[3]; + r2 -= (u16)data1 << 4; + gTasks[taskId].data[2] = r2 >> 16; + gTasks[taskId].data[3] = r2; + SetGpuReg(REG_OFFSET_BG1HOFS, gTasks[taskId].data[2]); + SetGpuReg(REG_OFFSET_BG1VOFS, gUnknown_0203BD24 + gUnknown_0203BD26); + } + + data4 = gTasks[taskId].data[4]; + if (data4 != 0) + { + r2 = (gTasks[taskId].data[5] << 16) + (u16)gTasks[taskId].data[6]; + r2 -= (u16)data4 << 4; + gTasks[taskId].data[5] = r2 >> 16; + gTasks[taskId].data[6] = r2; + SetGpuReg(REG_OFFSET_BG2HOFS, gTasks[taskId].data[5]); + if (gTasks[taskId].data[0] != 0) + SetGpuReg(REG_OFFSET_BG2VOFS, gUnknown_0203BD24 + gUnknown_0203BD26); + else + SetGpuReg(REG_OFFSET_BG2VOFS, gUnknown_0203BD24); + } + + data7 = gTasks[taskId].data[7]; + if (data7 != 0) + { + r2 = (gTasks[taskId].data[8] << 16) + (u16)gTasks[taskId].data[9]; + r2 -= (u16)data7 << 4; + gTasks[taskId].data[8] = r2 >> 16; + gTasks[taskId].data[9] = r2; + SetGpuReg(REG_OFFSET_BG3HOFS, gTasks[taskId].data[8]); + SetGpuReg(REG_OFFSET_BG3VOFS, gUnknown_0203BD24); + } +} + +void sub_817B540(u8 mode) +{ + u16 x; + u16 y; + switch (mode) + { + case 0: + default: + /* stuff */ + if (gMain.vblankCounter1 & 3 || gPaletteFade.active) + break; + if (gMain.vblankCounter1 & 4) + { + x = gPlttBufferUnfaded[9]; + y = gPlttBufferUnfaded[10]; + } + else + { + x = gPlttBufferUnfaded[10]; + y = gPlttBufferUnfaded[9]; + } + LoadPalette(&x, 9, 2); + LoadPalette(&y, 10, 2); + break; + case 2: + if (gMain.vblankCounter1 & 3 || gPaletteFade.active) + break; + if (gMain.vblankCounter1 & 4) + { + x = 0x3D27; + y = 0x295; + } + else + { + x = 0x31C; + y = 0x3D27; + } + LoadPalette(&x, 12, 2); + LoadPalette(&y, 13, 2); + break; + case 1: + break; + } +} + +static void sub_817B62C(struct Sprite *sprite) +{ + s32 var; + s16 var2 = gUnknown_0203BD28; + + if (var2 != 2) + { + switch (var2) + { + default: + DestroySprite(sprite); + break; + case 0: + var = ((sprite->pos1.x << 16) | (u16)sprite->data[2]) + (u16)sprite->data[1]; + sprite->pos1.x = var >> 16; + sprite->data[2] = var; + if (sprite->pos1.x > 0xFF) + sprite->pos1.x = -0x20; + if (sprite->data[0]) + sprite->pos2.y = -(gUnknown_0203BD24 + gUnknown_0203BD26); + else + sprite->pos2.y = -gUnknown_0203BD24; + break; + } + } +} + +static void sub_817B698(u8 a, const struct IntroCreditsSpriteMetadata *b, const union AnimCmd *const *c, u8 d) +{ + u8 i; + + for(i = 0; i < d; i++) + { + u8 sprite = CreateSprite(&gUnknown_085F504C, b[i].x, b[i].y, b[i].subpriority); + CalcCenterToCornerVec(&gSprites[sprite], b[i].shape, b[i].size, 0); + gSprites[sprite].oam.priority = 3; + gSprites[sprite].oam.shape = b[i].shape; + gSprites[sprite].oam.size = b[i].size; + gSprites[sprite].oam.paletteNum = 0; + gSprites[sprite].anims = c; + StartSpriteAnim(&gSprites[sprite], b[i].animNum); + gSprites[sprite].data[0] = a; + gSprites[sprite].data[1] = b[i].xOff; + gSprites[sprite].data[2] = 0; + } +} + +static void sub_817B76C(void) +{ + sub_817B698(0, gUnknown_085F50A4, gUnknown_085F5094, 9); +} + +static void sub_817B788(void) +{ + sub_817B698(1, gUnknown_085F5120, gUnknown_085F5114, 12); +} + +static void sub_817B7A4(void) +{ + sub_817B698(1, gUnknown_085F519C, gUnknown_085F5198, 6); +} + +static void nullsub_65(struct Sprite *sprite) +{ +} + +static void sub_817B7C4(struct Sprite* sprite) +{ + sprite->invisible = gSprites[sprite->data[0]].invisible; + sprite->pos1.x = gSprites[sprite->data[0]].pos1.x; + sprite->pos1.y = gSprites[sprite->data[0]].pos1.y + 8; + sprite->pos2.x = gSprites[sprite->data[0]].pos2.x; + sprite->pos2.y = gSprites[sprite->data[0]].pos2.y; +} + +u8 intro_create_brendan_sprite(s16 a, s16 b) +{ + u8 sprite = CreateSprite(&gUnknown_085F51EC, a, b, 2); + u8 brendan = CreateSprite(&gUnknown_085F523C, a, b + 8, 3); + gSprites[brendan].data[0] = sprite; + return sprite; +} + +u8 intro_create_may_sprite(s16 a, s16 b) +{ + u8 sprite = CreateSprite(&gUnknown_085F5204, a, b, 2); + u8 may = CreateSprite(&gUnknown_085F5254, a, b + 8, 3); + gSprites[may].data[0] = sprite; + return sprite; +} + +static void nullsub_66(struct Sprite *sprite) +{ +} + +static void sub_817B8E8(struct Sprite* sprite) +{ + sprite->invisible = gSprites[sprite->data[0]].invisible; + sprite->pos1.y = gSprites[sprite->data[0]].pos1.y; + sprite->pos2.x = gSprites[sprite->data[0]].pos2.x; + sprite->pos2.y = gSprites[sprite->data[0]].pos2.y; +} + +static u8 sub_817B948(s16 a, s16 b) +{ + u8 sprite = CreateSprite(&gUnknown_085F528C, a - 32, b, 5); + u8 latios = CreateSprite(&gUnknown_085F528C, a + 32, b, 6); + gSprites[latios].data[0] = sprite; + StartSpriteAnim(&gSprites[latios], 1); + gSprites[latios].callback = &sub_817B8E8; + return sprite; +} + +u8 intro_create_flygon_sprite(s16 a, s16 b) +{ + u8 sprite = CreateSprite(&gUnknown_085F52A4, a - 32, b, 5); + u8 flygon = CreateSprite(&gUnknown_085F52A4, a + 32, b, 6); + gSprites[flygon].data[0] = sprite; + StartSpriteAnim(&gSprites[flygon], 1); + gSprites[flygon].callback = &sub_817B8E8; + return sprite; +} diff --git a/src/item.c b/src/item.c index ef815fb81..319d167fc 100644 --- a/src/item.c +++ b/src/item.c @@ -5,41 +5,48 @@ #include "string_util.h" #include "text.h" #include "event_data.h" +#include "malloc.h" +#include "secret_base.h" +#include "item_menu.h" +#include "strings.h" +#include "load_save.h" -extern void ApplyNewEncryptionKeyToHword(u16* hword, u32 newKey); extern bool8 InBattlePyramid(void); +extern u16 gUnknown_0203CF30[]; +extern const struct Item gItems[]; -extern const u8 gText_PokeBalls[]; -extern const u8 gText_Berries[]; -extern const u8 gText_Berry[]; +// this file's functions +static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); +static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count); -bool8 CheckPyramidBagHasItem(u16 itemId, u16 count); -bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count); +// EWRAM variables +EWRAM_DATA struct BagPocket gBagPockets[POCKETS_COUNT] = {0}; -u16 GetBagItemQuantity(u16* quantity) +// code +static u16 GetBagItemQuantity(u16 *quantity) { return gSaveBlock2Ptr->encryptionKey ^ *quantity; } -void SetBagItemQuantity(u16* quantity, u16 newValue) +static void SetBagItemQuantity(u16 *quantity, u16 newValue) { *quantity = newValue ^ gSaveBlock2Ptr->encryptionKey; } -u16 GetBagItemId(u16* slot) +static u16 GetPCItemQuantity(u16 *quantity) { - return *slot; + return *quantity; } -void SetBagItemId(u16* slot, u16 newItemId) +static void SetPCItemQuantity(u16 *quantity, u16 newValue) { - *slot = newItemId; + *quantity = newValue; } void ApplyNewEncryptionKeyToBagItems(u32 newKey) { u32 pocket, item; - for (pocket = 0; pocket < 5; pocket++) + for (pocket = 0; pocket < POCKETS_COUNT; pocket++) { for (item = 0; item < gBagPockets[pocket].capacity; item++) ApplyNewEncryptionKeyToHword(&(gBagPockets[pocket].itemSlots[item].quantity), newKey); @@ -51,58 +58,57 @@ void ApplyNewEncryptionKeyToBagItems_(u32 newKey) // really GF? ApplyNewEncryptionKeyToBagItems(newKey); } -// TODO: move those max values to defines - void SetBagItemsPointers(void) { - gBagPockets[BAG_ITEMS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_Items; - gBagPockets[BAG_ITEMS - 1].capacity = 30; + gBagPockets[ITEMS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_Items; + gBagPockets[ITEMS_POCKET].capacity = BAG_ITEMS_COUNT; - gBagPockets[BAG_KEYITEMS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_KeyItems; - gBagPockets[BAG_KEYITEMS - 1].capacity = 30; + gBagPockets[KEYITEMS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_KeyItems; + gBagPockets[KEYITEMS_POCKET].capacity = BAG_KEYITEMS_COUNT; - gBagPockets[BAG_POKEBALLS - 1].itemSlots = gSaveBlock1Ptr->bagPocket_PokeBalls; - gBagPockets[BAG_POKEBALLS - 1].capacity = 16; + gBagPockets[BALLS_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_PokeBalls; + gBagPockets[BALLS_POCKET].capacity = BAG_POKEBALLS_COUNT; - gBagPockets[BAG_TMsHMs - 1].itemSlots = gSaveBlock1Ptr->bagPocket_TMHM; - gBagPockets[BAG_TMsHMs - 1].capacity = 64; + gBagPockets[TMHM_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_TMHM; + gBagPockets[TMHM_POCKET].capacity = BAG_TMHM_COUNT; - gBagPockets[BAG_BERRIES - 1].itemSlots = gSaveBlock1Ptr->bagPocket_Berries; - gBagPockets[BAG_BERRIES - 1].capacity = 46; + gBagPockets[BERRIES_POCKET].itemSlots = gSaveBlock1Ptr->bagPocket_Berries; + gBagPockets[BERRIES_POCKET].capacity = BAG_BERRIES_COUNT; } -void CopyItemName(u16 itemId, u8 *string) +void CopyItemName(u16 itemId, u8 *dst) { - StringCopy(string, ItemId_GetItem(itemId)->name); + StringCopy(dst, ItemId_GetName(itemId)); } -void CopyItemNameHandlePlural(u16 itemId, u8 *string, u32 quantity) +void CopyItemNameHandlePlural(u16 itemId, u8 *dst, u32 quantity) { if (itemId == ITEM_POKE_BALL) { if (quantity < 2) - StringCopy(string, ItemId_GetItem(ITEM_POKE_BALL)->name); + StringCopy(dst, ItemId_GetName(ITEM_POKE_BALL)); else - StringCopy(string, gText_PokeBalls); + StringCopy(dst, gText_PokeBalls); } else { if (itemId >= ITEM_CHERI_BERRY && itemId <= ITEM_ENIGMA_BERRY) - GetBerryCountString(string, gBerries[itemId - ITEM_CHERI_BERRY].name, quantity); + GetBerryCountString(dst, gBerries[itemId - ITEM_CHERI_BERRY].name, quantity); else - StringCopy(string, ItemId_GetItem(itemId)->name); + StringCopy(dst, ItemId_GetName(itemId)); } } -void GetBerryCountString(u8* dst, const u8* berryName, u32 quantity) +void GetBerryCountString(u8 *dst, const u8 *berryName, u32 quantity) { - const u8* berryString; - u8* txtPtr; + const u8 *berryString; + u8 *txtPtr; if (quantity < 2) berryString = gText_Berry; else berryString = gText_Berries; + txtPtr = StringCopy(dst, berryName); *txtPtr = CHAR_SPACE; StringCopy(txtPtr + 1, berryString); @@ -127,21 +133,21 @@ bool8 CheckBagHasItem(u16 itemId, u16 count) if (ItemId_GetPocket(itemId) == 0) return FALSE; - if (InBattlePyramid() || FlagGet(0x4004) == TRUE) + if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE) return CheckPyramidBagHasItem(itemId, count); pocket = ItemId_GetPocket(itemId) - 1; - //Check for item slots that contain the item + // Check for item slots that contain the item for (i = 0; i < gBagPockets[pocket].capacity; i++) { if (gBagPockets[pocket].itemSlots[i].itemId == itemId) { u16 quantity; - //Does this item slot contain enough of the item? + // Does this item slot contain enough of the item? quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity); if (quantity >= count) return TRUE; count -= quantity; - //Does this item slot and all previous slots contain enough of the item? + // Does this item slot and all previous slots contain enough of the item? if (count == 0) return TRUE; } @@ -152,69 +158,945 @@ bool8 CheckBagHasItem(u16 itemId, u16 count) bool8 HasAtLeastOneBerry(void) { u16 i; - for (i = 0x85; i < 0xB3; i++) + + for (i = FIRST_BERRY_INDEX; i < ITEM_BRIGHT_POWDER; i++) { if (CheckBagHasItem(i, 1) == TRUE) { - gSpecialVar_Result = 1; + gSpecialVar_Result = TRUE; return TRUE; } } - gSpecialVar_Result = 0; + gSpecialVar_Result = FALSE; return FALSE; } -/* Refuses to match. +#ifdef NONMATCHING +// Refuses to match. bool8 CheckBagHasSpace(u16 itemId, u16 count) { u8 i; - u8 pocket; - u16 slotCapacity; - u16 quantity; - if (ItemId_GetPocket(itemId) == 0) + if (ItemId_GetPocket(itemId) == POCKET_NONE) return FALSE; - if (InBattlePyramid() || FlagGet(0x4004) == TRUE) + + if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE) + { return CheckPyramidBagHasSpace(itemId, count); - pocket = ItemId_GetPocket(itemId) - 1; - if (pocket != BAG_BERRIES) - slotCapacity = 99; + } else - slotCapacity = 999; + { + u8 pocket; + u16 slotCapacity; + u16 ownedCount; - //Check space in any existing item slots that already contain this item - for (i = 0; i < gBagPockets[pocket].capacity; i++) + pocket = ItemId_GetPocket(itemId) - 1; + if (pocket != BERRIES_POCKET) + slotCapacity = 99; + else + slotCapacity = 999; + + // Check space in any existing item slots that already contain this item + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + { + ownedCount = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity); + if (ownedCount + count <= slotCapacity) + return TRUE; + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + return FALSE; + count -= slotCapacity - ownedCount; + if (count == 0) + return TRUE; + } + } + + // Check space in empty item slots + if (count > 0) + { + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == 0) + { + if (count <= slotCapacity) + return TRUE; + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + return FALSE; + count -= slotCapacity; + } + } + if (count > 0) + return FALSE; // No more item slots. The bag is full + } + + return TRUE; + } +} +#else +NAKED +bool8 CheckBagHasSpace(u16 itemId, u16 count) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r8, r0\n\ + lsls r1, 16\n\ + lsrs r5, r1, 16\n\ + bl ItemId_GetPocket\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080D6906\n\ + bl InBattlePyramid\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _080D6838\n\ + ldr r0, =0x00004004\n\ + bl FlagGet\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _080D684C\n\ +_080D6838:\n\ + mov r0, r8\n\ + adds r1, r5, 0\n\ + bl CheckPyramidBagHasSpace\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + b _080D6916\n\ + .pool\n\ +_080D684C:\n\ + mov r0, r8\n\ + bl ItemId_GetPocket\n\ + subs r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r7, =0x000003e7\n\ + cmp r2, 0x3\n\ + beq _080D6860\n\ + movs r7, 0x63\n\ +_080D6860:\n\ + movs r6, 0\n\ + ldr r1, =gBagPockets\n\ + lsls r4, r2, 3\n\ + adds r0, r4, r1\n\ + mov r9, r4\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r6, r0\n\ + bcs _080D68BC\n\ + subs r0, r2, 0x2\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r10, r0\n\ +_080D6878:\n\ + adds r0, r4, r1\n\ + ldr r1, [r0]\n\ + lsls r0, r6, 2\n\ + adds r1, r0, r1\n\ + ldrh r0, [r1]\n\ + cmp r0, r8\n\ + bne _080D68AC\n\ + adds r0, r1, 0x2\n\ + str r2, [sp]\n\ + bl GetBagItemQuantity\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + adds r0, r1, r5\n\ + ldr r2, [sp]\n\ + cmp r0, r7\n\ + ble _080D6914\n\ + mov r0, r10\n\ + cmp r0, 0x1\n\ + bls _080D6906\n\ + subs r0, r7, r1\n\ + subs r0, r5, r0\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0\n\ + beq _080D6914\n\ +_080D68AC:\n\ + adds r0, r6, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldr r1, =gBagPockets\n\ + adds r0, r4, r1\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r6, r0\n\ + bcc _080D6878\n\ +_080D68BC:\n\ + cmp r5, 0\n\ + beq _080D6914\n\ + movs r6, 0\n\ + ldr r3, =gBagPockets\n\ + mov r1, r9\n\ + adds r0, r1, r3\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r6, r0\n\ + bcs _080D6902\n\ + adds r4, r3, 0\n\ + subs r0, r2, 0x2\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ +_080D68D6:\n\ + adds r0, r1, r4\n\ + ldr r1, [r0]\n\ + lsls r0, r6, 2\n\ + adds r0, r1\n\ + ldrh r0, [r0]\n\ + cmp r0, 0\n\ + bne _080D68F2\n\ + cmp r5, r7\n\ + bls _080D6914\n\ + cmp r2, 0x1\n\ + bls _080D6906\n\ + subs r0, r5, r7\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ +_080D68F2:\n\ + adds r0, r6, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + mov r1, r9\n\ + adds r0, r1, r3\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r6, r0\n\ + bcc _080D68D6\n\ +_080D6902:\n\ + cmp r5, 0\n\ + beq _080D6914\n\ +_080D6906:\n\ + movs r0, 0\n\ + b _080D6916\n\ + .pool\n\ +_080D6914:\n\ + movs r0, 0x1\n\ +_080D6916:\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1"); +} +#endif // NONMATCHING + +bool8 AddBagItem(u16 itemId, u16 count) +{ + u8 i; + + if (ItemId_GetPocket(itemId) == POCKET_NONE) + return FALSE; + + // check Battle Pyramid Bag + if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE) { - if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + return AddPyramidBagItem(itemId, count); + } + else + { + struct BagPocket *itemPocket; + struct ItemSlot *newItems; + u16 slotCapacity; + u16 ownedCount; + u8 pocket = ItemId_GetPocket(itemId) - 1; + + itemPocket = &gBagPockets[pocket]; + newItems = AllocZeroed(itemPocket->capacity * sizeof(struct ItemSlot)); + memcpy(newItems, itemPocket->itemSlots, itemPocket->capacity * sizeof(struct ItemSlot)); + + if (pocket != BERRIES_POCKET) + slotCapacity = 99; + else + slotCapacity = 999; + + for (i = 0; i < itemPocket->capacity; i++) { - quantity = GetBagItemQuantity(&gBagPockets[pocket].itemSlots[i].quantity); - if (quantity + count <= slotCapacity) - return TRUE; - if (pocket == BAG_TMsHMs || pocket == BAG_BERRIES) + if (newItems[i].itemId == itemId) + { + ownedCount = GetBagItemQuantity(&newItems[i].quantity); + // check if won't exceed max slot capacity + if (ownedCount + count <= slotCapacity) + { + // successfully added to already existing item's count + SetBagItemQuantity(&newItems[i].quantity, ownedCount + count); + + // goto SUCCESS_ADD_ITEM; + // is equivalent but won't match + + memcpy(itemPocket->itemSlots, newItems, itemPocket->capacity * sizeof(struct ItemSlot)); + Free(newItems); + return TRUE; + } + else + { + // try creating another instance of the item if possible + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + { + Free(newItems); + return FALSE; + } + else + { + count -= slotCapacity - ownedCount; + SetBagItemQuantity(&newItems[i].quantity, slotCapacity); + // don't create another instance of the item if it's at max slot capacity and count is equal to 0 + if (count == 0) + { + goto SUCCESS_ADD_ITEM; + } + } + } + } + } + + // we're done if quantity is equal to 0 + if (count > 0) + { + // either no existing item was found or we have to create another instance, because the capacity was exceeded + for (i = 0; i < itemPocket->capacity; i++) + { + if (newItems[i].itemId == ITEM_NONE) + { + newItems[i].itemId = itemId; + if (count > slotCapacity) + { + // try creating a new slot with max capacity if duplicates are possible + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + { + Free(newItems); + return FALSE; + } + count -= slotCapacity; + SetBagItemQuantity(&newItems[i].quantity, slotCapacity); + } + else + { + // created a new slot and added quantity + SetBagItemQuantity(&newItems[i].quantity, count); + goto SUCCESS_ADD_ITEM; + } + } + } + + if (count > 0) + { + Free(newItems); return FALSE; - count -= slotCapacity - quantity; + } + } + + SUCCESS_ADD_ITEM: + memcpy(itemPocket->itemSlots, newItems, itemPocket->capacity * sizeof(struct ItemSlot)); + Free(newItems); + return TRUE; + } +} + +bool8 RemoveBagItem(u16 itemId, u16 count) +{ + u8 i; + u16 totalQuantity = 0; + + if (ItemId_GetPocket(itemId) == POCKET_NONE || itemId == ITEM_NONE) + return FALSE; + + // check Battle Pyramid Bag + if (InBattlePyramid() || FlagGet(FLAG_SPECIAL_FLAG_0x4004) == TRUE) + { + return RemovePyramidBagItem(itemId, count); + } + else + { + u8 pocket; + u8 var; + u16 ownedCount; + struct BagPocket *itemPocket; + + pocket = ItemId_GetPocket(itemId) - 1; + itemPocket = &gBagPockets[pocket]; + + for (i = 0; i < itemPocket->capacity; i++) + { + if (itemPocket->itemSlots[i].itemId == itemId) + totalQuantity += GetBagItemQuantity(&itemPocket->itemSlots[i].quantity); + } + + if (totalQuantity < count) + return FALSE; // We don't have enough of the item + + if (CurrentMapIsSecretBase() == TRUE) + { + VarSet(VAR_0x40EE, VarGet(VAR_0x40EE) | 0x200); + VarSet(VAR_0x40ED, itemId); + } + + var = sub_81ABB2C(pocket); + if (itemPocket->capacity > var + && itemPocket->itemSlots[var].itemId == itemId) + { + ownedCount = GetBagItemQuantity(&itemPocket->itemSlots[var].quantity); + if (ownedCount >= count) + { + SetBagItemQuantity(&itemPocket->itemSlots[var].quantity, ownedCount - count); + count = 0; + } + else + { + count -= ownedCount; + SetBagItemQuantity(&itemPocket->itemSlots[var].quantity, 0); + } + + if (GetBagItemQuantity(&itemPocket->itemSlots[var].quantity) == 0) + itemPocket->itemSlots[var].itemId = ITEM_NONE; + if (count == 0) return TRUE; } + + for (i = 0; i < itemPocket->capacity; i++) + { + if (itemPocket->itemSlots[i].itemId == itemId) + { + ownedCount = GetBagItemQuantity(&itemPocket->itemSlots[i].quantity); + if (ownedCount >= count) + { + SetBagItemQuantity(&itemPocket->itemSlots[i].quantity, ownedCount - count); + count = 0; + } + else + { + count -= ownedCount; + SetBagItemQuantity(&itemPocket->itemSlots[i].quantity, 0); + } + + if (GetBagItemQuantity(&itemPocket->itemSlots[i].quantity) == 0) + itemPocket->itemSlots[i].itemId = ITEM_NONE; + + if (count == 0) + return TRUE; + } + } + return TRUE; } +} - //Check space in empty item slots - if (count > 0) +u8 GetPocketByItemId(u16 itemId) +{ + return ItemId_GetPocket(itemId); +} + +void ClearItemSlots(struct ItemSlot *itemSlots, u8 itemCount) +{ + u16 i; + + for (i = 0; i < itemCount; i++) { - for (i = 0; i < gBagPockets[pocket].capacity; i++) + itemSlots[i].itemId = ITEM_NONE; + SetBagItemQuantity(&itemSlots[i].quantity, 0); + } +} + +static s32 FindFreePCItemSlot(void) +{ + s8 i; + + for (i = 0; i < PC_ITEMS_COUNT; i++) + { + if (gSaveBlock1Ptr->pcItems[i].itemId == ITEM_NONE) + return i; + } + return -1; +} + +u8 CountUsedPCItemSlots(void) +{ + u8 usedSlots = 0; + u8 i; + + for (i = 0; i < PC_ITEMS_COUNT; i++) + { + if (gSaveBlock1Ptr->pcItems[i].itemId != ITEM_NONE) + usedSlots++; + } + return usedSlots; +} + +bool8 CheckPCHasItem(u16 itemId, u16 count) +{ + u8 i; + + for (i = 0; i < PC_ITEMS_COUNT; i++) + { + if (gSaveBlock1Ptr->pcItems[i].itemId == itemId && GetPCItemQuantity(&gSaveBlock1Ptr->pcItems[i].quantity) >= count) + return TRUE; + } + return FALSE; +} + +bool8 AddPCItem(u16 itemId, u16 count) +{ + u8 i; + s8 freeSlot; + u16 ownedCount; + struct ItemSlot *newItems; + + // Copy PC items + newItems = AllocZeroed(sizeof(gSaveBlock1Ptr->pcItems)); + memcpy(newItems, gSaveBlock1Ptr->pcItems, sizeof(gSaveBlock1Ptr->pcItems)); + + // Use any item slots that already contain this item + for (i = 0; i < PC_ITEMS_COUNT; i++) + { + if (newItems[i].itemId == itemId) { - if (gBagPockets[pocket].itemSlots[i].itemId == 0) + ownedCount = GetPCItemQuantity(&newItems[i].quantity); + if (ownedCount + count <= 999) { - if (count <= slotCapacity) - return TRUE; - if (pocket == BAG_TMsHMs || pocket == BAG_BERRIES) - return FALSE; - count -= slotCapacity; + SetPCItemQuantity(&newItems[i].quantity, ownedCount + count); + memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); + Free(newItems); + return TRUE; + } + count += ownedCount - 999; + SetPCItemQuantity(&newItems[i].quantity, 999); + if (count == 0) + { + memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); + Free(newItems); + return TRUE; } } - if (count > 0) - return FALSE; //No more item slots. The bag is full } + // Put any remaining items into a new item slot. + if (count > 0) + { + freeSlot = FindFreePCItemSlot(); + if (freeSlot == -1) + { + Free(newItems); + return FALSE; + } + else + { + newItems[freeSlot].itemId = itemId; + SetPCItemQuantity(&newItems[freeSlot].quantity, count); + } + } + + // Copy items back to the PC + memcpy(gSaveBlock1Ptr->pcItems, newItems, sizeof(gSaveBlock1Ptr->pcItems)); + Free(newItems); return TRUE; -}*/ +} + +void RemovePCItem(u8 index, u16 count) +{ + // UB: should use GetPCItemQuantity and SetPCItemQuantity functions + gSaveBlock1Ptr->pcItems[index].quantity -= count; + if (gSaveBlock1Ptr->pcItems[index].quantity == 0) + { + gSaveBlock1Ptr->pcItems[index].itemId = ITEM_NONE; + CompactPCItems(); + } +} + +void CompactPCItems(void) +{ + u16 i; + u16 j; + + for (i = 0; i < PC_ITEMS_COUNT - 1; i++) + { + for (j = i + 1; j < PC_ITEMS_COUNT; j++) + { + if (gSaveBlock1Ptr->pcItems[i].itemId == 0) + { + struct ItemSlot temp = gSaveBlock1Ptr->pcItems[i]; + gSaveBlock1Ptr->pcItems[i] = gSaveBlock1Ptr->pcItems[j]; + gSaveBlock1Ptr->pcItems[j] = temp; + } + } + } +} + +void SwapRegisteredBike(void) +{ + switch (gSaveBlock1Ptr->registeredItem) + { + case ITEM_MACH_BIKE: + gSaveBlock1Ptr->registeredItem = ITEM_ACRO_BIKE; + break; + case ITEM_ACRO_BIKE: + gSaveBlock1Ptr->registeredItem = ITEM_MACH_BIKE; + break; + } +} + +u16 BagGetItemIdByPocketPosition(u8 pocketId, u16 pocketPos) +{ + return gBagPockets[pocketId - 1].itemSlots[pocketPos].itemId; +} + +u16 BagGetQuantityByPocketPosition(u8 pocketId, u16 pocketPos) +{ + return GetBagItemQuantity(&gBagPockets[pocketId - 1].itemSlots[pocketPos].quantity); +} + +static void SwapItemSlots(struct ItemSlot *a, struct ItemSlot *b) +{ + struct ItemSlot temp = *a; + *a = *b; + *b = temp; +} + +void CompactItemsInBagPocket(struct BagPocket *bagPocket) +{ + u16 i, j; + + for (i = 0; i < bagPocket->capacity - 1; i++) + { + for (j = i + 1; j < bagPocket->capacity; j++) + { + if (GetBagItemQuantity(&bagPocket->itemSlots[i].quantity) == 0) + SwapItemSlots(&bagPocket->itemSlots[i], &bagPocket->itemSlots[j]); + } + } +} + +void SortBerriesOrTMHMs(struct BagPocket *bagPocket) +{ + u16 i, j; + + for (i = 0; i < bagPocket->capacity - 1; i++) + { + for (j = i + 1; j < bagPocket->capacity; j++) + { + if (GetBagItemQuantity(&bagPocket->itemSlots[i].quantity) != 0) + { + if (GetBagItemQuantity(&bagPocket->itemSlots[j].quantity) == 0) + continue; + if (bagPocket->itemSlots[i].itemId <= bagPocket->itemSlots[j].itemId) + continue; + } + SwapItemSlots(&bagPocket->itemSlots[i], &bagPocket->itemSlots[j]); + } + } +} + +void MoveItemSlotInList(struct ItemSlot* itemSlots_, u32 from, u32 to_) +{ + // dumb assignments needed to match + struct ItemSlot *itemSlots = itemSlots_; + u32 to = to_; + + if (from != to) + { + s16 i, count; + struct ItemSlot firstSlot = itemSlots[from]; + + if (to > from) + { + to--; + for (i = from, count = to; i < count; i++) + itemSlots[i] = itemSlots[i + 1]; + } + else + { + for (i = from, count = to; i > count; i--) + itemSlots[i] = itemSlots[i - 1]; + } + itemSlots[to] = firstSlot; + } +} + +void ClearBag(void) +{ + u16 i; + + for (i = 0; i < POCKETS_COUNT; i++) + { + ClearItemSlots(gBagPockets[i].itemSlots, gBagPockets[i].capacity); + } +} + +u16 CountTotalItemQuantityInBag(u16 itemId) +{ + u16 i; + u16 ownedCount = 0; + struct BagPocket *bagPocket = &gBagPockets[ItemId_GetPocket(itemId) - 1]; + + for (i = 0; i < bagPocket->capacity; i++) + { + if (bagPocket->itemSlots[i].itemId == itemId) + ownedCount += GetBagItemQuantity(&bagPocket->itemSlots[i].quantity); + } + + return ownedCount; +} + +static bool8 CheckPyramidBagHasItem(u16 itemId, u16 count) +{ + u8 i; + u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl]; + u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl]; + + for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++) + { + if (items[i] == itemId) + { + if (quantities[i] >= count) + return TRUE; + + count -= quantities[i]; + if (count == 0) + return TRUE; + } + } + + return FALSE; +} + +static bool8 CheckPyramidBagHasSpace(u16 itemId, u16 count) +{ + u8 i; + u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl]; + u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl]; + + for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++) + { + if (items[i] == itemId || items[i] == ITEM_NONE) + { + if (quantities[i] + count <= 99) + return TRUE; + + count = (quantities[i] + count) - 99; + if (count == 0) + return TRUE; + } + } + + return FALSE; +} + +bool8 AddPyramidBagItem(u16 itemId, u16 count) +{ + u16 i; + + u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl]; + u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl]; + + u16 *newItems = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + u8 *newQuantities = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + + memcpy(newItems, items, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + memcpy(newQuantities, quantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + + for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++) + { + if (newItems[i] == itemId && newQuantities[i] < 99) + { + newQuantities[i] += count; + if (newQuantities[i] > 99) + { + count = newQuantities[i] - 99; + newQuantities[i] = 99; + } + else + { + count = 0; + } + + if (count == 0) + break; + } + } + + if (count > 0) + { + for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++) + { + if (newItems[i] == ITEM_NONE) + { + newItems[i] = itemId; + newQuantities[i] = count; + if (newQuantities[i] > 99) + { + count = newQuantities[i] - 99; + newQuantities[i] = 99; + } + else + { + count = 0; + } + + if (count == 0) + break; + } + } + } + + if (count == 0) + { + memcpy(items, newItems, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + memcpy(quantities, newQuantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + Free(newItems); + Free(newQuantities); + return TRUE; + } + else + { + Free(newItems); + Free(newQuantities); + return FALSE; + } +} + +bool8 RemovePyramidBagItem(u16 itemId, u16 count) +{ + u16 i; + + u16 *items = gSaveBlock2Ptr->pyramidBag.itemId[gSaveBlock2Ptr->frontierChosenLvl]; + u8 *quantities = gSaveBlock2Ptr->pyramidBag.quantity[gSaveBlock2Ptr->frontierChosenLvl]; + + i = gUnknown_0203CF30[3] + gUnknown_0203CF30[4]; + if (items[i] == itemId && quantities[i] >= count) + { + quantities[i] -= count; + if (quantities[i] == 0) + items[i] = ITEM_NONE; + return TRUE; + } + else + { + u16 *newItems = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + u8 *newQuantities = Alloc(PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + + memcpy(newItems, items, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + memcpy(newQuantities, quantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + + for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++) + { + if (newItems[i] == itemId) + { + if (newQuantities[i] >= count) + { + newQuantities[i] -= count; + count = 0; + if (newQuantities[i] == 0) + newItems[i] = ITEM_NONE; + } + else + { + count -= newQuantities[i]; + newQuantities[i] = 0; + newItems[i] = ITEM_NONE; + } + + if (count == 0) + break; + } + } + + if (count == 0) + { + memcpy(items, newItems, PYRAMID_BAG_ITEMS_COUNT * sizeof(u16)); + memcpy(quantities, newQuantities, PYRAMID_BAG_ITEMS_COUNT * sizeof(u8)); + Free(newItems); + Free(newQuantities); + return TRUE; + } + else + { + Free(newItems); + Free(newQuantities); + return FALSE; + } + } +} + +static u16 SanitizeItemId(u16 itemId) +{ + if (itemId >= ITEM_LAST_ID + 1) + return ITEM_NONE; + else + return itemId; +} + +const u8 *ItemId_GetName(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].name; +} + +u16 ItemId_GetId(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].itemId; +} + +u16 ItemId_GetPrice(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].price; +} + +u8 ItemId_GetHoldEffect(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].holdEffect; +} + +u8 ItemId_GetHoldEffectParam(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].holdEffectParam; +} + +const u8 *ItemId_GetDescription(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].description; +} + +u8 ItemId_GetImportance(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].importance; +} + +// unused +u8 ItemId_GetUnknownValue(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].unk19; +} + +u8 ItemId_GetPocket(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].pocket; +} + +u8 ItemId_GetType(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].type; +} + +ItemUseFunc ItemId_GetFieldFunc(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].fieldUseFunc; +} + +u8 ItemId_GetBattleUsage(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].battleUsage; +} + +ItemUseFunc ItemId_GetBattleFunc(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].battleUseFunc; +} + +u8 ItemId_GetSecondaryId(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].secondaryId; +} diff --git a/src/item_icon.c b/src/item_icon.c index 4aaad9c31..d6fedf892 100644 --- a/src/item_icon.c +++ b/src/item_icon.c @@ -4,13 +4,13 @@ #include "sprite.h" #include "decompress.h" #include "constants/items.h" +#include "data/item_icon_table.h" // EWRAM vars EWRAM_DATA void *gItemIconDecompressionBuffer = NULL; EWRAM_DATA void *gItemIcon4x4Buffer = NULL; // const rom data -extern const void *const gItemIconTable[][2]; // todo: move to C file static const struct OamData sOamData_ItemIcon = { diff --git a/src/item_menu.c b/src/item_menu.c new file mode 100755 index 000000000..4742d07a1 --- /dev/null +++ b/src/item_menu.c @@ -0,0 +1,2245 @@ +#include "global.h" +#include "item_menu.h" +#include "battle.h" +#include "battle_controllers.h" +#include "battle_frontier_2.h" +#include "berry_tag_screen.h" +#include "bg.h" +#include "constants/items.h" +#include "constants/songs.h" +#include "decompress.h" +#include "event_data.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_specials.h" +#include "graphics.h" +#include "gpu_regs.h" +#include "international_string_util.h" +#include "item.h" +#include "item_menu_icons.h" +#include "item_use.h" +#include "lilycove_lady.h" +#include "list_menu.h" +#include "link.h" +#include "mail.h" +#include "main.h" +#include "malloc.h" +#include "map_name_popup.h" +#include "menu.h" +#include "menu_indicators.h" +#include "money.h" +#include "overworld.h" +#include "palette.h" +#include "party_menu.h" +#include "player_pc.h" +#include "pokemon.h" +#include "pokemon_summary_screen.h" +#include "rom_818CFC8.h" +#include "scanline_effect.h" +#include "script.h" +#include "shop.h" +#include "sound.h" +#include "sprite.h" +#include "string.h" +#include "strings.h" +#include "string_util.h" +#include "task.h" +#include "text_window.h" +#include "menu_helpers.h" +#include "window.h" + +void GoToBagMenu(u8 bagMenuType, u8 pocketId, void ( *postExitMenuMainCallback2)()); +void CB2_Bag(void); +bool8 setup_bag_menu(void); +void bag_menu_init_bgs(void); +bool8 load_bag_menu_graphics(void); +void setup_bag_menu_textboxes(void); +void allocate_bag_item_list_buffers(void); +void load_bag_item_list_buffers(u8); +void bag_menu_print_pocket_names(u8*, u8*); +void bag_menu_copy_pocket_name_to_window(u32); +void bag_menu_draw_pocket_indicator_square(u8, u8); +void bag_menu_add_pocket_scroll_arrow_indicators_maybe(void); +void bag_menu_add_list_scroll_arrow_indicators_maybe(void); +void bag_menu_prepare_tmhm_move_window(void); +bool8 IsWallysBag(void); +void Task_WallyTutorialBagMenu(u8); +void Task_BagMenu(u8); +void get_name(s8*, u16); +u16 ItemIdToBattleMoveId(u16); +u16 BagGetItemIdByPocketPosition(u8, u16); +void AddBagItemIconSprite(u16, u8); +void bag_menu_print_description_box_text(int); +void bag_menu_print_cursor(u8, u8); +void bag_menu_print(u8, u8, const u8*, u8, u8, u8, u8, u8, u8); +bool8 ItemId_GetImportance(u16); +u16 BagGetQuantityByPocketPosition(u8, u16); +void sub_81AB89C(void); +void task_close_bag_menu_2(u8); +u8 AddItemMessageWindow(u8); +void bag_menu_RemoveBagItem_message_window(u8); +void set_callback3_to_bag(u8); +void sub_81ABC54(u8, s16); +u8 bag_menu_add_window(u8); +u8 GetSwitchBagPocketDirection(void); +void SwitchBagPocket(u8, s16, u16); +bool8 sub_81AC2C0(void); +void bag_menu_swap_items(u8); +void sub_81AC10C(u8); +void sub_81AC3C0(u8); +void sub_81AC498(u8); +void sub_81AC590(u8); +void PrintTMHMMoveData(u16); +void sub_81ACAF8(u8); +void sub_81ACB54(u8, u8, u8); +void Task_HandleInBattleItemMenuInput(u8); +void Task_HandleOutOfBattleItemMenuInput(u8); +bool8 sub_81ACDFC(s8); +void bag_menu_remove_window(u8); +void bag_menu_print_there_is_no_pokemon(u8); +void Task_ChooseHowManyToToss(u8); +void BagMenuConfirmToss(u8); +void bag_menu_yes_no(u8, u8, const struct YesNoFuncTable*); +void Task_ActuallyToss(u8); +void ItemMenu_Cancel(u8); +void sub_81AD350(u8); +void bag_menu_print_cant_be_held_msg(u8); +void bag_menu_AddMoney_window(void); +void sub_81AD680(u8); +void sub_81AD730(u8); +void sub_81AD6E4(u8); +void bag_menu_remove_money_window(void); +void bag_menu_RemoveBagItem_message_window(u8); +void sub_81AD794(u8); +void sub_81AD8C8(u8); +void sub_81AD9C0(u8); +void sub_81ADB14(u8); +void sub_81ADA7C(u8); +void sub_81ADC0C(u8); +void bag_menu_leave_maybe_3(void); +void bag_menu_leave_maybe_2(void); +void bag_menu_leave_maybe(void); +void sub_81ABA6C(void); +void sub_81ABAC4(void); +void sub_81ABAE0(void); +u8 sub_81AB1F0(u8); +void sub_81AC23C(u8); +void bag_menu_change_item_callback(s32 a, bool8 b, struct ListMenu*); +void sub_81AB520(u8 rboxId, int item_index_in_pocket, u8 a); +void ItemMenu_UseOutOfBattle(u8 taskId); +void ItemMenu_Toss(u8 taskId); +void ItemMenu_Register(u8 taskId); +void ItemMenu_Give(u8 taskId); +void ItemMenu_Cancel(u8 taskId); +void ItemMenu_UseInBattle(u8 taskId); +void ItemMenu_CheckTag(u8 taskId); +void unknown_ItemMenu_Confirm(u8 taskId); +void unknown_ItemMenu_Show(u8 taskId); +void unknown_ItemMenu_Give2(u8 taskId); +void unknown_ItemMenu_Confirm2(u8 taskId); +void unknown_item_menu_type(u8 taskId); +void item_menu_type_2(u8 taskId); +void display_sell_item_ask_str(u8 taskId); +void unknown_ItemMenu_Confirm(u8 taskId); +void display_deposit_item_ask_str(u8 taskId); +void item_menu_type_b(u8 taskId); +void BagMenuActuallyToss(u8 taskId); +void BagMenuCancelToss(u8 taskId); +void sub_81AD84C(u8 taskId); +void sub_81AD6FC(u8 taskId); + +// .rodata + +const struct BgTemplate gUnknown_08613F90[3] = { + {0, 0, 31, 0, 0, 1, 0}, + {1, 0, 30, 0, 0, 0, 0}, + {2, 3, 29, 0, 0, 2, 0} +}; + +const struct ListMenuTemplate gUnknown_08613F9C = { + NULL, bag_menu_change_item_callback, sub_81AB520, 0, 0, 0, 0, 8, 0, 1, 1, 0, 3, 0, 0, 0, 7, 0 +}; + +const struct MenuAction gUnknown_08613FB4[] = { + {gMenuText_Use, ItemMenu_UseOutOfBattle}, + {gMenuText_Toss, ItemMenu_Toss}, + {gMenuText_Register, ItemMenu_Register}, + {gMenuText_Give, ItemMenu_Give}, + {gText_Cancel2, ItemMenu_Cancel}, + {gMenuText_Use, ItemMenu_UseInBattle}, + {gMenuText_Check, ItemMenu_UseOutOfBattle}, + {gMenuText_Walk, ItemMenu_UseOutOfBattle}, + {gMenuText_Deselect, ItemMenu_Register}, + {gMenuText_CheckTag, ItemMenu_CheckTag}, + {gMenuText_Confirm, unknown_ItemMenu_Confirm}, + {gMenuText_Show, unknown_ItemMenu_Show}, + {gMenuText_Give2, unknown_ItemMenu_Give2}, + {gMenuText_Confirm, unknown_ItemMenu_Confirm2}, + {gText_EmptyString2, NULL} +}; + +const u8 gUnknown_0861402C[] = {0, 3, 1, 4}; +const u8 gUnknown_08614030[] = {0, 2, 14, 4}; +const u8 gUnknown_08614034[] = {3, 14, 1, 4}; +const u8 gUnknown_08614038[] = {0, 3, 14, 4}; +const u8 gUnknown_0861403C[] = {9, 14, 0, 3, 1, 4}; +const u8 gUnknown_08614042[] = {5, 4}; +const u8 gUnknown_08614044[] = {3, 4}; +const u8 gUnknown_08614046 = 4; +const u8 gUnknown_08614047[] = {10, 9, 14, 4}; +const u8 gUnknown_0861404B[] = {11, 4}; +const u8 gUnknown_0861404D[] = {12, 4}; +const u8 gUnknown_0861404F[] = {13, 4}; + +const TaskFunc gUnknown_08614054[] = { + unknown_item_menu_type, + unknown_item_menu_type, + item_menu_type_2, + display_sell_item_ask_str, + unknown_ItemMenu_Confirm, + unknown_item_menu_type, + display_deposit_item_ask_str, + unknown_item_menu_type, + unknown_item_menu_type, + unknown_item_menu_type, + NULL, + item_menu_type_b +}; + +const struct YesNoFuncTable gUnknown_08614084 = {BagMenuActuallyToss, BagMenuCancelToss}; + +const struct YesNoFuncTable gUnknown_0861408C = {sub_81AD84C, sub_81AD6FC}; + +const struct ArrowStruct gUnknown_08614094 = {0, 0x1C, 16, 1, 100, 16, -1, -1, 0x6F, 0x6F, 0}; + +const u8 gUnknown_086140A4[] = INCBIN_U8("graphics/interface/select_button.4bpp"); + +const u8 gUnknown_08614164[][3] = { + {0, 1, 3}, + {0, 1, 4}, + {0, 3, 6}, + {2, 1, 3}, + {0, 14, 10} +}; + +const struct WindowTemplate gUnknown_08614174[] = { + {0, 14, 2, 15, 16, 1, 0x27}, + {0, 0, 13, 14, 6, 1, 0x117}, + {0, 4, 1, 8, 2, 1, 0x1A1}, + {0, 1, 13, 5, 6, 12, 0x16B}, + {0, 7, 13, 4, 6, 12, 0x189}, + {1, 2, 15, 27, 4, 15, 0x1B1}, + {0xFF, 0, 0, 0, 0, 0, 0} +}; + +const struct WindowTemplate gUnknown_086141AC[] = { + {1, 22, 17, 7, 2, 15, 0x21D}, + {1, 22, 15, 7, 4, 15, 0x21D}, + {1, 15, 15, 14, 4, 15, 0x21D}, + {1, 15, 13, 14, 6, 15, 0x21D}, + {1, 2, 15, 27, 4, 15, 0x1B1}, + {1, 24, 15, 5, 4, 15, 0x21D}, + {1, 21, 9, 5, 4, 15, 0x21D}, + {1, 24, 17, 5, 2, 15, 0x21D}, + {1, 18, 11, 10, 2, 15, 0x245}, + {1, 1, 1, 10, 2, 15, 0x231} +}; + +// .text + +struct ListBuffer1 { + struct ListMenuItem subBuffers[65]; +}; + +struct ListBuffer2 { + s8 name[65][24]; +}; + +struct TempWallyStruct { + struct ItemSlot bagPocket_Items[30]; + struct ItemSlot bagPocket_PokeBalls[16]; + u16 cursorPosition[5]; + u16 scrollPosition[5]; + u8 filler[0x2]; + u16 pocket; +}; + +EWRAM_DATA struct UnkBagStruct *gUnknown_0203CE54 = 0; +EWRAM_DATA struct BagStruct gUnknown_0203CE58 = {0, 0, 0, {0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; +EWRAM_DATA struct ListBuffer1 *gUnknown_0203CE74 = 0; +EWRAM_DATA struct ListBuffer2 *gUnknown_0203CE78 = 0; +EWRAM_DATA u16 gSpecialVar_ItemId = 0; +EWRAM_DATA struct TempWallyStruct *gUnknown_0203CE80 = 0; + +extern u8 *gPocketNamesStringsTable[]; +extern u8 gUnknown_08D9A88C[]; +extern struct ListMenuTemplate gUnknown_08613F9C; +extern const u8 gMoveNames[][0xD]; +extern u8* gReturnToXStringsTable[]; +extern u32 gUnknown_0203CE5E[]; +extern const u8 EventScript_2736B3[]; +extern const u16 gUnknown_0860F074[]; + +void ResetBagScrollPositions(void) +{ + gUnknown_0203CE58.pocket = 0; + memset(gUnknown_0203CE58.cursorPosition, 0, 10); + memset(gUnknown_0203CE58.scrollPosition, 0, 10); +} + +void CB2_BagMenuFromStartMenu(void) +{ + GoToBagMenu(0, 5, CB2_ReturnToFieldWithOpenMenu); +} + +void sub_81AABB0(void) +{ + if (!InBattlePyramid()) + GoToBagMenu(1, 5, SetCB2ToReshowScreenAfterMenu2); + else + sub_81C4F98(1, SetCB2ToReshowScreenAfterMenu2); +} + +void CB2_ChooseBerry(void) +{ + GoToBagMenu(4, 3, sub_80861B0); +} + +void sub_81AABF0(void(*callback)(void)) +{ + GoToBagMenu(5, 3, callback); +} + +void CB2_GoToSellMenu(void) +{ + GoToBagMenu(3, 5, CB2_ExitSellMenu); +} + +void sub_81AAC14(void) +{ + GoToBagMenu(6, 5, sub_816B31C); +} + +void sub_81AAC28(void) +{ + GoToBagMenu(9, 5, bag_menu_leave_maybe_3); + gSpecialVar_0x8005 = 0; + gSpecialVar_Result = 0; +} + +void sub_81AAC50(void) +{ + GoToBagMenu(7, 5, bag_menu_leave_maybe_2); + gSpecialVar_Result = 0; +} + +void sub_81AAC70(void) +{ + GoToBagMenu(8, 5, bag_menu_leave_maybe); + gSpecialVar_Result = 0; +} + +void GoToBagMenu(u8 bagMenuType, u8 pocketId, void ( *postExitMenuMainCallback2)()) +{ + u8 temp; + gUnknown_0203CE54 = AllocZeroed(sizeof(struct UnkBagStruct)); + if (gUnknown_0203CE54 == 0) + { + SetMainCallback2(postExitMenuMainCallback2); + } + else + { + if (bagMenuType != 12) + gUnknown_0203CE58.location = bagMenuType; + if (postExitMenuMainCallback2) + gUnknown_0203CE58.bagCallback = postExitMenuMainCallback2; + if (pocketId <= 4) + gUnknown_0203CE58.pocket = pocketId; + temp = gUnknown_0203CE58.location - 4; + if (temp <= 1) + gUnknown_0203CE54->unk81B = 1; + gUnknown_0203CE54->unk0 = 0; + gUnknown_0203CE54->unk81A = 0xFF; + gUnknown_0203CE54->unk81E = -1; + gUnknown_0203CE54->unk81F = -1; + memset(gUnknown_0203CE54->unk804, 0xFF, sizeof(gUnknown_0203CE54->unk804)); + memset(gUnknown_0203CE54->unk810, 0xFF, 10); + SetMainCallback2(CB2_Bag); + } +} + +void c2_bag_3(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + do_scheduled_bg_tilemap_copies_to_vram(); + UpdatePaletteFade(); +} + +void vblank_cb_bag_menu(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_Bag(void) +{ + while(sub_81221EC() != TRUE && setup_bag_menu() != TRUE && sub_81221AC() != TRUE) {}; +} + +bool8 setup_bag_menu(void) +{ + u32 index; + u8 taskId; + + switch (gMain.state) + { + case 0: + SetVBlankHBlankCallbacksToNull(); + clear_scheduled_bg_copies_to_vram(); + gMain.state++; + break; + case 1: + ScanlineEffect_Stop(); + gMain.state++; + break; + case 2: + FreeAllSpritePalettes(); + gMain.state++; + break; + case 3: + ResetPaletteFade(); + gPaletteFade.bufferTransferDisabled = TRUE; + gMain.state++; + break; + case 4: + ResetSpriteData(); + gMain.state++; + break; + case 5: + gMain.state++; + break; + case 6: + if (sub_81221AC() == FALSE) + ResetTasks(); + gMain.state++; + break; + case 7: + bag_menu_init_bgs(); + gUnknown_0203CE54->unk834 = 0; + gMain.state++; + break; + case 8: + if (!load_bag_menu_graphics()) + break; + gMain.state++; + break; + case 9: + setup_bag_menu_textboxes(); + gMain.state++; + break; + case 10: + sub_81ABA6C(); + sub_81ABAC4(); + sub_81ABAE0(); + gMain.state++; + break; + case 11: + allocate_bag_item_list_buffers(); + gMain.state++; + break; + case 12: + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + gMain.state++; + break; + case 13: + bag_menu_print_pocket_names(gPocketNamesStringsTable[gUnknown_0203CE58.pocket], 0); + bag_menu_copy_pocket_name_to_window(0); + bag_menu_draw_pocket_indicator_square(gUnknown_0203CE58.pocket, 1); + gMain.state++; + break; + case 14: + taskId = sub_81AB1F0(gUnknown_0203CE58.location); + gTasks[taskId].data[0] = ListMenuInit(&gMultiuseListMenuTemplate, gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[8] = 0; + gMain.state++; + break; + case 15: + AddBagVisualSprite(gUnknown_0203CE58.pocket); + gMain.state++; + break; + case 16: + sub_80D4FAC(); + gMain.state++; + break; + case 17: + bag_menu_add_pocket_scroll_arrow_indicators_maybe(); + bag_menu_add_list_scroll_arrow_indicators_maybe(); + gMain.state++; + break; + case 18: + bag_menu_prepare_tmhm_move_window(); + gMain.state++; + break; + case 19: + BlendPalettes(-1, 16, 0); + gMain.state++; + break; + case 20: + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + gPaletteFade.bufferTransferDisabled = FALSE; + gMain.state++; + break; + default: + SetVBlankCallback(vblank_cb_bag_menu); + SetMainCallback2(c2_bag_3); + return TRUE; + } + return FALSE; +} + +void bag_menu_init_bgs(void) +{ + ResetVramOamAndBgCntRegs(); + memset(gUnknown_0203CE54->unk4, 0, 0x800); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, gUnknown_08613F90, 3); + SetBgTilemapBuffer(2, gUnknown_0203CE54->unk4); + ResetAllBgsCoordinates(); + schedule_bg_copy_tilemap_to_vram(2); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + ShowBg(0); + ShowBg(1); + ShowBg(2); + SetGpuReg(REG_OFFSET_BLDCNT, 0); +} + +bool8 load_bag_menu_graphics(void) +{ + switch (gUnknown_0203CE54->unk834) + { + case 0: + reset_temp_tile_data_buffers(); + decompress_and_copy_tile_data_to_vram(2, gBagScreen_Gfx, 0, 0, 0); + gUnknown_0203CE54->unk834++; + break; + case 1: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + LZDecompressWram(gUnknown_08D9A88C, gUnknown_0203CE54->unk4); + gUnknown_0203CE54->unk834++; + } + break; + case 2: + if (!IsWallysBag() && gSaveBlock2Ptr->playerGender != MALE) + LoadCompressedPalette(gBagScreenFemale_Pal, 0, 0x40); + else + LoadCompressedPalette(gBagScreenMale_Pal, 0, 0x40); + gUnknown_0203CE54->unk834++; + break; + case 3: + if (IsWallysBag() == TRUE || gSaveBlock2Ptr->playerGender == MALE) + LoadCompressedObjectPic(&gUnknown_0857FB34); + else + LoadCompressedObjectPic(&gUnknown_0857FB3C); + gUnknown_0203CE54->unk834++; + break; + case 4: + LoadCompressedObjectPalette(&gUnknown_0857FB44); + gUnknown_0203CE54->unk834++; + break; + default: + LoadListMenuArrowsGfx(); + gUnknown_0203CE54->unk834 = 0; + return TRUE; + } + return FALSE; +} + +u8 sub_81AB1F0(u8 a) +{ + u8 taskId; + if (a == 10) + taskId = CreateTask(Task_WallyTutorialBagMenu, 0); + else + taskId = CreateTask(Task_BagMenu, 0); + return taskId; +} + +void allocate_bag_item_list_buffers(void) +{ + gUnknown_0203CE74 = Alloc(sizeof(struct ListBuffer1)); + gUnknown_0203CE78 = Alloc(sizeof(struct ListBuffer2)); +} + +void load_bag_item_list_buffers(u8 pocketId) +{ + u16 i; + struct BagPocket *pocket = &gBagPockets[pocketId]; + struct ListMenuItem *subBuffer; + + if (!gUnknown_0203CE54->unk81B_2) + { + for (i = 0; i < gUnknown_0203CE54->unk829[pocketId] - 1; i++) + { + get_name(gUnknown_0203CE78->name[i], pocket->itemSlots[i].itemId); + subBuffer = gUnknown_0203CE74->subBuffers; + subBuffer[i].name = gUnknown_0203CE78->name[i]; + subBuffer[i].id = i; + } + StringCopy(gUnknown_0203CE78->name[i], gText_CloseBag); + subBuffer = gUnknown_0203CE74->subBuffers; + subBuffer[i].name = gUnknown_0203CE78->name[i]; + subBuffer[i].id = -2; + } + else + { + for (i = 0; i < gUnknown_0203CE54->unk829[pocketId]; i++) + { + get_name(gUnknown_0203CE78->name[i], pocket->itemSlots[i].itemId); + subBuffer = gUnknown_0203CE74->subBuffers; + subBuffer[i].name = gUnknown_0203CE78->name[i]; + subBuffer[i].id = i; + } + } + gMultiuseListMenuTemplate = gUnknown_08613F9C; + gMultiuseListMenuTemplate.totalItems = gUnknown_0203CE54->unk829[pocketId]; + gMultiuseListMenuTemplate.items = gUnknown_0203CE74->subBuffers; + gMultiuseListMenuTemplate.maxShowed = gUnknown_0203CE54->unk82E[pocketId]; +} + +void get_name(s8 *dest, u16 itemId) +{ + switch (gUnknown_0203CE58.pocket) + { + case 2: + StringCopy(gStringVar2, gMoveNames[ItemIdToBattleMoveId(itemId)]); + if (itemId >= ITEM_HM01) + { + ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_HM01 + 1, 2, 1); + StringExpandPlaceholders(dest, gText_ClearTo11Var1Clear5Var2); + } + else + { + ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_TM01 + 1, 2, 2); + StringExpandPlaceholders(dest, gText_UnkF908Var1Clear7Var2); + } + break; + case 3: + ConvertIntToDecimalStringN(gStringVar1, itemId - ITEM_CHERI_BERRY + 1, 2, 2); + CopyItemName(itemId, gStringVar2); + StringExpandPlaceholders(dest, gText_UnkF908Var1Clear7Var2); + break; + default: + CopyItemName(itemId, dest); + break; + } +} + +void bag_menu_change_item_callback(s32 a, bool8 b, struct ListMenu *unused) +{ + if (b != 1) + { + PlaySE(SE_SELECT); + ShakeBagVisual(); + } + if (gUnknown_0203CE54->unk81A == 0xFF) + { + RemoveBagItemIconSprite(1 ^ gUnknown_0203CE54->unk81B_1); + if (a != -2) + AddBagItemIconSprite(BagGetItemIdByPocketPosition(gUnknown_0203CE58.pocket + 1, a), gUnknown_0203CE54->unk81B_1); + else + AddBagItemIconSprite(-1, gUnknown_0203CE54->unk81B_1); + gUnknown_0203CE54->unk81B_1 ^= 1; + if (!gUnknown_0203CE54->unk81B_3) + bag_menu_print_description_box_text(a); + } +} + +void sub_81AB520(u8 rboxId, int item_index_in_pocket, u8 a) +{ + u16 itemId; + u16 itemQuantity; + bool8 unique; + int offset; + if (item_index_in_pocket != -2) + { + if (gUnknown_0203CE54->unk81A != 0xFF) + { + if (gUnknown_0203CE54->unk81A == (u8)item_index_in_pocket) + bag_menu_print_cursor(a, 2); + else + bag_menu_print_cursor(a, -1); + } + itemId = BagGetItemIdByPocketPosition(gUnknown_0203CE58.pocket + 1, item_index_in_pocket); + itemQuantity = BagGetQuantityByPocketPosition(gUnknown_0203CE58.pocket + 1, item_index_in_pocket); + if ((u16)(itemId - ITEM_HM01) <= 7) + BlitBitmapToWindow(rboxId, gBagMenuHMIcon_Gfx, 8, a - 1, 16, 16); + if (gUnknown_0203CE58.pocket == 3) + { + ConvertIntToDecimalStringN(gStringVar1, itemQuantity, 1, 3); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + offset = GetStringRightAlignXOffset(7, gStringVar4, 0x77); + bag_menu_print(rboxId, 7, gStringVar4, offset, a, 0, 0, -1, 0); + } + else if (gUnknown_0203CE58.pocket != 4 && (unique = ItemId_GetImportance(itemId)) == FALSE) + { + ConvertIntToDecimalStringN(gStringVar1, itemQuantity, 1, 2); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + offset = GetStringRightAlignXOffset(7, gStringVar4, 0x77); + bag_menu_print(rboxId, 7, gStringVar4, offset, a, unique, unique, -1, unique); + } + else + { + if (gSaveBlock1Ptr->registeredItem && gSaveBlock1Ptr->registeredItem == itemId) + BlitBitmapToWindow(rboxId, gUnknown_086140A4, 0x60, a - 1, 0x18, 16); + } + } +} + +void bag_menu_print_description_box_text(int a) +{ + u8* str; + if (a != -2) + { + str = (u8*)ItemId_GetDescription(BagGetItemIdByPocketPosition(gUnknown_0203CE58.pocket + 1, a)); + } + else + { + StringCopy(gStringVar1, gReturnToXStringsTable[gUnknown_0203CE58.location]); + StringExpandPlaceholders(gStringVar4, gText_ReturnToVar1); + str = gStringVar4; + } + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, str, 3, 1, 0, 0, 0, 0); +} + +void bag_menu_print_cursor_(u8 a, u8 b) +{ + bag_menu_print_cursor(ListMenuGetYCoordForPrintingArrowCursor(a), b); +} + +void bag_menu_print_cursor(u8 a, u8 b) +{ + if (b == 0xFF) + FillWindowPixelRect(0, 0, 0, a, GetMenuCursorDimensionByFont(1, 0), GetMenuCursorDimensionByFont(1, 1)); + else + bag_menu_print(0, 1, gText_SelectorArrow2, 0, a, 0, 0, 0, b); + +} + +void bag_menu_add_pocket_scroll_arrow_indicators_maybe(void) +{ + if (gUnknown_0203CE54->unk81E == 0xFF) + gUnknown_0203CE54->unk81E = AddScrollIndicatorArrowPairParametrized(2, 0xAC, 12, 0x94, gUnknown_0203CE54->unk829[gUnknown_0203CE58.pocket] - gUnknown_0203CE54->unk82E[gUnknown_0203CE58.pocket], 0x6E, 0x6E, &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]); +} + +void sub_81AB824(void) +{ + if (gUnknown_0203CE54->unk81E != 0xFF) + { + RemoveScrollIndicatorArrowPair(gUnknown_0203CE54->unk81E); + gUnknown_0203CE54->unk81E = 0xFF; + } + sub_81AB89C(); +} + +void bag_menu_add_list_scroll_arrow_indicators_maybe(void) +{ + if (gUnknown_0203CE54->unk81B != 1 && gUnknown_0203CE54->unk81F == 0xFF) + gUnknown_0203CE54->unk81F = AddScrollIndicatorArrowPair(&gUnknown_08614094, gUnknown_0203CE58.unk6); +} + +void sub_81AB89C(void) +{ + if (gUnknown_0203CE54->unk81F != 0xFF) + { + RemoveScrollIndicatorArrowPair(gUnknown_0203CE54->unk81F); + gUnknown_0203CE54->unk81F = 0xFF; + } +} + +void free_bag_item_list_buffers(void) +{ + Free(gUnknown_0203CE78); + Free(gUnknown_0203CE74); + FreeAllWindowBuffers(); + Free(gUnknown_0203CE54); +} + +void unknown_ItemMenu_Confirm(u8 taskId) +{ + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = task_close_bag_menu_2; +} + +void task_close_bag_menu_2(u8 taskId) +{ + s16* data = gTasks[taskId].data; + if (!gPaletteFade.active) + { + DestroyListMenuTask(data[0], &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + if (gUnknown_0203CE54->unk0 != 0) + SetMainCallback2(gUnknown_0203CE54->unk0); + else + SetMainCallback2(gUnknown_0203CE58.bagCallback); + sub_81AB824(); + ResetSpriteData(); + FreeAllSpritePalettes(); + free_bag_item_list_buffers(); + DestroyTask(taskId); + } +} + +void sub_81AB9A8(u8 pocketId) +{ + u16 i; + struct BagPocket *pocket = &gBagPockets[pocketId]; + switch (pocketId) + { + case 2: + case 3: + SortBerriesOrTMHMs(pocket); + break; + default: + CompactItemsInBagPocket(pocket); + break; + } + gUnknown_0203CE54->unk829[pocketId] = 0; + for (i = 0; i < pocket->capacity && pocket->itemSlots[i].itemId; i++) + gUnknown_0203CE54->unk829[pocketId]++; + if (!gUnknown_0203CE54->unk81B_2) + gUnknown_0203CE54->unk829[pocketId]++; + if (gUnknown_0203CE54->unk829[pocketId] > 8) + gUnknown_0203CE54->unk82E[pocketId] = 8; + else + gUnknown_0203CE54->unk82E[pocketId] = gUnknown_0203CE54->unk829[pocketId]; +} + +void sub_81ABA6C(void) +{ + u8 i; + for (i = 0; i < 5; i++) + sub_81AB9A8(i); +} + +void sub_81ABA88(u8 a) +{ + sub_812225C(&gUnknown_0203CE58.scrollPosition[a], &gUnknown_0203CE58.cursorPosition[a], gUnknown_0203CE54->unk82E[a], gUnknown_0203CE54->unk829[a]); +} + +void sub_81ABAC4(void) +{ + u8 i; + for (i = 0; i < 5; i++) + sub_81ABA88(i); +} + +void sub_81ABAE0(void) +{ + u8 i; + for (i = 0; i < 5; i++) + sub_8122298(&gUnknown_0203CE58.scrollPosition[i], &gUnknown_0203CE58.cursorPosition[i], gUnknown_0203CE54->unk82E[i], gUnknown_0203CE54->unk829[i], 8); +} + +u8 sub_81ABB2C(u8 pocketId) +{ + return gUnknown_0203CE58.scrollPosition[pocketId] + gUnknown_0203CE58.cursorPosition[pocketId]; +} + +void DisplayItemMessage(u8 taskId, u8 fontId, const u8 *str, void ( *callback)(u8 taskId)) +{ + s16* data = gTasks[taskId].data; + + data[10] = AddItemMessageWindow(4); + FillWindowPixelBuffer(data[10], 17); + DisplayMessageAndContinueTask(taskId, data[10], 10, 13, fontId, GetPlayerTextSpeed(), str, callback); + schedule_bg_copy_tilemap_to_vram(1); +} + +void bag_menu_inits_lists_menu(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + bag_menu_RemoveBagItem_message_window(4); + DestroyListMenuTask(data[0], scrollPos, cursorPos); + sub_81AB9A8(gUnknown_0203CE58.pocket); + sub_81ABA88(gUnknown_0203CE58.pocket); + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + schedule_bg_copy_tilemap_to_vram(0); + set_callback3_to_bag(taskId); +} + +void sub_81ABC3C(u8 a) +{ + sub_81ABC54(bag_menu_add_window(a), 1); +} + +void sub_81ABC54(u8 a, s16 b) +{ + u8 r3 = (gUnknown_0203CE58.pocket == 3) ? 3 : 2; + ConvertIntToDecimalStringN(gStringVar1, b, 2, r3); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + PrintTextOnWindow(a, 1, gStringVar4, GetStringCenterAlignXOffset(1, gStringVar4, 0x28), 2, 0, 0); +} + +void sub_81ABCC0(int a, int b, int c) +{ + u8 r3 = (gUnknown_0203CE58.pocket == 3) ? 3 : 2; + ConvertIntToDecimalStringN(gStringVar1, b, 2, r3); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + PrintTextOnWindow(a, 1, gStringVar4, 0, 1, -1, 0); + PrintMoneyAmount(a, 0x26, 1, c, 0); +} + +void Task_BagMenu(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + u16 select; + if (sub_81221EC() != TRUE && !gPaletteFade.active) + { + switch (GetSwitchBagPocketDirection()) + { + case 1: + SwitchBagPocket(taskId, -1, 0); + return; + case 2: + SwitchBagPocket(taskId, 1, 0); + return; + } + if ((select = (gMain.newKeys & SELECT_BUTTON))) + { + if (sub_81AC2C0() == 1) + { + ListMenuGetScrollAndRow(data[0], scrollPos, cursorPos); + if ((*scrollPos + *cursorPos) != gUnknown_0203CE54->unk829[gUnknown_0203CE58.pocket] - 1) + { + PlaySE(SE_SELECT); + bag_menu_swap_items(taskId); + } + } + return; + } + else + { + int r4 = ListMenuHandleInputGetItemId(data[0]); + ListMenuGetScrollAndRow(data[0], scrollPos, cursorPos); + switch (r4) + { + case -1: + break; + case -2: + if (gUnknown_0203CE58.location == 5) + { + PlaySE(SE_HAZURE); + break; + } + PlaySE(SE_SELECT); + gSpecialVar_ItemId = select; + gTasks[taskId].func = unknown_ItemMenu_Confirm; + break; + default: + PlaySE(SE_SELECT); + sub_81AB824(); + bag_menu_print_cursor_(data[0], 2); + data[1] = r4; + data[2] = BagGetQuantityByPocketPosition(gUnknown_0203CE58.pocket + 1, r4); + gSpecialVar_ItemId = BagGetItemIdByPocketPosition(gUnknown_0203CE58.pocket + 1, r4); + gUnknown_08614054[gUnknown_0203CE58.location](taskId); + break; + } + } + } +} + +void set_callback3_to_bag(u8 taskId) +{ + bag_menu_add_pocket_scroll_arrow_indicators_maybe(); + bag_menu_add_list_scroll_arrow_indicators_maybe(); + ClearWindowTilemap(3); + ClearWindowTilemap(4); + PutWindowTilemap(1); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = Task_BagMenu; +} + +u8 GetSwitchBagPocketDirection(void) +{ + u8 LRKeys; + if (gUnknown_0203CE54->unk81B != 0) + return 0; + LRKeys = GetLRKeysState(); + if ((gMain.newKeys & DPAD_LEFT) || LRKeys == 1) + { + PlaySE(SE_SELECT); + return 1; + } + if ((gMain.newKeys & DPAD_RIGHT) || LRKeys == 2) + { + PlaySE(SE_SELECT); + return 2; + } + return 0; +} + +void ChangeBagPocketId(u8 *bagPocketId, s8 deltaBagPocketId) +{ + if (deltaBagPocketId == 1 && *bagPocketId == 4) + *bagPocketId = 0; + else if (deltaBagPocketId == -1 && *bagPocketId == 0) + *bagPocketId = 4; + else + *bagPocketId += deltaBagPocketId; +} + +void SwitchBagPocket(u8 taskId, s16 deltaBagPocketId, u16 a3) +{ + s16* data = gTasks[taskId].data; + u8 pocketId; + + data[13] = 0; + data[12] = 0; + data[11] = deltaBagPocketId; + if (a3 == 0) + { + ClearWindowTilemap(0); + ClearWindowTilemap(1); + DestroyListMenuTask(data[0], &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + schedule_bg_copy_tilemap_to_vram(0); + gSprites[gUnknown_0203CE54->unk804[2 + (gUnknown_0203CE54->unk81B_1 ^ 1)]].invisible = 1; + sub_81AB824(); + } + pocketId = gUnknown_0203CE58.pocket; + ChangeBagPocketId(&pocketId, deltaBagPocketId); + if (deltaBagPocketId == 1) + { + bag_menu_print_pocket_names(gPocketNamesStringsTable[gUnknown_0203CE58.pocket], gPocketNamesStringsTable[pocketId]); + bag_menu_copy_pocket_name_to_window(0); + } + else + { + bag_menu_print_pocket_names(gPocketNamesStringsTable[pocketId], gPocketNamesStringsTable[gUnknown_0203CE58.pocket]); + bag_menu_copy_pocket_name_to_window(8); + } + bag_menu_draw_pocket_indicator_square(gUnknown_0203CE58.pocket, 0); + bag_menu_draw_pocket_indicator_square(pocketId, 1); + FillBgTilemapBufferRect_Palette0(2, 11, 14, 2, 15, 16); + schedule_bg_copy_tilemap_to_vram(2); + SetBagVisualPocketId(pocketId, 1); + RemoveBagSprite(1); + AddSwitchPocketRotatingBallSprite(deltaBagPocketId); + SetTaskFuncWithFollowupFunc(taskId, sub_81AC10C, gTasks[taskId].func); +} + +void sub_81AC10C(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (!sub_81221AC() && !IsWallysBag()) + { + switch (GetSwitchBagPocketDirection()) + { + case 1: + ChangeBagPocketId(&gUnknown_0203CE58.pocket, data[11]); + SwitchTaskToFollowupFunc(taskId); + SwitchBagPocket(taskId, -1, 1); + return; + case 2: + ChangeBagPocketId(&gUnknown_0203CE58.pocket, data[11]); + SwitchTaskToFollowupFunc(taskId); + SwitchBagPocket(taskId, 1, 1); + return; + } + } + switch (data[13]) + { + case 0: + sub_81AC23C(data[12]); + if (!(++data[12] & 1)) + { + if (data[11] == 1) + bag_menu_copy_pocket_name_to_window((u8)(data[12] >> 1)); + else + bag_menu_copy_pocket_name_to_window((u8)(8 - (data[12] >> 1))); + } + if (data[12] == 16) + data[13]++; + break; + case 1: + ChangeBagPocketId(&gUnknown_0203CE58.pocket, data[11]); + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + PutWindowTilemap(1); + PutWindowTilemap(2); + schedule_bg_copy_tilemap_to_vram(0); + bag_menu_add_pocket_scroll_arrow_indicators_maybe(); + bag_menu_add_list_scroll_arrow_indicators_maybe(); + SwitchTaskToFollowupFunc(taskId); + } +} + +void sub_81AC23C(u8 a) +{ + FillBgTilemapBufferRect_Palette0(2, 17, 14, a + 2, 15, 1); + schedule_bg_copy_tilemap_to_vram(2); +} + +void bag_menu_draw_pocket_indicator_square(u8 x, u8 is_current_bag) +{ + if (is_current_bag == 0) + FillBgTilemapBufferRect_Palette0(2, 0x1017, x + 5, 3, 1, 1); + else + FillBgTilemapBufferRect_Palette0(2, 0x102B, x + 5, 3, 1, 1); + schedule_bg_copy_tilemap_to_vram(2); +} + +bool8 sub_81AC2C0(void) +{ + if (gUnknown_0203CE58.location <= 1) + { + u8 temp = gUnknown_0203CE58.pocket - 2; + if (temp > 1) + return TRUE; + } + return FALSE; +} + +void bag_menu_swap_items(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + sub_81AF15C(data[0], 16, 1); + data[1] = gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket] + gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + gUnknown_0203CE54->unk81A = data[1]; + CopyItemName(BagGetItemIdByPocketPosition(gUnknown_0203CE58.pocket + 1, data[1]), gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_MoveVar1Where); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + sub_80D4FEC(data[1]); + sub_81AB89C(); + bag_menu_print_cursor_(data[0], 2); + gTasks[taskId].func = sub_81AC3C0; +} + +void sub_81AC3C0(u8 taskId) +{ + s16* data = gTasks[taskId].data; + int r7; + + if (sub_81221EC() != TRUE) + { + if (gMain.newKeys & SELECT_BUTTON) + { + PlaySE(SE_SELECT); + ListMenuGetScrollAndRow(data[0], &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + sub_81AC498(taskId); + } + else + { + r7 = ListMenuHandleInputGetItemId(data[0]); + ListMenuGetScrollAndRow(data[0], &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket], &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + sub_80D4FC8(0); + sub_80D4FEC(gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]); + switch (r7) + { + case -1: + break; + case -2: + PlaySE(SE_SELECT); + if (gMain.newKeys & A_BUTTON) + sub_81AC498(taskId); + else + sub_81AC590(taskId); + break; + default: + PlaySE(SE_SELECT); + sub_81AC498(taskId); + } + } + } +} + +void sub_81AC498(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + u16 realPos = (*scrollPos + *cursorPos); + + if (data[1] == realPos || data[1] == (realPos - 1)) + sub_81AC590(taskId); + else + { + MoveItemSlotInList(gBagPockets[gUnknown_0203CE58.pocket].itemSlots, data[1], realPos); + gUnknown_0203CE54->unk81A = -1; + DestroyListMenuTask(data[0], scrollPos, cursorPos); + if (data[1] < realPos) + gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]--; + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + sub_80D4FC8(1); + bag_menu_add_list_scroll_arrow_indicators_maybe(); + gTasks[taskId].func = Task_BagMenu; + } +} + +void sub_81AC590(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + + gUnknown_0203CE54->unk81A = -1; + DestroyListMenuTask(data[0], scrollPos, cursorPos); + if (data[1] < (*scrollPos + *cursorPos)) + gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]--; + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + sub_80D4FC8(1); + bag_menu_add_list_scroll_arrow_indicators_maybe(); + gTasks[taskId].func = Task_BagMenu; +} + +void sub_81AC644(u8 unused) +{ + switch (gUnknown_0203CE58.location - 1) + { + case 0: + case 9: + if (ItemId_GetBattleUsage(gSpecialVar_ItemId)) + { + gUnknown_0203CE54->unk820 = gUnknown_08614042; + gUnknown_0203CE54->unk828 = 2; + } + else + { + gUnknown_0203CE54->unk820 = &gUnknown_08614046; + gUnknown_0203CE54->unk828 = 1; + } + break; + case 4: + gUnknown_0203CE54->unk820 = gUnknown_08614047; + gUnknown_0203CE54->unk828 = 4; + break; + case 8: + if (!ItemId_GetImportance(gSpecialVar_ItemId) && gSpecialVar_ItemId != ITEM_ENIGMA_BERRY) + { + gUnknown_0203CE54->unk820 = gUnknown_0861404B; + gUnknown_0203CE54->unk828 = 2; + } + else + { + gUnknown_0203CE54->unk820 = &gUnknown_08614046; + gUnknown_0203CE54->unk828 = 1; + } + break; + case 6: + if (!ItemId_GetImportance(gSpecialVar_ItemId) && gSpecialVar_ItemId != ITEM_ENIGMA_BERRY) + { + gUnknown_0203CE54->unk820 = gUnknown_0861404D; + gUnknown_0203CE54->unk828 = 2; + } + else + { + gUnknown_0203CE54->unk820 = &gUnknown_08614046; + gUnknown_0203CE54->unk828 = 1; + } + break; + case 7: + if (!ItemId_GetImportance(gSpecialVar_ItemId) && gSpecialVar_ItemId != ITEM_ENIGMA_BERRY) + { + gUnknown_0203CE54->unk820 = gUnknown_0861404F; + gUnknown_0203CE54->unk828 = 2; + } + else + { + gUnknown_0203CE54->unk820 = &gUnknown_08614046; + gUnknown_0203CE54->unk828 = 1; + } + break; + case 1: + case 2: + case 3: + case 5: + default: + if (sub_81221AC() == TRUE || InUnionRoom() == TRUE) + { + if (gUnknown_0203CE58.pocket == 4 || !sub_8122148(gSpecialVar_ItemId)) + { + gUnknown_0203CE54->unk820 = &gUnknown_08614046; + gUnknown_0203CE54->unk828 = 1; + } + else + { + gUnknown_0203CE54->unk820 = gUnknown_08614044; + gUnknown_0203CE54->unk828 = 2; + } + } + else + { + switch (gUnknown_0203CE58.pocket) + { + case 0: + gUnknown_0203CE54->unk820 = &gUnknown_0203CE54->unk824; + gUnknown_0203CE54->unk828 = 4; + memcpy(&gUnknown_0203CE54->unk824, &gUnknown_0861402C, 4); + if (ItemIsMail(gSpecialVar_ItemId) == TRUE) + gUnknown_0203CE54->unk824 = 6; + break; + case 4: + gUnknown_0203CE54->unk820 = &gUnknown_0203CE54->unk824; + gUnknown_0203CE54->unk828 = 4; + memcpy(&gUnknown_0203CE54->unk824, &gUnknown_08614030, 4); + if (gSaveBlock1Ptr->registeredItem == gSpecialVar_ItemId) + gUnknown_0203CE54->unk825 = 8; + if (gSpecialVar_ItemId == ITEM_MACH_BIKE || gSpecialVar_ItemId == ITEM_ACRO_BIKE) + { + if (TestPlayerAvatarFlags(6)) + gUnknown_0203CE54->unk824 = 7; + } + break; + case 1: + gUnknown_0203CE54->unk820 = gUnknown_08614034; + gUnknown_0203CE54->unk828 = 4; + break; + case 2: + gUnknown_0203CE54->unk820 = gUnknown_08614038; + gUnknown_0203CE54->unk828 = 4; + break; + case 3: + gUnknown_0203CE54->unk820 = gUnknown_0861403C; + gUnknown_0203CE54->unk828 = 6; + break; + } + } + } + if (gUnknown_0203CE58.pocket == 2) + { + ClearWindowTilemap(1); + PrintTMHMMoveData(gSpecialVar_ItemId); + PutWindowTilemap(3); + PutWindowTilemap(4); + schedule_bg_copy_tilemap_to_vram(0); + } + else + { + CopyItemName(gSpecialVar_ItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_Var1IsSelected); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + } + if (gUnknown_0203CE54->unk828 == 1) + sub_81ACAF8(bag_menu_add_window(0)); + else if (gUnknown_0203CE54->unk828 == 2) + sub_81ACAF8(bag_menu_add_window(1)); + else if (gUnknown_0203CE54->unk828 == 4) + sub_81ACB54(bag_menu_add_window(2), 2, 2); + else + sub_81ACB54(bag_menu_add_window(3), 2, 3); +} + +void sub_81ACAF8(u8 a) +{ + AddItemMenuActionTextPrinters(a, 7, 8, 1, 0, 16, gUnknown_0203CE54->unk828, gUnknown_08613FB4, gUnknown_0203CE54->unk820); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(a, gUnknown_0203CE54->unk828, 0); +} + +void sub_81ACB54(u8 a, u8 b, u8 c) +{ + sub_8198DBC(a, 7, 8, 1, 0x38, b, c, gUnknown_08613FB4, gUnknown_0203CE54->unk820); + sub_8199944(a, 0x38, b, c, 0); +} + +void unknown_item_menu_type(u8 taskId) +{ + sub_81AC644(taskId); + if (gUnknown_0203CE54->unk828 <= 2) + gTasks[taskId].func = Task_HandleInBattleItemMenuInput; + else + gTasks[taskId].func = Task_HandleOutOfBattleItemMenuInput; +} + +void Task_HandleInBattleItemMenuInput(u8 taskId) +{ + if (sub_81221EC() != TRUE) + { + s8 r4 = ProcessMenuInputNoWrapAround(); + switch (r4) + { + case -2: + break; + case -1: + PlaySE(SE_SELECT); + gUnknown_08613FB4[4].func.void_u8(taskId); + break; + default: + PlaySE(SE_SELECT); + gUnknown_08613FB4[gUnknown_0203CE54->unk820[r4]].func.void_u8(taskId); + break; + } + } +} + +void Task_HandleOutOfBattleItemMenuInput(u8 taskId) +{ + if (sub_81221EC() != TRUE) + { + s8 cursorPos = GetMenuCursorPos(); + if (gMain.newKeys & DPAD_UP) + { + if (cursorPos > 0 && sub_81ACDFC(cursorPos - 2)) + { + PlaySE(SE_SELECT); + sub_8199134(0, -1); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (cursorPos < (gUnknown_0203CE54->unk828 - 2) && sub_81ACDFC(cursorPos + 2)) + { + PlaySE(SE_SELECT); + sub_8199134(0, 1); + } + } + else if ((gMain.newKeys & DPAD_LEFT) || GetLRKeysState() == 1) + { + if ((cursorPos & 1) && sub_81ACDFC(cursorPos - 1)) + { + PlaySE(SE_SELECT); + sub_8199134(-1, 0); + } + } + else if ((gMain.newKeys & DPAD_RIGHT) || GetLRKeysState() == 2) + { + if (!(cursorPos & 1) && sub_81ACDFC(cursorPos + 1)) + { + PlaySE(SE_SELECT); + sub_8199134(1, 0); + } + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_08613FB4[gUnknown_0203CE54->unk820[cursorPos]].func.void_u8(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_08613FB4[4].func.void_u8(taskId); + } + } +} + +bool8 sub_81ACDFC(s8 a) +{ + if (a < 0) + return FALSE; + if (a > gUnknown_0203CE54->unk828) + return FALSE; + if (gUnknown_0203CE54->unk820[a] == 14) + return FALSE; + return TRUE; +} + +void bag_menu_remove_some_window(void) +{ + if (gUnknown_0203CE54->unk828 == 1) + bag_menu_remove_window(0); + else if (gUnknown_0203CE54->unk828 == 2) + { + bag_menu_remove_window(1); + } + else if (gUnknown_0203CE54->unk828 == 4) + { + bag_menu_remove_window(2); + } + else + bag_menu_remove_window(3); +} + +void ItemMenu_UseOutOfBattle(u8 taskId) +{ + if (ItemId_GetFieldFunc(gSpecialVar_ItemId)) + { + bag_menu_remove_some_window(); + if (CalculatePlayerPartyCount() == 0 && ItemId_GetType(gSpecialVar_ItemId) == 1) + bag_menu_print_there_is_no_pokemon(taskId); + else + { + FillWindowPixelBuffer(1, 0); + schedule_bg_copy_tilemap_to_vram(0); + if (gUnknown_0203CE58.pocket != 3) + ItemId_GetFieldFunc(gSpecialVar_ItemId)(taskId); + else + sub_80FDD10(taskId); + } + } +} + +void ItemMenu_Toss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + bag_menu_remove_some_window(); + data[8] = 1; + if (data[2] == 1) + { + BagMenuConfirmToss(taskId); + } + else + { + CopyItemName(gSpecialVar_ItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_TossHowManyVar1s); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + sub_81ABC3C(7); + gTasks[taskId].func = Task_ChooseHowManyToToss; + } +} + +void BagMenuConfirmToss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + CopyItemName(gSpecialVar_ItemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, data[8], 0, 3); + StringExpandPlaceholders(gStringVar4, gText_ConfirmTossItems); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + bag_menu_yes_no(taskId, 5, &gUnknown_08614084); +} + +void BagMenuCancelToss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + bag_menu_print_description_box_text(data[1]); + bag_menu_print_cursor_(data[0], 0); + set_callback3_to_bag(taskId); +} + +void Task_ChooseHowManyToToss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (AdjustQuantityAccordingToDPadInput(&data[8], data[2]) == TRUE) + { + sub_81ABC54(gUnknown_0203CE54->unk817, data[8]); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_remove_window(7); + BagMenuConfirmToss(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_remove_window(7); + BagMenuCancelToss(taskId); + } +} + +void BagMenuActuallyToss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + CopyItemName(gSpecialVar_ItemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, data[8], 0, 3); + StringExpandPlaceholders(gStringVar4, gText_ThrewAwayVar2Var1s); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + gTasks[taskId].func = Task_ActuallyToss; +} + +void Task_ActuallyToss(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + PlaySE(SE_SELECT); + RemoveBagItem(gSpecialVar_ItemId, data[8]); + DestroyListMenuTask(data[0], scrollPos, cursorPos); + sub_81AB9A8(gUnknown_0203CE58.pocket); + sub_81ABA88(gUnknown_0203CE58.pocket); + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + schedule_bg_copy_tilemap_to_vram(0); + set_callback3_to_bag(taskId); + } +} + +void ItemMenu_Register(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + + if (gSaveBlock1Ptr->registeredItem == gSpecialVar_ItemId) + gSaveBlock1Ptr->registeredItem = 0; + else + gSaveBlock1Ptr->registeredItem = gSpecialVar_ItemId; + DestroyListMenuTask(data[0], scrollPos, cursorPos); + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + schedule_bg_copy_tilemap_to_vram(0); + ItemMenu_Cancel(taskId); +} + +void ItemMenu_Give(u8 taskId) +{ + bag_menu_remove_some_window(); + if (!itemid_80BF6D8_mail_related(gSpecialVar_ItemId)) + { + DisplayItemMessage(taskId, 1, gText_CantWriteMail, sub_81AD350); + } + else if (!ItemId_GetImportance(gSpecialVar_ItemId)) + { + if (CalculatePlayerPartyCount() == 0) + bag_menu_print_there_is_no_pokemon(taskId); + else + { + gUnknown_0203CE54->unk0 = sub_81B7F60; + unknown_ItemMenu_Confirm(taskId); + } + } + else + { + bag_menu_print_cant_be_held_msg(taskId); + } +} + +void bag_menu_print_there_is_no_pokemon(u8 taskId) +{ + DisplayItemMessage(taskId, 1, gText_NoPokemon, sub_81AD350); +} + +void bag_menu_print_cant_be_held_msg(u8 taskId) +{ + CopyItemName(gSpecialVar_ItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_Var1CantBeHeld); + DisplayItemMessage(taskId, 1, gStringVar4, sub_81AD350); +} + +void sub_81AD350(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_inits_lists_menu(taskId); + } +} + +void ItemMenu_CheckTag(u8 taskId) +{ + gUnknown_0203CE54->unk0 = DoBerryTagScreen; + unknown_ItemMenu_Confirm(taskId); +} + +void ItemMenu_Cancel(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + bag_menu_remove_some_window(); + bag_menu_print_description_box_text(data[1]); + schedule_bg_copy_tilemap_to_vram(0); + schedule_bg_copy_tilemap_to_vram(1); + bag_menu_print_cursor_(data[0], 0); + set_callback3_to_bag(taskId); +} + +void ItemMenu_UseInBattle(u8 taskId) +{ + if (ItemId_GetBattleFunc(gSpecialVar_ItemId)) + { + bag_menu_remove_some_window(); + ItemId_GetBattleFunc(gSpecialVar_ItemId)(taskId); + } +} + +void bag_menu_mail_related(void) +{ + GoToBagMenu(12, 5, NULL); +} + +void item_menu_type_2(u8 taskId) +{ + if (!itemid_80BF6D8_mail_related(gSpecialVar_ItemId)) + { + DisplayItemMessage(taskId, 1, gText_CantWriteMail, sub_81AD350); + } + else if (!sub_8122148(gSpecialVar_ItemId)) + { + CopyItemName(gSpecialVar_ItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_Var1CantBeHeldHere); + DisplayItemMessage(taskId, 1, gStringVar4, sub_81AD350); + } + else if (gUnknown_0203CE58.pocket != 4 && !ItemId_GetImportance(gSpecialVar_ItemId)) + { + unknown_ItemMenu_Confirm(taskId); + } + else + { + bag_menu_print_cant_be_held_msg(taskId); + } +} + +void item_menu_type_b(u8 taskId) +{ + if (ItemIsMail(gSpecialVar_ItemId) == TRUE) + DisplayItemMessage(taskId, 1, gText_CantWriteMail, sub_81AD350); + else if (gUnknown_0203CE58.pocket != 4 && !ItemId_GetImportance(gSpecialVar_ItemId)) + gTasks[taskId].func = unknown_ItemMenu_Confirm; + else + bag_menu_print_cant_be_held_msg(taskId); +} + +bool8 UseRegisteredKeyItemOnField(void) +{ + u8 taskId; + + if (InUnionRoom() == TRUE || InBattlePyramid() || InBattlePike() || InMultiBattleRoom() == TRUE) + return FALSE; + HideMapNamePopUpWindow(); + ChangeBgY_ScreenOff(0, 0, 0); + if (gSaveBlock1Ptr->registeredItem != ITEM_NONE) + { + if (CheckBagHasItem(gSaveBlock1Ptr->registeredItem, 1) == TRUE) + { + ScriptContext2_Enable(); + FreezeMapObjects(); + sub_808B864(); + sub_808BCF4(); + gSpecialVar_ItemId = gSaveBlock1Ptr->registeredItem; + taskId = CreateTask(ItemId_GetFieldFunc(gSaveBlock1Ptr->registeredItem), 8); + gTasks[taskId].data[3] = 1; + return TRUE; + } + else + gSaveBlock1Ptr->registeredItem = ITEM_NONE; + } + ScriptContext1_SetupScript(EventScript_2736B3); + return TRUE; +} + +void display_sell_item_ask_str(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (ItemId_GetPrice(gSpecialVar_ItemId) == 0) + { + CopyItemName(gSpecialVar_ItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_CantBuyKeyItem); + DisplayItemMessage(taskId, 1, gStringVar4, bag_menu_inits_lists_menu); + } + else + { + data[8] = 1; + if (data[2] == 1) + { + bag_menu_AddMoney_window(); + sub_81AD680(taskId); + } + else + { + CopyItemName(gSpecialVar_ItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gText_HowManyToSell); + DisplayItemMessage(taskId, 1, gStringVar4, sub_81AD730); + } + } +} + +void sub_81AD680(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + ConvertIntToDecimalStringN(gStringVar1, (ItemId_GetPrice(gSpecialVar_ItemId) / 2) * data[8], 0, 6); + StringExpandPlaceholders(gStringVar4, gText_ICanPayVar1); + DisplayItemMessage(taskId, 1, gStringVar4, sub_81AD6E4); +} + +void sub_81AD6E4(u8 taskId) +{ + bag_menu_yes_no(taskId, 6, &gUnknown_0861408C); +} + +void sub_81AD6FC(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + bag_menu_remove_money_window(); + bag_menu_RemoveBagItem_message_window(4); + bag_menu_print_cursor_(data[0], 0); + set_callback3_to_bag(taskId); +} + +void sub_81AD730(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u8 windowId = bag_menu_add_window(8); + + sub_81ABCC0(windowId, 1, (ItemId_GetPrice(gSpecialVar_ItemId) / 2) * data[8]); + bag_menu_AddMoney_window(); + gTasks[taskId].func = sub_81AD794; +} + +void sub_81AD794(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (AdjustQuantityAccordingToDPadInput(&data[8], data[2]) == TRUE) + { + sub_81ABCC0(gUnknown_0203CE54->unk818, data[8], (ItemId_GetPrice(gSpecialVar_ItemId) / 2) * data[8]); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_remove_window(8); + sub_81AD680(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_print_cursor_(data[0], 0); + bag_menu_remove_money_window(); + bag_menu_remove_window(8); + bag_menu_RemoveBagItem_message_window(4); + set_callback3_to_bag(taskId); + } +} + +void sub_81AD84C(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + CopyItemName(gSpecialVar_ItemId, gStringVar2); + ConvertIntToDecimalStringN(gStringVar1, (ItemId_GetPrice(gSpecialVar_ItemId) / 2) * data[8], 0, 6); + StringExpandPlaceholders(gStringVar4, gText_TurnedOverVar1ForVar2); + DisplayItemMessage(taskId, 1, gStringVar4, sub_81AD8C8); +} + +void sub_81AD8C8(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16* scrollPos = &gUnknown_0203CE58.scrollPosition[gUnknown_0203CE58.pocket]; + u16* cursorPos = &gUnknown_0203CE58.cursorPosition[gUnknown_0203CE58.pocket]; + + PlaySE(SE_REGI); + RemoveBagItem(gSpecialVar_ItemId, data[8]); + AddMoney(&gSaveBlock1Ptr->money, (ItemId_GetPrice(gSpecialVar_ItemId) / 2) * data[8]); + DestroyListMenuTask(data[0], scrollPos, cursorPos); + sub_81AB9A8(gUnknown_0203CE58.pocket); + sub_81ABA88(gUnknown_0203CE58.pocket); + load_bag_item_list_buffers(gUnknown_0203CE58.pocket); + data[0] = ListMenuInit(&gMultiuseListMenuTemplate, *scrollPos, *cursorPos); + bag_menu_print_cursor_(data[0], 2); + PrintMoneyAmountInMoneyBox(gUnknown_0203CE54->unk819, GetMoney(&gSaveBlock1Ptr->money), 0); + gTasks[taskId].func = sub_81AD9C0; +} + +void sub_81AD9C0(u8 taskId) +{ + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + PlaySE(SE_SELECT); + bag_menu_remove_money_window(); + bag_menu_inits_lists_menu(taskId); + } +} + +void display_deposit_item_ask_str(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + data[8] = 1; + if (data[2] == 1) + { + sub_81ADB14(taskId); + } + else + { + CopyItemName(gSpecialVar_ItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gText_DepositHowManyVar1); + FillWindowPixelBuffer(1, 0); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + sub_81ABC3C(7); + gTasks[taskId].func = sub_81ADA7C; + } +} + +void sub_81ADA7C(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (AdjustQuantityAccordingToDPadInput(&data[8], data[2]) == TRUE) + { + sub_81ABC54(gUnknown_0203CE54->unk817, data[8]); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_remove_window(7); + sub_81ADB14(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + bag_menu_print_description_box_text(data[1]); + bag_menu_print_cursor_(data[0], 0); + bag_menu_remove_window(7); + set_callback3_to_bag(taskId); + } +} + +void sub_81ADB14(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + FillWindowPixelBuffer(1, 0); + if (ItemId_GetImportance(gSpecialVar_ItemId)) + { + bag_menu_print(1, 1, gText_CantStoreImportantItems, 3, 1, 0, 0, 0, 0); + gTasks[taskId].func = sub_81ADC0C; + } + else if (AddPCItem(gSpecialVar_ItemId, data[8]) == TRUE) + { + CopyItemName(gSpecialVar_ItemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, data[8], 0, 3); + StringExpandPlaceholders(gStringVar4, gText_DepositedVar2Var1s); + bag_menu_print(1, 1, gStringVar4, 3, 1, 0, 0, 0, 0); + gTasks[taskId].func = Task_ActuallyToss; + } + else + { + bag_menu_print(1, 1, gText_NoRoomForItems, 3, 1, 0, 0, 0, 0); + gTasks[taskId].func = sub_81ADC0C; + } +} + +void sub_81ADC0C(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + PlaySE(SE_SELECT); + bag_menu_print_description_box_text(data[1]); + bag_menu_print_cursor_(data[0], 0); + set_callback3_to_bag(taskId); + } +} + +bool8 IsWallysBag(void) +{ + if (gUnknown_0203CE58.location == 10) + return TRUE; + return FALSE; +} + +void PrepareBagForWallyTutorial(void) +{ + u32 i; + + gUnknown_0203CE80 = AllocZeroed(sizeof(struct TempWallyStruct)); + memcpy(gUnknown_0203CE80->bagPocket_Items, gSaveBlock1Ptr->bagPocket_Items, sizeof(gSaveBlock1Ptr->bagPocket_Items)); + memcpy(gUnknown_0203CE80->bagPocket_PokeBalls, gSaveBlock1Ptr->bagPocket_PokeBalls, sizeof(gSaveBlock1Ptr->bagPocket_PokeBalls)); + gUnknown_0203CE80->pocket = gUnknown_0203CE58.pocket; + for (i = 0; i <= 4; i++) + { + gUnknown_0203CE80->cursorPosition[i] = gUnknown_0203CE58.cursorPosition[i]; + gUnknown_0203CE80->scrollPosition[i] = gUnknown_0203CE58.scrollPosition[i]; + } + ClearItemSlots(gSaveBlock1Ptr->bagPocket_Items, 30); + ClearItemSlots(gSaveBlock1Ptr->bagPocket_PokeBalls, 16); + ResetBagScrollPositions(); +} + +void RestoreBagAfterWallyTutorial(void) +{ + u32 i; + + memcpy(gSaveBlock1Ptr->bagPocket_Items, gUnknown_0203CE80->bagPocket_Items, sizeof(gUnknown_0203CE80->bagPocket_Items)); + memcpy(gSaveBlock1Ptr->bagPocket_PokeBalls, gUnknown_0203CE80->bagPocket_PokeBalls, sizeof(gUnknown_0203CE80->bagPocket_PokeBalls)); + gUnknown_0203CE58.pocket = gUnknown_0203CE80->pocket; + for (i = 0; i <= 4; i++) + { + gUnknown_0203CE58.cursorPosition[i] = gUnknown_0203CE80->cursorPosition[i]; + gUnknown_0203CE58.scrollPosition[i] = gUnknown_0203CE80->scrollPosition[i]; + } + Free(gUnknown_0203CE80); +} + +void DoWallyTutorialBagMenu(void) +{ + PrepareBagForWallyTutorial(); + AddBagItem(ITEM_POTION, 1); + AddBagItem(ITEM_POKE_BALL, 1); + GoToBagMenu(10, 0, SetCB2ToReshowScreenAfterMenu2); +} + +void Task_WallyTutorialBagMenu(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + switch (data[8]) + { + case 0x66: + PlaySE(SE_SELECT); + SwitchBagPocket(taskId, 1, 0); + data[8]++; + break; + case 0xCC: + PlaySE(SE_SELECT); + bag_menu_print_cursor_(data[0], 2); + gSpecialVar_ItemId = ITEM_POKE_BALL; + sub_81AC644(taskId); + data[8]++; + break; + case 0x132: + PlaySE(SE_SELECT); + bag_menu_remove_some_window(); + DestroyListMenuTask(data[0], 0, 0); + RestoreBagAfterWallyTutorial(); + unknown_ItemMenu_Confirm(taskId); + break; + default: + data[8]++; + break; + } + } +} + +void unknown_ItemMenu_Show(u8 taskId) +{ + gSpecialVar_0x8005 = gSpecialVar_ItemId; + gSpecialVar_Result = 1; + bag_menu_remove_some_window(); + unknown_ItemMenu_Confirm(taskId); +} + +void bag_menu_leave_maybe_3(void) +{ + gFieldCallback = sub_819FA50; + SetMainCallback2(CB2_ReturnToField); +} + +void unknown_ItemMenu_Give2(u8 taskId) +{ + RemoveBagItem(gSpecialVar_ItemId, 1); + gSpecialVar_Result = 1; + bag_menu_remove_some_window(); + unknown_ItemMenu_Confirm(taskId); +} + +void bag_menu_leave_maybe_2(void) +{ + gFieldCallback = sub_818DEF4; + SetMainCallback2(CB2_ReturnToField); +} + +void unknown_ItemMenu_Confirm2(u8 taskId) +{ + gSpecialVar_Result = 1; + bag_menu_remove_some_window(); + unknown_ItemMenu_Confirm(taskId); +} + +void bag_menu_leave_maybe(void) +{ + gFieldCallback = sub_818E564; + SetMainCallback2(CB2_ReturnToField); +} + +void bag_menu_print_pocket_names(u8 *pocketName1, u8 *pocketName2) +{ + struct WindowTemplate window = {0, 0, 0, 0, 0, 0, 0}; + u16 windowId; + int offset; + + window.width = 16; + window.height = 2; + windowId = AddWindow(&window); + FillWindowPixelBuffer(windowId, 0); + offset = GetStringCenterAlignXOffset(1, pocketName1, 0x40); + bag_menu_print(windowId, 1, pocketName1, offset, 1, 0, 0, -1, 1); + if (pocketName2) + { + offset = GetStringCenterAlignXOffset(1, pocketName2, 0x40); + bag_menu_print(windowId, 1, pocketName2, offset + 0x40, 1, 0, 0, -1, 1); + } + CpuCopy32((u8*)GetWindowAttribute(windowId, 7), gUnknown_0203CE54->unk844, 0x400); + RemoveWindow(windowId); +} + +void bag_menu_copy_pocket_name_to_window(u32 a) +{ + u8 (* r4)[32][32]; + u8* windowAttribute; + int b; + if (a > 8) + a = 8; + r4 = &gUnknown_0203CE54->unk844; + windowAttribute = (u8*)GetWindowAttribute(2, 7); + CpuCopy32(r4[0][a], windowAttribute, 0x100); + b = a + 16; + CpuCopy32(r4[0][b], windowAttribute + 0x100, 0x100); + CopyWindowToVram(2, 2); +} + +void setup_bag_menu_textboxes(void) +{ + u8 i; + + InitWindows(gUnknown_08614174); + DeactivateAllTextPrinters(); + sub_809882C(0, 1, -32); + copy_textbox_border_tile_patterns_to_vram(0, 10, -48); + sub_819A2BC(-64, 1); + LoadPalette(&gUnknown_0860F074, 0xF0, 0x20); + for (i = 0; i < 3; i++) + { + FillWindowPixelBuffer(i, 0); + PutWindowTilemap(i); + } + schedule_bg_copy_tilemap_to_vram(0); + schedule_bg_copy_tilemap_to_vram(1); +} + +void bag_menu_print(u8 a, u8 b, const u8 *str, u8 c, u8 d, u8 e, u8 f, u8 g, u8 h) +{ + AddTextPrinterParameterized2(a, b, c, d, e, f, gUnknown_08614164[h], g, str); +} + +u8 sub_81AE124(u8 a) +{ + return gUnknown_0203CE54->unk810[a]; +} + +u8 bag_menu_add_window(u8 a) +{ + u8 *ptr = &gUnknown_0203CE54->unk810[a]; + if (*ptr == 0xFF) + { + *ptr = AddWindow(&gUnknown_086141AC[a]); + SetWindowBorderStyle(*ptr, 0, 1, 14); + schedule_bg_copy_tilemap_to_vram(1); + } + return *ptr; +} + +void bag_menu_remove_window(u8 a) +{ + u8 *ptr = &gUnknown_0203CE54->unk810[a]; + if (*ptr != 0xFF) + { + sub_8198070(*ptr, 0); + ClearWindowTilemap(*ptr); + RemoveWindow(*ptr); + schedule_bg_copy_tilemap_to_vram(1); + *ptr = 0xFF; + } +} + +u8 AddItemMessageWindow(u8 a) +{ + u8 *ptr = &gUnknown_0203CE54->unk810[a]; + if (*ptr == 0xFF) + *ptr = AddWindow(&gUnknown_086141AC[a]); + return *ptr; +} + +void bag_menu_RemoveBagItem_message_window(u8 a) +{ + u8 *ptr = &gUnknown_0203CE54->unk810[a]; + if (*ptr != 0xFF) + { + sub_8197DF8(*ptr, 0); + ClearWindowTilemap(*ptr); + RemoveWindow(*ptr); + schedule_bg_copy_tilemap_to_vram(1); + *ptr = 0xFF; + } +} + +void bag_menu_yes_no(u8 a, u8 b, const struct YesNoFuncTable *funcTable) +{ + CreateYesNoMenuWithCallbacks(a, &gUnknown_086141AC[b], 1, 0, 2, 1, 14, funcTable); +} + +void bag_menu_AddMoney_window(void) +{ + u8 windowId = bag_menu_add_window(9); + PrintMoneyAmountInMoneyBoxWithBorder(windowId, 1, 14, GetMoney(&gSaveBlock1Ptr->money)); + AddMoneyLabelObject(19, 11); +} + +void bag_menu_remove_money_window(void) +{ + bag_menu_remove_window(9); + RemoveMoneyLabelObject(); +} + +void bag_menu_prepare_tmhm_move_window(void) +{ + FillWindowPixelBuffer(3, 0); + blit_move_info_icon(3, 19, 0, 0); + blit_move_info_icon(3, 20, 0, 12); + blit_move_info_icon(3, 21, 0, 24); + blit_move_info_icon(3, 22, 0, 36); + CopyWindowToVram(3, 2); +} + +void PrintTMHMMoveData(u16 itemId) +{ + u8 i; + u16 moveId; + const u8* text; + + FillWindowPixelBuffer(4, 0); + if (itemId == ITEM_NONE) + { + for (i = 0; i < 4; i++) + bag_menu_print(4, 1, gText_ThreeDashes, 7, i * 12, 0, 0, -1, 4); + CopyWindowToVram(4, 2); + } + else + { + moveId = ItemIdToBattleMoveId(itemId); + blit_move_info_icon(4, gBattleMoves[moveId].type + 1, 0, 0); + if (gBattleMoves[moveId].power <= 1) + { + text = gText_ThreeDashes; + } + else + { + ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[moveId].power, 1, 3); + text = gStringVar1; + } + bag_menu_print(4, 1, text, 7, 12, 0, 0, -1, 4); + if (gBattleMoves[moveId].accuracy == 0) + { + text = gText_ThreeDashes; + } + else + { + ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[moveId].accuracy, 1, 3); + text = gStringVar1; + } + bag_menu_print(4, 1, text, 7, 24, 0, 0, -1, 4); + ConvertIntToDecimalStringN(gStringVar1, gBattleMoves[moveId].pp, 1, 3); + bag_menu_print(4, 1, gStringVar1, 7, 36, 0, 0, -1, 4); + CopyWindowToVram(4, 2); + } +} diff --git a/src/item_menu_icons.c b/src/item_menu_icons.c new file mode 100644 index 000000000..f12bb454e --- /dev/null +++ b/src/item_menu_icons.c @@ -0,0 +1,684 @@ +#include "global.h" +#include "sprite.h" +#include "decompress.h" +#include "item_menu.h" +#include "item_icon.h" +#include "item_menu_icons.h" +#include "window.h" +#include "menu_helpers.h" +#include "berry.h" +#include "graphics.h" +#include "constants/items.h" +#include "item.h" +#include "item_use.h" +#include "constants/hold_effects.h" + +struct CompressedTilesPal +{ + const u8 *tiles; + const u8 *pal; +}; + +extern void sub_80D5860(struct Sprite *sprite); +extern void sub_80D58F8(struct Sprite *sprite); +extern void sub_80D5968(struct Sprite *sprite); +extern void sub_80D5A94(struct Sprite *sprite); +extern void sub_80D5B48(struct Sprite *sprite); + +// this file's functions +static void SpriteCB_BagVisualSwitchingPockets(struct Sprite *sprite); +static void SpriteCB_ShakeBagVisual(struct Sprite *sprite); +static void SpriteCB_SwitchPocketRotatingBallInit(struct Sprite *sprite); +static void SpriteCB_SwitchPocketRotatingBallContinue(struct Sprite *sprite); + +// static const rom data +static const u16 gUnknown_0857F564[] = INCBIN_U16("graphics/interface/bag_spinner.gbapal"); +static const u8 gUnknown_0857F584[] = INCBIN_U8("graphics/interface/bag_spinner.4bpp"); +static const u8 gUnknown_0857F604[] = INCBIN_U8("graphics/unused/cherry.4bpp"); +static const u16 gUnknown_0857FA84[] = INCBIN_U16("graphics/unused/cherry.gbapal"); + +static const struct OamData sOamData_857FAA4 = +{ + .y = 0, + .affineMode = 1, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_857FAAC[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_857FAB4[] = +{ + ANIMCMD_FRAME(64, 4), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_857FABC[] = +{ + ANIMCMD_FRAME(128, 4), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_857FAC4[] = +{ + ANIMCMD_FRAME(192, 4), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_857FACC[] = +{ + ANIMCMD_FRAME(256, 4), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_857FAD4[] = +{ + ANIMCMD_FRAME(320, 4), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_857FADC[] = +{ + sSpriteAnim_857FAAC, + sSpriteAnim_857FAB4, + sSpriteAnim_857FAC4, + sSpriteAnim_857FACC, + sSpriteAnim_857FAD4, + sSpriteAnim_857FABC +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FAF4[] = +{ + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_END +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FB04[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 254, 2), + AFFINEANIMCMD_FRAME(0, 0, 2, 4), + AFFINEANIMCMD_FRAME(0, 0, 254, 4), + AFFINEANIMCMD_FRAME(0, 0, 2, 2), + AFFINEANIMCMD_END +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_857FB2C[] = +{ + sSpriteAffineAnim_857FAF4, + sSpriteAffineAnim_857FB04 +}; + +const struct CompressedSpriteSheet gUnknown_0857FB34 = +{ + gBagMaleTiles, 0x3000, 100 +}; + +const struct CompressedSpriteSheet gUnknown_0857FB3C = +{ + gBagFemaleTiles, 0x3000, 100 +}; + +const struct CompressedSpritePalette gUnknown_0857FB44 = +{ + gBagPalette, 100 +}; + +static const struct SpriteTemplate gUnknown_0857FB4C = +{ + .tileTag = 100, + .paletteTag = 100, + .oam = &sOamData_857FAA4, + .anims = sSpriteAnimTable_857FADC, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_857FB2C, + .callback = SpriteCallbackDummy, +}; + +static const struct OamData sOamData_857FB64 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 4, + .size = 1, + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_857FB6C[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_857FB74[] = +{ + sSpriteAnim_857FB6C +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FB78[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 8, 16), + AFFINEANIMCMD_END +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FB88[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 248, 16), + AFFINEANIMCMD_END +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_857FB98[] = +{ + sSpriteAffineAnim_857FB78, +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_857FB9C[] = +{ + sSpriteAffineAnim_857FB88, +}; + +static const struct SpriteSheet gUnknown_0857FBA0 = +{ + gUnknown_0857F584, 0x80, 101 +}; + +static const struct SpritePalette gUnknown_0857FBA8 = +{ + gUnknown_0857F564, 101 +}; + +static const struct SpriteTemplate gUnknown_0857FBB0 = +{ + .tileTag = 101, + .paletteTag = 101, + .oam = &sOamData_857FB64, + .anims = sSpriteAnimTable_857FB74, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_857FB98, + .callback = SpriteCB_SwitchPocketRotatingBallInit, +}; + +static const struct OamData sOamData_857FBC8 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 7, + .affineParam = 0 +}; + +static const struct OamData sOamData_857FBD0 = +{ + .y = 0, + .affineMode = 3, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 7, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_857FBD8[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_857FBE0[] = +{ + sSpriteAnim_857FBD8 +}; + +static const struct SpriteFrameImage sSpriteImageTable_857FBE4[] = +{ + {&gDecompressionBuffer[0], 0x800}, +}; + +static const struct SpriteTemplate gUnknown_0857FBEC = +{ + .tileTag = 65535, + .paletteTag = 30020, + .oam = &sOamData_857FBC8, + .anims = sSpriteAnimTable_857FBE0, + .images = sSpriteImageTable_857FBE4, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FC04[] = +{ + AFFINEANIMCMD_FRAME(-1, -1, 253, 96), + AFFINEANIMCMD_FRAME(0, 0, 0, 16), + AFFINEANIMCMD_FRAME(-2, -2, 255, 64), + AFFINEANIMCMD_FRAME(-8, 0, 0, 16), + AFFINEANIMCMD_FRAME(0, -8, 0, 16), + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_JUMP(0) +}; + +static const union AffineAnimCmd sSpriteAffineAnim_857FC3C[] = +{ + AFFINEANIMCMD_FRAME(-1, -1, 3, 96), + AFFINEANIMCMD_FRAME(0, 0, 0, 16), + AFFINEANIMCMD_FRAME(-2, -2, 1, 64), + AFFINEANIMCMD_FRAME(-8, 0, 0, 16), + AFFINEANIMCMD_FRAME(0, -8, 0, 16), + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_JUMP(0) +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_857FC74[] = +{ + sSpriteAffineAnim_857FC04, + sSpriteAffineAnim_857FC3C +}; + +static const struct SpriteTemplate gUnknown_0857FC7C = +{ + .tileTag = 0xFFFF, + .paletteTag = 0x7544, + .oam = &sOamData_857FBD0, + .anims = sSpriteAnimTable_857FBE0, + .images = sSpriteImageTable_857FBE4, + .affineAnims = sSpriteAffineAnimTable_857FC74, + .callback = SpriteCallbackDummy, +}; + +static const struct CompressedTilesPal gBerryPicTable[] = +{ + {gBerryPic_Cheri, gBerryPalette_Cheri}, + {gBerryPic_Chesto, gBerryPalette_Chesto}, + {gBerryPic_Pecha, gBerryPalette_Pecha}, + {gBerryPic_Rawst, gBerryPalette_Rawst}, + {gBerryPic_Aspear, gBerryPalette_Aspear}, + {gBerryPic_Leppa, gBerryPalette_Leppa}, + {gBerryPic_Oran, gBerryPalette_Oran}, + {gBerryPic_Persim, gBerryPalette_Persim}, + {gBerryPic_Lum, gBerryPalette_Lum}, + {gBerryPic_Sitrus, gBerryPalette_Sitrus}, + {gBerryPic_Figy, gBerryPalette_Figy}, + {gBerryPic_Wiki, gBerryPalette_Wiki}, + {gBerryPic_Mago, gBerryPalette_Mago}, + {gBerryPic_Aguav, gBerryPalette_Aguav}, + {gBerryPic_Iapapa, gBerryPalette_Iapapa}, + {gBerryPic_Razz, gBerryPalette_Razz}, + {gBerryPic_Bluk, gBerryPalette_Bluk}, + {gBerryPic_Nanab, gBerryPalette_Nanab}, + {gBerryPic_Wepear, gBerryPalette_Wepear}, + {gBerryPic_Pinap, gBerryPalette_Pinap}, + {gBerryPic_Pomeg, gBerryPalette_Pomeg}, + {gBerryPic_Kelpsy, gBerryPalette_Kelpsy}, + {gBerryPic_Qualot, gBerryPalette_Qualot}, + {gBerryPic_Hondew, gBerryPalette_Hondew}, + {gBerryPic_Grepa, gBerryPalette_Grepa}, + {gBerryPic_Tamato, gBerryPalette_Tamato}, + {gBerryPic_Cornn, gBerryPalette_Cornn}, + {gBerryPic_Magost, gBerryPalette_Magost}, + {gBerryPic_Rabuta, gBerryPalette_Rabuta}, + {gBerryPic_Nomel, gBerryPalette_Nomel}, + {gBerryPic_Spelon, gBerryPalette_Spelon}, + {gBerryPic_Pamtre, gBerryPalette_Pamtre}, + {gBerryPic_Watmel, gBerryPalette_Watmel}, + {gBerryPic_Durin, gBerryPalette_Durin}, + {gBerryPic_Belue, gBerryPalette_Belue}, + {gBerryPic_Liechi, gBerryPalette_Liechi}, + {gBerryPic_Ganlon, gBerryPalette_Ganlon}, + {gBerryPic_Salac, gBerryPalette_Salac}, + {gBerryPic_Petaya, gBerryPalette_Petaya}, + {gBerryPic_Apicot, gBerryPalette_Apicot}, + {gBerryPic_Lansat, gBerryPalette_Lansat}, + {gBerryPic_Starf, gBerryPalette_Starf}, + {gBerryPic_Enigma, gBerryPalette_Enigma}, +}; + +const struct CompressedSpriteSheet gUnknown_0857FDEC = +{ + gBerryCheckCircle_Gfx, 0x800, 10000 +}; + +const struct CompressedSpritePalette gUnknown_0857FDF4 = +{ + gUnknown_08D9BEF0, 10000 +}; + +static const struct OamData sOamData_857FDFC = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_857FE04[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_857FE0C[] = +{ + sSpriteAnim_857FE04 +}; + +static const struct SpriteTemplate gUnknown_0857FE10 = +{ + .tileTag = 10000, + .paletteTag = 10000, + .oam = &sOamData_857FDFC, + .anims = sSpriteAnimTable_857FE0C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +const struct SpriteTemplate gUnknown_0857FE28 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80D5860, +}; + +const struct SpriteTemplate gUnknown_0857FE40 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80D58F8, +}; + +const struct SpriteTemplate gUnknown_0857FE58 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80D5968, +}; + +const struct SpriteTemplate gUnknown_0857FE70 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80D5A94, +}; + +const struct SpriteTemplate gUnknown_0857FE88 = +{ + .tileTag = 0, + .paletteTag = 0, + .oam = &gDummyOamData, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80D5B48, +}; + +#include "data/text/item_descriptions.h" +#include "data/items.h" + +// code +void RemoveBagSprite(u8 id) +{ + u8 *spriteId = &gUnknown_0203CE54->unk804[id]; + if (*spriteId != 0xFF) + { + FreeSpriteTilesByTag(id + 100); + FreeSpritePaletteByTag(id + 100); + FreeSpriteOamMatrix(&gSprites[*spriteId]); + DestroySprite(&gSprites[*spriteId]); + *spriteId = 0xFF; + } +} + +void AddBagVisualSprite(u8 bagPocketId) +{ + u8 *spriteId = &gUnknown_0203CE54->unk804[0]; + *spriteId = CreateSprite(&gUnknown_0857FB4C, 68, 66, 0); + SetBagVisualPocketId(bagPocketId, FALSE); +} + +void SetBagVisualPocketId(u8 bagPocketId, bool8 isSwitchingPockets) +{ + struct Sprite *sprite = &gSprites[gUnknown_0203CE54->unk804[0]]; + if (isSwitchingPockets) + { + sprite->pos2.y = -5; + sprite->callback = SpriteCB_BagVisualSwitchingPockets; + sprite->data[0] = bagPocketId + 1; + StartSpriteAnim(sprite, 0); + } + else + { + StartSpriteAnim(sprite, bagPocketId + 1); + } +} + +static void SpriteCB_BagVisualSwitchingPockets(struct Sprite *sprite) +{ + if (sprite->pos2.y != 0) + { + sprite->pos2.y++; + } + else + { + StartSpriteAnim(sprite, sprite->data[0]); + sprite->callback = SpriteCallbackDummy; + } +} + +void ShakeBagVisual(void) +{ + struct Sprite *sprite = &gSprites[gUnknown_0203CE54->unk804[0]]; + if (sprite->affineAnimEnded) + { + StartSpriteAffineAnim(sprite, 1); + sprite->callback = SpriteCB_ShakeBagVisual; + } +} + +static void SpriteCB_ShakeBagVisual(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + { + StartSpriteAffineAnim(sprite, 0); + sprite->callback = SpriteCallbackDummy; + } +} + +void AddSwitchPocketRotatingBallSprite(s16 rotationDirection) +{ + u8 *spriteId = &gUnknown_0203CE54->unk804[1]; + LoadSpriteSheet(&gUnknown_0857FBA0); + LoadSpritePalette(&gUnknown_0857FBA8); + *spriteId = CreateSprite(&gUnknown_0857FBB0, 16, 16, 0); + gSprites[*spriteId].data[0] = rotationDirection; +} + +static void update_switch_pocket_rotating_ball_coords(struct Sprite *sprite) +{ + sprite->centerToCornerVecX = sprite->data[1] - ((sprite->data[3] + 1) & 1); + sprite->centerToCornerVecY = sprite->data[1] - ((sprite->data[3] + 1) & 1); +} + +static void SpriteCB_SwitchPocketRotatingBallInit(struct Sprite *sprite) +{ + sprite->oam.affineMode = 1; + if (sprite->data[0] == -1) + sprite->affineAnims = sSpriteAffineAnimTable_857FB98; + else + sprite->affineAnims = sSpriteAffineAnimTable_857FB9C; + + InitSpriteAffineAnim(sprite); + sprite->data[1] = sprite->centerToCornerVecX; + sprite->data[1] = sprite->centerToCornerVecY; + update_switch_pocket_rotating_ball_coords(sprite); + sprite->callback = SpriteCB_SwitchPocketRotatingBallContinue; +} + +static void SpriteCB_SwitchPocketRotatingBallContinue(struct Sprite *sprite) +{ + sprite->data[3]++; + update_switch_pocket_rotating_ball_coords(sprite); + if (sprite->data[3] == 16) + RemoveBagSprite(1); +} + +void AddBagItemIconSprite(u16 itemId, u8 id) +{ + u8 *spriteId = &gUnknown_0203CE54->unk804[id + 2]; + if (*spriteId == 0xFF) + { + u8 iconSpriteId; + + FreeSpriteTilesByTag(id + 102); + FreeSpritePaletteByTag(id + 102); + iconSpriteId = AddItemIconSprite(id + 102, id + 102, itemId); + if (iconSpriteId != MAX_SPRITES) + { + *spriteId = iconSpriteId; + gSprites[iconSpriteId].pos2.x = 24; + gSprites[iconSpriteId].pos2.y = 88; + } + } +} + +void RemoveBagItemIconSprite(u8 id) +{ + RemoveBagSprite(id + 2); +} + +void sub_80D4FAC(void) +{ + sub_8122344(&gUnknown_0203CE54->unk804[4], 8); +} + +void sub_80D4FC8(u8 arg0) +{ + sub_81223FC(&gUnknown_0203CE54->unk804[4], 8, arg0); +} + +void sub_80D4FEC(u8 arg0) +{ + sub_8122448(&gUnknown_0203CE54->unk804[4], 136, 120, (arg0 + 1) * 16); +} + +static void sub_80D5018(void *mem0, void *mem1) +{ + u8 i, j; + + memset(mem1, 0, 0x800); + mem1 += 0x100; + for (i = 0; i < 6; i++) + { + mem1 += 0x20; + for (j = 0; j < 6; j++) + { + memcpy(mem1, mem0, 0x20); + mem1 += 0x20; + mem0 += 0x20; + } + if (i != 5) + mem1 += 0x20; + } +} + +static void sub_80D5070(u8 berryId) +{ + struct CompressedSpritePalette pal; + + if (berryId == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY) - 1 && IsEnigmaBerryValid()) + { + // unknown empty if statement + } + + pal.data = gBerryPicTable[berryId].pal; + pal.tag = 0x7544; + LoadCompressedObjectPalette(&pal); + LZDecompressWram(gBerryPicTable[berryId].tiles, &gDecompressionBuffer[0x1000]); + sub_80D5018(&gDecompressionBuffer[0x1000], &gDecompressionBuffer[0]); +} + +u8 CreateBerryTagSprite(u8 id, s16 x, s16 y) +{ + sub_80D5070(id); + return CreateSprite(&gUnknown_0857FBEC, x, y, 0); +} + +void FreeBerryTagSpritePalette(void) +{ + FreeSpritePaletteByTag(0x7544); +} + +u8 sub_80D511C(u8 berryId, u8 x, u8 y, bool8 startAffine) +{ + u8 spriteId; + + FreeSpritePaletteByTag(0x7544); + sub_80D5070(berryId); + spriteId = CreateSprite(&gUnknown_0857FC7C, x, y, 0); + if (startAffine == TRUE) + StartSpriteAffineAnim(&gSprites[spriteId], 1); + + return spriteId; +} + +u8 CreateBerryFlavorCircleSprite(s16 x) +{ + return CreateSprite(&gUnknown_0857FE10, x, 116, 0); +} diff --git a/src/item_use.c b/src/item_use.c index 1fdd925ac..d036da6d3 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -1,6 +1,7 @@ #include "global.h" #include "item_use.h" #include "battle.h" +#include "main.h" #include "berry.h" #include "bike.h" #include "coins.h" @@ -45,7 +46,7 @@ extern void ItemUseOutOfBattle_EvolutionStone(u8 b); extern void bag_menu_mail_related(void); extern void OpenPokeblockCase(u8 a, void(*b)(void)); extern void overworld_free_bg_tilemaps(void); -extern bool32 sav1_map_is_biking_allowed(void); +extern bool32 Overworld_IsBikingAllowed(void); extern bool8 IsPlayerFacingSurfableFishableWater(void); extern bool8 sub_81221AC(void); extern u8 gText_ItemFinderNothing[]; @@ -85,9 +86,8 @@ extern void sub_81C59BC(void); extern void sub_81AB9A8(u8); extern void sub_81ABA88(u8); extern void sub_80B7CC8(void); -extern void flagmods_08054D70(void); +extern void Overworld_ResetStateAfterDigEscRope(void); extern u8* sub_806CF78(u16); -extern bool8 ExecuteTableBasedItemEffect_(struct Pokemon*, u16, u8, u8); extern void sub_81B89F0(void); extern u8 GetItemEffectType(u16); extern struct MapConnection *sub_8088A8C(s16, s16); @@ -114,13 +114,13 @@ void sub_80FE024(u8 taskId); void sub_80FE124(u8 taskId); void sub_80FE164(u8 taskId); -void DisplayItemMessage(u8 taskId, u8 a, u8* str, void(*callback)(u8 taskId)); +void DisplayItemMessage(u8 taskId, u8 a, const u8* str, void(*callback)(u8 taskId)); void DisplayItemMessageInBattlePyramid(u8 taskId, u8* str, void(*callback)(u8 taskId)); void DisplayItemMessageOnField(u8 taskId, u8* str, void(*callback)(u8 taskId)); void sub_81C6714(u8 taskId); void CleanUpAfterFailingToUseRegisteredKeyItemOnField(u8 taskId); void StartFishing(u8 a); -bool8 ItemfinderCheckForHiddenItems(struct MapEvents *, u8); +bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *, u8); u8 sub_80FD9B0(s16 a, s16 b); void sub_80FDA24(u8 a); void sub_80FD8E0(u8 taskId, s16 x, s16 y); @@ -166,7 +166,7 @@ void MapPostLoadHook_UseItem(void) void Task_CallItemUseOnFieldCallback(u8 taskId) { - if (sub_80ABDFC() == 1) + if (IsWeatherNotFadingIn() == 1) gUnknown_0203A0F4(taskId); } @@ -237,7 +237,7 @@ void ItemUseOutOfBattle_Bike(u8 taskId) DisplayCannotDismountBikeMessage(taskId, data[3]); else { - if (sav1_map_is_biking_allowed() == TRUE && IsBikingDisallowedByPlayer() == 0) + if (Overworld_IsBikingAllowed() == TRUE && IsBikingDisallowedByPlayer() == 0) { gUnknown_0203A0F4 = ItemUseOnFieldCB_Bike; SetUpItemUseOnFieldCallback(taskId); @@ -364,7 +364,7 @@ void sub_80FD5CC(u8 taskId) DestroyTask(taskId); } -bool8 ItemfinderCheckForHiddenItems(struct MapEvents *events, u8 taskId) +bool8 ItemfinderCheckForHiddenItems(const struct MapEvents *events, u8 taskId) { int distanceX, distanceY; s16 x, y, i, newDistanceX, newDistanceY; @@ -391,7 +391,7 @@ bool8 ItemfinderCheckForHiddenItems(struct MapEvents *events, u8 taskId) return FALSE; } -bool8 sub_80FD6D4(struct MapEvents *events, s16 x, s16 y) +bool8 sub_80FD6D4(const struct MapEvents *events, s16 x, s16 y) { u8 bgEventCount = events->bgEventCount; struct BgEvent *bgEvent = events->bgEvents; @@ -638,7 +638,7 @@ void sub_80FDC00(u8 taskId) if (!gPaletteFade.active) { overworld_free_bg_tilemaps(); - OpenPokeblockCase(0, c2_exit_to_overworld_2_switch); + OpenPokeblockCase(0, CB2_ReturnToField); DestroyTask(taskId); } } @@ -679,7 +679,7 @@ void sub_80FDD10(u8 taskId) { gUnknown_0203A0F4 = sub_80FDD74; gFieldCallback = MapPostLoadHook_UseItem; - *gUnknown_0203CE54 = c2_exit_to_overworld_2_switch; + *gUnknown_0203CE54 = CB2_ReturnToField; unknown_ItemMenu_Confirm(taskId); } else @@ -905,13 +905,13 @@ void task08_080A1C44(u8 taskId) void re_escape_rope(u8 taskId) { - flagmods_08054D70(); + Overworld_ResetStateAfterDigEscRope(); sub_80FE058(); gTasks[taskId].data[0] = 0; DisplayItemMessageOnField(taskId, gStringVar4, task08_080A1C44); } -bool8 sub_80FE314(void) +bool8 CanUseEscapeRopeOnCurrMap(void) { if (gMapHeader.flags & 2) return TRUE; @@ -921,7 +921,7 @@ bool8 sub_80FE314(void) void ItemUseOutOfBattle_EscapeRope(u8 taskId) { - if (sub_80FE314() == TRUE) + if (CanUseEscapeRopeOnCurrMap() == TRUE) { gUnknown_0203A0F4 = re_escape_rope; SetUpItemUseOnFieldCallback(taskId); @@ -984,7 +984,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId) { u16 partyId = gBattlerPartyIndexes[gBattlerInMenuId]; - if (ExecuteTableBasedItemEffect_(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE) + if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE) { if (!InBattlePyramid()) DisplayItemMessage(taskId, 1, gText_WontHaveEffect, bag_menu_inits_lists_menu); diff --git a/src/librfu_rfu.c b/src/librfu_rfu.c index cf3fe12ad..c5aa25c10 100644 --- a/src/librfu_rfu.c +++ b/src/librfu_rfu.c @@ -3,38 +3,6 @@ #include "librfu.h" -struct RfuUnk1 -{ - u8 unk_0[0x14]; - u32 unk_14; - u32 unk_18; - struct RfuIntrStruct unk_1c; -}; - -struct RfuUnk2 -{ - u8 unk_0[0x68]; - u32 unk_68; - u32 unk_6c; - u8 unk_70[0x70]; -}; - -struct RfuUnk3 -{ - u32 unk_0; - u32 unk_4; - u8 unk_8[0xD4]; - u32 unk_dc; -}; - -extern u32 *gUnknown_03007890; -extern u32 *gUnknown_03007894; -extern struct RfuUnk3* gUnknown_03007898; -extern struct RfuUnk2* gUnknown_03007880[4]; -extern struct RfuUnk1* gUnknown_03007870[4]; -extern void* sub_82E53F4; -extern void rfu_STC_clearAPIVariables(void); - // Nonmatching, only register differences /*u16 rfu_initializeAPI(u32 *unk0, u16 unk1, IntrFunc *interrupt, bool8 copyInterruptToRam) { diff --git a/src/lilycove_lady.c b/src/lilycove_lady.c index cbfb8484c..6c798967a 100644 --- a/src/lilycove_lady.c +++ b/src/lilycove_lady.c @@ -392,7 +392,7 @@ bool8 sub_818DC60(void) static void sub_818DCAC(u8 *dest, u16 itemId) { - StringCopy(dest, ItemId_GetItem(itemId)->name); + StringCopy(dest, ItemId_GetName(itemId)); } void sub_818DCC8(void) @@ -606,7 +606,6 @@ u8 sub_818E06C(void) } } -#ifdef NONMATCHING static u8 sub_818E13C(void) { u8 retval; @@ -627,9 +626,11 @@ static u8 sub_818E13C(void) len = sub_818E258(gUnknown_0203CD68->playerName); if (len == sub_818E258(gSaveBlock2Ptr->playerName)) { + u8 *name = gUnknown_0203CD68->playerName; for (i = 0; i < len; i ++) { - if (gUnknown_0203CD68->playerName[i] != gSaveBlock2Ptr->playerName[i]) + name = gUnknown_0203CD68->playerName; + if (name[i] != gSaveBlock2Ptr->playerName[i]) { retval = 2; break; @@ -640,85 +641,6 @@ static u8 sub_818E13C(void) } return retval; } -#else -__attribute__((naked)) static u8 sub_818E13C(void) -{ - asm_unified("\tpush {r4-r7,lr}\n" - "\tmovs r7, 0x1\n" - "\tldr r5, =gUnknown_0203CD68\n" - "\tldr r0, =gSaveBlock1Ptr\n" - "\tldr r1, [r0]\n" - "\tldr r2, =0x00003b58\n" - "\tadds r0, r1, r2\n" - "\tstr r0, [r5]\n" - "\tldrb r0, [r0, 0x18]\n" - "\tcmp r0, 0xFF\n" - "\tbne _0818E174\n" - "\tldr r0, =gStringVar1\n" - "\tldr r1, =gText_Lady2\n" - "\tbl StringCopy7\n" - "\tmovs r7, 0\n" - "\tb _0818E1DC\n" - "\t.pool\n" - "_0818E174:\n" - "\tldr r4, =gStringVar1\n" - "\tldr r0, =0x00003b70\n" - "\tadds r1, r0\n" - "\tadds r0, r4, 0\n" - "\tbl StringCopy7\n" - "\tldr r0, [r5]\n" - "\tadds r0, 0x2D\n" - "\tldrb r1, [r0]\n" - "\tadds r0, r4, 0\n" - "\tbl ConvertInternationalString\n" - "\tldr r0, [r5]\n" - "\tadds r0, 0x18\n" - "\tbl sub_818E258\n" - "\tlsls r0, 24\n" - "\tlsrs r4, r0, 24\n" - "\tldr r6, =gSaveBlock2Ptr\n" - "\tldr r0, [r6]\n" - "\tbl sub_818E258\n" - "\tlsls r0, 24\n" - "\tlsrs r0, 24\n" - "\tcmp r4, r0\n" - "\tbne _0818E1DC\n" - "\tldr r0, [r5]\n" - "\tmovs r2, 0\n" - "\tcmp r2, r4\n" - "\tbcs _0818E1DC\n" - "\tldr r1, [r6]\n" - "\tldrb r0, [r0, 0x18]\n" - "\tldrb r1, [r1]\n" - "\tcmp r0, r1\n" - "\tbne _0818E1DA\n" - "_0818E1BA:\n" - "\tadds r0, r2, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r2, r0, 24\n" - "\tcmp r2, r4\n" - "\tbcs _0818E1DC\n" - "\tldr r0, =gUnknown_0203CD68\n" - "\tldr r1, [r0]\n" - "\tadds r1, 0x18\n" - "\tadds r1, r2\n" - "\tldr r0, =gSaveBlock2Ptr\n" - "\tldr r0, [r0]\n" - "\tadds r0, r2\n" - "\tldrb r1, [r1]\n" - "\tldrb r0, [r0]\n" - "\tcmp r1, r0\n" - "\tbeq _0818E1BA\n" - "_0818E1DA:\n" - "\tmovs r7, 0x2\n" - "_0818E1DC:\n" - "\tadds r0, r7, 0\n" - "\tpop {r4-r7}\n" - "\tpop {r1}\n" - "\tbx r1\n" - "\t.pool"); -} -#endif static u8 sub_818E1F4(void) { @@ -749,7 +671,7 @@ static u8 sub_818E258(const u8 *str) void sub_818E274(void) { - StringCopy(gStringVar1, ItemId_GetItem(gUnknown_0203CD68->itemId)->name); + StringCopy(gStringVar1, ItemId_GetName(gUnknown_0203CD68->itemId)); } bool8 sub_818E298(void) @@ -1079,7 +1001,7 @@ void sub_818E914(void) void sub_818E92C(void) { - OpenPokeblockCase(3, c2_exit_to_overworld_2_switch); + OpenPokeblockCase(3, CB2_ReturnToField); } void sub_818E940(void) diff --git a/src/link.c b/src/link.c index ae2cd1992..acdb6cae0 100644 --- a/src/link.c +++ b/src/link.c @@ -1,6 +1,34 @@ // Includes #include "global.h" +#include "m4a.h" +#include "malloc.h" +#include "reset_save_heap.h" +#include "save.h" +#include "bg.h" +#include "window.h" +#include "librfu.h" +#include "random.h" +#include "decompress.h" +#include "string_util.h" +#include "event_data.h" +#include "item_menu.h" +#include "overworld.h" +#include "gpu_regs.h" +#include "palette.h" +#include "task.h" +#include "scanline_effect.h" +#include "menu.h" +#include "text.h" +#include "strings.h" +#include "constants/songs.h" +#include "sound.h" +#include "trade.h" +#include "battle.h" +#include "link.h" +#include "link_rfu.h" + +extern u16 gUnknown_03005DA8; // Static type declarations @@ -8,7 +36,7 @@ struct BlockTransfer { u16 pos; u16 size; - void *src; + const u8 *src; bool8 active; u8 multiplayerId; }; @@ -23,34 +51,2392 @@ struct LinkTestBGInfo // Static RAM declarations -IWRAM_DATA struct BlockTransfer gUnknown_03000D10; +IWRAM_DATA struct BlockTransfer sBlockSend; IWRAM_DATA u32 link_c_unused_03000d1c; -IWRAM_DATA struct BlockTransfer gUnknown_03000D20[4]; -IWRAM_DATA u32 gUnknown_03000D50; +IWRAM_DATA struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS]; +IWRAM_DATA u32 sBlockSendDelayCounter; IWRAM_DATA u32 gUnknown_03000D54; IWRAM_DATA u8 gUnknown_03000D58; -IWRAM_DATA u32 gUnknown_03000D5C; +IWRAM_DATA u32 sPlayerDataExchangeStatus; IWRAM_DATA u32 gUnknown_03000D60; -IWRAM_DATA u8 gUnknown_03000D64[4]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D68[4]; -IWRAM_DATA u8 gUnknown_03000D6C; -IWRAM_DATA bool8 gUnknown_03000D6D; -IWRAM_DATA u16 gUnknown_03000D6E; -IWRAM_DATA u16 gUnknown_03000D70; -IWRAM_DATA u8 gUnknown_03000D72; -IWRAM_DATA u8 gUnknown_03000D73; -IWRAM_DATA u8 gUnknown_03000D74[4]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D78[8]; // not really, but won't match otherwise -IWRAM_DATA u8 gUnknown_03000D80[16]; -IWRAM_DATA u16 gUnknown_03000D90[8]; -IWRAM_DATA u32 gUnknown_03000DA0; -IWRAM_DATA u32 gUnknown_03000DA4; -IWRAM_DATA void *gUnknown_03000DA8; -IWRAM_DATA void *gUnknown_03000DAC; -IWRAM_DATA bool32 gUnknown_03000DB0; +IWRAM_DATA u8 sLinkTestLastBlockSendPos; +ALIGNED() IWRAM_DATA u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS]; +IWRAM_DATA u8 sNumVBlanksWithoutSerialIntr; +IWRAM_DATA bool8 sSendBufferEmpty; +IWRAM_DATA u16 sSendNonzeroCheck; +IWRAM_DATA u16 sRecvNonzeroCheck; +IWRAM_DATA u8 sChecksumAvailable; +IWRAM_DATA u8 sHandshakePlayerCount; + +u16 gLinkPartnersHeldKeys[6]; +u32 gLinkDebugSeed; +struct LinkPlayerBlock gLocalLinkPlayerBlock; +bool8 gLinkErrorOccurred; +u32 gLinkDebugFlags; +u32 gFiller_03003074; +bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS]; +u8 gBlockReceivedStatus[MAX_LINK_PLAYERS]; +u32 gFiller_03003080; +u16 gLinkHeldKeys; +u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; +u32 gLinkStatus; +bool8 gUnknown_030030E4; +bool8 gUnknown_030030E8; +bool8 gUnknown_030030EC[MAX_LINK_PLAYERS]; +bool8 gUnknown_030030F0[MAX_LINK_PLAYERS]; +u16 gUnknown_030030F4; +u8 gSuppressLinkErrorMessage; +bool8 gWirelessCommType; +bool8 gSavedLinkPlayerCount; +u16 gSendCmd[CMD_LENGTH]; +u8 gSavedMultiplayerId; +bool8 gReceivedRemoteLinkPlayers; +struct LinkTestBGInfo gLinkTestBGInfo; +void (*gLinkCallback)(void); +u8 gShouldAdvanceLinkState; +u16 gLinkTestBlockChecksums[MAX_LINK_PLAYERS]; +u8 gBlockRequestType; +u32 gFiller_03003154; +u32 gFiller_03003158; +u32 gFiller_0300315c; +u8 gLastSendQueueCount; +struct Link gLink; +u8 gLastRecvQueueCount; +u16 gLinkSavedIme; +u32 gFiller_03004138; +u32 gFiller_0300413C; + +EWRAM_DATA u8 gLinkTestDebugValuesEnabled = 0; +EWRAM_DATA u8 gUnknown_020223BD = 0; +EWRAM_DATA u32 gUnknown_020223C0 = 0; +EWRAM_DATA u16 gBlockRecvBuffer[MAX_RFU_PLAYERS][BLOCK_BUFFER_SIZE / 2] = {}; +EWRAM_DATA u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE] = {}; +EWRAM_DATA bool8 gLinkOpen = FALSE; +EWRAM_DATA u16 gLinkType = 0; +EWRAM_DATA u16 gLinkTimeOutCounter = 0; +EWRAM_DATA struct LinkPlayer gLocalLinkPlayer = {}; +EWRAM_DATA struct LinkPlayer gLinkPlayers[MAX_RFU_PLAYERS] = {}; +EWRAM_DATA struct LinkPlayer gSavedLinkPlayers[MAX_RFU_PLAYERS] = {}; +EWRAM_DATA struct { + u32 status; + u8 lastRecvQueueCount; + u8 lastSendQueueCount; + u8 unk_06; +} sLinkErrorBuffer = {}; +EWRAM_DATA u16 gUnknown_02022B08 = 0; +EWRAM_DATA void *gUnknown_02022B0C = NULL; // Static ROM declarations +static void InitLocalLinkPlayer(void); +static void sub_80096BC(void); +static void CB2_LinkTest(void); +static void ProcessRecvCmds(u8 unused); +static void sub_8009F70(void); +static void ResetBlockSend(void); +static bool32 InitBlockSend(const void *src, size_t size); +static void LinkCB_BlockSendBegin(void); +static void LinkCB_BlockSend(void); +static void LinkCB_BlockSendEnd(void); +static void SetBlockReceivedFlag(u8 who); +static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size); +static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2); +static void LinkCB_RequestPlayerDataExchange(void); +static void Task_PrintTestData(u8 taskId); + +static void sub_800AC80(void); +static void sub_800ACAC(void); +static void sub_800AD5C(void); +static void sub_800AD88(void); +static void sub_800AE30(void); +static void sub_800AE5C(void); + +static void CheckErrorStatus(void); +static void CB2_PrintErrorMessage(void); +static bool8 IsSioMultiMaster(void); +static void sub_800B4A4(void); +static void DisableSerial(void); +static void EnableSerial(void); +static void CheckMasterOrSlave(void); +static void InitTimer(void); +static void EnqueueSendCmd(u16 *sendCmd); +static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH]); + +static void StartTransfer(void); +static bool8 DoHandshake(void); +static void DoRecv(void); +static void DoSend(void); +static void StopTimer(void); +static void SendRecvDone(void); + // .rodata +ALIGNED(4) const u16 gWirelessLinkDisplayPal[] = INCBIN_U16("graphics/interface/wireless_link_display.gbapal"); +const u8 gWirelessLinkDisplayGfx[] = INCBIN_U8("graphics/interface/wireless_link_display.4bpp.lz"); +const u8 gWirelessLinkDisplayTilemap[] = INCBIN_U8("graphics/interface/wireless_link_display.bin.lz"); +const u16 gLinkTestDigitsPal[] = INCBIN_U16("graphics/interface/link_test_digits.gbapal"); +const u16 gLinkTestDigitsGfx[] = INCBIN_U16("graphics/interface/link_test_digits.4bpp"); +const u8 unkstring_82ed160[] = _("{HIGHLIGHT TRANSPARENT}{COLOR WHITE}"); +const u16 g2BlankTilesGfx[] = INCBIN_U16("graphics/interface/blank_1x2.4bpp"); +const struct BlockRequest gUnknown_082ED1A8[] = { + {gBlockSendBuffer, 200}, + {gBlockSendBuffer, 200}, + {gBlockSendBuffer, 100}, + {gBlockSendBuffer, 220}, + {gBlockSendBuffer, 40} +}; +const u8 gBGControlRegs[] = { + REG_OFFSET_BG0CNT, + REG_OFFSET_BG1CNT, + REG_OFFSET_BG2CNT, + REG_OFFSET_BG3CNT +}; +const char gASCIIGameFreakInc[] = "GameFreak inc."; +const char gASCIITestPrint[] = "TEST PRINT\nP0\nP1\nP2\nP3"; +const struct BgTemplate gUnknown_082ED1FC[] = { + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .priority = 0 + }, { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 8, + .priority = 1 + } +}; +const struct WindowTemplate gUnknown_082ED204[] = { + {0x00, 0x00, 0x00, 0x1E, 0x05, 0x0F, 0x0002}, + {0x00, 0x00, 0x06, 0x1E, 0x07, 0x0F, 0x0098}, + {0x00, 0x00, 0x0D, 0x1E, 0x07, 0x0F, 0x016A}, + DUMMY_WIN_TEMPLATE +}; +const u8 gUnknown_082ED224[] = { + 0x00, 0x01, 0x02, 0x00, + 0xff, 0xfe, 0xff, 0x00 +}; + // .text + +bool8 sub_80093CC(void) +{ + sub_800B488(); + sub_800E700(); + if (sub_800BEC0() == 0x8001) + { + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + return TRUE; + } + sub_800B4A4(); + CloseLink(); + RestoreSerialTimer3IntrHandlers(); + return FALSE; +} + +void Task_DestroySelf(u8 taskId) +{ + DestroyTask(taskId); +} + +static void InitLinkTestBG(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock, u16 a4) +{ + LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20); + DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock) + (16 * a4), sizeof gLinkTestDigitsGfx); + gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; + gLinkTestBGInfo.paletteNum = paletteNum; + gLinkTestBGInfo.dummy_8 = a4; + switch (bgNum) + { + case 1: + SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + case 2: + SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + case 3: + SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_PRIORITY(1) | BGCNT_CHARBASE(charBaseBlock)); + break; + } + SetGpuReg(REG_OFFSET_BG0HOFS + bgNum * 4, 0); + SetGpuReg(REG_OFFSET_BG0VOFS + bgNum * 4, 0); +} + +void sub_80094EC(u8 paletteNum, u8 bgNum, u8 screenBaseBlock, u8 charBaseBlock) +{ + LoadPalette(gLinkTestDigitsPal, paletteNum * 16, 0x20); + DmaCopy16(3, gLinkTestDigitsGfx, (u16 *)BG_CHAR_ADDR(charBaseBlock), sizeof gLinkTestDigitsGfx); + gLinkTestBGInfo.screenBaseBlock = screenBaseBlock; + gLinkTestBGInfo.paletteNum = paletteNum; + gLinkTestBGInfo.dummy_8 = 0; + SetGpuReg(gBGControlRegs[bgNum], BGCNT_SCREENBASE(screenBaseBlock) | BGCNT_CHARBASE(charBaseBlock)); +} + +void LinkTestScreen(void) +{ + int i; + + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetTasks(); + SetVBlankCallback(sub_80096BC); + ResetBlockSend(); + gLinkType = 0x1111; + OpenLink(); + SeedRng(gMain.vblankCounter2); + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gSaveBlock2Ptr->playerTrainerId[i] = Random() % 256; + } + InitLinkTestBG(0, 2, 4, 0, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON); + CreateTask(Task_DestroySelf, 0); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + gUnknown_03000D60 = 0; + InitLocalLinkPlayer(); + CreateTask(Task_PrintTestData, 0); + SetMainCallback2(CB2_LinkTest); +} + +void sub_8009628(u8 a0) +{ + gLocalLinkPlayer.lp_field_18 = a0; +} + +static void InitLocalLinkPlayer(void) +{ + gLocalLinkPlayer.trainerId = gSaveBlock2Ptr->playerTrainerId[0] | (gSaveBlock2Ptr->playerTrainerId[1] << 8) | (gSaveBlock2Ptr->playerTrainerId[2] << 16) | (gSaveBlock2Ptr->playerTrainerId[3] << 24); + StringCopy(gLocalLinkPlayer.name, gSaveBlock2Ptr->playerName); + gLocalLinkPlayer.gender = gSaveBlock2Ptr->playerGender; + gLocalLinkPlayer.linkType = gLinkType; + gLocalLinkPlayer.language = gGameLanguage; + gLocalLinkPlayer.version = gGameVersion + 0x4000; + gLocalLinkPlayer.lp_field_2 = 0x8000; + gLocalLinkPlayer.name[8] = IsNationalPokedexEnabled(); + if (FlagGet(FLAG_0x87F)) + { + gLocalLinkPlayer.name[8] |= 0x10; + } +} + +static void sub_80096BC(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void InitLink(void) +{ + int i; + + for (i = 0; i < 8; i++) + { + gSendCmd[i] = 0xefff; + } + gLinkOpen = TRUE; + EnableSerial(); +} + +static void Task_TriggerHandshake(u8 taskId) +{ + if (++gTasks[taskId].data[0] == 5) + { + gShouldAdvanceLinkState = 1; + DestroyTask(taskId); + } +} + +void OpenLink(void) +{ + int i; + + if (!gWirelessCommType) + { + ResetSerial(); + InitLink(); + gLinkCallback = LinkCB_RequestPlayerDataExchange; + gLinkVSyncDisabled = FALSE; + gLinkErrorOccurred = FALSE; + gSuppressLinkErrorMessage = FALSE; + ResetBlockReceivedFlags(); + ResetBlockSend(); + gUnknown_03000D54 = 0; + gUnknown_030030E8 = FALSE; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + CreateTask(Task_TriggerHandshake, 2); + } + else + { + sub_800E700(); + } + gReceivedRemoteLinkPlayers = 0; + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gRemoteLinkPlayersNotReceived[i] = TRUE; + gUnknown_030030F0[i] = FALSE; + gUnknown_030030EC[i] = FALSE; + } +} + +void CloseLink(void) +{ + gReceivedRemoteLinkPlayers = FALSE; + if (gWirelessCommType) + { + sub_800EDD4(); + } + gLinkOpen = FALSE; + DisableSerial(); +} + +static void TestBlockTransfer(u8 nothing, u8 is, u8 used) +{ + u8 i; + u8 status; + + if (sLinkTestLastBlockSendPos != sBlockSend.pos) + { + LinkTest_prnthex(sBlockSend.pos, 2, 3, 2); + sLinkTestLastBlockSendPos = sBlockSend.pos; + } + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if (sLinkTestLastBlockRecvPos[i] != sBlockRecv[i].pos) + { + LinkTest_prnthex(sBlockRecv[i].pos, 2, i + 4, 2); + sLinkTestLastBlockRecvPos[i] = sBlockRecv[i].pos; + } + } + status = GetBlockReceivedStatus(); + if (status == 0xF) // 0b1111 + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + if ((status >> i) & 1) + { + gLinkTestBlockChecksums[i] = LinkTestCalcBlockChecksum(gBlockRecvBuffer[i], sBlockRecv[i].size); + ResetBlockReceivedFlag(i); + if (gLinkTestBlockChecksums[i] != 0x0342) + { + gLinkTestDebugValuesEnabled = FALSE; + gUnknown_020223BD = FALSE; + } + } + } + } +} + +static void LinkTestProcessKeyInput(void) +{ + if (gMain.newKeys & A_BUTTON) + { + gShouldAdvanceLinkState = 1; + } + if (gMain.heldKeys & B_BUTTON) + { + InitBlockSend(gHeap + 0x4000, 0x00002004); + } + if (gMain.newKeys & L_BUTTON) + { + BeginNormalPaletteFade(-1, 0, 16, 0, 2); + } + if (gMain.newKeys & START_BUTTON) + { + SetSuppressLinkErrorMessage(TRUE); + } + if (gMain.newKeys & R_BUTTON) + { + TrySavingData(1); + } + if (gMain.newKeys & SELECT_BUTTON) + { + sub_800AC34(); + } + if (gLinkTestDebugValuesEnabled) + { + SetLinkDebugValues(gMain.vblankCounter2, gLinkCallback ? gLinkVSyncDisabled : gLinkVSyncDisabled | 0x10); + } +} + +static void CB2_LinkTest(void) +{ + LinkTestProcessKeyInput(); + TestBlockTransfer(1, 1, 0); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +u16 LinkMain2(const u16 *heldKeys) +{ + u8 i; + + if (!gLinkOpen) + { + return 0; + } + for (i = 0; i < 8; i++) + { + gSendCmd[i] = 0; + } + gLinkHeldKeys = *heldKeys; + if (gLinkStatus & LINK_STAT_CONN_ESTABLISHED) + { + ProcessRecvCmds(SIO_MULTI_CNT->id); + if (gLinkCallback != NULL) + { + gLinkCallback(); + } + CheckErrorStatus(); + } + return gLinkStatus; +} + +static void HandleReceiveRemoteLinkPlayer(u8 who) +{ + int i; + int count; + + count = 0; + gRemoteLinkPlayersNotReceived[who] = FALSE; + for (i = 0; i < GetLinkPlayerCount_2(); i++) + { + count += gRemoteLinkPlayersNotReceived[i]; + } + if (count == 0 && gReceivedRemoteLinkPlayers == 0) + { + gReceivedRemoteLinkPlayers = 1; + } +} + +static void ProcessRecvCmds(u8 unused) +{ + u16 i; + + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gLinkPartnersHeldKeys[i] = 0; + if (gRecvCmds[i][0] == 0) + { + continue; + } + switch (gRecvCmds[i][0]) + { + case LINKCMD_SEND_LINK_TYPE: + { + struct LinkPlayerBlock *block; + + InitLocalLinkPlayer(); + block = &gLocalLinkPlayerBlock; + block->linkPlayer = gLocalLinkPlayer; + memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1); + memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1); + InitBlockSend(block, sizeof(*block)); + break; + } + case LINKCMD_SEND_HELD_KEYS: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + case LINKCMD_0x5555: + gUnknown_030030E8 = TRUE; + break; + case LINKCMD_0x5566: + gUnknown_030030E8 = TRUE; + break; + case LINKCMD_INIT_BLOCK: + { + struct BlockTransfer *blockRecv; + + blockRecv = &sBlockRecv[i]; + blockRecv->pos = 0; + blockRecv->size = gRecvCmds[i][1]; + blockRecv->multiplayerId = gRecvCmds[i][2]; + break; + } + case LINKCMD_CONT_BLOCK: + { + if (sBlockRecv[i].size > BLOCK_BUFFER_SIZE) + { + u16 *buffer; + u16 j; + + buffer = (u16 *)gDecompressionBuffer; + for (j = 0; j < CMD_LENGTH - 1; j++) + { + buffer[(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1]; + } + } + else + { + u16 j; + + for (j = 0; j < CMD_LENGTH - 1; j++) + { + gBlockRecvBuffer[i][(sBlockRecv[i].pos / 2) + j] = gRecvCmds[i][j + 1]; + } + } + + sBlockRecv[i].pos += (CMD_LENGTH - 1) * 2; + + if (sBlockRecv[i].pos >= sBlockRecv[i].size) + { + if (gRemoteLinkPlayersNotReceived[i] == TRUE) + { + struct LinkPlayerBlock *block; + struct LinkPlayer *linkPlayer; + + block = (struct LinkPlayerBlock *)&gBlockRecvBuffer[i]; + linkPlayer = &gLinkPlayers[i]; + *linkPlayer = block->linkPlayer; + if ((linkPlayer->version & 0xFF) == VERSION_RUBY || (linkPlayer->version & 0xFF) == VERSION_SAPPHIRE) + { + linkPlayer->name[10] = 0; + linkPlayer->name[9] = 0; + linkPlayer->name[8] = 0; + } + sub_800B524(linkPlayer); + if (strcmp(block->magic1, gASCIIGameFreakInc) != 0 + || strcmp(block->magic2, gASCIIGameFreakInc) != 0) + { + SetMainCallback2(CB2_LinkError); + } + else + { + HandleReceiveRemoteLinkPlayer(i); + } + } + else + { + SetBlockReceivedFlag(i); + } + } + } + break; + case LINKCMD_0x5FFF: + gUnknown_030030F0[i] = TRUE; + break; + case LINKCMD_0x2FFE: + gUnknown_030030EC[i] = TRUE; + break; + case LINKCMD_0xAAAA: + sub_800A418(); + break; + case LINKCMD_0xCCCC: + SendBlock(0, gUnknown_082ED1A8[gRecvCmds[i][1]].address, gUnknown_082ED1A8[gRecvCmds[i][1]].size); + break; + case LINKCMD_SEND_HELD_KEYS_2: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + } + } +} + +static void BuildSendCmd(u16 command) +{ + switch (command) + { + case LINKCMD_SEND_LINK_TYPE: + gSendCmd[0] = LINKCMD_SEND_LINK_TYPE; + gSendCmd[1] = gLinkType; + break; + case LINKCMD_0x2FFE: + gSendCmd[0] = LINKCMD_0x2FFE; + break; + case LINKCMD_SEND_HELD_KEYS: + gSendCmd[0] = LINKCMD_SEND_HELD_KEYS; + gSendCmd[1] = gMain.heldKeys; + break; + case LINKCMD_0x5555: + gSendCmd[0] = LINKCMD_0x5555; + break; + case LINKCMD_0x6666: + gSendCmd[0] = LINKCMD_0x6666; + gSendCmd[1] = 0; + break; + case LINKCMD_0x7777: + { + u8 i; + + gSendCmd[0] = LINKCMD_0x7777; + for (i = 0; i < 5; i++) + { + gSendCmd[i + 1] = 0xEE; + } + break; + } + case LINKCMD_INIT_BLOCK: + gSendCmd[0] = LINKCMD_INIT_BLOCK; + gSendCmd[1] = sBlockSend.size; + gSendCmd[2] = sBlockSend.multiplayerId + 0x80; + break; + case LINKCMD_0xAAAA: + gSendCmd[0] = LINKCMD_0xAAAA; + break; + case LINKCMD_0xAAAB: + gSendCmd[0] = LINKCMD_0xAAAB; + gSendCmd[1] = gSpecialVar_ItemId; + break; + case LINKCMD_0xCCCC: + gSendCmd[0] = LINKCMD_0xCCCC; + gSendCmd[1] = gBlockRequestType; + break; + case LINKCMD_0x5FFF: + gSendCmd[0] = LINKCMD_0x5FFF; + gSendCmd[1] = gUnknown_030030F4; + break; + case LINKCMD_0x5566: + gSendCmd[0] = LINKCMD_0x5566; + break; + case LINKCMD_SEND_HELD_KEYS_2: + if (gUnknown_03005DA8 == 0 || gLinkTransferringData) + { + break; + } + gSendCmd[0] = LINKCMD_SEND_HELD_KEYS_2; + gSendCmd[1] = gUnknown_03005DA8; + break; + } +} + +void sub_8009F18(void) +{ + if (gWirelessCommType) + { + sub_800F804(); + } + gLinkCallback = sub_8009F70; +} + +bool32 sub_8009F3C(void) +{ + if (gWirelessCommType) + { + return sub_800F7E4(); + } + if (gLinkCallback == sub_8009F70) + { + return TRUE; + } + return FALSE; +} + +static void sub_8009F70(void) +{ + if (gReceivedRemoteLinkPlayers == TRUE) + { + BuildSendCmd(LINKCMD_SEND_HELD_KEYS_2); + } +} + +void ClearLinkCallback(void) +{ + if (gWirelessCommType) + { + Rfu_set_zero(); + } + else + { + gLinkCallback = NULL; + } +} + +void ClearLinkCallback_2(void) +{ + if (gWirelessCommType) + { + Rfu_set_zero(); + } + else + { + gLinkCallback = NULL; + } +} + +u8 GetLinkPlayerCount(void) +{ + if (gWirelessCommType) + { + return sub_80104F4(); + } + return EXTRACT_PLAYER_COUNT(gLinkStatus); +} + +static int sub_8009FF8(u32 version1, u32 version2) +{ + int i; + u8 nPlayers; + + nPlayers = GetLinkPlayerCount(); + for (i = 0; i < nPlayers; i++) + { + if ((gLinkPlayers[i].version & 0xFF) == version1 || (gLinkPlayers[i].version & 0xFF) == version2) + { + return 1; + } + } + return -1; +} + +u32 sub_800A03C(void) +{ + return 2; +} + +bool32 sub_800A040(void) +{ + if (GetLinkPlayerCount() != 4 || sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) < 0) + { + return FALSE; + } + return TRUE; +} + +bool32 Link_AnyPartnersPlayingRubyOrSapphire(void) +{ + if (sub_8009FF8(VERSION_RUBY, VERSION_SAPPHIRE) >= 0) + { + return TRUE; + } + return FALSE; +} + +bool32 sub_800A07C(void) +{ + int i; + + i = sub_8009FF8(VERSION_FIRE_RED, VERSION_LEAF_GREEN); + if (i >= 0 && gLinkPlayers[i].language == LANGUAGE_JAPANESE) + { + return TRUE; + } + return FALSE; +} + +void OpenLinkTimed(void) +{ + sPlayerDataExchangeStatus = EXCHANGE_NOT_STARTED; + gLinkTimeOutCounter = 0; + OpenLink(); +} + +u8 GetLinkPlayerDataExchangeStatusTimed(int lower, int upper) +{ + int i; + int count; + u32 index; + u8 cmpVal; + u32 linkType1; + u32 linkType2; + + count = 0; + if (gReceivedRemoteLinkPlayers == TRUE) + { + cmpVal = GetLinkPlayerCount_2(); + if (lower > cmpVal || cmpVal > upper) + { + sPlayerDataExchangeStatus = EXCHANGE_STAT_6; + return 6; + } + else + { + if (GetLinkPlayerCount() == 0) + { + gLinkErrorOccurred = TRUE; + CloseLink(); + } + for (i = 0, index = 0; i < GetLinkPlayerCount(); index++, i++) + { + if (gLinkPlayers[index].linkType == gLinkPlayers[0].linkType) + { + count++; + } + } + if (count == GetLinkPlayerCount()) + { + if (gLinkPlayers[0].linkType == 0x1133) + { + switch (sub_807A728()) + { + case 1: + sPlayerDataExchangeStatus = EXCHANGE_STAT_4; + break; + case 2: + sPlayerDataExchangeStatus = EXCHANGE_STAT_5; + break; + case 0: + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + break; + } + } + else + { + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + } + } + else + { + sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS; + linkType1 = gLinkPlayers[GetMultiplayerId()].linkType; + linkType2 = gLinkPlayers[GetMultiplayerId() ^ 1].linkType; + if ((linkType1 == 0x2266 && linkType2 == 0x2277) || (linkType1 == 0x2277 && linkType2 == 0x2266)) + { + gSpecialVar_0x8005 = 3; + } + } + } + } + else if (++gLinkTimeOutCounter > 600) + { + sPlayerDataExchangeStatus = EXCHANGE_TIMED_OUT; + } + return sPlayerDataExchangeStatus; +} + +bool8 IsLinkPlayerDataExchangeComplete(void) +{ + u8 i; + u8 count; + bool8 retval; + + count = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + if (gLinkPlayers[i].linkType == gLinkPlayers[0].linkType) + { + count++; + } + } + if (count == GetLinkPlayerCount()) + { + retval = TRUE; + sPlayerDataExchangeStatus = EXCHANGE_COMPLETE; + } + else + { + retval = FALSE; + sPlayerDataExchangeStatus = EXCHANGE_IN_PROGRESS; + } + return retval; +} + +u32 GetLinkPlayerTrainerId(u8 who) +{ + return gLinkPlayers[who].trainerId; +} + +void ResetLinkPlayers(void) +{ + int i; + + for (i = 0; i <= MAX_LINK_PLAYERS; i++) + { + gLinkPlayers[i] = (struct LinkPlayer){}; + } +} + +static void ResetBlockSend(void) +{ + sBlockSend.active = FALSE; + sBlockSend.pos = 0; + sBlockSend.size = 0; + sBlockSend.src = NULL; +} + +static bool32 InitBlockSend(const void *src, size_t size) +{ + if (sBlockSend.active) + { + return FALSE; + } + sBlockSend.multiplayerId = GetMultiplayerId(); + sBlockSend.active = TRUE; + sBlockSend.size = size; + sBlockSend.pos = 0; + if (size > 0x100) + { + sBlockSend.src = src; + } + else + { + if (src != gBlockSendBuffer) + { + memcpy(gBlockSendBuffer, src, size); + } + sBlockSend.src = gBlockSendBuffer; + } + BuildSendCmd(LINKCMD_INIT_BLOCK); + gLinkCallback = LinkCB_BlockSendBegin; + sBlockSendDelayCounter = 0; + return TRUE; +} + +static void LinkCB_BlockSendBegin(void) +{ + if (++sBlockSendDelayCounter > 2) + { + gLinkCallback = LinkCB_BlockSend; + } +} + +static void LinkCB_BlockSend(void) +{ + int i; + const u8 *src; + + src = sBlockSend.src; + gSendCmd[0] = LINKCMD_CONT_BLOCK; + for (i = 0; i < 7; i++) + { + gSendCmd[i + 1] = (src[sBlockSend.pos + i * 2 + 1] << 8) | src[sBlockSend.pos + i * 2]; + } + sBlockSend.pos += 14; + if (sBlockSend.size <= sBlockSend.pos) + { + sBlockSend.active = FALSE; + gLinkCallback = LinkCB_BlockSendEnd; + } +} + +static void LinkCB_BlockSendEnd(void) +{ + gLinkCallback = NULL; +} + +static void sub_800A3F8(void) +{ + GetMultiplayerId(); + BuildSendCmd(LINKCMD_SEND_HELD_KEYS); + gUnknown_020223C0++; +} + +void sub_800A418(void) +{ + gUnknown_020223C0 = 0; + if (gWirelessCommType) + { + sub_800F850(); + } + else + { + gLinkCallback = sub_800A3F8; + } +} + +u32 sub_800A44C(void) +{ + return gUnknown_020223C0; +} + +void sub_800A458(void) +{ + BuildSendCmd(LINKCMD_0xAAAA); +} + +u8 GetMultiplayerId(void) +{ + if (gWirelessCommType == TRUE) + { + return rfu_get_multiplayer_id(); + } + return SIO_MULTI_CNT->id; +} + +u8 bitmask_all_link_players_but_self(void) +{ + u8 mpId; + + mpId = GetMultiplayerId(); + return ((1 << MAX_LINK_PLAYERS) - 1) ^ (1 << mpId); +} + +bool8 SendBlock(u8 unused, const void *src, u16 size) +{ + if (gWirelessCommType == TRUE) + { + return sub_800FE84(src, size); + } + return InitBlockSend(src, size); +} + +bool8 sub_800A4D8(u8 a0) +{ + if (gWirelessCommType == TRUE) + { + return sub_8010100(a0); + } + if (gLinkCallback == NULL) + { + gBlockRequestType = a0; + BuildSendCmd(LINKCMD_0xCCCC); + return TRUE; + } + return FALSE; +} + +bool8 sub_800A520(void) +{ + if (gWirelessCommType == TRUE) + { + return sub_8010500(); + } + return gLinkCallback == NULL; +} + +u8 GetBlockReceivedStatus(void) +{ + if (gWirelessCommType == TRUE) + { + return sub_800FCD8(); + } + return (gBlockReceivedStatus[3] << 3) | (gBlockReceivedStatus[2] << 2) | (gBlockReceivedStatus[1] << 1) | (gBlockReceivedStatus[0] << 0); +} + +static void SetBlockReceivedFlag(u8 who) +{ + if (gWirelessCommType == TRUE) + { + sub_800F6FC(who); + } + else + { + gBlockReceivedStatus[who] = TRUE; + } +} + +void ResetBlockReceivedFlags(void) +{ + int i; + + if (gWirelessCommType == TRUE) + { + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + sub_800F728(i); + } + } + else + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gBlockReceivedStatus[i] = FALSE; + } + } +} + +void ResetBlockReceivedFlag(u8 who) +{ + if (gWirelessCommType == TRUE) + { + sub_800F728(who); + } + else if (gBlockReceivedStatus[who]) + { + gBlockReceivedStatus[who] = FALSE; + } +} + +void sub_800A620(void) +{ + if ((gLinkStatus & LINK_STAT_MASTER) && EXTRACT_PLAYER_COUNT(gLinkStatus) > 1) + { + gShouldAdvanceLinkState = 1; + } +} + +static u16 LinkTestCalcBlockChecksum(const u16 *src, u16 size) +{ + u16 chksum; + u16 i; + + chksum = 0; + for (i = 0; i < size / 2; i++) + { + chksum += src[i]; + } + return chksum; +} + +static void LinkTest_prnthexchar(char a0, u8 a1, u8 a2) +{ + u16 *vAddr; + + vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); + vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + 1 + gLinkTestBGInfo.dummy_8); +} + +static void LinkTest_prntchar(char a0, u8 a1, u8 a2) +{ + u16 *vAddr; + + vAddr = (u16 *)BG_SCREEN_ADDR(gLinkTestBGInfo.screenBaseBlock); + vAddr[a2 * 32 + a1] = (gLinkTestBGInfo.paletteNum << 12) | (a0 + gLinkTestBGInfo.dummy_8); +} + +static void LinkTest_prnthex(u32 pos, u8 a0, u8 a1, u8 a2) +{ + char sp[32 / 2]; + int i; + + for (i = 0; i < a2; i++) + { + sp[i] = pos & 0xf; + pos >>= 4; + } + for (i = a2 - 1; i >= 0; i--) + { + LinkTest_prnthexchar(sp[i], a0, a1); + a0++; + } +} + +static void LinkTest_prntint(int a0, u8 a1, u8 a2, u8 a3) +{ + char sp[32 / 2]; + int sp10; + int i; + + sp10 = -1; + if (a0 < 0) + { + sp10 = a1; + a0 = -a0; + } + for (i = 0; i < a3; i++) + { + sp[i] = a0 % 10; + a0 /= 10; + } + for (i = a3 - 1; i >= 0; i--) + { + LinkTest_prnthexchar(sp[i], a1, a2); + a1++; + } + if (sp10 != -1) + { + LinkTest_prnthexchar(*"\n", sp10, a2); + } +} + +static void LinkTest_prntstr(const char *a0, u8 a1, u8 a2) +{ + int r6; + int i; + int r5; + + r5 = 0; + r6 = 0; + for (i = 0; a0[i] != 0; a0++) + { + if (a0[i] == *"\n") + { + r5++; + r6 = 0; + } + else + { + LinkTest_prntchar(a0[i], a1 + r6, a2 + r5); + r6++; + } + } +} + +static void LinkCB_RequestPlayerDataExchange(void) +{ + if (gLinkStatus & LINK_STAT_MASTER) + { + BuildSendCmd(LINKCMD_SEND_LINK_TYPE); + } + gLinkCallback = NULL; +} + +static void Task_PrintTestData(u8 taskId) +{ + char sp[32]; + int i; + + strcpy(sp, gASCIITestPrint); + LinkTest_prntstr(sp, 5, 2); + LinkTest_prnthex(gShouldAdvanceLinkState, 2, 1, 2); + LinkTest_prnthex(gLinkStatus, 15, 1, 8); + LinkTest_prnthex(gLink.state, 2, 10, 2); + LinkTest_prnthex(EXTRACT_PLAYER_COUNT(gLinkStatus), 15, 10, 2); + LinkTest_prnthex(GetMultiplayerId(), 15, 12, 2); + LinkTest_prnthex(gLastSendQueueCount, 25, 1, 2); + LinkTest_prnthex(gLastRecvQueueCount, 25, 2, 2); + LinkTest_prnthex(GetBlockReceivedStatus(), 15, 5, 2); + LinkTest_prnthex(gLinkDebugSeed, 2, 12, 8); + LinkTest_prnthex(gLinkDebugFlags, 2, 13, 8); + LinkTest_prnthex(GetSioMultiSI(), 25, 5, 1); + LinkTest_prnthex(IsSioMultiMaster(), 25, 6, 1); + LinkTest_prnthex(IsLinkConnectionEstablished(), 25, 7, 1); + LinkTest_prnthex(HasLinkErrorOccurred(), 25, 8, 1); + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + LinkTest_prnthex(gLinkTestBlockChecksums[i], 10, 4 + i, 4); + } +} + +void SetLinkDebugValues(u32 seed, u32 flags) +{ + gLinkDebugSeed = seed; + gLinkDebugFlags = flags; +} + +u8 sub_800A9A8(void) +{ + int i; + u8 flags; + + flags = 0; + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + flags |= (1 << i); + } + return flags; +} + +u8 sub_800A9D8(void) +{ + int i; + u8 flags; + + flags = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + flags |= (1 << i); + } + return flags; +} + +void sub_800AA04(u8 a0) +{ + int i; + + gSavedLinkPlayerCount = a0; + gSavedMultiplayerId = GetMultiplayerId(); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + gSavedLinkPlayers[i] = gLinkPlayers[i]; + } +} + +u8 sub_800AA48(void) +{ + return gSavedLinkPlayerCount; +} + +u8 sub_800AA54(void) +{ + return gSavedMultiplayerId; +} + +bool8 sub_800AA60(void) +{ + int i; + unsigned count; + + count = 0; + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + if (gLinkPlayers[i].trainerId == gSavedLinkPlayers[i].trainerId) + { + if (gLinkType == 0x2288) + { + if (gLinkType == gLinkPlayers[i].linkType) + { + count++; + } + } + else + { + count++; + } + } + } + if (count == gSavedLinkPlayerCount) + { + if (GetLinkPlayerCount_2() == gSavedLinkPlayerCount) + { + return TRUE; + } + } + return FALSE; +} + +void sub_800AAF4(void) +{ + int i; + + // Clearly not what was meant to be written, but here it is anyway. + for (i = 0; i < 4; i++) + { + CpuSet(&gSavedLinkPlayers[i], NULL, sizeof(struct LinkPlayer)); + } +} + +void sub_800AB18(void) +{ + u8 i; + + for (i = 0; i < gSavedLinkPlayerCount; i++) + { + if (gSavedLinkPlayers[i].trainerId != gLinkPlayers[i].trainerId || StringCompare(gSavedLinkPlayers[i].name, gLinkPlayers[i].name) != 0) + { + gLinkErrorOccurred = TRUE; + CloseLink(); + SetMainCallback2(CB2_LinkError); + } + } +} + +void sub_800AB98(void) +{ + gSavedLinkPlayerCount = 0; + gSavedMultiplayerId = 0; +} + +u8 GetLinkPlayerCount_2(void) +{ + return EXTRACT_PLAYER_COUNT(gLinkStatus); +} + +bool8 IsLinkMaster(void) +{ + if (gWirelessCommType) + { + return Rfu_IsMaster(); + } + return EXTRACT_MASTER(gLinkStatus); +} + +u8 sub_800ABE8(void) +{ + return gUnknown_03000D58; +} + +void sub_800ABF4(u16 a0) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback == NULL) + { + gLinkCallback = sub_800AC80; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = a0; + } + } +} + +void sub_800AC34(void) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback != NULL) + { + gUnknown_02022B08++; + } + else + { + gLinkCallback = sub_800AC80; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + } + } +} + +static void sub_800AC80(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x5FFF); + gLinkCallback = sub_800ACAC; + } +} + +static void sub_800ACAC(void) +{ + int i; + unsigned count; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + count = 0; + for (i = 0; i < linkPlayerCount; i++) + { + if (gUnknown_030030F0[i]) + { + count++; + } + } + if (count == linkPlayerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + gLinkVSyncDisabled = TRUE; + CloseLink(); + gLinkCallback = NULL; + gUnknown_030030E4 = TRUE; + } +} + +void sub_800AD10(void) +{ + if (gWirelessCommType == TRUE) + { + task_add_05_task_del_08FA224_when_no_RfuFunc(); + } + else + { + if (gLinkCallback != NULL) + { + gUnknown_02022B08++; + } + else + { + gLinkCallback = sub_800AD5C; + gUnknown_030030E4 = FALSE; + gUnknown_030030F4 = 0; + } + } +} + +static void sub_800AD5C(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x5FFF); + gLinkCallback = sub_800AD88; + } +} + +static void sub_800AD88(void) +{ + int i; + unsigned count; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + count = 0; + for (i = 0; i < linkPlayerCount; i++) + { + if (gLinkPlayers[i].language == LANGUAGE_JAPANESE) + { + count++; + } + else if (gUnknown_030030F0[i]) + { + count++; + } + } + if (count == linkPlayerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + gLinkVSyncDisabled = TRUE; + CloseLink(); + gLinkCallback = NULL; + gUnknown_030030E4 = TRUE; + } +} + +void sub_800ADF8(void) +{ + if (gWirelessCommType == TRUE) + { + sub_8010434(); + } + else + { + if (gLinkCallback == NULL) + { + gLinkCallback = sub_800AE30; + } + gUnknown_030030E4 = FALSE; + } +} + +static void sub_800AE30(void) +{ + if (gLastRecvQueueCount == 0) + { + BuildSendCmd(LINKCMD_0x2FFE); + gLinkCallback = sub_800AE5C; + } +} + +static void sub_800AE5C(void) +{ + u8 i; + u8 linkPlayerCount; + + linkPlayerCount = GetLinkPlayerCount(); + for (i = 0; i < linkPlayerCount; i++) + { + if (!gUnknown_030030EC[i]) + { + break; + } + } + if (i == linkPlayerCount) + { + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + gUnknown_030030EC[i] = FALSE; + } + gLinkCallback = NULL; + } +} + +static void CheckErrorStatus(void) +{ + if (gLinkOpen && EXTRACT_LINK_ERRORS(gLinkStatus)) + { + if (!gSuppressLinkErrorMessage) + { + sLinkErrorBuffer.status = gLinkStatus; + sLinkErrorBuffer.lastRecvQueueCount = gLastRecvQueueCount; + sLinkErrorBuffer.lastSendQueueCount = gLastSendQueueCount; + SetMainCallback2(CB2_LinkError); + } + gLinkErrorOccurred = TRUE; + CloseLink(); + } +} + +void sub_800AF18(u32 status, u8 lastSendQueueCount, u8 lastRecvQueueCount, u8 unk_06) +{ + sLinkErrorBuffer.status = status; + sLinkErrorBuffer.lastSendQueueCount = lastSendQueueCount; + sLinkErrorBuffer.lastRecvQueueCount = lastRecvQueueCount; + sLinkErrorBuffer.unk_06 = unk_06; +} + +void CB2_LinkError(void) +{ + u8 *tilemapBuffer; + + SetGpuReg(REG_OFFSET_DISPCNT, 0); + m4aMPlayStop(&gMPlayInfo_SE1); + m4aMPlayStop(&gMPlayInfo_SE2); + m4aMPlayStop(&gMPlayInfo_SE3); + InitHeap(gHeap, HEAP_SIZE); + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetPaletteFadeControl(); + FillPalette(0, 0, 2); + ResetTasks(); + ScanlineEffect_Stop(); + if (gWirelessCommType) + { + if (!sLinkErrorBuffer.unk_06) + { + gWirelessCommType = 3; + } + sub_800E604(); + } + SetVBlankCallback(sub_80096BC); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, gUnknown_082ED1FC, 2); + gUnknown_02022B0C = tilemapBuffer = malloc(0x800); + SetBgTilemapBuffer(1, tilemapBuffer); + if (InitWindows(gUnknown_082ED204)) + { + DeactivateAllTextPrinters(); + reset_temp_tile_data_buffers(); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON); + LoadPalette(gUnknown_0860F074, 0xf0, 0x20); + gSoftResetDisabled = FALSE; + CreateTask(Task_DestroySelf, 0); + StopMapMusic(); + gMain.callback1 = NULL; + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + SetMainCallback2(CB2_PrintErrorMessage); + } +} + +static void sub_800B080(void) +{ + LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0); + copy_decompressed_tile_data_to_vram_autofree(1, gWirelessLinkDisplayGfx, FALSE, 0, 0); + CopyToBgTilemapBuffer(1, gWirelessLinkDisplayTilemap, 0, 0); + CopyBgTilemapBufferToVram(1); + LoadPalette(gWirelessLinkDisplayPal, 0, 0x20); + FillWindowPixelBuffer(0, 0x00); + FillWindowPixelBuffer(2, 0x00); + box_print(0, 3, 2, 6, gUnknown_082ED224, 0, gText_CommErrorEllipsis); + box_print(2, 3, 2, 1, gUnknown_082ED224, 0, gText_MoveCloserToLinkPartner); + PutWindowTilemap(0); + PutWindowTilemap(2); + CopyWindowToVram(0, 0); + CopyWindowToVram(2, 3); +} + +static void sub_800B138(void) +{ + LoadBgTiles(0, g2BlankTilesGfx, 0x20, 0); + FillWindowPixelBuffer(1, 0x00); + FillWindowPixelBuffer(2, 0x00); + box_print(1, 3, 2, 0, gUnknown_082ED224, 0, gText_CommErrorCheckConnections); + PutWindowTilemap(1); + PutWindowTilemap(2); + CopyWindowToVram(1, 0); + CopyWindowToVram(2, 3); +} + +static void CB2_PrintErrorMessage(void) +{ + switch (gMain.state) + { + case 00: + if (sLinkErrorBuffer.unk_06) + { + sub_800B080(); + } + else + { + sub_800B138(); + } + break; + case 02: + ShowBg(0); + if (sLinkErrorBuffer.unk_06) + { + ShowBg(1); + } + break; + case 30: + PlaySE(SE_BOO); + break; + case 60: + PlaySE(SE_BOO); + break; + case 90: + PlaySE(SE_BOO); + break; + case 130: + if (gWirelessCommType == 2) + { + box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnTitleScreen); + } + else if (gWirelessCommType == 1) + { + box_print(0, 3, 2, 20, gUnknown_082ED224, 0, gText_ABtnRegistrationCounter); + } + break; + } + if (gMain.state == 160) + { + if (gWirelessCommType == 1) + { + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_PIN); + gWirelessCommType = 0; + sLinkErrorBuffer.unk_06 = 0; + sub_81700F8(); + } + } + else if (gWirelessCommType == 2) + { + if (gMain.newKeys & A_BUTTON) + { + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + DoSoftReset(); + } + } + } + if (gMain.state != 160) + { + gMain.state++; + } +} + +// TODO: there might be a file boundary here, let's name it + +bool8 GetSioMultiSI(void) +{ + return (REG_SIOCNT & 0x04) != 0; +} + +static bool8 IsSioMultiMaster(void) +{ + return (REG_SIOCNT & 0x8) && !(REG_SIOCNT & 0x04); +} + +bool8 IsLinkConnectionEstablished(void) +{ + return EXTRACT_CONN_ESTABLISHED(gLinkStatus); +} + +void SetSuppressLinkErrorMessage(bool8 flag) +{ + gSuppressLinkErrorMessage = flag; +} + +bool8 HasLinkErrorOccurred(void) +{ + return gLinkErrorOccurred; +} + +void sub_800B348(void) +{ + struct LinkPlayerBlock *block; + + InitLocalLinkPlayer(); + block = &gLocalLinkPlayerBlock; + block->linkPlayer = gLocalLinkPlayer; + memcpy(block->magic1, gASCIIGameFreakInc, sizeof(block->magic1) - 1); + memcpy(block->magic2, gASCIIGameFreakInc, sizeof(block->magic2) - 1); + memcpy(gBlockSendBuffer, block, sizeof(*block)); +} + +void sub_800B3A4(u32 who) +{ + u8 who_ = who; + struct LinkPlayerBlock *block; + struct LinkPlayer *player; + + block = (struct LinkPlayerBlock *)gBlockRecvBuffer[who_]; + player = &gLinkPlayers[who_]; + *player = block->linkPlayer; + sub_800B524(player); + if (strcmp(block->magic1, gASCIIGameFreakInc) != 0 || strcmp(block->magic2, gASCIIGameFreakInc) != 0) + { + SetMainCallback2(CB2_LinkError); + } +} + +bool8 HandleLinkConnection(void) +{ + bool32 r4; + bool32 r5; + + if (gWirelessCommType == 0) + { + gLinkStatus = LinkMain1(&gShouldAdvanceLinkState, gSendCmd, gRecvCmds); + LinkMain2(&gMain.heldKeys); + if ((gLinkStatus & LINK_STAT_RECEIVED_NOTHING) && sub_808766C() == TRUE) + { + return TRUE; + } + } + else + { + r4 = sub_8010EC0(); + r5 = sub_8010F1C(); + if (sub_808766C() == TRUE) + { + if (r4 == TRUE || sub_800F0B8() || r5) + { + return TRUE; + } + } + } + return FALSE; +} + +void sub_800B488(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 1; + } +} + +static void sub_800B4A4(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 0; + } +} + +void sub_800B4C0(void) +{ + if (gReceivedRemoteLinkPlayers == 0) + { + gWirelessCommType = 0; + } +} + +u32 sub_800B4DC(void) +{ + if (gWirelessCommType != 0) + { + return sub_80124D4(); + } + return gLink.recvQueue.count; +} + +bool8 sub_800B504(void) +{ + if (sub_800B4DC() > 2) + { + return TRUE; + } + return FALSE; +} + +u8 sub_800B518(void) +{ + return gWirelessCommType; +} + +void sub_800B524(struct LinkPlayer *player) +{ + player->name[10] = player->name[8]; + ConvertInternationalString(player->name, player->language); +} + +static void DisableSerial(void) +{ + DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + REG_SIOCNT = SIO_MULTI_MODE; + REG_TMCNT_H(3) = 0; + REG_IF = INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL; + REG_SIOMLT_SEND = 0; + REG_SIOMLT_RECV = 0; + CpuFill32(0, &gLink, sizeof(gLink)); +} + +static void EnableSerial(void) +{ + DisableInterrupts(INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + REG_RCNT = 0; + REG_SIOCNT = SIO_MULTI_MODE; + REG_SIOCNT |= SIO_115200_BPS | SIO_INTR_ENABLE; + EnableInterrupts(INTR_FLAG_SERIAL); + REG_SIOMLT_SEND = 0; + CpuFill32(0, &gLink, sizeof(gLink)); + sNumVBlanksWithoutSerialIntr = 0; + sSendNonzeroCheck = 0; + sRecvNonzeroCheck = 0; + sChecksumAvailable = 0; + sHandshakePlayerCount = 0; + gLastSendQueueCount = 0; + gLastRecvQueueCount = 0; +} + +void ResetSerial(void) +{ + EnableSerial(); + DisableSerial(); +} + +// link_main1.c + +u32 LinkMain1(u8 *shouldAdvanceLinkState, u16 *sendCmd, u16 (*recvCmds)[CMD_LENGTH]) +{ + u32 retVal; + u32 retVal2; + + switch (gLink.state) + { + case LINK_STATE_START0: + DisableSerial(); + gLink.state = 1; + break; + case LINK_STATE_START1: + if (*shouldAdvanceLinkState == 1) + { + EnableSerial(); + gLink.state = 2; + } + break; + case LINK_STATE_HANDSHAKE: + switch (*shouldAdvanceLinkState) + { + default: + CheckMasterOrSlave(); + break; + case 1: + if (gLink.isMaster == LINK_MASTER && gLink.playerCount > 1) + { + gLink.handshakeAsMaster = TRUE; + } + break; + case 2: + gLink.state = LINK_STATE_START0; + REG_SIOMLT_SEND = 0; + break; + } + break; + case LINK_STATE_INIT_TIMER: + InitTimer(); + gLink.state = LINK_STATE_CONN_ESTABLISHED; + // fallthrough + case LINK_STATE_CONN_ESTABLISHED: + EnqueueSendCmd(sendCmd); + DequeueRecvCmds(recvCmds); + break; + } + *shouldAdvanceLinkState = 0; + retVal = gLink.localId; + retVal |= (gLink.playerCount << LINK_STAT_PLAYER_COUNT_SHIFT); + if (gLink.isMaster == LINK_MASTER) + { + retVal |= LINK_STAT_MASTER; + } + { + u32 receivedNothing = gLink.receivedNothing << LINK_STAT_RECEIVED_NOTHING_SHIFT; + u32 link_field_F = gLink.link_field_F << LINK_STAT_UNK_FLAG_9_SHIFT; + u32 hardwareError = gLink.hardwareError << LINK_STAT_ERROR_HARDWARE_SHIFT; + u32 badChecksum = gLink.badChecksum << LINK_STAT_ERROR_CHECKSUM_SHIFT; + u32 queueFull = gLink.queueFull << LINK_STAT_ERROR_QUEUE_FULL_SHIFT; + u32 val; + + if (gLink.state == LINK_STATE_CONN_ESTABLISHED) + { + val = LINK_STAT_CONN_ESTABLISHED; + val |= receivedNothing; + val |= retVal; + val |= link_field_F; + val |= hardwareError; + val |= badChecksum; + val |= queueFull; + } + else + { + val = retVal; + val |= receivedNothing; + val |= link_field_F; + val |= hardwareError; + val |= badChecksum; + val |= queueFull; + } + + retVal = val; + } + + if (gLink.lag == LAG_MASTER) + { + retVal |= LINK_STAT_ERROR_LAG_MASTER; + } + + if (gLink.localId >= MAX_LINK_PLAYERS) + { + retVal |= LINK_STAT_ERROR_INVALID_ID; + } + + retVal2 = retVal; + if (gLink.lag == LAG_SLAVE) + { + retVal2 |= LINK_STAT_ERROR_LAG_SLAVE; + } + + return retVal2; +} + +static void CheckMasterOrSlave(void) +{ + u32 terminals; + + terminals = *(vu32 *)REG_ADDR_SIOCNT & (SIO_MULTI_SD | SIO_MULTI_SI); + if (terminals == SIO_MULTI_SD && gLink.localId == 0) + { + gLink.isMaster = LINK_MASTER; + } + else + { + gLink.isMaster = LINK_SLAVE; + } +} + +static void InitTimer(void) +{ + if (gLink.isMaster) + { + REG_TM3CNT_L = -197; + REG_TM3CNT_H = TIMER_64CLK | TIMER_INTR_ENABLE; + EnableInterrupts(INTR_FLAG_TIMER3); + } +} + +static void EnqueueSendCmd(u16 *sendCmd) +{ + u8 i; + u8 offset; + + gLinkSavedIme = REG_IME; + REG_IME = 0; + if (gLink.sendQueue.count < QUEUE_CAPACITY) + { + offset = gLink.sendQueue.pos + gLink.sendQueue.count; + if (offset >= QUEUE_CAPACITY) + { + offset -= QUEUE_CAPACITY; + } + for (i = 0; i < CMD_LENGTH; i++) + { + sSendNonzeroCheck |= *sendCmd; + gLink.sendQueue.data[i][offset] = *sendCmd; + *sendCmd = 0; + sendCmd++; + } + } + else + { + gLink.queueFull = QUEUE_FULL_SEND; + } + if (sSendNonzeroCheck) + { + gLink.sendQueue.count++; + sSendNonzeroCheck = 0; + } + REG_IME = gLinkSavedIme; + gLastSendQueueCount = gLink.sendQueue.count; +} + + +static void DequeueRecvCmds(u16 (*recvCmds)[CMD_LENGTH]) +{ + u8 i; + u8 j; + + gLinkSavedIme = REG_IME; + REG_IME = 0; + if (gLink.recvQueue.count == 0) + { + for (i = 0; i < gLink.playerCount; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + recvCmds[i][j] = 0; + } + } + + gLink.receivedNothing = TRUE; + } + else + { + for (i = 0; i < gLink.playerCount; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + recvCmds[i][j] = gLink.recvQueue.data[i][j][gLink.recvQueue.pos]; + } + } + gLink.recvQueue.count--; + gLink.recvQueue.pos++; + if (gLink.recvQueue.pos >= QUEUE_CAPACITY) + { + gLink.recvQueue.pos = 0; + } + gLink.receivedNothing = FALSE; + } + REG_IME = gLinkSavedIme; +} + +// link_intr.c + +void LinkVSync(void) +{ + if (gLink.isMaster) + { + switch (gLink.state) + { + case LINK_STATE_CONN_ESTABLISHED: + if (gLink.serialIntrCounter < 9) + { + if (gLink.hardwareError != TRUE) + { + gLink.lag = LAG_MASTER; + } + else + { + StartTransfer(); + } + } + else if (gLink.lag != LAG_MASTER) + { + gLink.serialIntrCounter = 0; + StartTransfer(); + } + break; + case LINK_STATE_HANDSHAKE: + StartTransfer(); + break; + } + } + else if (gLink.state == LINK_STATE_CONN_ESTABLISHED || gLink.state == LINK_STATE_HANDSHAKE) + { + if (++sNumVBlanksWithoutSerialIntr > 10) + { + if (gLink.state == LINK_STATE_CONN_ESTABLISHED) + { + gLink.lag = LAG_SLAVE; + } + if (gLink.state == LINK_STATE_HANDSHAKE) + { + gLink.playerCount = 0; + gLink.link_field_F = FALSE; + } + } + } +} + +void Timer3Intr(void) +{ + StopTimer(); + StartTransfer(); +} + +void SerialCB(void) +{ + gLink.localId = SIO_MULTI_CNT->id; + switch (gLink.state) + { + case LINK_STATE_CONN_ESTABLISHED: + gLink.hardwareError = SIO_MULTI_CNT->error; + DoRecv(); + DoSend(); + SendRecvDone(); + break; + case LINK_STATE_HANDSHAKE: + if (DoHandshake()) + { + if (gLink.isMaster) + { + gLink.state = LINK_STATE_INIT_TIMER; + gLink.serialIntrCounter = 8; + } + else + { + gLink.state = LINK_STATE_CONN_ESTABLISHED; + } + } + break; + } + gLink.serialIntrCounter++; + sNumVBlanksWithoutSerialIntr = 0; + if (gLink.serialIntrCounter == 8) + { + gLastRecvQueueCount = gLink.recvQueue.count; + } +} + +static void StartTransfer(void) +{ + REG_SIOCNT |= SIO_START; +} + +static bool8 DoHandshake(void) +{ + u8 i; + u8 playerCount; + u16 minRecv; + + playerCount = 0; + minRecv = 0xFFFF; + if (gLink.handshakeAsMaster == TRUE) + { + REG_SIOMLT_SEND = MASTER_HANDSHAKE; + } + else + { + REG_SIOMLT_SEND = SLAVE_HANDSHAKE; + } + *(u64 *)gLink.tempRecvBuffer = REG_SIOMLT_RECV; + REG_SIOMLT_RECV = 0; + gLink.handshakeAsMaster = FALSE; + for (i = 0; i < 4; i++) + { + if ((gLink.tempRecvBuffer[i] & ~0x3) == SLAVE_HANDSHAKE || gLink.tempRecvBuffer[i] == MASTER_HANDSHAKE) + { + playerCount++; + if (minRecv > gLink.tempRecvBuffer[i] && gLink.tempRecvBuffer[i] != 0) + { + minRecv = gLink.tempRecvBuffer[i]; + } + } + else + { + if (gLink.tempRecvBuffer[i] != 0xFFFF) + { + playerCount = 0; + } + break; + } + } + gLink.playerCount = playerCount; + if (gLink.playerCount > 1 && gLink.playerCount == sHandshakePlayerCount && gLink.tempRecvBuffer[0] == MASTER_HANDSHAKE) + { + return TRUE; + } + if (gLink.playerCount > 1) + { + gLink.link_field_F = (minRecv & 3) + 1; + } + else + { + gLink.link_field_F = 0; + } + sHandshakePlayerCount = gLink.playerCount; + return FALSE; +} + +static void DoRecv(void) +{ + u16 recv[4]; + u8 i; + u8 index; + + *(u64 *)recv = REG_SIOMLT_RECV; + if (gLink.sendCmdIndex == 0) + { + for (i = 0; i < gLink.playerCount; i++) + { + if (gLink.checksum != recv[i] && sChecksumAvailable) + { + gLink.badChecksum = TRUE; + } + } + gLink.checksum = 0; + sChecksumAvailable = TRUE; + } + else + { + index = gLink.recvQueue.pos + gLink.recvQueue.count; + if (index >= QUEUE_CAPACITY) + { + index -= QUEUE_CAPACITY; + } + if (gLink.recvQueue.count < QUEUE_CAPACITY) + { + for (i = 0; i < gLink.playerCount; i++) + { + gLink.checksum += recv[i]; + sRecvNonzeroCheck |= recv[i]; + gLink.recvQueue.data[i][gLink.recvCmdIndex][index] = recv[i]; + } + } + else + { + gLink.queueFull = QUEUE_FULL_RECV; + } + gLink.recvCmdIndex++; + if (gLink.recvCmdIndex == CMD_LENGTH && sRecvNonzeroCheck) + { + gLink.recvQueue.count++; + sRecvNonzeroCheck = 0; + } + } +} + +static void DoSend(void) +{ + if (gLink.sendCmdIndex == CMD_LENGTH) + { + REG_SIOMLT_SEND = gLink.checksum; + if (!sSendBufferEmpty) + { + gLink.sendQueue.count--; + gLink.sendQueue.pos++; + if (gLink.sendQueue.pos >= QUEUE_CAPACITY) + { + gLink.sendQueue.pos = 0; + } + } + else + { + sSendBufferEmpty = FALSE; + } + } + else + { + if (!sSendBufferEmpty && gLink.sendQueue.count == 0) + { + sSendBufferEmpty = TRUE; + } + if (sSendBufferEmpty) + { + REG_SIOMLT_SEND = 0; + } + else + { + REG_SIOMLT_SEND = gLink.sendQueue.data[gLink.sendCmdIndex][gLink.sendQueue.pos]; + } + gLink.sendCmdIndex++; + } +} + +static void StopTimer(void) +{ + if (gLink.isMaster) + { + REG_TM3CNT_H &= ~TIMER_ENABLE; + REG_TM3CNT_L = -197; + } +} + +static void SendRecvDone(void) +{ + if (gLink.recvCmdIndex == CMD_LENGTH) + { + gLink.sendCmdIndex = 0; + gLink.recvCmdIndex = 0; + } + else if (gLink.isMaster) + { + REG_TM3CNT_H |= TIMER_ENABLE; + } +} + +void ResetSendBuffer(void) +{ + u8 i; + u8 j; + + gLink.sendQueue.count = 0; + gLink.sendQueue.pos = 0; + for (i = 0; i < CMD_LENGTH; i++) + { + for (j = 0; j < QUEUE_CAPACITY; j++) + { + gLink.sendQueue.data[i][j] = 0xEFFF; + } + } +} + +void ResetRecvBuffer(void) +{ + u8 i; + u8 j; + u8 k; + + gLink.recvQueue.count = 0; + gLink.recvQueue.pos = 0; + for (i = 0; i < MAX_LINK_PLAYERS; i++) + { + for (j = 0; j < CMD_LENGTH; j++) + { + for (k = 0; k < QUEUE_CAPACITY; k++) + { + gLink.recvQueue.data[i][j][k] = 0xEFFF; + } + } + } +} diff --git a/src/link_rfu.c b/src/link_rfu.c new file mode 100644 index 000000000..37aa20950 --- /dev/null +++ b/src/link_rfu.c @@ -0,0 +1,4942 @@ + +// Includes +#include "global.h" +#include "malloc.h" +#include "battle.h" +#include "berry_blender.h" +#include "task.h" +#include "random.h" +#include "decompress.h" +#include "text.h" +#include "string_util.h" +#include "event_data.h" +#include "overworld.h" +#include "link.h" +#include "librfu.h" +#include "rom_8011DC0.h" +#include "link_rfu.h" + +extern u16 gUnknown_03005DA8; + +// Static type declarations + +// Static RAM declarations + +struct UnkRfuStruct_1 gUnknown_03004140; +struct UnkRfuStruct_2 gUnknown_03005000; + +IWRAM_DATA u8 gUnknown_03000D74; +ALIGNED(4) IWRAM_DATA u8 gUnknown_03000D78[8]; +IWRAM_DATA u8 gUnknown_03000D80[16]; +IWRAM_DATA u16 gUnknown_03000D90[8]; + +EWRAM_DATA u8 gWirelessStatusIndicatorSpriteId = 0; +EWRAM_DATA ALIGNED(4) struct UnkLinkRfuStruct_02022B14 gUnknown_02022B14 = {}; +EWRAM_DATA ALIGNED(2) u8 gUnknown_02022B22[8] = {}; +EWRAM_DATA struct UnkLinkRfuStruct_02022B2C gUnknown_02022B2C = {}; +EWRAM_DATA struct UnkLinkRfuStruct_02022B44 gUnknown_02022B44 = {}; + +// Static ROM declarations + +static void sub_800C000(void); +static void sub_800C7B4(u16 r8, u16 r6); +static void sub_800C744(u32 a0); +static void sub_800CEB0(u16 r6); +static void sub_800CF34(void); +static void sub_800D158(void); +static void sub_800D20C(void); +static void sub_800D268(void); +static u8 sub_800D294(void); +static void sub_800D30C(u8 a0, u8 a1); +static void sub_800D334(u8 a0); +static void sub_800D358(u8 a0); +static void sub_800D434(void); +static void sub_800D610(void); +void sub_800D630(void); +static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2); +static void sub_800EAB4(void); +static void sub_800EAFC(void); +void sub_800ED34(u16 unused); +static void sub_800EDBC(u16 unused); +static void sub_800F048(void); +static void sub_800F86C(u8 unused); +static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data); +void sub_800FD14(u16 command); +static void rfufunc_80F9F44(void); +static void sub_800FFB0(void); +static void rfufunc_80FA020(void); +bool32 sub_8010454(u32 a0); +static void sub_8010528(void); +void sub_8010750(void); +int sub_80107A0(void); +void sub_801084C(u8 taskId); +void sub_80109E8(u16 a0); +void sub_8010A70(void *a0); +void sub_8010AAC(u8 taskId); +void sub_8010D0C(u8 taskId); +void sub_80115EC(u16 a0); +u8 sub_8011CE4(const u8 *a0, u16 a1); +void sub_8011D6C(u8 a0); +void sub_8011E94(u8 a0, u8 a1); +u8 sub_8012224(void); +void sub_801227C(void); + +// .rodata + +const u16 gWirelessLinkIconPalette[] = INCBIN_U16("graphics/interface/wireless_link_icon.gbapal"); +const u8 gWirelessLinkIconPic[] = INCBIN_U8("graphics/interface/wireless_link_icon.4bpp.lz"); +const u8 sWireless_ASCIItoRSETable[] = { + 0xff, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x00, 0xab, 0xb5, 0xb6, 0xb1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb2, 0xf1, 0x00, 0xae, 0xad, 0xba, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0x00, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0x00, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, + 0xd2, 0xd3, 0xd4, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, + 0x00, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0x2d, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x35, 0x36, 0x50, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0xad, 0xb3, 0xb4, 0x00, 0xaf, 0x7d, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xa0, + 0xae, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7e, 0xb0, 0xac, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2e, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94 +}; +const u8 sWireless_RSEtoASCIITable[] = { + 0x20, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, + 0x9d, 0x9e, 0x9f, 0xa0, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0x7b, 0xf1, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x84, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xa6, 0xdd, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xf2, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, + 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0xaf, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x21, 0xdf, 0xa1, 0xb0, 0xa5, + 0xde, 0x24, 0x2a, 0xa2, 0xa3, 0x22, 0x23, 0x20, + 0xa4, 0x20, 0x2f, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, + 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x20, + 0x20, 0x2b, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00 +}; +const struct OamData sWirelessStatusIndicatorOamData = { + .size = 1 +}; +static const union AnimCmd sWirelessStatusIndicatorAnim0[] = { + // 3 bars + ANIMCMD_FRAME( 4, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_FRAME(16, 10), + ANIMCMD_FRAME(12, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim1[] = { + // 2 bars + ANIMCMD_FRAME( 4, 5), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_FRAME(12, 10), + ANIMCMD_FRAME( 8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim2[] = { + // 1 bar + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim3[] = { + // searching + ANIMCMD_FRAME( 4, 10), + ANIMCMD_FRAME(20, 10), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd sWirelessStatusIndicatorAnim4[] = { + // error + ANIMCMD_FRAME(24, 10), + ANIMCMD_FRAME( 4, 10), + ANIMCMD_JUMP(0) +}; +static const union AnimCmd *const sWirelessStatusIndicatorAnims[] = { + sWirelessStatusIndicatorAnim0, + sWirelessStatusIndicatorAnim1, + sWirelessStatusIndicatorAnim2, + sWirelessStatusIndicatorAnim3, + sWirelessStatusIndicatorAnim4 +}; +const struct CompressedSpriteSheet sWirelessStatusIndicatorSpriteSheet = { + gWirelessLinkIconPic, 0x0380, 0xD431 +}; +const struct SpritePalette sWirelessStatusIndicatorSpritePalette = { + gWirelessLinkIconPalette, 0xD432 +}; +static const struct SpriteTemplate sWirelessStatusIndicatorSpriteTemplate = { + 0xD431, + 0xD432, + &sWirelessStatusIndicatorOamData, + sWirelessStatusIndicatorAnims, + NULL, + gDummySpriteAffineAnimTable, + SpriteCallbackDummy +}; + +const struct UnkLinkRfuStruct_02022B2C gUnknown_082ED608 = { + 0x04, 0x20, 0x00, 0x00, 0x02, + &gUnknown_02022B14, + gUnknown_02022B22, + 0x01, 0x00, 0x258, 0x12c +}; +const u8 gUnknown_082ED620[] = { + 0, 3, 2, 1, 0 +}; +const u32 gUnknown_082ED628[] = { + 0x000000, + 0x000001, + 0x000003, + 0x000007, + 0x00000f, + 0x00001f, + 0x00003f, + 0x00007f, + 0x0000ff, + 0x0001ff, + 0x0003ff, + 0x0007ff, + 0x000fff, + 0x001fff, + 0x003fff, + 0x007fff, + 0x00ffff, + 0x01ffff, + 0x03ffff, + 0x07ffff, + 0x0fffff, + 0x1fffff, + 0x3fffff, + 0x7fffff, + 0xffffff +}; +const u8 gUnknown_082ED68C[] = { + 0, 0, 1, + 1, 2, 2, + 2, 2, 3 +}; +const u8 gUnknown_082ED695[] = { + 0, 1, 1, 2, + 1, 2, 2, 3, + 1, 2, 2, 3, + 2, 3, 3, 4 +}; +const u8 gUnknown_082ED6A5[] = { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; +const struct { + u8 *buffer; + u32 size; +} gUnknown_082ED6B8[] = { + { gBlockSendBuffer, 200 }, + { gBlockSendBuffer, 200 }, + { gBlockSendBuffer, 100 }, + { gBlockSendBuffer, 220 }, + { gBlockSendBuffer, 40 } +}; +const u16 gUnknown_082ED6E0[] = { + 0x0002, 0x7f7d, 0x0000, 0xffff +}; + +const char sUnref_082ED6E8[][15] = { + "RFU WAIT", + "RFU BOOT", + "RFU ERROR", + "RFU RESET", + "RFU CONFIG", + "RFU START", + "RFU SC POLL", + "RFU SP POLL", + "RFU START", + "RFU SEND ERR", + "RFU CP POLL" +}; +const char sUnref_082ED6E9[][16] = { + " ", + "RECOVER START ", + "DISSCONECT ", + "RECOVER SUUSES", + "RECOVER FAILED" +}; +const TaskFunc gUnknown_082ED7E0[] = { + sub_801084C, + sub_8010AAC, + sub_8010D0C +}; +const char gUnknown_082ED7EC[] = "PokemonSioInfo"; +const char gUnknown_082ED7FC[] = "LINK LOSS DISCONNECT!"; +const char gUnknown_082ED814[] = "LINK LOSS RECOVERY NOW"; + +// .text + +u32 sub_800BEC0(void) +{ + u32 r4; + + r4 = rfu_REQBN_softReset_and_checkID(); + if (r4 == 0x8001) + { + gUnknown_03004140.unk_08 = 1; + } + if (gUnknown_03004140.unk_04 != 0x17 && gUnknown_03004140.unk_04 != 0x01) + { + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + } + gUnknown_03004140.unk_07 = 0; + gUnknown_03004140.unk_0d = 0; + gUnknown_03004140.unk_01 = 0; + gUnknown_03004140.unk_00 = 0; + gUnknown_03004140.unk_06 = -1; + sub_800D610(); + return r4; +} + +void rfu_REQ_sendData_wrapper(u8 r2) +{ + u8 val; + if (!gUnknown_03007890->unk_00) + { + val = gUnknown_03004140.unk_02; + r2 = 0; + if (val == 1) + { + r2 = 1; + } + } + else + { + gUnknown_03004140.unk_03 = 0; + } + rfu_REQ_sendData(r2); +} + +int sub_800BF4C(void (*func1)(u8, u8), void (*func2)(u16)) +{ + if (func1 == NULL) + { + return 4; + } + CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, filler_48)); + gUnknown_03004140.unk_06 = -1; + gUnknown_03004140.unk_40 = func1; + gUnknown_03004140.unk_44 = func2; + rfu_setMSCCallback(sub_800CEB0); + rfu_setREQCallback(sub_800C7B4); + return 0; +} + +void sub_800BFA0(void) +{ + CpuFill16(0, &gUnknown_03004140, offsetof(struct UnkRfuStruct_1, unk_40)); + gUnknown_03004140.unk_06 = -1; +} + +void sub_800BFCC(const struct UnkLinkRfuStruct_02022B2C *unk0) +{ + sub_800C000(); + gUnknown_03004140.unk_04 = 1; + gUnknown_03004140.unk_05 = 2; + gUnknown_03004140.unk_3c = unk0; + gUnknown_03004140.unk_09 = unk0->unk_11; + gUnknown_03004140.unk_32 = unk0->unk_12; + gUnknown_03004140.unk_18 = unk0->unk_14; + if (unk0->unk_10) + { + gUnknown_03004140.unk_0b = 1; + } +} + +static void sub_800C000(void) +{ + u8 i; + + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + gUnknown_03004140.unk_06 = -1; + gUnknown_03004140.unk_07 = 0; + gUnknown_03004140.unk_10 = 0; + gUnknown_03004140.unk_0c = 0; + gUnknown_03004140.unk_24 = 0; + gUnknown_03004140.unk_30 = 0; + for (i = 0; i < 4; i++) + { + gUnknown_03004140.unk_28[i] = 0; + gUnknown_03004140.unk_34[i] = 0; + } +} + +void sub_800C048(void) +{ + gUnknown_03004140.unk_04 = 0x15; +} + +u8 sub_800C054(u8 r5, u16 r7, u16 r8, const u16 *r6) +{ + u8 i; + const u16 *buffer; + + if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 != 0x08 || r5 != 1)) + { + gUnknown_03004140.unk_14 = 1; + sub_800D30C(0xf3, 0x01); + return 1; + } + if (!rfu_getMasterSlave()) + { + gUnknown_03004140.unk_14 = 2; + sub_800D30C(0xf3, 0x01); + return 2; + } + for (i = 0, buffer = r6; i < 16; i++) + { + if (*buffer++ == 0xFFFF) + { + break; + } + } + if (i == 16) + { + gUnknown_03004140.unk_14 = 4; + sub_800D30C(0xf3, 0x01); + return 4; + } + if (r5 > 1) + { + gUnknown_03004140.unk_07 = 1; + r5 = 1; + r7 = 0; + } + else + { + gUnknown_03004140.unk_07 = 0; + } + if (r5 != 0) + { + gUnknown_03004140.unk_04 = 5; + } + else + { + gUnknown_03004140.unk_04 = 9; + if (gUnknown_03004140.unk_0b) + { + gUnknown_03004140.unk_0b = 2; + } + } + gUnknown_03004140.unk_06 = r5; + gUnknown_03004140.unk_1a = r7; + gUnknown_03004140.unk_26 = r8; + gUnknown_03004140.unk_20 = r6; + return 0; +} + +u8 sub_800C12C(u16 r6, u16 r8) +{ + u8 i; + struct RfuUnk5 *tmp; + + if (gUnknown_03004140.unk_04 != 0 && (gUnknown_03004140.unk_04 < 9 || gUnknown_03004140.unk_04 > 11)) + { + gUnknown_03004140.unk_14 = 1; + sub_800D30C(0xF3, 0x01); + return 1; + } + if (!rfu_getMasterSlave()) + { + gUnknown_03004140.unk_14 = 2; + sub_800D30C(0xF3, 0x01); + return 2; + } + for (i = 0; i < gUnknown_03007890->unk_08; i++) + { + if (gUnknown_03007890->unk_14[i].unk_00 == r6) + { + break; + } + } + if (gUnknown_03007890->unk_08 == 0 || i == gUnknown_03007890->unk_08) + { + gUnknown_03004140.unk_14 = 3; + sub_800D30C(0xF3, 0x01); + return 3; + } + if (gUnknown_03004140.unk_04 == 0 || gUnknown_03004140.unk_04 == 9) + { + gUnknown_03004140.unk_04 = 12; + gUnknown_03004140.unk_05 = 13; + } + else + { + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 12; + } + gUnknown_03004140.unk_1e = r6; + gUnknown_03004140.unk_1a = r8; + if (gUnknown_03004140.unk_07 != 0) + { + gUnknown_03004140.unk_07 = 7; + } + return 0; +} + +void sub_800C210(u8 a0) +{ + u8 i; + + if (a0 & gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_30 &= ~a0; + for (i = 0; i < 4; i++) + { + if ((a0 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + i = gUnknown_03007890->unk_03 & a0; + if (i) + { + sub_800D334(i); + } + gUnknown_03004140.unk_14 = i; + sub_800D30C(0x33, i); + } +} + +void sub_800C27C(bool8 a0) +{ + u8 r2; + + r2 = 0; + gUnknown_03004140.unk_07 = 0; + if (a0) + { + sub_800C000(); + gUnknown_03004140.unk_04 = 23; + } + else + { + switch (gUnknown_03004140.unk_04) + { + case 5: + gUnknown_03004140.unk_04 = 8; + gUnknown_03004140.unk_05 = 0; + r2 = 0x13; + break; + case 6: + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + break; + case 7: + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + break; + case 8: + break; + case 9: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x21; + break; + case 10: + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + break; + case 11: + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + break; + case 12: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x23; + break; + case 13: + gUnknown_03004140.unk_04 = 14; + break; + case 14: + gUnknown_03004140.unk_04 = 14; + break; + case 15: + break; + case 16: + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11; + gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12; + sub_800D334(gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03; + sub_800D30C(0x33, 0x01); + return; + case 17: + gUnknown_03004140.unk_04 = 18; + break; + case 18: + gUnknown_03004140.unk_04 = 18; + break; + default: + gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_04 = 0; + r2 = 0x43; + break; + } + if (gUnknown_03004140.unk_04 == 0) + { + sub_800D30C(r2, 0); + } + } +} + +bool8 sub_800C36C(u16 a0) +{ + bool8 retVal; + u8 i; + u8 sp0; + u8 sp1; + u8 sp2; + u8 flags; + + retVal = FALSE; + rfu_REQBN_watchLink(a0, &sp0, &sp1, &sp2); + if (sp0) + { + gUnknown_03004140.unk_14 = sp0; + gUnknown_03004140.unk_16 = sp1; + if (gUnknown_03004140.unk_09) + { + gUnknown_03004140.unk_0a = 1; + if (gUnknown_03004140.unk_06 == 0 && sp1 == 0) + { + gUnknown_03004140.unk_0a = 4; + } + if (gUnknown_03004140.unk_0a == 1) + { + for (i = 0; i < 4; i++) + { + if ((sp0 >> i) & 1) + { + gUnknown_03004140.unk_30 |= (1 << i); + gUnknown_03004140.unk_34[i] = gUnknown_03004140.unk_32; + } + } + sub_800D30C(0x31, 0x01); + } + else + { + gUnknown_03004140.unk_0a = 0; + sub_800D334(sp0); + retVal = TRUE; + sub_800D30C(0x33, 0x01); + } + } + else + { + sub_800D334(sp0); + retVal = TRUE; + sub_800D30C(0x30, 0x02); + } + sub_800D610(); + } + if (gUnknown_03007890->unk_00 == 1) + { + if (sp2) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_30 >> i) & 1 && (sp2 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + gUnknown_03004140.unk_30 &= ~sp2; + gUnknown_03004140.unk_14 = sp2; + sub_800D30C(0x32, 0x01); + } + if (gUnknown_03004140.unk_30) + { + flags = 0; + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_30 >> i) & 1 && gUnknown_03004140.unk_34[i] && --gUnknown_03004140.unk_34[i] == 0) + { + gUnknown_03004140.unk_30 &= ~(1 << i); + flags |= (1 << i); + } + } + if (flags) + { + sub_800D334(flags); + retVal = TRUE; + gUnknown_03004140.unk_14 = flags; + sub_800D30C(0x33, 0x01); + } + } + if (!gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_0a = 0; + } + } + return retVal; +} + +void rfu_syncVBlank_(void) +{ + if (rfu_syncVBlank()) + { + sub_800D30C(0xF1, 0x00); + sub_800D610(); + } +} + +void sub_800C54C(u32 a0) +{ + u8 r2; + + if (gUnknown_03004140.unk_40 == NULL && gUnknown_03004140.unk_04 != 0) + { + gUnknown_03004140.unk_04 = 0; + } + else + { + if (gUnknown_03004140.unk_07 != 0) + { + sub_800C744(a0); + } + do + { + if (gUnknown_03004140.unk_04 != 0) + { + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = 1; + switch (gUnknown_03004140.unk_04) + { + case 23: + r2 = sub_800BEC0() == 0x8001 ? 0x44 : 0xFF; + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(r2, 0); + break; + case 1: + if (sub_800BEC0() == 0x8001) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 3; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0xFF, 0); + } + break; + case 2: + rfu_REQ_reset(); + break; + case 3: + rfu_REQ_configSystem(gUnknown_03004140.unk_3c->unk_02, gUnknown_03004140.unk_3c->unk_00, gUnknown_03004140.unk_3c->unk_01); + break; + case 4: + rfu_REQ_configGameData(gUnknown_03004140.unk_3c->unk_04, gUnknown_03004140.unk_3c->unk_06, gUnknown_03004140.unk_3c->unk_08, gUnknown_03004140.unk_3c->unk_0c); + break; + case 5: + rfu_REQ_startSearchChild(); + break; + case 6: + rfu_REQ_pollSearchChild(); + break; + case 7: + rfu_REQ_endSearchChild(); + break; + case 8: + break; + case 9: + rfu_REQ_startSearchParent(); + break; + case 10: + rfu_REQ_pollSearchParent(); + break; + case 11: + rfu_REQ_endSearchParent(); + break; + case 12: + rfu_REQ_startConnectParent(gUnknown_03004140.unk_1e); + break; + case 13: + rfu_REQ_pollConnectParent(); + break; + case 14: + rfu_REQ_endConnectParent(); + break; + case 15: + break; + case 16: + rfu_REQ_CHILD_startConnectRecovery(gUnknown_03007890->unk_03); + break; + case 17: + rfu_REQ_CHILD_pollConnectRecovery(); + break; + case 18: + rfu_REQ_CHILD_endConnectRecovery(); + break; + case 19: + rfu_REQ_changeMasterSlave(); + break; + case 20: + break; + case 21: + rfu_REQ_stopMode(); + break; + case 22: + break; + } + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = 0; + } + } while (gUnknown_03004140.unk_04 == 18 || gUnknown_03004140.unk_04 == 19); + if (gUnknown_03007890->unk_00 != 1 || !sub_800C36C(0)) + { + sub_800CF34(); + sub_800D158(); + sub_800D268(); + sub_800D434(); + } + } +} + +static void sub_800C744(u32 a0) +{ + if (gUnknown_03004140.unk_07 == 5) + { + gUnknown_03004140.unk_06 = 1; + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c; + if (gUnknown_03004140.unk_1a) + { + gUnknown_03004140.unk_07 = 6; + } + else + { + gUnknown_03004140.unk_07 = 1; + } + } + if (gUnknown_03004140.unk_07 == 1) + { + gUnknown_03004140.unk_06 = 1; + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_1a = a0 % 140; + gUnknown_03004140.unk_1c = 140 - gUnknown_03004140.unk_1a; + if (gUnknown_03004140.unk_1a) + { + gUnknown_03004140.unk_07 = 2; + } + else + { + gUnknown_03004140.unk_07 = 3; + } + } + if (gUnknown_03004140.unk_07 == 3) + { + gUnknown_03004140.unk_06 = 0; + gUnknown_03004140.unk_1a = 40; + gUnknown_03004140.unk_07 = 4; + gUnknown_03004140.unk_04 = 9; + } +} + +static void sub_800C7B4(u16 r8, u16 r6) +{ + u8 sp0; + register u8 *stwiRecvBuffer asm("r0"); + u8 *tmp; + u8 i; + + if (gUnknown_03004140.unk_0e != 0) + { + gUnknown_03004140.unk_0e = 0; + switch (r8) + { + case 16: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 4; + } + break; + case 23: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 0; + } + break; + case 22: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x00, 0x00); + } + break; + case 25: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 6; + } + break; + case 26: + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 7; + gUnknown_03004140.unk_05 = 8; + } + break; + case 27: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_05 = 0; + if (gUnknown_03004140.unk_07 == 0) + { + sub_800D30C(0x13, 0x00); + } + } + break; + case 28: + if (r6 == 0) + { + if (gUnknown_03004140.unk_0b == 1 && gUnknown_03004140.unk_1a > 1) + { + gUnknown_03004140.unk_1a--; + } + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 10; + } + break; + case 29: + if (r6 == 0) + { + sp0 = sub_800D294(); + gUnknown_03004140.unk_14 = sp0; + if (sp0) + { + sub_800D30C(0x20, 0x01); + } + if (gUnknown_03004140.unk_0b && gUnknown_03004140.unk_1a != 1 && gUnknown_03007890->unk_08 == 4) + { + rfu_REQ_endSearchParent(); + rfu_waitREQComplete(); + gUnknown_03004140.unk_04 = 9; + gUnknown_03004140.unk_0b = 1; + } + } + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 11; + gUnknown_03004140.unk_05 = 0; + } + break; + case 30: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + if (gUnknown_03004140.unk_07 == 0) + { + if (gUnknown_03004140.unk_04 == 0) + { + sub_800D30C(0x21, 0x00); + } + } + else if (gUnknown_03004140.unk_07 != 7) + { + gUnknown_03004140.unk_04 = 5; + gUnknown_03004140.unk_07 = 5; + } + } + break; + case 31: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 13; + } + break; + case 32: + if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10) && !sp0) + { + gUnknown_03004140.unk_04 = 14; + } + if (gUnknown_03004140.unk_1a && --gUnknown_03004140.unk_1a == 0) + { + gUnknown_03004140.unk_04 = 14; + } + break; + case 33: + if (r6 == 0 && !rfu_getConnectParentStatus(&sp0, &gUnknown_03004140.unk_10)) + { + if (!sp0) + { + gUnknown_03004140.unk_04 = 19; + gUnknown_03004140.unk_05 = 15; + gUnknown_03004140.unk_1e = 0x22; + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_10; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + gUnknown_03004140.unk_1e = 0x23; + gUnknown_03004140.unk_14 = sp0; + if (gUnknown_03004140.unk_07) + { + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + } + } + sub_800D30C(gUnknown_03004140.unk_1e, 0x01); + gUnknown_03004140.unk_1e = 0; + } + break; + case 50: + if (r6 == 0) + { + gUnknown_03004140.unk_14 = gUnknown_03007890->unk_03; + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 17; + for (gUnknown_03004140.unk_10 = 0; gUnknown_03004140.unk_10 < 4; gUnknown_03004140.unk_10 ++) + { + if ((gUnknown_03007890->unk_03 >> gUnknown_03004140.unk_10) & 1) + { + break; + } + } + } + break; + case 51: + if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0) && sp0 < 2) + { + gUnknown_03004140.unk_04 = 18; + } + if (gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] && --gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] == 0) + { + gUnknown_03004140.unk_04 = 18; + } + break; + case 52: + if (r6 == 0 && !rfu_CHILD_getConnectRecoveryStatus(&sp0)) + { + if (!sp0) + { + gUnknown_03004140.unk_04 = 19; + gUnknown_03004140.unk_05 = 22; + gUnknown_03004140.unk_1e = 0x32; + } + else + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D334(gUnknown_03007890->unk_03); + gUnknown_03004140.unk_1e = 0x33; + } + gUnknown_03004140.unk_34[gUnknown_03004140.unk_10] = 0; + gUnknown_03004140.unk_30 = 0; + gUnknown_03004140.unk_0a = 0; + sub_800D30C(gUnknown_03004140.unk_1e, 0x01); + gUnknown_03004140.unk_1e = 0; + } + break; + case 39: + if (r6 == 0) + { + if (gUnknown_03004140.unk_05 == 22) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_11; + gUnknown_03004140.unk_05 = gUnknown_03004140.unk_12; + gUnknown_03004140.unk_02 = 1; + sub_800D30C(0x41, 0x00); + } + else if (gUnknown_03004140.unk_05 == 15) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_02 = 1; + sub_800D30C(0x41, 0x00); + gUnknown_03004140.unk_24 |= 1 << gUnknown_03004140.unk_10; + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = gUnknown_03004140.unk_26; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + tmp = &sp0; + *tmp = rfu_NI_CHILD_setSendGameName(gUnknown_03004140.unk_10, 0x0e); + if (*tmp) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D610(); + sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = sp0; + sub_800D30C(0x25, 0x01); + } + } + } + break; + case 61: + if (r6 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x42, 0x00); + } + break; + } + gUnknown_03004140.unk_0e = 1; + } + else if (r6 == 3 && gUnknown_03004140.unk_0f && (r8 == 0x24 || r8 == 0x26 || r8 == 0x27)) + { + rfu_REQ_RFUStatus(); + rfu_waitREQComplete(); + rfu_getRFUStatus(&sp0); + if (sp0 == 0 && gUnknown_03007890->unk_00 == 0) + { + stwiRecvBuffer = rfu_getSTWIRecvBuffer(); + stwiRecvBuffer[4] = gUnknown_03007890->unk_02; + stwiRecvBuffer[5] = 1; + sub_800C36C(0x29); + r6 = 0; + } + } + switch (r8) + { + case 48: + if (r6 == 0) + { + stwiRecvBuffer = rfu_getSTWIRecvBuffer(); + gUnknown_03004140.unk_14 = stwiRecvBuffer[8]; + sub_800D358(gUnknown_03004140.unk_14); + if (gUnknown_03004140.unk_30) + { + gUnknown_03004140.unk_30 &= ~gUnknown_03004140.unk_14; + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_14 >> i) & 1) + { + gUnknown_03004140.unk_34[i] = 0; + } + } + if (gUnknown_03004140.unk_06 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + } + } + sp0 = gUnknown_03004140.unk_00 & gUnknown_03004140.unk_14; + for (i = 0; i < 4; i++) + { + if ((sp0 >> i) & 1 && gUnknown_03004140.unk_01) + { + gUnknown_03004140.unk_01--; + } + } + gUnknown_03004140.unk_00 &= ~gUnknown_03004140.unk_14; + if (gUnknown_03004140.unk_07) + { + if (gUnknown_03007890->unk_00 == 0xFF) + { + if (gUnknown_03004140.unk_07 == 8) + { + gUnknown_03004140.unk_1a = gUnknown_03004140.unk_1c; + gUnknown_03004140.unk_07 = 6; + gUnknown_03004140.unk_04 = 6; + } + else if (gUnknown_03004140.unk_04 != 6 && gUnknown_03004140.unk_04 != 7) + { + gUnknown_03004140.unk_07 = 1; + gUnknown_03004140.unk_04 = 5; + } + } + } + if (gUnknown_03007890->unk_00 == 0xFF) + { + if (gUnknown_03004140.unk_04 == 0) + { + gUnknown_03004140.unk_06 = -1; + } + } + if (gUnknown_03004140.unk_0e == 0) + { + sub_800D30C(0x40, 0x01); + } + } + break; + case 38: + sub_800D20C(); + if (gUnknown_03007890->unk_00 != 0xFF) + { + sub_800D30C(0x50, 0x00); + } + break; + case 16: + case 61: + if (r6 == 0) + { + gUnknown_03004140.unk_0d = 0; + gUnknown_03004140.unk_01 = 0; + gUnknown_03004140.unk_00 = 0;; + gUnknown_03004140.unk_06 = -1; + sub_800D610(); + if (r8 == 61) + { + sub_800BFA0(); + } + } + break; + } + if (r6 != 0) + { + if (r8 == 28 && r6 != 0 && gUnknown_03004140.unk_07 == 4) + { + gUnknown_03007890->unk_00 = 1; + gUnknown_03007890->unk_02 = 15; + sub_800D334(15); + rfu_waitREQComplete(); + return; + } + else + { + gUnknown_03004140.unk_14 = r8; + gUnknown_03004140.unk_16 = r6; + if (gUnknown_03004140.unk_0e) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + } + sub_800D30C(0xf0, 0x02); + sub_800D610(); + } + } + if (r8 == 0xFF) + { + sub_800D30C(0xf2, 0x00); + sub_800D610(); + } +} + +static void sub_800CEB0(u16 r6) +{ + u8 r7; + u8 sp0; + + r7 = gUnknown_03004140.unk_0e; + gUnknown_03004140.unk_0e = 0; + gUnknown_03004140.unk_0f = 1; + if (gUnknown_03007890->unk_00 == 0) + { + sub_800C36C(r6); + if (gUnknown_03004140.unk_02 != 1) + { + sub_800D610(); + gUnknown_03004140.unk_0f = 0; + gUnknown_03004140.unk_0e = r7; + return; + } + } + else + { + if (!rfu_UNI_PARENT_getDRAC_ACK(&sp0)) + { + gUnknown_03004140.unk_03 |= sp0; + } + } + if (gUnknown_03004140.unk_44 != NULL) + { + gUnknown_03004140.unk_44(r6); + rfu_waitREQComplete(); + if (gUnknown_03004140.unk_02 == 2) + { + sub_800D610(); + } + } + gUnknown_03004140.unk_0f = 0; + gUnknown_03004140.unk_0e = r7; +} + +static void sub_800CF34(void) +{ + u8 flags; + u8 sp0; + u8 i; + u8 r5; + u8 r4; + const u16 *ptr; + + if (gUnknown_03004140.unk_04 == 5 || gUnknown_03004140.unk_04 == 6 || gUnknown_03004140.unk_04 == 7 || gUnknown_03004140.unk_04 == 8) + { + flags = ((gUnknown_03007890->unk_02 ^ gUnknown_03004140.unk_0c) & gUnknown_03007890->unk_02) & ~gUnknown_03007890->unk_07; + gUnknown_03004140.unk_0c = gUnknown_03007890->unk_02; + if (flags) + { + gUnknown_03004140.unk_14 = flags; + sub_800D30C(0x10, 0x01); + } + sp0 = 0x00; + for (i = 0; i < 4; i++) + { + r4 = 1 << i; + r5 = 0x00; + if (flags & r4) + { + gUnknown_03004140.unk_28[i] = gUnknown_03004140.unk_26; + gUnknown_03004140.unk_24 |= r4; + } + else if (gUnknown_03004140.unk_24 & r4) + { + if (gUnknown_03007880[i]->unk_34 == 0x46) + { + if (gUnknown_03007880[i]->unk_61 == 1) + { + r5 = 0x02; + for (ptr = gUnknown_03004140.unk_20; *ptr != 0xFFFF; ptr++) + { + if (gUnknown_03007890->unk_14[i].unk_04 == *ptr) + { + gUnknown_03004140.unk_00 |= r4; + gUnknown_03004140.unk_01++; + sp0 |= r4; + r5 |= 0x01; + break; + } + } + if (!(r5 & 0x01)) + { + r5 |= 0x04; + } + } + } + else if (--gUnknown_03004140.unk_28[i] == 0) + { + r5 = 0x06; + } + if (r5 & 0x02) + { + gUnknown_03004140.unk_24 &= ~r4; + gUnknown_03004140.unk_28[i] = 0; + rfu_clearSlot(0x08, i); + } + if (r5 & 0x04) + { + gUnknown_03004140.unk_0d |= r4; + } + } + } + if (sp0) + { + gUnknown_03004140.unk_14 = sp0; + sub_800D30C(0x11, 0x01); + } + if (gUnknown_03004140.unk_0d) + { + r5 = 0x01; + if (gUnknown_03007890->unk_06 && ((gUnknown_03004140.unk_03 & gUnknown_03004140.unk_00) != gUnknown_03004140.unk_00)) + { + r5 = 0x00; + } + if (r5) + { + sub_800D334(gUnknown_03004140.unk_0d); + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_0d; + gUnknown_03004140.unk_0d = 0; + sub_800D30C(0x12, 0x01); + } + } + if (gUnknown_03004140.unk_24 == 0 && gUnknown_03004140.unk_04 == 8) + { + if (gUnknown_03004140.unk_07 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D30C(0x14, 0x00); + } + else + { + if (gUnknown_03004140.unk_07 == 2) + { + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + } + else + { + gUnknown_03004140.unk_07 = 1; + gUnknown_03004140.unk_04 = 5; + } + if (gUnknown_03004140.unk_00) + { + gUnknown_03004140.unk_1a = 0; + gUnknown_03004140.unk_07 = 8; + gUnknown_03004140.unk_04 = 5; + } + } + } + } +} + +static void sub_800D158(void) +{ + u16 imeBak = REG_IME; + REG_IME = 0; + if (gUnknown_03004140.unk_04 == 15) + { + if (--gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] == 0 || gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x27) + { + sub_800D630(); + gUnknown_03004140.unk_04 = 24; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10); + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0; + } + } + REG_IME = imeBak; + if (gUnknown_03004140.unk_04 == 24) + { + if (gUnknown_03004140.unk_02 == 1) + { + sub_800D630(); + } + if (gUnknown_03004140.unk_02 == 0) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + sub_800D334(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + gUnknown_03004140.unk_14 = 0; + sub_800D30C(0x25, 0x01); + } + } +} + +static void sub_800D20C(void) +{ + if (gUnknown_03004140.unk_04 == 15 && gUnknown_03007880[gUnknown_03004140.unk_10]->unk_0 == 0x26) + { + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + rfu_clearSlot(4, gUnknown_03004140.unk_10); + gUnknown_03004140.unk_24 &= ~(1 << gUnknown_03004140.unk_10); + gUnknown_03004140.unk_28[gUnknown_03004140.unk_10] = 0; + sub_800D30C(0x24, 0x00); + } +} + +static void sub_800D268(void) +{ + if (gUnknown_03004140.unk_06 == 0 && gUnknown_03004140.unk_0a == 1) + { + gUnknown_03004140.unk_11 = gUnknown_03004140.unk_04; + gUnknown_03004140.unk_12 = gUnknown_03004140.unk_05; + gUnknown_03004140.unk_04 = 16; + gUnknown_03004140.unk_05 = 17; + gUnknown_03004140.unk_0a = 2; + } +} + +static u8 sub_800D294(void) +{ + u8 i; + const u16 *ptr; + u8 flags = 0x00; + + for (i = 0; i < gUnknown_03007890->unk_08; i++) + { + for (ptr = gUnknown_03004140.unk_20; *ptr != 0xffff; ptr++) + { + if (gUnknown_03007890->unk_14[i].unk_04 == *ptr) + { + flags |= (1 << i); + } + } + } + return flags; +} + +static void sub_800D30C(u8 a0, u8 a1) +{ + if (gUnknown_03004140.unk_40 != NULL) + { + gUnknown_03004140.unk_40(a0, a1); + } + gUnknown_03004140.unk_14 = gUnknown_03004140.unk_16 = 0; +} + +static void sub_800D334(u8 a0) +{ + u8 unk_0e_bak = gUnknown_03004140.unk_0e; + gUnknown_03004140.unk_0e = 1; + rfu_REQ_disconnect(a0); + rfu_waitREQComplete(); + gUnknown_03004140.unk_0e = unk_0e_bak; +} + +static void sub_800D358(u8 a0) +{ + u8 i; + + if (gUnknown_03007890->unk_04) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_0 & 0x8000 && gUnknown_03007880[i]->unk_1a & a0) + { + rfu_changeSendTarget(0x20, i, gUnknown_03007880[i]->unk_1a & ~a0); + } + } + } + if (gUnknown_03007890->unk_05) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_4e & a0) + { + rfu_NI_stopReceivingData(i); + } + } + } + if (gUnknown_03007890->unk_06) + { + gUnknown_03007890->unk_06 &= ~a0; + for (i = 0; i < 4; i++) + { + if (gUnknown_03007870[i]->unk_0 == 0x8024 && a0 & gUnknown_03007870[i]->unk_3) + { + gUnknown_03007870[i]->unk_3 &= ~a0; + } + } + } +} + +static void sub_800D434(void) +{ + u8 i; + u8 j; + u8 flags; + + if (gUnknown_03004140.unk_18) + { + if (gUnknown_03007890->unk_04) + { + for (i = 0; i < 4; i ++) + { + if (gUnknown_03007880[i]->unk_0 & 0x8000) + { + flags = 0; + for (j = 0; j < 4; j++) + { + if ((gUnknown_03007880[i]->unk_1a >> j) & 1 && gUnknown_03007880[j]->unk_2 > gUnknown_03004140.unk_18) + { + flags |= (1 << j); + } + if (flags) + { + rfu_changeSendTarget(0x20, i, flags ^ gUnknown_03007880[i]->unk_1a); + } + } + } + } + } + if (gUnknown_03007890->unk_05) + { + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_34 & 0x8000 && gUnknown_03007880[i]->unk_36 > gUnknown_03004140.unk_18) + { + rfu_NI_stopReceivingData(i); + } + } + } + } +} + +void sub_800D52C(void (*func)(u16)) +{ + gUnknown_03004140.unk_44 = func; + rfu_setMSCCallback(sub_800CEB0); +} + +void sub_800D544(void (*func)(u8, u8)) +{ + gUnknown_03004140.unk_40 = func; +} + +u8 sub_800D550(u8 a0, u16 a1) +{ + u16 imeBak; + if (gUnknown_03004140.unk_09 && a0 == 0 && gUnknown_03004140.unk_30) + { + return 5; + } + imeBak = REG_IME; + REG_IME = 0; + gUnknown_03004140.unk_09 = a0; + gUnknown_03004140.unk_32 = a1; + REG_IME = imeBak; + return 0; +} + +u8 sub_800D594(u16 a0) +{ + if (gUnknown_03007890->unk_04 | gUnknown_03007890->unk_05) + { + gUnknown_03004140.unk_14 = 6; + sub_800D30C(0xf3, 0x01); + return 6; + } + gUnknown_03004140.unk_18 = a0; + return 0; +} + +u8 sub_800D5D0(u8 a0) +{ + if (gUnknown_03004140.unk_04 == 9 || gUnknown_03004140.unk_04 == 10 || gUnknown_03004140.unk_04 == 11) + { + gUnknown_03004140.unk_14 = 7; + sub_800D30C(0xf3, 0x01); + return 7; + } + if (a0) + { + gUnknown_03004140.unk_0b = 1; + } + else + { + gUnknown_03004140.unk_0b = 0; + } + return 0; +} + +static void sub_800D610(void) +{ + if (gUnknown_03004140.unk_02) + { + gUnknown_03004140.unk_02 = 0; + sub_800D30C(0x45, 0x00); + } +} + +void sub_800D630(void) +{ + if (gUnknown_03004140.unk_02 == 0) + { + sub_800D30C(0x45, 0x00); + } + else if (gUnknown_03004140.unk_02 == 1) + { + gUnknown_03004140.unk_02 = 2; + } +} + +void sub_800D658(void) +{ + if (gUnknown_03004140.unk_07) + { + switch (gUnknown_03004140.unk_04) + { + case 5: + gUnknown_03004140.unk_07 = 3; + gUnknown_03004140.unk_04 = 9; + break; + case 6: + gUnknown_03004140.unk_07 = 2; + gUnknown_03004140.unk_1a = 1; + break; + case 7: + case 8: + gUnknown_03004140.unk_07 = 2; + break; + case 9: + case 10: + gUnknown_03004140.unk_1a = 40; + break; + case 11: + gUnknown_03004140.unk_1a = 40; + gUnknown_03004140.unk_04 = 10; + break; + } + } +} + +// TODO: Is there a file boundary here? + +void sub_800D6C8(struct UnkRfuStruct_2_Sub_124 *ptr) +{ + int i; + int j; + + for (i = 0; i < 32; i++) + { + for (j = 0; j < 70; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_8c1 = 0; + ptr->unk_8c0 = 0; + ptr->unk_8c2 = 0; + ptr->unk_8c3 = 0; +} + +void sub_800D724(struct UnkRfuStruct_2_Sub_9e8 *ptr) +{ + int i; + int j; + + for (i = 0; i < 40; i++) + { + for (j = 0; j < 14; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_231 = 0; + ptr->unk_230 = 0; + ptr->unk_232 = 0; + ptr->unk_233 = 0; +} + +void sub_800D780(struct UnkRfuStruct_Sub_Unused *ptr) +{ + int i; + int j; + + for (i = 0; i < 2; i++) + { + for (j = 0; j < 256; j++) + { + ptr->unk_00[i][j] = 0; + } + } + ptr->unk_201 = 0; + ptr->unk_200 = 0; + ptr->unk_202 = 0; + ptr->unk_203 = 0; +} + +void sub_800D7D8(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2) +{ + int i; + u16 imeBak; + u8 count; + + if (q1->unk_8c2 < 32) + { + imeBak = REG_IME; + REG_IME = 0; + count = 0; + for (i = 0; i < 70; i += 14) + { + if (q2[i] == 0 && q2[i + 1] == 0) + { + count++; + } + } + if (count != 5) + { + for (i = 0; i < 70; i++) + { + q1->unk_00[q1->unk_8c0][i] = q2[i]; + } + q1->unk_8c0++; + q1->unk_8c0 %= 32; + q1->unk_8c2++; + for (i = 0; i < 70; i++) + { + q2[i] = 0; + } + } + REG_IME = imeBak; + } + else + { + q1->unk_8c3 = 1; + } +} + +void sub_800D888(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2) +{ + int i; + u16 imeBak; + + if (q1->unk_232 < 40) + { + imeBak = REG_IME; + REG_IME = 0; + for (i = 0; i < 14; i++) + { + if (q2[i] != 0) + { + break; + } + } + if (i != 14) + { + for (i = 0; i < 14; i++) + { + q1->unk_00[q1->unk_230][i] = q2[i]; + } + q1->unk_230++; + q1->unk_230 %= 40; + q1->unk_232++; + for (i = 0; i < 14; i++) + { + q2[i] = 0; + } + } + REG_IME = imeBak; + } + else + { + q1->unk_233 = 1; + } +} + +bool8 sub_800D934(struct UnkRfuStruct_2_Sub_124 *q1, u8 *q2) +{ + u16 imeBak; + int i; + + imeBak = REG_IME; + REG_IME = 0; + if (q1->unk_8c0 == q1->unk_8c1 || q1->unk_8c3 != 0) + { + for (i = 0; i < 70; i++) + { + q2[i] = 0; + } + REG_IME = imeBak; + return FALSE; + } + for (i = 0; i < 70; i++) + { + q2[i] = q1->unk_00[q1->unk_8c1][i]; + } + q1->unk_8c1++; + q1->unk_8c1 %= 32; + q1->unk_8c2--; + REG_IME = imeBak; + return TRUE; +} + +bool8 sub_800D9DC(struct UnkRfuStruct_2_Sub_9e8 *q1, u8 *q2) +{ + int i; + u16 imeBak; + + if (q1->unk_230 == q1->unk_231 || q1->unk_233 != 0) + { + return FALSE; + } + imeBak = REG_IME; + REG_IME = 0; + for (i = 0; i < 14; i++) + { + q2[i] = q1->unk_00[q1->unk_231][i]; + } + q1->unk_231++; + q1->unk_231 %= 40; + q1->unk_232--; + REG_IME = imeBak; + return TRUE; +} + +void sub_800DA68(struct UnkRfuStruct_2_Sub_c1c *q1, const u8 *q2) +{ + int i; + + if (q2[1] == 0) + { + sub_800DAC8(q1, NULL); + } + else + { + for (i = 0; i < 14; i++) + { + q1->unk_00[q1->unk_1c][i] = q2[i]; + } + q1->unk_1c++; + q1->unk_1c %= 2; + if (q1->unk_1e < 2) + { + q1->unk_1e++; + } + else + { + q1->unk_1d = q1->unk_1c; + } + } +} + +static bool8 sub_800DAC8(struct UnkRfuStruct_2_Sub_c1c *q1, u8 *q2) +{ + int i; + + if (q1->unk_1e == 0) + { + return FALSE; + } + if (q2 != NULL) + { + for (i = 0; i < 14; i++) + { + q2[i] = q1->unk_00[q1->unk_1d][i]; + } + } + q1->unk_1d++; + q1->unk_1d %= 2; + q1->unk_1e--; + return TRUE; +} + +void sub_800DB18(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2) +{ + int i; + + if (q1->unk_202 < 2) + { + for (i = 0; i < 256; i++) + { + q1->unk_00[q1->unk_200][i] = q2[i]; + } + q1->unk_200++; + q1->unk_200 %= 2; + q1->unk_202++; + } + else + { + q1->unk_203 = 1; + } +} + +bool8 sub_800DB84(struct UnkRfuStruct_Sub_Unused *q1, u8 *q2) +{ + int i; + + if (q1->unk_200 == q1->unk_201 || q1->unk_203) + { + return FALSE; + } + for (i = 0; i < 256; i++) + { + q2[i] = q1->unk_00[q1->unk_201][i]; + } + q1->unk_201++; + q1->unk_201 %= 2; + q1->unk_202--; + return TRUE; +} + +void sub_800DBF8(u8 *q1, u8 mode) +{ + int i; + u8 rval; + u16 r5 = 0; + switch (mode) + { + case 0: + for (i = 0; i < 200; i++) + { + q1[i] = i + 1; + r5 += i + 1; + } + *((u16 *)(q1 + i)) = r5; + break; + case 1: + for (i = 0; i < 100; i++) + { + q1[i] = i + 1; + r5 += i + 1; + } + *((u16 *)(q1 + 200)) = r5; + break; + case 2: + for (i = 0; i < 200; i++) + { + rval = Random(); + q1[i] = rval; + r5 += rval; + } + *((u16 *)(q1 + i)) = r5; + break; + case 3: + for (i = 0; i < 200; i++) + { + q1[i] = i + 1 + gUnknown_03000D74; + r5 += (i + 1 + gUnknown_03000D74) & 0xFF; + } + *((u16 *)(q1 + i)) = r5; + gUnknown_03000D74++; + break; + } +} + +void PkmnStrToASCII(u8 *q1, const u8 *q2) +{ + int i; + + for (i = 0; q2[i] != EOS; i++) + { + q1[i] = sWireless_RSEtoASCIITable[q2[i]]; + } + q1[i] = 0; +} + +void ASCIIToPkmnStr(u8 *q1, const u8 *q2) +{ + int i; + + for (i = 0; q2[i] != 0; i++) + { + q1[i] = sWireless_ASCIItoRSETable[q2[i]]; + } + q1[i] = EOS; +} + +#ifdef NONMATCHING +u8 sub_800DD1C(u8 maxFlags) +{ + u8 flagCount = 0; + u8 flags = gUnknown_03007890->unk_02; + u8 i; + + if (gUnknown_03007890->unk_00 == 1) + { + i = 0; + for (i = 0; i < 4; flags >>= 1, i++) + { + if (flags & 1) + { + if (maxFlags == flagCount + 1) + { + return gUnknown_03007890->unk_0a[i]; + } + flagCount++; + } + } + } + else + { + for (i = 0; i < 4; flags >>= 1, i++) + { + if (flags & 1) + { + return gUnknown_03007890->unk_0a[i]; + } + } + } + return 0; +} +#else +NAKED u8 sub_800DD1C(u8 maxFlags) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tmovs r6, 0\n" + "\tldr r0, =gUnknown_03007890\n" + "\tldr r4, [r0]\n" + "\tldrb r2, [r4, 0x2]\n" + "\tldrb r1, [r4]\n" + "\tadds r7, r0, 0\n" + "\tcmp r1, 0x1\n" + "\tbne _0800DD72\n" + "\tmovs r3, 0\n" + "\tands r1, r2\n" + "\tcmp r1, 0\n" + "\tbeq _0800DD4E\n" + "\tcmp r5, 0x1\n" + "\tbne _0800DD48\n" + "\tldrb r0, [r4, 0xA]\n" + "\tb _0800DD8C\n" + "\t.pool\n" + "_0800DD48:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r6, r0, 24\n" + "_0800DD4E:\n" + "\tlsrs r2, 1\n" + "\tadds r0, r3, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r3, r0, 24\n" + "\tcmp r3, 0x3\n" + "\tbhi _0800DD8A\n" + "\tmovs r0, 0x1\n" + "\tands r0, r2\n" + "\tcmp r0, 0\n" + "\tbeq _0800DD4E\n" + "\tadds r0, r6, 0x1\n" + "\tcmp r5, r0\n" + "\tbne _0800DD48\n" + "_0800DD68:\n" + "\tldr r0, [r7]\n" + "\tadds r0, 0xA\n" + "\tadds r0, r3\n" + "\tldrb r0, [r0]\n" + "\tb _0800DD8C\n" + "_0800DD72:\n" + "\tmovs r3, 0\n" + "\tmovs r1, 0x1\n" + "_0800DD76:\n" + "\tadds r0, r2, 0\n" + "\tands r0, r1\n" + "\tcmp r0, 0\n" + "\tbne _0800DD68\n" + "\tlsrs r2, 1\n" + "\tadds r0, r3, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r3, r0, 24\n" + "\tcmp r3, 0x3\n" + "\tbls _0800DD76\n" + "_0800DD8A:\n" + "\tmovs r0, 0\n" + "_0800DD8C:\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1"); +} +#endif + +void sub_800DD94(struct UnkLinkRfuStruct_02022B14 *data, u8 r9, bool32 r2, int r3) +{ + int i; + + for (i = 0; i < 2; i++) + { + data->playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i]; + } + for (i = 0; i < 4; i++) + { + data->unk_04[i] = r3; + r3 >>= 8; + } + data->playerGender = gSaveBlock2Ptr->playerGender; + data->unk_0a_0 = r9; + data->unk_0a_7 = r2; + data->unk_00_0 = 2; + data->unk_01_2 = 3; + data->unk_00_4 = 0; + data->unk_00_5 = 0; + data->unk_00_6 = 0; + data->unk_00_7 = FlagGet(FLAG_0x87F); + data->unk_01_0 = IsNationalPokedexEnabled(); + data->unk_01_1 = FlagGet(FLAG_SYS_GAME_CLEAR); +} + +bool8 sub_800DE7C(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2, u8 idx) +{ + bool8 retVal; + + if (gUnknown_03004140.unk_06 == 1) + { + retVal = TRUE; + if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04) && ((gUnknown_03007890->unk_07 >> idx) & 1)) + { + memcpy(buff1, &gUnknown_03007890->unk_14[idx].unk_06, sizeof(gUnknown_03007890->unk_14[idx].unk_06)); + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, sizeof(gUnknown_03007890->unk_14[idx].unk_15)); + } + else + { + memset(buff1, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_06)); + memset(buff2, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_15)); + } + } + else + { + retVal = FALSE; + if (sub_8010454(gUnknown_03007890->unk_14[idx].unk_04)) + { + memcpy(buff1, &gUnknown_03007890->unk_14[idx].unk_06, sizeof(gUnknown_03007890->unk_14[idx].unk_06)); + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, sizeof(gUnknown_03007890->unk_14[idx].unk_15)); + } + else + { + memset(buff1, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_06)); + memset(buff2, 0, sizeof(gUnknown_03007890->unk_14[idx].unk_15)); + } + } + return retVal; +} + +bool8 sub_800DF34(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2, u8 idx) +{ + bool8 retVal = FALSE; + if (gUnknown_03007890->unk_14[idx].unk_04 == 0x7F7D) + { + *buff1 = gUnknown_03007890->unk_14[idx].unk_06; + memcpy(buff2, gUnknown_03007890->unk_14[idx].unk_15, 8); + retVal = TRUE; + } + else + { + *buff1 = (struct UnkLinkRfuStruct_02022B14){}; + memset(buff2, 0, 8); + } + return retVal; +} + +void sub_800DF90(struct UnkLinkRfuStruct_02022B14 *buff1, u8 *buff2) +{ + *buff1 = gUnknown_02022B14; + memcpy(buff2, gUnknown_02022B22, 8); +} + +void CreateWirelessStatusIndicatorSprite(u8 x, u8 y) +{ + u8 sprId; + + if (x == 0 && y == 0) + { + x = 0xE7; + y = 0x08; + } + if (gUnknown_03007890->unk_00 == 1) + { + sprId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0); + gSprites[sprId].data[7] = 0x1234; + gSprites[sprId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag); + gSprites[sprId].invisible = TRUE; + gWirelessStatusIndicatorSpriteId = sprId; + } + else + { + gWirelessStatusIndicatorSpriteId = CreateSprite(&sWirelessStatusIndicatorSpriteTemplate, x, y, 0); + gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0x1234; + gSprites[gWirelessStatusIndicatorSpriteId].data[6] = GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag); + gSprites[gWirelessStatusIndicatorSpriteId].invisible = TRUE; + } +} + +void sub_800E084(void) +{ + if (gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234) + { + gSprites[gWirelessStatusIndicatorSpriteId].data[7] = 0; + DestroySprite(&gSprites[gWirelessStatusIndicatorSpriteId]); + gMain.oamBuffer[125] = gDummyOamData; + CpuCopy16(&gDummyOamData, (struct OamData *)OAM + 125, sizeof(struct OamData)); + } +} + +void sub_800E0E8(void) +{ + if (GetSpriteTileStartByTag(sWirelessStatusIndicatorSpriteSheet.tag) == 0xFFFF) + { + LoadCompressedObjectPic(&sWirelessStatusIndicatorSpriteSheet); + } + LoadSpritePalette(&sWirelessStatusIndicatorSpritePalette); + gWirelessStatusIndicatorSpriteId = 0xFF; +} + +u8 sub_800E124(void) +{ + u8 i; + u8 flags = gUnknown_03007890->unk_02; + for (i = 0; i < 4; i++) + { + if (flags & 1) + { + return gUnknown_03007890->unk_0a[i]; + } + flags >>= 1; + } + return 0; +} + +void sub_800E15C(struct Sprite *sprite, int signalStrengthAnimNum) +{ + if (sprite->data[2] != signalStrengthAnimNum) + { + sprite->data[2] = signalStrengthAnimNum; + sprite->data[3] = 0; + sprite->data[4] = 0; + } +} + +void sub_800E174(void) +{ + if (gWirelessStatusIndicatorSpriteId != 0xFF && gSprites[gWirelessStatusIndicatorSpriteId].data[7] == 0x1234) + { + struct Sprite *sprite = &gSprites[gWirelessStatusIndicatorSpriteId]; + u8 signalStrength = 255; + u8 i = 0; + if (gUnknown_03007890->unk_00 == 1) + { + for (i = 0; i < GetLinkPlayerCount() - 1; i++) + { + if (signalStrength >= sub_800DD1C(i + 1)) + { + signalStrength = sub_800DD1C(i + 1); + } + } + } + else + { + signalStrength = sub_800E124(); + } + if (sub_8012224() == TRUE) + { + sprite->data[0] = 4; + } + else if (signalStrength < 25) + { + sprite->data[0] = 3; + } + else if (signalStrength >= 25 && signalStrength < 127) + { + sprite->data[0] = 2; + } + else if (signalStrength >= 127 && signalStrength < 229) + { + sprite->data[0] = 1; + } + else if (signalStrength >= 229) + { + sprite->data[0] = 0; + } + if (sprite->data[0] != sprite->data[1]) + { + sub_800E15C(sprite, sprite->data[0]); + sprite->data[1] = sprite->data[0]; + } + if (sprite->anims[sprite->data[2]][sprite->data[4]].frame.duration < sprite->data[3]) + { + sprite->data[4]++; + sprite->data[3] = 0; + if (sprite->anims[sprite->data[2]][sprite->data[4]].type == -2) + { + sprite->data[4] = 0; + } + } + else + { + sprite->data[3]++; + } + gMain.oamBuffer[125] = sWirelessStatusIndicatorOamData; + gMain.oamBuffer[125].x = sprite->pos1.x + sprite->centerToCornerVecX; + gMain.oamBuffer[125].y = sprite->pos1.y + sprite->centerToCornerVecY; + gMain.oamBuffer[125].paletteNum = sprite->oam.paletteNum; + gMain.oamBuffer[125].tileNum = sprite->data[6] + sprite->anims[sprite->data[2]][sprite->data[4]].frame.imageValue; + CpuCopy16(gMain.oamBuffer + 125, (struct OamData *)OAM + 125, sizeof(struct OamData)); + if (sub_8011A74() == 1) + { + sub_800E084(); + } + } +} + +void sub_800E378(struct UnkSaveSubstruct_3b98 *dest, u32 trainerId, const u8 *name) +{ + dest->trainerId = trainerId; + StringCopy(dest->trainerName, name); +} + +bool32 sub_800E388(const u8 *name) +{ + int i; + + for (i = 0; i < 8; i++) + { + if (name[i] != 0) + { + return TRUE; + } + } + return FALSE; +} + +void sub_800E3A8(void) +{ + if (gWirelessCommType != 0) + { + int i; + int j; + int cnt; + int sp0[5]; + struct UnkSaveSubstruct_3b98 *sp14 = calloc(20, sizeof(struct UnkSaveSubstruct_3b98)); + for (i = 0; i < GetLinkPlayerCount(); i++) + { + sp0[i] = -1; + for (j = 0; j < 20; j++) + { + if ((u16)gLinkPlayers[i].trainerId == gSaveBlock1Ptr->unk_3B98[j].trainerId && StringCompare(gLinkPlayers[i].name, gSaveBlock1Ptr->unk_3B98[j].trainerName) == 0) + { + sp0[i] = j; + } + } + } + cnt = 0; + for (i = 0; i < GetLinkPlayerCount(); i++) + { + if (i != GetMultiplayerId() && gLinkPlayers[i].language != LANGUAGE_JAPANESE) + { + sub_800E378(&sp14[cnt], (u16)gLinkPlayers[i].trainerId, gLinkPlayers[i].name); + if (sp0[i] >= 0) + { + memset(gSaveBlock1Ptr->unk_3B98[sp0[i]].trainerName, 0, 8); + } + cnt++; + } + } + for (i = 0; i < 20; i++) + { + if (sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName)) + { + sub_800E378(&sp14[cnt], gSaveBlock1Ptr->unk_3B98[i].trainerId, gSaveBlock1Ptr->unk_3B98[i].trainerName); + if (++cnt >= 20) + { + break; + } + } + } + memcpy(gSaveBlock1Ptr->unk_3B98, sp14, 20 * sizeof(struct UnkSaveSubstruct_3b98)); + free(sp14); + } +} + +bool32 sub_800E540(u16 id, u8 *name) +{ + int i; + + for (i = 0; i < 20; i++) + { + if (StringCompare(gSaveBlock1Ptr->unk_3B98[i].trainerName, name) == 0 && gSaveBlock1Ptr->unk_3B98[i].trainerId == id) + { + return TRUE; + } + if (!sub_800E388(gSaveBlock1Ptr->unk_3B98[i].trainerName)) + { + return FALSE; + } + } + return FALSE; +} + +void sub_800E5AC(void) +{ + int i; + + for (i = 0; i < 20; i++) + { + gSaveBlock1Ptr->unk_3B98[i].trainerId = 0; + CpuFill16(0, gSaveBlock1Ptr->unk_3B98[i].trainerName, 8); + } +} + +void nullsub_5(void *unused_0, u8 unused_1, u8 unused_2) +{ + // debug? +} + +void nullsub_13(u8 unused_0, u8 unused_1, u8 unused_2, u8 unused_3) +{ + +} + +void sub_800E604(void) +{ + int i; + u8 unk_ee_bak = gUnknown_03005000.unk_ee; + CpuFill16(0, &gUnknown_03005000, sizeof gUnknown_03005000); + gUnknown_03005000.unk_ee = unk_ee_bak; + gUnknown_03005000.unk_0c = 0xFF; + if (gUnknown_03005000.unk_ee != 4) + { + gUnknown_03005000.unk_ee = 0; + } + for (i = 0; i < 5; i++) + { + sub_800FCC4(gUnknown_03005000.unk_80 + i); + } + sub_800FCC4(&gUnknown_03005000.unk_6c); + sub_800D6C8(&gUnknown_03005000.unk_124); + sub_800D724(&gUnknown_03005000.unk_9e8); + CpuFill16(0, gSendCmd, sizeof gSendCmd); + CpuFill16(0, gRecvCmds, sizeof gRecvCmds); + CpuFill16(0, gLinkPlayers, sizeof gLinkPlayers) +} + +void sub_800E6D0(void) +{ + IntrFunc serialIntr = gIntrTable[1]; + IntrFunc timerIntr = gIntrTable[2]; + sub_800E700(); + rfu_REQ_stopMode(); + rfu_waitREQComplete(); + REG_IME = 0; + gIntrTable[1] = serialIntr; + gIntrTable[2] = timerIntr; + REG_IME = INTR_FLAG_VBLANK; +} + +void sub_800E700(void) +{ + if (!rfu_initializeAPI(gUnknown_03004140.unk_50, sizeof gUnknown_03004140.unk_50, gIntrTable + 1, TRUE)) + { + gLinkType = 0; + sub_800AAF4(); + sub_80111B0(0); + sub_800E604(); + rfu_setTimerInterrupt(3, gIntrTable + 2); + } +} + +void sub_800E748(u8 taskId) +{ + sub_8010750(); + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_02022B2C); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 2: + sub_800C054(gUnknown_03005000.unk_0c, 0, 240, gUnknown_082ED6E0); + gUnknown_03005000.unk_04 = 3; + gTasks[taskId].data[1] = 6; + break; + case 3: + break; + case 4: + sub_800C27C(FALSE); + gUnknown_03005000.unk_04 = 5; + break; + case 5: + break; + case 18: + gUnknown_03005000.unk_cdb = 0; + sub_800D52C(sub_800EDBC); + sub_800EAB4(); + sub_800EAFC(); + gUnknown_03005000.unk_04 = 20; + gTasks[taskId].data[1] = 8; + CreateTask(sub_801084C, 5); + DestroyTask(taskId); + break; + } +} + +u8 sub_800E87C(u8 idx) +{ + return gUnknown_082ED6A5[idx]; +} + +void sub_800E88C(int r2, int r5) +{ + u8 i; + u8 r4 = 1; + int r1 = r2; + int r6 = 0; + if (r5 == -1) + { + for (i = 0; i < 4; r2 >>= 1, i++) + { + if (r2 & 1) + { + gUnknown_03005000.unk_cde[i] = r4; + r4++; + } + } + } + else + { + for (i = 0; i < 4; r1 >>= 1, i++) + { + if (!(r1 & 1)) + { + gUnknown_03005000.unk_cde[i] = 0; + } + } + for (r4 = 4; r4 != 0; r4--) + { + for (i = 0; i < 4 && gUnknown_03005000.unk_cde[i] != r4; i++); + if (i == 4) + { + r6 = r4; + } + } + for (r5 &= ~r2, i = 0; i < 4; r5 >>= 1, i++) + { + if (r5 & 1) + { + gUnknown_03005000.unk_cde[i] = r6++; + } + } + } +} + +void sub_800E94C(u8 taskId) +{ + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_082ED608); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 6: + sub_800C054(gUnknown_03005000.unk_0c, 0, 0xf0, gUnknown_082ED6E0); + gUnknown_03005000.unk_04 = 7; + gTasks[taskId].data[1] = 7; + break; + case 7: + break; + case 9: + gTasks[taskId].data[1] = 10; + break; + case 11: + switch (sub_80107A0()) + { + case 5: + gUnknown_03005000.unk_04 = 12; + break; + case 6: + case 9: + sub_800D630(); + gUnknown_03005000.unk_ce4 = 2; + DestroyTask(taskId); + break; + } + break; + case 12: + { + u8 r5 = 1 << gUnknown_03005000.unk_c3e; + rfu_clearSlot(12, gUnknown_03005000.unk_c3e); + rfu_setRecvBuffer(16, gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_c3f, 70); + rfu_UNI_setSendData(r5, gUnknown_03005000.unk_4c, 14); + gTasks[taskId].data[1] = 8; + DestroyTask(taskId); + if (gUnknown_02022B44.unk_0f == 0) + { + sub_801227C(); + gUnknown_02022B44.unk_0f++; + } + CreateTask(sub_801084C, 5); + break; + } + } +} + +static void sub_800EAB4(void) +{ + u8 i; + u8 r5 = gUnknown_03004140.unk_00; + for (i = 0; i < 4; i++) + { + if (r5 & 1) + { + rfu_setRecvBuffer(16, i, gUnknown_03005000.unk_14[i], 14); + rfu_clearSlot(3, i); + } + r5 >>= 1; + } +} + +static void sub_800EAFC(void) +{ + u8 r5 = gUnknown_03004140.unk_00; + rfu_UNI_setSendData(r5, gUnknown_03005000.unk_c87, 70); + gUnknown_03005000.unk_cda = sub_800E87C(r5); + gUnknown_03005000.unk_ce2 = r5; + sub_800E88C(r5, -1); + gUnknown_03005000.unk_0c = 1; +} + +void sub_800EB44(u8 taskId) +{ + if (sub_800F7DC()->unk_0a_0 == 0x54 && sub_8011A74() == 4) + { + rfu_REQ_disconnect(gUnknown_03004140.unk_00); + rfu_waitREQComplete(); + sub_8011A64(0, 0); + } + switch (gUnknown_03005000.unk_04) + { + case 0: + sub_800BFCC(&gUnknown_02022B2C); + gUnknown_03005000.unk_04 = 1; + gTasks[taskId].data[1] = 1; + break; + case 1: + break; + case 17: + sub_800C054(2, 0, 240, gUnknown_082ED6E0); + sub_800D52C(sub_800ED34); + gUnknown_03005000.unk_04 = 18; + break; + case 18: + break; + case 13: + if (rfu_UNI_setSendData(1 << gUnknown_03005000.unk_c3e, gUnknown_03005000.unk_4c, 14) == 0) + { + gUnknown_03005000.unk_0c = 0; + DestroyTask(taskId); + if (gTasks[taskId].data[7]) + { + CreateTask(sub_8010D0C, 1); + } + else + { + CreateTask(sub_801084C, 5); + } + } + break; + case 14: + sub_800C27C(0); + gUnknown_03005000.unk_04 = 15; + break; + case 15: + break; + case 16: + gUnknown_03005000.unk_cdb = 0; + sub_800D52C(sub_800EDBC); + sub_8011068(1); + sub_800EAB4(); + sub_800EAFC(); + gUnknown_03005000.unk_04 = 20; + gTasks[taskId].data[1] = 8; + gUnknown_03005000.unk_0c = 1; + CreateTask(sub_801084C, 5); + gUnknown_03005000.unk_ce8 = 1; + DestroyTask(taskId); + break; + } +} + +void sub_800ED10(void) +{ + sub_800C054(1, 0, 240, gUnknown_082ED6E0); +} + +void sub_800ED28(void) +{ + sub_800C27C(FALSE); +} + +void sub_800ED34(u16 unused) +{ + int i; + + for (i = 0; i < 14; i++) + { + gUnknown_03005000.unk_4c[i] = 0; + } + rfu_REQ_recvData(); + rfu_waitREQComplete(); + if (gUnknown_03007870[gUnknown_03005000.unk_c3e]->unk_12) + { + gUnknown_03005000.unk_cd0++; + sub_800D7D8(&gUnknown_03005000.unk_124, gUnknown_03005000.unk_c3f); + gUnknown_02022B44.unk_06++; + sub_800F048(); + rfu_UNI_readySendData(gUnknown_03005000.unk_c3e); + rfu_UNI_clearRecvNewDataFlag(gUnknown_03005000.unk_c3e); + } + rfu_REQ_sendData_wrapper(1); +} + +static void sub_800EDBC(u16 unused) +{ + gUnknown_03005000.unk_cdb = 1; +} + +void sub_800EDD4(void) +{ + u8 i; + + sub_800C048(); + if (gUnknown_03005000.unk_0c == 1) + { + if (FuncIsActiveTask(sub_800E748) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + else if (gUnknown_03005000.unk_0c == 0) + { + if (FuncIsActiveTask(sub_800E94C) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + else if (gUnknown_03005000.unk_0c == 2) + { + if (FuncIsActiveTask(sub_800EB44) == TRUE) + { + DestroyTask(gUnknown_03005000.unk_67); + sub_800E604(); + } + } + for (i = 0; i < 3; i++) + { + if (FuncIsActiveTask(gUnknown_082ED7E0[i]) == TRUE) + { + DestroyTask(FindTaskIdByFunc(gUnknown_082ED7E0[i])); + } + } +} + +void sub_800EE78(void) +{ + gUnknown_03005000.unk_67 = CreateTask(sub_800E748, 1); +} + +bool8 sub_800EE94(void) +{ + if (gUnknown_03005000.unk_04 == 7 && gUnknown_03005000.unk_ccd) + { + return TRUE; + } + return FALSE; +} + +bool8 sub_800EEBC(void) +{ + if (gUnknown_03005000.unk_04 == 7 && !sub_800C12C(gUnknown_03007890->unk_14[gUnknown_03005000.unk_c3d].unk_00, 240)) + { + gUnknown_03005000.unk_04 = 9; + return TRUE; + } + return FALSE; +} + +void sub_800EF00(void) +{ + gUnknown_03005000.unk_67 = CreateTask(sub_800E94C, 1); +} + +bool8 sub_800EF1C(void) +{ + if (gUnknown_03004140.unk_00) + { + return TRUE; + } + return FALSE; +} + +void sub_800EF38(void) +{ + gUnknown_03005000.unk_04 = 4; + gUnknown_03005000.unk_ce7 = gUnknown_03004140.unk_00; +} + +bool8 sub_800EF58(bool32 a0) +{ + if (gUnknown_03005000.unk_04 == 17 || a0) + { + gUnknown_03005000.unk_04 = 18; + return TRUE; + } + return FALSE; +} + +void sub_800EF7C(void) +{ + gUnknown_03005000.unk_04 = 14; +} + +void sub_800EF88(u8 a0) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + if (a0 & 1) + { + rfu_UNI_readySendData(i); + break; + } + a0 >>= 1; + } +} + +#ifdef NONMATCHING +// FIXME: gUnknown_03005000.unk_c87 should be in r5 +// FIXME: gRecvCmds should be in r6 and r7 +void sub_800EFB0(void) +{ + int i, j; + for (i = 0; i < 5; i++) + { + for (j = 0; j < 7; j++) + { + gUnknown_03005000.unk_c87[i][j][1] = gRecvCmds[i][j] >> 8; + gUnknown_03005000.unk_c87[i][j][0] = gRecvCmds[i][j]; + } + } + CpuFill16(0, gRecvCmds, sizeof gRecvCmds); +} +#else +NAKED void sub_800EFB0(void) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tsub sp, 0x4\n" + "\tmovs r2, 0\n" + "\tldr r7, =gRecvCmds\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r6, r7, 0\n" + "\tldr r1, =0x00000c87\n" + "\tadds r5, r0, r1\n" + "_0800EFC0:\n" + "\tmovs r3, 0\n" + "\tlsls r0, r2, 3\n" + "\tlsls r1, r2, 4\n" + "\tadds r4, r2, 0x1\n" + "\tsubs r0, r2\n" + "\tlsls r0, 1\n" + "\tadds r2, r0, r5\n" + "\tadds r1, r6\n" + "_0800EFD0:\n" + "\tldrh r0, [r1]\n" + "\tlsrs r0, 8\n" + "\tstrb r0, [r2, 0x1]\n" + "\tldrh r0, [r1]\n" + "\tstrb r0, [r2]\n" + "\tadds r2, 0x2\n" + "\tadds r1, 0x2\n" + "\tadds r3, 0x1\n" + "\tcmp r3, 0x6\n" + "\tble _0800EFD0\n" + "\tadds r2, r4, 0\n" + "\tcmp r2, 0x4\n" + "\tble _0800EFC0\n" + "\tmovs r0, 0\n" + "\tmov r1, sp\n" + "\tstrh r0, [r1]\n" + "\tldr r2, =0x01000028\n" + "\tmov r0, sp\n" + "\tadds r1, r7, 0\n" + "\tbl CpuSet\n" + "\tadd sp, 0x4\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800F014(void) +{ + int i; + for (i = 0; i < 7; i++) + { + gRecvCmds[0][i] = gSendCmd[i]; + } + for (i = 0; i < 7; i++) + { + gSendCmd[i] = 0; + } +} + +static void sub_800F048(void) +{ + if (gUnknown_03005000.unk_c3c) + { + u8 r2 = sub_800DAC8(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c); + if (gUnknown_03005000.unk_c1c.unk_1e == 0) + { + gUnknown_03005000.unk_c3c = 0; + } + if (r2) + { + return; + } + } + if (gUnknown_03005000.unk_c3c == 0) + { + sub_800D9DC(&gUnknown_03005000.unk_9e8, gUnknown_03005000.unk_4c); + sub_800DA68(&gUnknown_03005000.unk_c1c, gUnknown_03005000.unk_4c); + } +} + +bool32 sub_800F0B8(void) +{ + int i; + int j; + + if (gUnknown_03007890->unk_06 == 0) + { + return FALSE; + } + for (i = 0; i < 5; i++) + { + for (j = 0; j < 7; j++) + { + if (gRecvCmds[i][j] != 0) + { + return FALSE; + } + } + } + return TRUE; +} + +bool32 sub_800F0F8(void) +{ + if (gUnknown_03005000.unk_04 < 20) + { + rfu_REQ_recvData(); + rfu_waitREQComplete(); + rfu_REQ_sendData_wrapper(0); + } + else + { + gUnknown_03005000.unk_cdb = 0; + if ((gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02) == gUnknown_03005000.unk_ce2 && (gUnknown_03005000.unk_ce2 & gUnknown_03007890->unk_02)) + { + if (!gUnknown_03005000.unk_cdc) + { + if (gUnknown_03005000.unk_ce3) + { + sub_8011D6C(gUnknown_03005000.unk_ce3); + gUnknown_03005000.unk_ce3 = 0; + if (gUnknown_03005000.unk_ce4 == 1) + { + sub_8011A64(2, 0x8000); + sub_8011170(0x8000); + return FALSE; + } + if (!gUnknown_03004140.unk_00) + { + sub_800EDD4(); + gReceivedRemoteLinkPlayers = 0; + return FALSE; + } + } + sub_800EFB0(); + rfu_UNI_readySendData(gUnknown_03005000.unk_cda); + rfu_REQ_sendData_wrapper(1); + } + else + { + rfu_REQ_PARENT_resumeRetransmitAndChange(); + } + gUnknown_03005000.unk_0e = 1; + } + } + return FALSE; +} + +bool32 sub_800F1E0(void) +{ + u16 i; + u16 flags; + u8 r0; + u16 j; + u8 retval; + + if (gUnknown_03005000.unk_04 >= 20 && gUnknown_03005000.unk_0e == 1) + { + rfu_waitREQComplete(); + while (gUnknown_03005000.unk_cdb == 0) + { + if (gUnknown_03005000.unk_ee != 0) + { + return FALSE; + } + } + rfu_REQ_recvData(); + rfu_waitREQComplete(); + if ((gUnknown_03004140.unk_03 & gUnknown_03005000.unk_ce2) == gUnknown_03005000.unk_ce2) + { + gUnknown_03005000.unk_cdc = 0; + gUnknown_02022B44.unk_06++; + flags = gUnknown_03004140.unk_00; + for (i = 0; i < 4; i++) + { + if (flags & 1) + { + if (gUnknown_03005000.unk_14[i][1]) + { + if (gUnknown_03005000.unk_cee[i] != 0xff && (gUnknown_03005000.unk_14[i][0] >> 5) != ((gUnknown_03005000.unk_cee[i] + 1) & 7)) + { + if (++gUnknown_03005000.unk_cea[i] > 4) + sub_8011170(0x8100); + } + else + { + gUnknown_03005000.unk_cee[i] = gUnknown_03005000.unk_14[i][0] / 32; + gUnknown_03005000.unk_cea[i] = 0; + gUnknown_03005000.unk_14[i][0] &= 0x1f; + r0 = gUnknown_03005000.unk_cde[i]; + for (j = 0; j < 7; j++) + { + gRecvCmds[r0][j] = (gUnknown_03005000.unk_14[i][(j << 1) + 1] << 8) | gUnknown_03005000.unk_14[i][(j << 1) + 0]; + gUnknown_03005000.unk_14[i][(j << 1) + 1] = 0; + gUnknown_03005000.unk_14[i][(j << 1) + 0] = 0; + } + } + } + rfu_UNI_clearRecvNewDataFlag(i); + } + flags >>= 1; + } + sub_800F014(); + sub_800F86C(0); + sub_8010528(); + if (gUnknown_03005000.unk_ce5 && !gUnknown_03005000.unk_cd9) + { + gUnknown_02022B44.unk_0e = 0; + rfu_clearSlot(3, gUnknown_03005000.unk_cda); + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce5 >> i) & 1) + { + rfu_setRecvBuffer(0x10, i, gUnknown_03005000.unk_14[i], 14); + } + } + sub_800E88C(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_ce2 | gUnknown_03005000.unk_ce5); + gUnknown_03005000.unk_ce9 = gUnknown_03005000.unk_ce5; + gUnknown_03005000.unk_ce2 |= gUnknown_03005000.unk_ce5; + gUnknown_03005000.unk_ce5 = 0; + rfu_UNI_setSendData(gUnknown_03005000.unk_ce2, gUnknown_03005000.unk_c87, 70); + gUnknown_03005000.unk_cda = sub_800E87C(gUnknown_03005000.unk_ce2); + CreateTask(sub_8010AAC, 0); + } + } + else + { + gUnknown_03005000.unk_cdc = 1; + gUnknown_03005000.unk_0e = 0; + } + gUnknown_03005000.unk_0e = 0; + } + retval = gUnknown_03005000.unk_cdc; + return gUnknown_03007890->unk_06 ? retval & 1 : FALSE; +} + +void sub_800F498(u16 *a0, u8 *a1) +{ + int i; + + if (a0[0]) + { + a0[0] |= (gUnknown_03005000.unk_102 << 5); + gUnknown_03005000.unk_102 = (gUnknown_03005000.unk_102 + 1) & 7; + for (i = 0; i < 7; i++) + { + a1[2 * i + 1] = a0[i] >> 8; + a1[2 * i + 0] = a0[i]; + } + } + else + { + for (i = 0; i < 14; i++) + a1[i] = 0; + } +} + +bool32 sub_800F4F0(void) +{ + u8 i; + u8 j; + u8 sp00[MAX_RFU_PLAYERS * (2 * (CMD_LENGTH - 1))]; + u8 sp48[2 * (CMD_LENGTH - 1)]; + u8 switchval; + + sub_800D934(&gUnknown_03005000.unk_124, sp00); + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + for (j = 0; j < CMD_LENGTH - 1; j++) + { + gRecvCmds[i][j] = (sp00[i * 14 + (j << 1) + 1] << 8) | sp00[i * 14 + (j << 1) + 0]; + } + } + sub_800F86C(0); + if (gUnknown_03004140.unk_02 == 0 && gUnknown_03005000.unk_ce4) + { + rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + rfu_waitREQComplete(); + switchval = sub_8011A74(); + if (switchval != 1 && switchval != 6 && switchval != 9) + sub_8011A64(2, 0x9000); + rfu_clearAllSlot(); + gReceivedRemoteLinkPlayers = FALSE; + gUnknown_03005000.unk_00 = 0; + if (gUnknown_03005000.unk_ce4 == 1) + { + sub_8011A64(2, 0x9000); + sub_8011170(0x9000); + } + gUnknown_03004140.unk_04 = gUnknown_03004140.unk_05 = 0; + gUnknown_03005000.unk_ce4 = 0; + } + if (gUnknown_03005000.unk_cd0) + { + gUnknown_03005000.unk_cd0--; + sub_8010528(); + sub_800F498(gSendCmd, sp48); + sub_800D888(&gUnknown_03005000.unk_9e8, sp48); + for (i = 0; i < CMD_LENGTH - 1; i++) + gSendCmd[i] = 0; + } + return sub_800F0B8(); +} + +#ifdef NONMATCHING +void sub_800F638(u8 unused, u32 flags) +{ + int i; + int j; + + u8 *r10 = gUnknown_03005000.unk_6c.unk_04; + for (i = 0; i < gUnknown_03005000.unk_6c.unk_02; i++) + { + if (!(flags & 1)) + { + gUnknown_03000D90[0] = (~0x76ff) | i; + for (j = 0; j < 7; j++) + { + gUnknown_03000D90[j + 1] = (r10[12 * i + (j << 1) + 1] << 8) | r10[12 * i + (j << 1) + 0]; + } + for (j = 0; j < 7; j++) + // This should be an ascending loop. + // GCC compiles this as descending. + { + gUnknown_03000D80[2 * j + 1] = gUnknown_03000D90[j] >> 8; + gUnknown_03000D80[2 * j + 0] = gUnknown_03000D90[j]; + } + sub_800D888(&gUnknown_03005000.unk_9e8, gUnknown_03000D80); + gUnknown_03005000.unk_6c.unk_0c |= (1 << i); + } + flags >>= 1; + } +} +#else +NAKED void sub_800F638(u8 unused, u32 flags) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tldr r0, =gUnknown_03005000\n" + "\tldr r2, [r0, 0x70]\n" + "\tmov r10, r2\n" + "\tmovs r5, 0\n" + "\tadds r2, r0, 0\n" + "\tadds r2, 0x6E\n" + "\tldrh r3, [r2]\n" + "\tcmp r5, r3\n" + "\tbge _0800F6D4\n" + "\tmov r9, r0\n" + "\tldr r0, =gUnknown_03000D90\n" + "\tmov r8, r0\n" + "_0800F65A:\n" + "\tmovs r0, 0x1\n" + "\tands r0, r1\n" + "\tlsrs r7, r1, 1\n" + "\tadds r6, r5, 0x1\n" + "\tcmp r0, 0\n" + "\tbne _0800F6C8\n" + "\tldr r1, =0xffff8900\n" + "\tadds r0, r1, 0\n" + "\tadds r1, r5, 0\n" + "\torrs r1, r0\n" + "\tmov r2, r8\n" + "\tstrh r1, [r2]\n" + "\tmovs r4, 0\n" + "\tlsls r0, r5, 1\n" + "\tldr r3, =gUnknown_03000D80\n" + "\tmov r12, r3\n" + "\tadds r0, r5\n" + "\tlsls r0, 2\n" + "\tmov r1, r10\n" + "\tadds r2, r0, r1\n" + "\tmov r3, r8\n" + "\tadds r3, 0x2\n" + "_0800F686:\n" + "\tldrb r1, [r2, 0x1]\n" + "\tlsls r1, 8\n" + "\tldrb r0, [r2]\n" + "\torrs r0, r1\n" + "\tstrh r0, [r3]\n" + "\tadds r2, 0x2\n" + "\tadds r3, 0x2\n" + "\tadds r4, 0x1\n" + "\tcmp r4, 0x6\n" + "\tble _0800F686\n" + "\tmovs r4, 0\n" + "\tldr r2, =gUnknown_03000D90\n" + "\tldr r1, =gUnknown_03000D80\n" + "_0800F6A0:\n" + "\tldrh r0, [r2]\n" + "\tlsrs r0, 8\n" + "\tstrb r0, [r1, 0x1]\n" + "\tldrh r0, [r2]\n" + "\tstrb r0, [r1]\n" + "\tadds r2, 0x2\n" + "\tadds r1, 0x2\n" + "\tadds r4, 0x1\n" + "\tcmp r4, 0x6\n" + "\tble _0800F6A0\n" + "\tldr r0, =gUnknown_03005000+0x9E8\n" + "\tmov r1, r12\n" + "\tbl sub_800D888\n" + "\tmovs r1, 0x1\n" + "\tlsls r1, r5\n" + "\tmov r2, r9\n" + "\tldr r0, [r2, 0x78]\n" + "\torrs r0, r1\n" + "\tstr r0, [r2, 0x78]\n" + "_0800F6C8:\n" + "\tadds r1, r7, 0\n" + "\tadds r5, r6, 0\n" + "\tldr r3, =gUnknown_03005000+0x6E\n" + "\tldrh r3, [r3]\n" + "\tcmp r5, r3\n" + "\tblt _0800F65A\n" + "_0800F6D4:\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800F6FC(u8 a0) +{ + if (gUnknown_03005000.unk_0c == 1 && a0) + gUnknown_03005000.unk_61[a0] = 1; + else + gUnknown_03005000.unk_5c[a0] = 1; +} + +void sub_800F728(u8 a0) +{ + gUnknown_03005000.unk_5c[a0] = 0; + gUnknown_03005000.unk_80[a0].unk_12 = 0; +} + +u8 sub_800F74C(const u8 *a0) +{ + u8 i; + + if (gUnknown_03005000.unk_0c == 1) + return FALSE; + for (i = 0; i < 4; i++) + { + gUnknown_03005000.unk_cde[i] = a0[i]; + } + return a0[gUnknown_03005000.unk_c3e]; +} + +void rfu_func_080F97B8(void) +{ + if (gReceivedRemoteLinkPlayers && gUnknown_03005DA8 && gLinkTransferringData != 1) + { + gUnknown_03000D78[0]++; + gUnknown_03005DA8 |= (gUnknown_03000D78[0] << 8); + sub_800FD14(0xbe00); + } +} + +struct UnkLinkRfuStruct_02022B14 *sub_800F7DC(void) +{ + return &gUnknown_02022B14; +} + +bool32 sub_800F7E4(void) +{ + return gUnknown_03005000.unk_00 == rfu_func_080F97B8; +} + +void sub_800F804(void) +{ + gUnknown_03005000.unk_00 = rfu_func_080F97B8; +} + +void Rfu_set_zero(void) +{ + gUnknown_03005000.unk_00 = NULL; +} + +void sub_800F820(void) +{ + sub_800FD14(0x4400); + if (GetMultiplayerId() == 0) + gSendCmd[6] = GetBlenderArrowPosition(); + gUnknown_020223C0++; +} + +void sub_800F850(void) +{ + if (gUnknown_03005000.unk_00 == NULL) + gUnknown_03005000.unk_00 = sub_800F820; +} + +static void sub_800F86C(u8 unused) +{ + u16 i; + u16 j; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + switch (gRecvCmds[i][0] & 0xff00) + { + case 0x7800: + if (gUnknown_03005000.unk_0c == 0 && gReceivedRemoteLinkPlayers != 0) + return; + // fallthrough + case 0x7700: + if (gUnknown_03007890->unk_00 == 0) + { + gUnknown_03005000.playerCount = gRecvCmds[i][1]; + gUnknown_03005000.unk_cce = sub_800F74C((u8 *)(gRecvCmds[i] + 2)); + } + break; + case 0x8800: + if (gUnknown_03005000.unk_80[i].unk_12 == 0) + { + gUnknown_03005000.unk_80[i].unk_00 = 0; + gUnknown_03005000.unk_80[i].unk_02 = gRecvCmds[i][1]; + gUnknown_03005000.unk_80[i].unk_11 = gRecvCmds[i][2]; + gUnknown_03005000.unk_80[i].unk_08 = 0; + gUnknown_03005000.unk_80[i].unk_12 = 1; + gUnknown_03005000.unk_5c[i] = 0; + } + break; + case 0x8900: + if (gUnknown_03005000.unk_80[i].unk_12 == 1) + { + gUnknown_03005000.unk_80[i].unk_00 = gRecvCmds[i][0] & 0xff; + gUnknown_03005000.unk_80[i].unk_08 |= (1 << gUnknown_03005000.unk_80[i].unk_00); + for (j = 0; j < 6; j++) + gBlockRecvBuffer[i][gUnknown_03005000.unk_80[i].unk_00 * 6 + j] = gRecvCmds[i][j + 1]; + if (gUnknown_03005000.unk_80[i].unk_08 == gUnknown_082ED628[gUnknown_03005000.unk_80[i].unk_02]) + { + gUnknown_03005000.unk_80[i].unk_12 = 2; + sub_800F6FC(i); + if (sub_800F7DC()->unk_0a_0 == 0x45 && gReceivedRemoteLinkPlayers != 0 && gUnknown_03005000.unk_0c == 0) + sub_8010A70(gBlockRecvBuffer); + } + } + break; + case 0xa100: + sub_800FE84(gUnknown_082ED6B8[gRecvCmds[i][1]].buffer, (u16)gUnknown_082ED6B8[gRecvCmds[i][1]].size); + break; + case 0x5f00: + gUnknown_03005000.unk_e4[i] = 1; + break; + case 0x6600: + if (gUnknown_03005000.unk_100 == gRecvCmds[i][1]) + gUnknown_03005000.unk_e9[i] = 1; + break; + case 0xed00: + if (gUnknown_03005000.unk_0c == 0) + { + if (gReceivedRemoteLinkPlayers != 0) + { + if (gRecvCmds[i][1] & gUnknown_03007890->unk_02) + { + gReceivedRemoteLinkPlayers = 0; + sub_800D630(); + gUnknown_03005000.unk_ce4 = gRecvCmds[i][2]; + } + gUnknown_03005000.playerCount = gRecvCmds[i][3]; + sub_80109E8(gRecvCmds[i][1]); + } + } + else + { + sub_800FD14(0xee00); + gSendCmd[1] = gRecvCmds[i][1]; + gSendCmd[2] = gRecvCmds[i][2]; + gSendCmd[3] = gRecvCmds[i][3]; + } + break; + case 0xee00: + if (gUnknown_03005000.unk_0c == 1) + { + gUnknown_03005000.unk_ce3 |= gRecvCmds[i][1]; + gUnknown_03005000.unk_ce4 = gRecvCmds[i][2]; + sub_80109E8(gRecvCmds[i][1]); + } + break; + case 0x4400: + case 0xbe00: + gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; + break; + } + if (gUnknown_03005000.unk_0c == 1 && gUnknown_03005000.unk_61[i]) + { + if (gUnknown_03005000.unk_61[i] == 4) + { + gUnknown_03005000.unk_5c[i] = 1; + gUnknown_03005000.unk_61[i] = 0; + } + else + gUnknown_03005000.unk_61[i]++; + } + } +} + +bool8 sub_800FC60(void) +{ + int i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12) + return FALSE; + } + return TRUE; +} + +bool8 sub_800FC88(void) +{ + int i; + + for (i = 0; i < gUnknown_03005000.playerCount; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12 != 2 || gUnknown_03005000.unk_5c[i] != 1) + return FALSE; + } + return TRUE; +} + +static void sub_800FCC4(struct UnkRfuStruct_2_Sub_6c *data) +{ + data->unk_00 = 0; + data->unk_02 = 0; + data->unk_04 = NULL; + data->unk_08 = 0; + data->unk_10 = 0; + data->unk_11 = 0; + data->unk_12 = 0; +} + +u8 sub_800FCD8(void) +{ + u8 flags = 0; + int i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_03005000.unk_80[i].unk_12 == 2 && gUnknown_03005000.unk_5c[i] == 1) + { + flags |= (1 << i); + } + } + return flags; +} + +#ifdef NONMATCHING +// The switch tree is incorrect +void sub_800FD14(u16 command) +{ + u8 i; + u8 *buff; + u8 tmp; + + gSendCmd[0] = command; + switch (command) + { + case 0x8800: + gSendCmd[1] = gUnknown_03005000.unk_6c.unk_02; + gSendCmd[2] = gUnknown_03005000.unk_6c.unk_11 + 0x80; + break; + case 0xa100: + if (sub_800FC60()) + gSendCmd[1] = gUnknown_03005000.unk_5a; + break; + case 0x7800: + case 0x7700: + tmp = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3; + gUnknown_03005000.playerCount = gUnknown_082ED695[tmp] + 1; + gSendCmd[1] = gUnknown_03005000.playerCount; + buff = (u8 *)(gSendCmd + 2); + for (i = 0; i < 4; i++) + buff[i] = gUnknown_03005000.unk_cde[i]; + break; + case 0x6600: + case 0x5f00: + gSendCmd[1] = gUnknown_03005000.unk_100; + break; + case 0x4400: + gSendCmd[0] = 0x4400; + gSendCmd[1] = gMain.heldKeys; + break; + case 0x2f00: + for (i = 0; i < 6; i++) + gSendCmd[1 + i] = gUnknown_03005000.unk_f2[i]; + break; + case 0xbe00: + gSendCmd[1] = gUnknown_03005DA8; + break; + } +} +#else +NAKED void sub_800FD14(u16 command) +{ + asm_unified("\tpush {r4,r5,lr}\n" + "\tlsls r0, 16\n" + "\tlsrs r1, r0, 16\n" + "\tldr r5, =gSendCmd\n" + "\tstrh r1, [r5]\n" + "\tmovs r0, 0xF0\n" + "\tlsls r0, 7\n" + "\tadds r4, r5, 0\n" + "\tcmp r1, r0\n" + "\tbeq _0800FDB0_case_7700_case_7800\n" + "\tcmp r1, r0\n" + "\tbgt _0800FD62\n" + "\tmovs r0, 0xBE\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE00_case_5f00_case_6600\n" + "\tcmp r1, r0\n" + "\tbgt _0800FD50\n" + "\tmovs r0, 0xBC\n" + "\tlsls r0, 6\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE20_case_2f00\n" + "\tmovs r0, 0x88\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE14_case_4400\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FD50:\n" + "\tmovs r0, 0xCC\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE00_case_5f00_case_6600\n" + "\tmovs r0, 0xEE\n" + "\tlsls r0, 7\n" + "\tcmp r1, r0\n" + "\tbeq _0800FDB0_case_7700_case_7800\n" + "\tb _0800FE46_break\n" + "_0800FD62:\n" + "\tmovs r0, 0xBE\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FE40_case_be00\n" + "\tcmp r1, r0\n" + "\tbgt _0800FE46_break\n" + "\tmovs r0, 0x88\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FD80_case_8800\n" + "\tmovs r0, 0xA1\n" + "\tlsls r0, 8\n" + "\tcmp r1, r0\n" + "\tbeq _0800FD98_case_a100\n" + "\tb _0800FE46_break\n" + "_0800FD80_case_8800:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r1, r0, 0\n" + "\tadds r1, 0x6E\n" + "\tldrh r1, [r1]\n" + "\tstrh r1, [r5, 0x2]\n" + "\tadds r0, 0x7D\n" + "\tldrb r0, [r0]\n" + "\tadds r0, 0x80\n" + "\tstrh r0, [r5, 0x4]\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FD98_case_a100:\n" + "\tbl sub_800FC60\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _0800FE46_break\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r0, 0x5A\n" + "\tldrb r0, [r0]\n" + "\tb _0800FE44_str_break\n" + "\t.pool\n" + "_0800FDB0_case_7700_case_7800:\n" + "\tldr r3, =gUnknown_03005000\n" + "\tldr r1, =0x00000ce2\n" + "\tadds r0, r3, r1\n" + "\tldr r2, =0x00000ce3\n" + "\tadds r1, r3, r2\n" + "\tldrb r2, [r0]\n" + "\tldrb r0, [r1]\n" + "\teors r0, r2\n" + "\tldr r1, =gUnknown_082ED695\n" + "\tadds r0, r1\n" + "\tldrb r0, [r0]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r3, 0xD]\n" + "\tldrb r0, [r3, 0xD]\n" + "\tstrh r0, [r4, 0x2]\n" + "\tadds r2, r4, 0x4\n" + "\tmovs r4, 0\n" + "\tldr r0, =0x00000cde\n" + "\tadds r3, r0\n" + "_0800FDD6:\n" + "\tadds r1, r2, r4\n" + "\tadds r0, r4, r3\n" + "\tldrb r0, [r0]\n" + "\tstrb r0, [r1]\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tcmp r4, 0x3\n" + "\tbls _0800FDD6\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE00_case_5f00_case_6600:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tmovs r1, 0x80\n" + "\tlsls r1, 1\n" + "\tadds r0, r1\n" + "\tldrh r0, [r0]\n" + "\tstrh r0, [r4, 0x2]\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE14_case_4400:\n" + "\tstrh r1, [r5]\n" + "\tldr r0, =gMain\n" + "\tldrh r0, [r0, 0x2C]\n" + "\tb _0800FE44_str_break\n" + "\t.pool\n" + "_0800FE20_case_2f00:\n" + "\tmovs r4, 0\n" + "\tldr r3, =gUnknown_03005000+0xF2\n" + "_0800FE24:\n" + "\tadds r2, r4, 0x1\n" + "\tlsls r1, r2, 1\n" + "\tadds r1, r5\n" + "\tlsls r0, r4, 1\n" + "\tadds r0, r3\n" + "\tldrh r0, [r0]\n" + "\tstrh r0, [r1]\n" + "\tlsls r2, 24\n" + "\tlsrs r4, r2, 24\n" + "\tcmp r4, 0x5\n" + "\tbls _0800FE24\n" + "\tb _0800FE46_break\n" + "\t.pool\n" + "_0800FE40_case_be00:\n" + "\tldr r0, =gUnknown_03005DA8\n" + "\tldrh r0, [r0]\n" + "_0800FE44_str_break:\n" + "\tstrh r0, [r5, 0x2]\n" + "_0800FE46_break:\n" + "\tpop {r4,r5}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_800FE50(u16 *a0) +{ + if (gSendCmd[0] == 0 && sub_8011A80() == 0) + { + memcpy(gUnknown_03005000.unk_f2, a0, sizeof(gUnknown_03005000.unk_f2)); + sub_800FD14(0x2f00); + } +} + +bool32 sub_800FE84(const u8 *src, size_t size) +{ + bool8 r4; + if (gUnknown_03005000.unk_00 != NULL) + return FALSE; + if (gSendCmd[0] != 0) + return FALSE; + if (gUnknown_03005000.unk_6c.unk_10 != 0) + { + gUnknown_02022B44.unk_83++; + return FALSE; + } + r4 = (size % 12) != 0; + gUnknown_03005000.unk_6c.unk_11 = GetMultiplayerId(); + gUnknown_03005000.unk_6c.unk_10 = 1; + gUnknown_03005000.unk_6c.unk_02 = (size / 12) + r4; + gUnknown_03005000.unk_6c.unk_00 = 0; + if (size > 0x100) + gUnknown_03005000.unk_6c.unk_04 = src; + else + { + if (src != gBlockSendBuffer) + memcpy(gBlockSendBuffer, src, size); + gUnknown_03005000.unk_6c.unk_04 = gBlockSendBuffer; + } + sub_800FD14(0x8800); + gUnknown_03005000.unk_00 = rfufunc_80F9F44; + gUnknown_03005000.unk_5b = 0; + return TRUE; +} + +static void rfufunc_80F9F44(void) +{ + if (gSendCmd[0] == 0) + { + sub_800FD14(0x8800); + if (gUnknown_03005000.unk_0c == 1) + { + if (++gUnknown_03005000.unk_5b > 2) + gUnknown_03005000.unk_00 = sub_800FFB0; + } + else + { + if ((gRecvCmds[GetMultiplayerId()][0] & 0xff00) == 0x8800) + gUnknown_03005000.unk_00 = sub_800FFB0; + } + } +} + +static void sub_800FFB0(void) +{ + int i; + const u8 *src = gUnknown_03005000.unk_6c.unk_04; + gSendCmd[0] = 0x8900 | gUnknown_03005000.unk_6c.unk_00; + for (i = 0; i < 7; i++) + gSendCmd[i + 1] = (src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 1] << 8) | src[(i << 1) + gUnknown_03005000.unk_6c.unk_00 * 12 + 0]; + gUnknown_03005000.unk_6c.unk_00++; + if (gUnknown_03005000.unk_6c.unk_02 <= gUnknown_03005000.unk_6c.unk_00) + { + gUnknown_03005000.unk_6c.unk_10 = 0; + gUnknown_03005000.unk_00 = rfufunc_80FA020; + } +} + +static void rfufunc_80FA020(void) +{ + const u8 *src = gUnknown_03005000.unk_6c.unk_04; + u8 mpId = GetMultiplayerId(); + int i; + if (gUnknown_03005000.unk_0c == 0) + { + gSendCmd[0] = (~0x76ff) | (gUnknown_03005000.unk_6c.unk_02 - 1); + for (i = 0; i < 7; i++) + gSendCmd[i + 1] = (src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 1] << 8) | src[(i << 1) + (gUnknown_03005000.unk_6c.unk_02 - 1) * 12 + 0]; + if ((u8)gRecvCmds[mpId][0] == gUnknown_03005000.unk_6c.unk_02 - 1) + { + if (gUnknown_03005000.unk_80[mpId].unk_08 != gUnknown_082ED628[gUnknown_03005000.unk_80[mpId].unk_02]) + { + sub_800F638(mpId, gUnknown_03005000.unk_80[mpId].unk_08); + gUnknown_02022B44.unk_64++; + } + else + gUnknown_03005000.unk_00 = NULL; + } + } + else + gUnknown_03005000.unk_00 = NULL; +} + +bool8 sub_8010100(u8 a0) +{ + gUnknown_03005000.unk_5a = a0; + sub_800FD14(0xa100); + return TRUE; +} + +void sub_801011C(void) +{ + rfu_clearAllSlot(); + sub_800C048(); + gReceivedRemoteLinkPlayers = 0; + gUnknown_03005000.unk_ef = 1; + gUnknown_03005000.unk_00 = NULL; +} + +void sub_8010148(void) +{ + rfu_REQ_disconnect(gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03); + rfu_waitREQComplete(); + sub_801011C(); +} + +void sub_8010168(void) +{ + if (gUnknown_03005000.unk_0c == 0) + { + sub_800D630(); + gUnknown_03005000.unk_ce4 = 2; + } + else + gUnknown_03005000.unk_00 = sub_8010148; +} + +void sub_8010198(void) +{ + sub_800D630(); + gUnknown_03005000.unk_ce4 = 1; + gUnknown_03005000.unk_ce3 = gUnknown_03007890->unk_02 | gUnknown_03007890->unk_03; +} + +void sub_80101CC(void) +{ + int i; + u8 playerCount = gUnknown_03005000.playerCount; + int count = 0; + + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + if (gUnknown_03005000.unk_e4[i]) + count++; + } + if (count == playerCount) + { + gBattleTypeFlags &= ~BATTLE_TYPE_20; + if (gUnknown_03005000.unk_0c == 0) + { + gUnknown_03005000.unk_ee = 3; + sub_8010168(); + } + else + gUnknown_03005000.unk_00 = sub_8010168; + } +} + +void sub_801022C(void) +{ + if (gSendCmd[0] == 0 && gUnknown_03005000.unk_ce8 == 0) + { + sub_800FD14(0x5f00); + gUnknown_03005000.unk_00 = sub_80101CC; + } +} + +void sub_8010264(u8 taskId) +{ + if (gUnknown_03005000.unk_00 == NULL) + { + gUnknown_03005000.unk_cd9 = 1; + gUnknown_03005000.unk_00 = sub_801022C; + DestroyTask(taskId); + } +} + +void task_add_05_task_del_08FA224_when_no_RfuFunc(void) +{ + if (!FuncIsActiveTask(sub_8010264)) + CreateTask(sub_8010264, 5); +} + +void sub_80102B8(void) +{ + u8 playerCount; + u8 i; + + if (GetMultiplayerId() != 0) + { + u8 r4 = gUnknown_03005000.unk_124.unk_8c2; + if (r4 == 0 && gUnknown_03005000.unk_fe > 0x3c) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_fe = r4; + } + } + playerCount = GetLinkPlayerCount(); + for (i = 0; i < playerCount; i++) + { + if (gUnknown_03005000.unk_e9[i] == 0) + break; + } + if (i == playerCount) + { + for (i = 0; i < MAX_RFU_PLAYERS; i++) + gUnknown_03005000.unk_e9[i] = 0; + gUnknown_03005000.unk_100++; + gUnknown_03005000.unk_00 = NULL; + } + gUnknown_03005000.unk_fe++; +} + +void sub_8010358(void) +{ + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_80102B8; + } +} + +void sub_8010390(void) +{ + u8 i; + u8 playerCount; + + if (GetMultiplayerId() != 0) + { + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_80102B8; + } + } + else + { + playerCount = GetLinkPlayerCount(); + for (i = 1; i < playerCount; i++) + { + if (gUnknown_03005000.unk_e9[i] == 0) + break; + } + if (i == playerCount) + { + if (gUnknown_03005000.unk_124.unk_8c2 == 0 && gSendCmd[0] == 0) + { + sub_800FD14(0x6600); + gUnknown_03005000.unk_00 = sub_8010358; + } + } + } +} + +void sub_8010434(void) +{ + if (gUnknown_03005000.unk_00 == NULL) + { + gUnknown_03005000.unk_00 = sub_8010390; + gUnknown_03005000.unk_fe = 0; + } +} + +bool32 sub_8010454(u32 a0) +{ + int i; + for (i = 0; gUnknown_082ED6E0[i] != a0; i++) + { + if (gUnknown_082ED6E0[i] == 0xffff) + return FALSE; + } + return TRUE; +} + +u8 sub_801048C(bool32 a0) +{ + if (a0 == 0) + return sub_800D550(0, 0); + sub_800D550(1, 0x258); + return FALSE; +} + +void sub_80104B0(void) +{ + gUnknown_03005000.unk_cd9 = 1; + sub_800C27C(FALSE); +} + +u8 rfu_get_multiplayer_id(void) +{ + if (gUnknown_03005000.unk_0c == 1) + return 0; + return gUnknown_03005000.unk_cce; +} + +u8 sub_80104F4(void) +{ + return gUnknown_03005000.playerCount; +} + +bool8 sub_8010500(void) +{ + if (gUnknown_03005000.unk_f1 == 2) + return FALSE; + return gUnknown_03005000.unk_00 ? FALSE : TRUE; +} + +static void sub_8010528(void) +{ + if (gUnknown_03005000.unk_00) + gUnknown_03005000.unk_00(); +} + +bool8 sub_8010540(void) +{ + int i; + bool8 retval = FALSE; + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd1[i] < 5 || gUnknown_03005000.unk_cd1[i] > 6) + { + if (gUnknown_03007880[i]->unk_34 == 0x46 || gUnknown_03007880[i]->unk_34 == 0x48) + { + if (gUnknown_03005000.unk_cd5[i] == 8) + { + gUnknown_03005000.unk_cd1[i] = 9; + gUnknown_03005000.unk_cd5[i] = 10; + rfu_clearSlot(8, i); + rfu_NI_setSendData(1 << i, 8, gUnknown_03005000.unk_cd1 + i, 1); + retval = TRUE; + } + + } + else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47) + rfu_clearSlot(8, i); + { + + } + } + } + return retval; +} + +bool8 sub_80105EC(void) +{ + u8 flags = 0; + int i; + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd5[i] == 11) + { + flags |= (1 << i); + gUnknown_03005000.unk_cd5[i] = 0; + } + } + if (flags) + { + rfu_REQ_disconnect(flags); + rfu_waitREQComplete(); + } + for (i = 0; i < 4; i++) + { + if (gUnknown_03005000.unk_cd5[i] == 10 || gUnknown_03005000.unk_cd5[i] == 11) + return TRUE; + } + return FALSE; +} + +bool8 sub_801064C(u16 a0, const u8 *a1) +{ + u8 r1 = sub_8011CE4(a1, a0); + if (r1 == 0xFF) + return TRUE; + if (gUnknown_03005000.unk_cd1[r1] == 9) + return TRUE; + return FALSE; +} + +void sub_8010688(u8 a0, u16 a1, const u8 *a2) +{ + u8 r4 = sub_8011CE4(a2, a1); + gUnknown_03005000.unk_cd1[r4] = a0; + rfu_clearSlot(4, r4); + rfu_NI_setSendData(1 << r4, 8, gUnknown_03005000.unk_cd1 + r4, 1); +} + +void sub_80106D4(void) +{ + gUnknown_03005000.unk_c85 = 8; + rfu_clearSlot(4, gUnknown_03005000.unk_c3e); + rfu_NI_setSendData(1 << gUnknown_03005000.unk_c3e, 8, &gUnknown_03005000.unk_c85, 1); +} + +u8 sub_8010714(u16 a0, const u8 *a1) +{ + u8 r0 = sub_8011CE4(a1, a0); + if (r0 == 0xff) + return 2; + if (gUnknown_03007880[r0]->unk_0 == 0) + return TRUE; + return FALSE; +} + +void sub_8010750(void) +{ + int i; + + sub_8010540(); + for (i = 0; i < 4; i++) + { + if (gUnknown_03007880[i]->unk_0 == 0x26 || gUnknown_03007880[i]->unk_0 == 0x27) + { + if (gUnknown_03005000.unk_cd5[i] == 10) + gUnknown_03005000.unk_cd5[i] = 11; + rfu_clearSlot(4, i); + } + } +} + +int sub_80107A0(void) +{ + int retval = 0; + if (gUnknown_03005000.unk_c85 == 8) + { + if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x26 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_0 == 0x27) + rfu_clearSlot(4, gUnknown_03005000.unk_c3e); + } + if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x46 || gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x48) + { + rfu_clearSlot(8, gUnknown_03005000.unk_c3e); + sub_8011A64(gUnknown_03005000.unk_c86, 0); + retval = gUnknown_03005000.unk_c86; + } + else if (gUnknown_03007880[gUnknown_03005000.unk_c3e]->unk_34 == 0x47) + { + rfu_clearSlot(8, gUnknown_03005000.unk_c3e); + retval = 6; + } + return retval; +} + +void sub_801084C(u8 taskId) +{ + int i; + + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + { + gUnknown_03005000.unk_ce8 = 0; + DestroyTask(taskId); + } + switch (gTasks[taskId].data[0]) + { + case 0: + if (sub_800FC60()) + { + ResetBlockReceivedFlags(); + sub_800B348(); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (gUnknown_03005000.unk_0c == 1) + { + if (gReceivedRemoteLinkPlayers) + sub_800FD14(0x7800); + else + sub_800FD14(0x7700); + gTasks[taskId].data[0] = 101; + } + else + gTasks[taskId].data[0] = 2; + break; + case 101: + if (gSendCmd[0] == 0) + gTasks[taskId].data[0] = 2; + break; + case 2: + if (gUnknown_03005000.playerCount) + gTasks[taskId].data[0]++; + break; + case 3: + if (gUnknown_03005000.unk_0c == 1) + { + if (sub_800FC60()) + { + gUnknown_03005000.unk_5a = 0; + sub_800FD14(0xa100); + gTasks[taskId].data[0]++; + } + } + else + gTasks[taskId].data[0]++; + break; + case 4: + if (sub_800FC88()) + gTasks[taskId].data[0]++; + break; + case 5: + for (i = 0; i < gUnknown_03005000.playerCount; i++) + { + sub_800B3A4(i); + sub_800F728(i); + } + gTasks[taskId].data[0]++; + break; + case 6: + DestroyTask(taskId); + gReceivedRemoteLinkPlayers = 1; + gUnknown_03005000.unk_ce8 = 0; + sub_800D550(1, 0x258); + if (gUnknown_03005000.unk_ce6) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce6 >> i) & 1) + { + gUnknown_03005000.unk_ce5 = 1 << i; + gUnknown_03005000.unk_ce6 ^= (1 << i); + } + } + } + break; + } +} + +void sub_80109E8(u16 a0) +{ + int i; + + for (i = 0; i < 4; i++) + { + if ((a0 >> i) & 1) + gUnknown_03005000.unk_cde[i] = 0; + } +} + +void sub_8010A14(const struct UnkRfuStruct_8010A14 *a0) +{ + int i; + gUnknown_03005000.playerCount = a0->unk_0f; + for (i = 0; i < 4; i++) + gUnknown_03005000.unk_cde[i] = a0->unk_10[i]; + for (i = 0; i < MAX_RFU_PLAYERS; i++) + { + gLinkPlayers[i] = a0->unk_14[i]; + sub_800B524(gLinkPlayers + i); + } +} + +void sub_8010A70(void *a0) +{ + if (strcmp(gUnknown_082ED7EC, a0) == 0) + { + sub_8010A14(a0); + CpuFill16(0, a0, sizeof(struct UnkRfuStruct_8010A14)); + ResetBlockReceivedFlag(0); + } +} + +void sub_8010AAC(u8 taskId) +{ + int i; + struct LinkPlayerBlock *r2; + struct UnkRfuStruct_8010A14 *r5; + u8 r4 = gUnknown_03005000.unk_cde[gUnknown_082ED68C[gUnknown_03005000.unk_ce9]]; + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + { + gUnknown_03005000.unk_ce8 = 0; + DestroyTask(taskId); + } + switch (gTasks[taskId].data[0]) + { + case 0: + if (gSendCmd[0] == 0) + { + ResetBlockReceivedFlag(r4); + sub_800FD14(0x7800); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (gSendCmd[0] == 0) + gTasks[taskId].data[0]++; + break; + case 2: + if ((GetBlockReceivedStatus() >> r4) & 1) + { + ResetBlockReceivedFlag(r4); + r2 = (struct LinkPlayerBlock *)gBlockRecvBuffer[r4]; + gLinkPlayers[r4] = r2->linkPlayer; + sub_800B524(gLinkPlayers + r4); + gTasks[taskId].data[0]++; + } + break; + case 3: + r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer; + memcpy(r5->unk_00, gUnknown_082ED7EC, sizeof gUnknown_082ED7EC); + r5->unk_0f = gUnknown_03005000.playerCount; + for (i = 0; i < 4; i++) + r5->unk_10[i] = gUnknown_03005000.unk_cde[i]; + memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers); + gTasks[taskId].data[0]++; + // fallthrough + case 4: + r5 = (struct UnkRfuStruct_8010A14 *)gBlockSendBuffer; + r5->unk_0f = gUnknown_03005000.playerCount; + for (i = 0; i < 4; i++) + r5->unk_10[i] = gUnknown_03005000.unk_cde[i]; + memcpy(r5->unk_14, gLinkPlayers, sizeof gLinkPlayers); + if (SendBlock(0, gBlockSendBuffer, 0xa0)) + gTasks[taskId].data[0]++; + break; + case 5: + if (sub_800A520() && GetBlockReceivedStatus() & 1) + { + CpuFill16(0, gBlockRecvBuffer, sizeof(struct UnkRfuStruct_8010A14)); + ResetBlockReceivedFlag(0); + gUnknown_03005000.unk_ce8 = 0; + if (gUnknown_03005000.unk_ce6) + { + for (i = 0; i < 4; i++) + { + if ((gUnknown_03005000.unk_ce6 >> i) & 1) + { + gUnknown_03005000.unk_ce5 = 1 << i; + gUnknown_03005000.unk_ce6 ^= (1 << i); + gUnknown_03005000.unk_ce8 = 1; + break; + } + } + } + DestroyTask(taskId); + } + break; + } +} + +void sub_8010D0C(u8 taskId) +{ + if (gUnknown_03005000.unk_f1 == 1 || gUnknown_03005000.unk_f1 == 2) + DestroyTask(taskId); + switch (gTasks[taskId].data[0]) + { + case 0: + if (gUnknown_03005000.playerCount) + { + sub_800B348(); + SendBlock(0, gBlockSendBuffer, sizeof(struct LinkPlayerBlock)); + gTasks[taskId].data[0]++; + } + break; + case 1: + if (sub_800A520()) + gTasks[taskId].data[0]++; + break; + case 2: + if (GetBlockReceivedStatus() & 1) + { + sub_8010A14((const struct UnkRfuStruct_8010A14 *)gBlockRecvBuffer); + ResetBlockReceivedFlag(0); + gReceivedRemoteLinkPlayers = 1; + DestroyTask(taskId); + } + break; + } +} + +void sub_8010DB4(void) +{ + if (gUnknown_03005000.unk_ee == 1 && gUnknown_03004140.unk_02 == 0) + { + if (gMain.callback2 == sub_8018438 || gUnknown_03004140.unk_3c->unk_04) + gWirelessCommType = 2; + SetMainCallback2(CB2_LinkError); + gMain.savedCallback = CB2_LinkError; + sub_800AF18((gUnknown_03005000.unk_0a << 16) | (gUnknown_03005000.unk_10 << 8) | gUnknown_03005000.unk_12, gUnknown_03005000.unk_124.unk_8c2, gUnknown_03005000.unk_9e8.unk_232, sub_8011A74() == 2); + gUnknown_03005000.unk_ee = 2; + CloseLink(); + } + else if (gUnknown_03005000.unk_9e8.unk_233 == 1 || gUnknown_03005000.unk_124.unk_8c3 == 1) + { + if (gUnknown_03004140.unk_02) + sub_800D630(); + sub_8011A64(1, 0x7000); + sub_8011170(0x7000); + } +} + +void rfu_REQ_recvData_then_sendData(void) +{ + if (gUnknown_03004140.unk_06 == 1) + { + rfu_REQ_recvData(); + rfu_waitREQComplete(); + rfu_REQ_sendData_wrapper(0); + } +} + +bool32 sub_8010EC0(void) +{ + bool32 retval = FALSE; + gUnknown_03005000.unk_ccd = 0; + sub_800C54C(Random2()); + if (gUnknown_03005000.unk_ef == 0) + { + switch (gUnknown_03005000.unk_0c) + { + case 1: + sub_800F0F8(); + break; + case 0: + retval = sub_800F4F0(); + break; + case 2: + rfu_REQ_recvData_then_sendData(); + break; + } + } + return retval; +} + +bool32 sub_8010F1C(void) +{ + bool32 retval = FALSE; + if (gUnknown_03005000.unk_ef == 0) + { + if (gUnknown_03005000.unk_0c == 1) + retval = sub_800F1E0(); + sub_8010DB4(); + } + return retval; +} + +void sub_8010F48(void) +{ + StringCopy(gUnknown_02022B22, gSaveBlock2Ptr->playerName); +} + +void sub_8010F60(void) +{ + gUnknown_02022B14 = (struct UnkLinkRfuStruct_02022B14){}; + sub_800DD94(&gUnknown_02022B14, 0, 0, 0); +} + +void sub_8010F84(u8 a0, u32 a1, u32 a2) +{ + sub_800DD94(&gUnknown_02022B14, a0, a2, a1); +} + +void sub_8010FA0(bool32 a0, bool32 a1) +{ + gUnknown_02022B14.unk_00_4 = a0; + gUnknown_02022B14.unk_00_5 = a1; +} + +void sub_8010FCC(u32 a0, u32 a1, u32 a2) +{ + gUnknown_02022B14.unk_09_2 = a0; + gUnknown_02022B14.unk_08_0 = a1; + gUnknown_02022B14.unk_0b_1 = a2; +} + +u8 sub_801100C(int a0) +{ + u8 retval = 0x80; + retval |= (gLinkPlayers[a0].gender << 3); + retval |= (gLinkPlayers[a0].trainerId & 7); + return retval; +} + +void sub_801103C(void) +{ + struct UnkLinkRfuStruct_02022B14 *r5 = &gUnknown_02022B14; + int i; + + for (i = 1; i < GetLinkPlayerCount(); i++) + r5->unk_04[i - 1] = sub_801100C(i); +} + +void sub_8011068(u8 a0) +{ + gUnknown_02022B14.unk_0a_7 = a0; + rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22); +} + +void sub_8011090(u8 a0, u32 a1, u32 a2) +{ + if (a0) + sub_8010F84(a0, a1, a2); + rfu_REQ_configGameData(0, 2, &gUnknown_02022B14, gUnknown_02022B22); +} + +void sub_80110B8(u32 a0) +{ + int i; + u32 r5; + u32 r7; + int r8; + + if (sub_800F7DC()->unk_0a_0 == 0x45) + { + r5 = 0; + r7 = 0; + r8 = gUnknown_03005000.unk_ce2 ^ gUnknown_03005000.unk_ce3; + for (i = 0; i < 4; i++) + { + if ((r8 >> i) & 1) + { + r7 |= ((0x80 | ((gLinkPlayers[gUnknown_03005000.unk_cde[i]].gender & 1) << 3) | (gLinkPlayers[gUnknown_03005000.unk_cde[i]].trainerId & 7)) << (r5 << 3)); + r5++; + if (r5 == a0 - 1) + break; + } + } + sub_8011090(0x45, r7, 0); + } +} + +void sub_8011170(u32 a0) +{ + if (gUnknown_03005000.unk_ee == 0) + { + gUnknown_03005000.unk_10 = gUnknown_03004140.unk_14; + gUnknown_03005000.unk_12 = gUnknown_03004140.unk_16; + gUnknown_03005000.unk_0a = a0; + gUnknown_03005000.unk_ee = 1; + } +} + +void sub_80111A0(void) +{ + gUnknown_03005000.unk_ee = 0; +} + +void sub_80111B0(bool32 a0) +{ + if (!a0) + gUnknown_03005000.unk_ee = 0; + else + gUnknown_03005000.unk_ee = 4; +} + +void sub_80111DC(void) +{ + sub_8011E94(gUnknown_03004140.unk_00, 1); + gUnknown_03005000.unk_00 = NULL; +} + +void sub_80111FC(void) +{ + gUnknown_03005000.unk_00 = sub_80111DC; +} + +#ifdef NONMATCHING +void sub_801120C(u8 a0) +{ + u8 i; + u8 r6 = 0; + struct RfuUnk5Sub *unk5Sub; + switch (a0) + { + case 0x00: + gUnknown_03005000.unk_04 = 2; + break; + case 0x10: + break; + case 0x11: + sub_80115EC(gUnknown_03004140.unk_14); + for (i = 0; i < 4; i++) + { + if ((gUnknown_03004140.unk_14 >> i) & 1) + { + unk5Sub = &gUnknown_03007890->unk_14[i]; + if (unk5Sub->unk_06.unk_0a_0 == sub_800F7DC()->unk_0a_0) + { + gUnknown_03005000.unk_cd1[i] = 0; + gUnknown_03005000.unk_cd5[i] = 0; + rfu_setRecvBuffer(0x20, i, gUnknown_03005000.unk_cd5 + i, 1); + } + else + { + r6 |= (1 << i); + } + } + } + if (r6) + { + rfu_REQ_disconnect(r6); + rfu_waitREQComplete(); + } + break; + case 0x12: + break; + case 0x13: + break; + case 0x14: + if (gUnknown_03005000.unk_ce7 != gUnknown_03004140.unk_00) + { + rfu_REQ_disconnect(gUnknown_03005000.unk_ce7 ^ gUnknown_03004140.unk_00); + rfu_waitREQComplete(); + } + gUnknown_03005000.unk_04 = 0x11; + break; + case 0x31: + gUnknown_03005000.unk_f0 = 1; + break; + case 0x32: + gUnknown_03005000.unk_f0 = 3; + break; + case 0x30: + case 0x33: + gUnknown_03005000.unk_f0 = 4; + gUnknown_03005000.unk_ce2 &= ~gUnknown_03004140.unk_14; + if (gReceivedRemoteLinkPlayers == 1) + { + if (gUnknown_03005000.unk_ce2 == 0) + sub_8011170(a0); + else + sub_80111FC(); + } + sub_8011A64(2, a0); + break; + case 0x42 ... 0x44: + break; + case 0xf3: + sub_8011A64(1, a0); + sub_8011170(a0); + gUnknown_03005000.unk_ef = 1; + break; + case 0xf0 ... 0xf2: + case 0xff: + sub_8011170(a0); + sub_8011A64(1, a0); + gUnknown_03005000.unk_cdb = 1; + break; + } +} +#else +NAKED void sub_801120C(u8 a0) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tmovs r6, 0\n" + "\tcmp r4, 0x32\n" + "\tbne _08011222\n" + "\tb _08011360_case_32\n" + "_08011222:\n" + "\tcmp r4, 0x32\n" + "\tbgt _08011252\n" + "\tcmp r4, 0x13\n" + "\tbgt _08011240\n" + "\tcmp r4, 0x12\n" + "\tblt _08011230\n" + "\tb _080113EE_break\n" + "_08011230:\n" + "\tcmp r4, 0x10\n" + "\tbne _08011236\n" + "\tb _080113EE_break\n" + "_08011236:\n" + "\tcmp r4, 0x10\n" + "\tbgt _0801128C_case_11\n" + "\tcmp r4, 0\n" + "\tbeq _0801127E_case_00\n" + "\tb _080113EE_break\n" + "_08011240:\n" + "\tcmp r4, 0x30\n" + "\tbne _08011246\n" + "\tb _0801136C_case_30_case_33\n" + "_08011246:\n" + "\tcmp r4, 0x30\n" + "\tble _0801124C\n" + "\tb _08011354_case_31\n" + "_0801124C:\n" + "\tcmp r4, 0x14\n" + "\tbeq _08011328_case_14\n" + "\tb _080113EE_break\n" + "_08011252:\n" + "\tcmp r4, 0x44\n" + "\tbgt _08011264\n" + "\tcmp r4, 0x42\n" + "\tblt _0801125C\n" + "\tb _080113EE_break\n" + "_0801125C:\n" + "\tcmp r4, 0x33\n" + "\tbne _08011262\n" + "\tb _0801136C_case_30_case_33\n" + "_08011262:\n" + "\tb _080113EE_break\n" + "_08011264:\n" + "\tcmp r4, 0xF3\n" + "\tbne _0801126A\n" + "\tb _080113BA_case_f3\n" + "_0801126A:\n" + "\tcmp r4, 0xF3\n" + "\tbgt _08011276\n" + "\tcmp r4, 0xF0\n" + "\tbge _08011274\n" + "\tb _080113EE_break\n" + "_08011274:\n" + "\tb _080113D4_case_f0_f1_f2_ff\n" + "_08011276:\n" + "\tcmp r4, 0xFF\n" + "\tbne _0801127C\n" + "\tb _080113D4_case_f0_f1_f2_ff\n" + "_0801127C:\n" + "\tb _080113EE_break\n" + "_0801127E_case_00:\n" + "\tldr r1, =gUnknown_03005000\n" + "\tmovs r0, 0x2\n" + "\tstrh r0, [r1, 0x4]\n" + "\tb _080113EE_break\n" + "\t.pool\n" + "_0801128C_case_11:\n" + "\tldr r0, =gUnknown_03004140\n" + "\tldrh r0, [r0, 0x14]\n" + "\tbl sub_80115EC\n" + "\tmovs r5, 0\n" + "\tmovs r0, 0x1\n" + "\tmov r8, r0\n" + "\tldr r1, =gUnknown_03005000\n" + "\tmov r9, r1\n" + "\tldr r3, =0x00000cd5\n" + "\tadd r3, r9\n" + "\tmov r10, r3\n" + "\tmovs r7, 0x7F\n" + "_080112A6:\n" + "\tldr r0, =gUnknown_03004140\n" + "\tldrh r0, [r0, 0x14]\n" + "\tasrs r0, r5\n" + "\tmov r1, r8\n" + "\tands r0, r1\n" + "\tcmp r0, 0\n" + "\tbeq _0801130E\n" + "\tldr r0, =gUnknown_03007890\n" + "\tlsls r1, r5, 5\n" + "\tadds r1, 0x14\n" + "\tldr r0, [r0]\n" + "\tadds r0, r1\n" + "\tldrb r0, [r0, 0x10]\n" + "\tadds r4, r7, 0\n" + "\tands r4, r0\n" + "\tbl sub_800F7DC\n" + "\tldrb r1, [r0, 0xA]\n" + "\tadds r0, r7, 0\n" + "\tands r0, r1\n" + "\tcmp r4, r0\n" + "\tbne _08011304\n" + "\tldr r0, =0x00000cd1\n" + "\tadd r0, r9\n" + "\tadds r0, r5, r0\n" + "\tmovs r1, 0\n" + "\tstrb r1, [r0]\n" + "\tmov r3, r10\n" + "\tadds r2, r5, r3\n" + "\tstrb r1, [r2]\n" + "\tmovs r0, 0x20\n" + "\tadds r1, r5, 0\n" + "\tmovs r3, 0x1\n" + "\tbl rfu_setRecvBuffer\n" + "\tb _0801130E\n" + "\t.pool\n" + "_08011304:\n" + "\tmov r0, r8\n" + "\tlsls r0, r5\n" + "\torrs r6, r0\n" + "\tlsls r0, r6, 24\n" + "\tlsrs r6, r0, 24\n" + "_0801130E:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tcmp r5, 0x3\n" + "\tbls _080112A6\n" + "\tcmp r6, 0\n" + "\tbeq _080113EE_break\n" + "\tadds r0, r6, 0\n" + "\tbl rfu_REQ_disconnect\n" + "\tbl rfu_waitREQComplete\n" + "\tb _080113EE_break\n" + "_08011328_case_14:\n" + "\tldr r4, =gUnknown_03005000\n" + "\tldr r1, =0x00000ce7\n" + "\tadds r0, r4, r1\n" + "\tldr r1, =gUnknown_03004140\n" + "\tldrb r2, [r0]\n" + "\tldrb r0, [r1]\n" + "\tcmp r2, r0\n" + "\tbeq _08011342\n" + "\teors r0, r2\n" + "\tbl rfu_REQ_disconnect\n" + "\tbl rfu_waitREQComplete\n" + "_08011342:\n" + "\tmovs r0, 0x11\n" + "\tstrh r0, [r4, 0x4]\n" + "\tb _080113EE_break\n" + "\t.pool\n" + "_08011354_case_31:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r0, 0xF0\n" + "\tb _080113EA\n" + "\t.pool\n" + "_08011360_case_32:\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r0, 0xF0\n" + "\tmovs r1, 0x3\n" + "\tb _080113EC\n" + "\t.pool\n" + "_0801136C_case_30_case_33:\n" + "\tldr r1, =gUnknown_03005000\n" + "\tadds r2, r1, 0\n" + "\tadds r2, 0xF0\n" + "\tmovs r0, 0x4\n" + "\tstrb r0, [r2]\n" + "\tldr r3, =0x00000ce2\n" + "\tadds r1, r3\n" + "\tldr r0, =gUnknown_03004140\n" + "\tldrb r2, [r0, 0x14]\n" + "\tldrb r0, [r1]\n" + "\tadds r3, r0, 0\n" + "\tbics r3, r2\n" + "\tadds r2, r3, 0\n" + "\tstrb r2, [r1]\n" + "\tldr r0, =gReceivedRemoteLinkPlayers\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x1\n" + "\tbne _080113B0\n" + "\tcmp r2, 0\n" + "\tbne _080113AC\n" + "\tadds r0, r4, 0\n" + "\tbl sub_8011170\n" + "\tb _080113B0\n" + "\t.pool\n" + "_080113AC:\n" + "\tbl sub_80111FC\n" + "_080113B0:\n" + "\tmovs r0, 0x2\n" + "\tadds r1, r4, 0\n" + "\tbl sub_8011A64\n" + "\tb _080113EE_break\n" + "_080113BA_case_f3:\n" + "\tmovs r0, 0x1\n" + "\tmovs r1, 0xF3\n" + "\tbl sub_8011A64\n" + "\tmovs r0, 0xF3\n" + "\tbl sub_8011170\n" + "\tldr r0, =gUnknown_03005000\n" + "\tadds r0, 0xEF\n" + "\tb _080113EA\n" + "\t.pool\n" + "_080113D4_case_f0_f1_f2_ff:\n" + "\tadds r0, r4, 0\n" + "\tbl sub_8011170\n" + "\tmovs r0, 0x1\n" + "\tadds r1, r4, 0\n" + "\tbl sub_8011A64\n" + "\tldr r0, =gUnknown_03005000\n" + "\tldr r1, =0x00000cdb\n" + "\tadds r0, r1\n" + "\tldrb r1, [r0]\n" + "_080113EA:\n" + "\tmovs r1, 0x1\n" + "_080113EC:\n" + "\tstrb r1, [r0]\n" + "_080113EE_break:\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif diff --git a/src/list_menu.c b/src/list_menu.c new file mode 100644 index 000000000..c78d32bb3 --- /dev/null +++ b/src/list_menu.c @@ -0,0 +1,633 @@ +#include "global.h" +#include "menu.h" +#include "list_menu.h" +#include "window.h" +#include "text_window.h" +#include "main.h" +#include "task.h" +#include "menu_indicators.h" +#include "strings.h" +#include "sound.h" +#include "constants/songs.h" + +struct UnknownMysteryGiftLinkMenuStruct +{ + s32 field_0; + u8 field_4; + u8 field_5; + u8 field_6; +}; + +struct UnknownListMenuPals +{ + u8 cursorPal:4; + u8 fillValue:4; + u8 cursorShadowPal:4; + u8 lettersSpacing:6; + u8 field_2_2:6; // unused + u8 fontId:7; + u8 field_3_7:1; +}; + +extern struct UnknownMysteryGiftLinkMenuStruct gUnknown_0203CE84; + +// this file's functions +static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow); +static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAndCallCallback, u8 count, bool8 movingDown); +static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOffset, u16 count); +static void ListMenuDrawCursor(struct ListMenu *list); +static void ListMenuCallSelectionChangedCallback(struct ListMenu *list, u8 a2); +static u8 ListMenuAddCursorObject(struct ListMenu *list, u32 cursorKind); + +// IWRAM common +struct UnknownListMenuPals gUnknown_03006300; +struct ListMenuTemplate gMultiuseListMenuTemplate; + +// code +static void ListMenuDummyTask(u8 taskId) +{ + +} + +s32 DoMysteryGiftListMenu(struct WindowTemplate *windowTemplate, struct ListMenuTemplate *listMenuTemplate, u8 arg2, u16 tileNum, u16 palNum) +{ + switch (gUnknown_0203CE84.field_4) + { + case 0: + default: + gUnknown_0203CE84.field_5 = AddWindow(windowTemplate); + switch (arg2) + { + case 2: + sub_809882C(gUnknown_0203CE84.field_5, tileNum, palNum); + case 1: + sub_8098858(gUnknown_0203CE84.field_5, tileNum, palNum / 16); + break; + } + gMultiuseListMenuTemplate = *listMenuTemplate; + gMultiuseListMenuTemplate.windowId = gUnknown_0203CE84.field_5; + gUnknown_0203CE84.field_6 = ListMenuInit(&gMultiuseListMenuTemplate, 0, 0); + CopyWindowToVram(gUnknown_0203CE84.field_5, 1); + gUnknown_0203CE84.field_4 = 1; + break; + case 1: + gUnknown_0203CE84.field_0 = ListMenuHandleInputGetItemId(gUnknown_0203CE84.field_6); + if (gMain.newKeys & A_BUTTON) + { + gUnknown_0203CE84.field_4 = 2; + } + if (gMain.newKeys & B_BUTTON) + { + gUnknown_0203CE84.field_0 = LIST_B_PRESSED; + gUnknown_0203CE84.field_4 = 2; + } + if (gUnknown_0203CE84.field_4 == 2) + { + if (arg2 == 0) + { + ClearWindowTilemap(gUnknown_0203CE84.field_5); + } + else + { + switch (arg2) + { + case 0: // can never be reached, because of the if statement above + sub_819746C(gUnknown_0203CE84.field_5, FALSE); + break; + case 2: + case 1: + sub_819746C(gUnknown_0203CE84.field_5, FALSE); + break; + } + } + + CopyWindowToVram(gUnknown_0203CE84.field_5, 1); + } + break; + case 2: + DestroyListMenuTask(gUnknown_0203CE84.field_6, NULL, NULL); + RemoveWindow(gUnknown_0203CE84.field_5); + gUnknown_0203CE84.field_4 = 0; + return gUnknown_0203CE84.field_0; + } + + return -1; +} + +u8 ListMenuInit(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow) +{ + u8 taskId = ListMenuInitInternal(listMenuTemplate, scrollOffset, selectedRow); + PutWindowTilemap(listMenuTemplate->windowId); + CopyWindowToVram(listMenuTemplate->windowId, 2); + + return taskId; +} + +// unused +u8 ListMenuInitWithWindows(struct ListMenuTemplate *listMenuTemplate, struct UnknownListMenuWindowStruct *arg1, u16 scrollOffset, u16 selectedRow) +{ + s32 i; + + u8 taskId = ListMenuInitInternal(listMenuTemplate, scrollOffset, selectedRow); + for (i = 0; arg1[i].palNum != 0xFF; i++) + { + PutWindowRectTilemapOverridePalette(listMenuTemplate->windowId, + arg1[i].x, + arg1[i].y, + arg1[i].width, + arg1[i].height, + arg1[i].palNum); + } + CopyWindowToVram(listMenuTemplate->windowId, 2); + + return taskId; +} + +s32 ListMenuHandleInputGetItemId(u8 listTaskId) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + if (gMain.newKeys & A_BUTTON) + { + return list->template.items[list->scrollOffset + list->selectedRow].id; + } + else if (gMain.newKeys & B_BUTTON) + { + return LIST_B_PRESSED; + } + else if (gMain.newAndRepeatedKeys & DPAD_UP) + { + ListMenuChangeSelection(list, TRUE, 1, FALSE); + return LIST_NOTHING_CHOSEN; + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + ListMenuChangeSelection(list, TRUE, 1, TRUE); + return LIST_NOTHING_CHOSEN; + } + else // try to move by one window scroll + { + bool16 rightButton, leftButton; + switch (list->template.scrollMultiple) + { + case LIST_NO_MULTIPLE_SCROLL: + default: + leftButton = FALSE; + rightButton = FALSE; + break; + case LIST_MULTIPLE_SCROLL_DPAD: + leftButton = gMain.newAndRepeatedKeys & DPAD_LEFT; + rightButton = gMain.newAndRepeatedKeys & DPAD_RIGHT; + break; + case LIST_MULTIPLE_SCROLL_L_R: + leftButton = gMain.newAndRepeatedKeys & L_BUTTON; + rightButton = gMain.newAndRepeatedKeys & R_BUTTON; + break; + } + + if (leftButton) + { + ListMenuChangeSelection(list, TRUE, list->template.maxShowed, FALSE); + return LIST_NOTHING_CHOSEN; + } + else if (rightButton) + { + ListMenuChangeSelection(list, TRUE, list->template.maxShowed, TRUE); + return LIST_NOTHING_CHOSEN; + } + else + { + return LIST_NOTHING_CHOSEN; + } + } +} + +void DestroyListMenuTask(u8 listTaskId, u16 *scrollOffset, u16 *selectedRow) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + if (scrollOffset != NULL) + *scrollOffset = list->scrollOffset; + if (selectedRow != NULL) + *selectedRow = list->selectedRow; + + if (list->unk_1E != 0xFF) + ListMenuRemoveCursorObject(list->unk_1E, list->template.cursorKind - 2); + + DestroyTask(listTaskId); +} + +void sub_81AE70C(u8 listTaskId) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + FillWindowPixelBuffer(list->template.windowId, (list->template.fillValue << 4) | (list->template.fillValue)); + ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed); + ListMenuDrawCursor(list); + CopyWindowToVram(list->template.windowId, 2); +} + +// unused +void ChangeListMenuPals(u8 listTaskId, u8 cursorPal, u8 fillValue, u8 cursorShadowPal) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + list->template.cursorPal = cursorPal; + list->template.fillValue = fillValue; + list->template.cursorShadowPal = cursorShadowPal; +} + +// unused +void ChangeListMenuCoords(u8 listTaskId, u8 x, u8 y) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + SetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_LEFT, x); + SetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_TOP, y); +} + +// unused +s32 ListMenuTestInput(struct ListMenuTemplate *template, u32 scrollOffset, u32 selectedRow, u16 keys, u16 *newScrollOffset, u16 *newSelectedRow) +{ + struct ListMenu list; + + list.template = *template; + list.scrollOffset = scrollOffset; + list.selectedRow = selectedRow; + list.unk_1C = 0; + list.unk_1D = 0; + + if (keys == DPAD_UP) + ListMenuChangeSelection(&list, FALSE, 1, FALSE); + if (keys == DPAD_DOWN) + ListMenuChangeSelection(&list, FALSE, 1, TRUE); + + if (newScrollOffset != NULL) + *newScrollOffset = list.scrollOffset; + if (newSelectedRow != NULL) + *newSelectedRow = list.selectedRow; + + return LIST_NOTHING_CHOSEN; +} + +void ListMenuGetCurrentItemArrayId(u8 listTaskId, u16 *arrayId) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + if (arrayId != NULL) + *arrayId = list->scrollOffset + list->selectedRow; +} + +void ListMenuGetScrollAndRow(u8 listTaskId, u16 *scrollOffset, u16 *selectedRow) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + if (scrollOffset != NULL) + *scrollOffset = list->scrollOffset; + if (selectedRow != NULL) + *selectedRow = list->selectedRow; +} + +u16 ListMenuGetYCoordForPrintingArrowCursor(u8 listTaskId) +{ + struct ListMenu *list = (void*) gTasks[listTaskId].data; + u8 yMultiplier = GetFontAttribute(list->template.fontId, 1) + list->template.unk_16_3; + + return list->selectedRow * yMultiplier + list->template.upText_Y; +} + +static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 scrollOffset, u16 selectedRow) +{ + u8 listTaskId = CreateTask(ListMenuDummyTask, 0); + struct ListMenu *list = (void*) gTasks[listTaskId].data; + + list->template = *listMenuTemplate; + list->scrollOffset = scrollOffset; + list->selectedRow = selectedRow; + list->unk_1C = 0; + list->unk_1D = 0; + list->unk_1E = 0xFF; + list->unk_1F = 0; + + gUnknown_03006300.cursorPal = list->template.cursorPal; + gUnknown_03006300.fillValue = list->template.fillValue; + gUnknown_03006300.cursorShadowPal = list->template.cursorShadowPal; + gUnknown_03006300.lettersSpacing = list->template.lettersSpacing; + gUnknown_03006300.fontId = list->template.fontId; + gUnknown_03006300.field_3_7 = 0; + + if (list->template.totalItems < list->template.maxShowed) + list->template.maxShowed = list->template.totalItems; + + FillWindowPixelBuffer(list->template.windowId, (list->template.fillValue << 4) | (list->template.fillValue)); + ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed); + ListMenuDrawCursor(list); + ListMenuCallSelectionChangedCallback(list, 1); + + return listTaskId; +} + +static void ListMenuPrint(struct ListMenu *list, const u8 *str, u8 x, u8 y) +{ + u8 colors[3]; + if (gUnknown_03006300.field_3_7) + { + colors[0] = gUnknown_03006300.fillValue; + colors[1] = gUnknown_03006300.cursorPal; + colors[2] = gUnknown_03006300.cursorShadowPal; + AddTextPrinterParameterized2(list->template.windowId, + gUnknown_03006300.fontId, + x, y, + gUnknown_03006300.lettersSpacing, + 0, colors, TEXT_SPEED_FF, str); + + gUnknown_03006300.field_3_7 = 0; + } + else + { + colors[0] = list->template.fillValue; + colors[1] = list->template.cursorPal; + colors[2] = list->template.cursorShadowPal; + AddTextPrinterParameterized2(list->template.windowId, + list->template.fontId, + x, y, + list->template.lettersSpacing, + 0, colors, TEXT_SPEED_FF, str); + } +} + +static void ListMenuPrintEntries(struct ListMenu *list, u16 startIndex, u16 yOffset, u16 count) +{ + s32 i; + u8 x, y; + u8 yMultiplier = GetFontAttribute(list->template.fontId, 1) + list->template.unk_16_3; + + for (i = 0; i < count; i++) + { + if (list->template.items[startIndex].id != -3) + x = list->template.unk_12; + else + x = list->template.unk_11; + + y = (yOffset + i) * yMultiplier + list->template.upText_Y; + if (list->template.unk_08 != NULL) + list->template.unk_08(list->template.windowId, list->template.items[startIndex].id, y); + + ListMenuPrint(list, list->template.items[startIndex].name, x, y); + startIndex++; + } +} + +static void ListMenuDrawCursor(struct ListMenu *list) +{ + u8 yMultiplier = GetFontAttribute(list->template.fontId, 1) + list->template.unk_16_3; + u8 x = list->template.cursor_X; + u8 y = list->selectedRow * yMultiplier + list->template.upText_Y; + switch (list->template.cursorKind) + { + case 0: + ListMenuPrint(list, gText_SelectorArrow2, x, y); + break; + case 1: + break; + case 2: + if (list->unk_1E == 0xFF) + list->unk_1E = ListMenuAddCursorObject(list, 0); + ListMenuUpdateCursorObject(list->unk_1E, + GetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_LEFT) * 8 - 1, + GetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_TOP) * 8 + y - 1, 0); + break; + case 3: + if (list->unk_1E == 0xFF) + list->unk_1E = ListMenuAddCursorObject(list, 1); + ListMenuUpdateCursorObject(list->unk_1E, + GetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_LEFT) * 8 + x, + GetWindowAttribute(list->template.windowId, WINDOW_TILEMAP_TOP) * 8 + y, 1); + break; + } +} + +static u8 ListMenuAddCursorObject(struct ListMenu *list, u32 cursorKind) +{ + struct CursorStruct cursor; + + cursor.unk0 = 0; + cursor.unk1 = 0xA0; + cursor.unk2 = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8 + 2; + cursor.unk4 = GetFontAttribute(list->template.fontId, 1) + 2; + cursor.unk6 = 0x4000; + cursor.unk8 = 0xFFFF; + cursor.unkA = 0xF; + + return ListMenuAddCursorObjectInternal(&cursor, cursorKind); +} + +static void ListMenuErasePrintedCursor(struct ListMenu *list, u16 selectedRow) +{ + u8 cursorKind = list->template.cursorKind; + if (cursorKind == 0) + { + u8 yMultiplier = GetFontAttribute(list->template.fontId, 1) + list->template.unk_16_3; + u8 width = GetMenuCursorDimensionByFont(list->template.fontId, 0); + u8 height = GetMenuCursorDimensionByFont(list->template.fontId, 1); + FillWindowPixelRect(list->template.windowId, + (list->template.fillValue << 4) | (list->template.fillValue), + list->template.cursor_X, + selectedRow * yMultiplier + list->template.upText_Y, + width, + height); + } +} + +static u8 ListMenuUpdateSelectedRowIndexAndScrollOffset(struct ListMenu *list, bool8 movingDown) +{ + u16 selectedRow = list->selectedRow; + u16 scrollOffset = list->scrollOffset; + u16 newRow; + u32 newScroll; + + if (!movingDown) + { + if (list->template.maxShowed == 1) + newRow = 0; + else + newRow = list->template.maxShowed - ((list->template.maxShowed / 2) + (list->template.maxShowed % 2)) - 1; + + if (scrollOffset == 0) + { + while (selectedRow != 0) + { + selectedRow--; + if (list->template.items[scrollOffset + selectedRow].id != -3) + { + list->selectedRow = selectedRow; + return 1; + } + } + + return 0; + } + else + { + while (selectedRow > newRow) + { + selectedRow--; + if (list->template.items[scrollOffset + selectedRow].id != -3) + { + list->selectedRow = selectedRow; + return 1; + } + } + + newScroll = scrollOffset - 1; + } + } + else + { + if (list->template.maxShowed == 1) + newRow = 0; + else + newRow = ((list->template.maxShowed / 2) + (list->template.maxShowed % 2)); + + if (scrollOffset == list->template.totalItems - list->template.maxShowed) + { + while (selectedRow < list->template.maxShowed - 1) + { + selectedRow++; + if (list->template.items[scrollOffset + selectedRow].id != -3) + { + list->selectedRow = selectedRow; + return 1; + } + } + + return 0; + } + else + { + while (selectedRow < newRow) + { + selectedRow++; + if (list->template.items[scrollOffset + selectedRow].id != -3) + { + list->selectedRow = selectedRow; + return 1; + } + } + + newScroll = scrollOffset + 1; + } + } + + list->selectedRow = newRow; + list->scrollOffset = newScroll; + return 2; +} + +static void ListMenuScroll(struct ListMenu *list, u8 count, bool8 movingDown) +{ + if (count >= list->template.maxShowed) + { + FillWindowPixelBuffer(list->template.windowId, (list->template.fillValue << 4) | (list->template.fillValue)); + ListMenuPrintEntries(list, list->scrollOffset, 0, list->template.maxShowed); + } + else + { + u8 yMultiplier = GetFontAttribute(list->template.fontId, 1) + list->template.unk_16_3; + + if (!movingDown) + { + u16 y, width, height; + + ScrollWindow(list->template.windowId, 1, count * yMultiplier, (list->template.fillValue << 4) | (list->template.fillValue)); + ListMenuPrintEntries(list, list->scrollOffset, 0, count); + + y = (list->template.maxShowed * yMultiplier) + list->template.upText_Y; + width = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8; + height = (GetWindowAttribute(list->template.windowId, WINDOW_HEIGHT) * 8) - y; + FillWindowPixelRect(list->template.windowId, + (list->template.fillValue << 4) | (list->template.fillValue), + 0, y, width, height); + } + else + { + u16 width; + + ScrollWindow(list->template.windowId, 0, count * yMultiplier, (list->template.fillValue << 4) | (list->template.fillValue)); + ListMenuPrintEntries(list, list->scrollOffset + (list->template.maxShowed - count), list->template.maxShowed - count, count); + + width = GetWindowAttribute(list->template.windowId, WINDOW_WIDTH) * 8; + FillWindowPixelRect(list->template.windowId, + (list->template.fillValue << 4) | (list->template.fillValue), + 0, 0, width, list->template.upText_Y); + } + } +} + +static bool8 ListMenuChangeSelection(struct ListMenu *list, bool8 updateCursorAndCallCallback, u8 count, bool8 movingDown) +{ + u16 oldSelectedRow; + u8 selectionChange, i, cursorCount; + + oldSelectedRow = list->selectedRow; + cursorCount = 0; + selectionChange = 0; + for (i = 0; i < count; i++) + { + do + { + u8 ret = ListMenuUpdateSelectedRowIndexAndScrollOffset(list, movingDown); + selectionChange |= ret; + if (ret != 2) + break; + cursorCount++; + } while (list->template.items[list->scrollOffset + list->selectedRow].id == -3); + } + + if (updateCursorAndCallCallback) + { + switch (selectionChange) + { + case 0: + default: + return TRUE; + case 1: + ListMenuErasePrintedCursor(list, oldSelectedRow); + ListMenuDrawCursor(list); + ListMenuCallSelectionChangedCallback(list, 0); + CopyWindowToVram(list->template.windowId, 2); + break; + case 2: + case 3: + ListMenuErasePrintedCursor(list, oldSelectedRow); + ListMenuScroll(list, cursorCount, movingDown); + ListMenuDrawCursor(list); + ListMenuCallSelectionChangedCallback(list, 0); + CopyWindowToVram(list->template.windowId, 2); + break; + } + } + + return FALSE; +} + +static void ListMenuCallSelectionChangedCallback(struct ListMenu *list, u8 a2) +{ + if (list->template.moveCursorFunc != NULL) + list->template.moveCursorFunc(list->template.items[list->scrollOffset + list->selectedRow].id, a2, list); +} + +// unused +void sub_81AF028(u8 cursorPal, u8 fillValue, u8 cursorShadowPal) +{ + gUnknown_03006300.cursorPal = cursorPal; + gUnknown_03006300.fillValue = fillValue; + gUnknown_03006300.cursorShadowPal = cursorShadowPal; + gUnknown_03006300.field_3_7 = 1; +} + +void sub_81AF078(s32 arg0, u8 arg1, struct ListMenu *list) +{ + if (!arg1) + PlaySE(SE_SELECT); +} diff --git a/src/load_save.c b/src/load_save.c index a516c08c2..917c1dfe1 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -4,33 +4,30 @@ #include "main.h" #include "pokemon.h" #include "random.h" +#include "malloc.h" +#include "item.h" extern void* gUnknown_0203CF5C; extern bool16 IdentifyFlash(void); -extern void SetBagItemsPointers(void); extern void SetDecorationInventoriesPointers(void); extern void ApplyNewEncryptionKeyToGameStats(u32 key); -extern void ApplyNewEncryptionKeyToBagItems(u32 newKey); -extern void ApplyNewEncryptionKeyToBagItems_(u32 key); extern void ApplyNewEncryptionKeyToBerryPowder(u32 key); extern void sub_8084FAC(int unused); -// this is probably wrong or misleading due to it being used in ResetHeap... -extern void InitHeap(void *pointer, u32 size); - #define SAVEBLOCK_MOVE_RANGE 128 struct LoadedSaveData { - /*0x0000*/ struct ItemSlot items[30]; - /*0x0078*/ struct ItemSlot keyItems[30]; - /*0x00F0*/ struct ItemSlot pokeBalls[16]; - /*0x0130*/ struct ItemSlot TMsHMs[64]; - /*0x0230*/ struct ItemSlot berries[46]; + /*0x0000*/ struct ItemSlot items[BAG_ITEMS_COUNT]; + /*0x0078*/ struct ItemSlot keyItems[BAG_KEYITEMS_COUNT]; + /*0x00F0*/ struct ItemSlot pokeBalls[BAG_POKEBALLS_COUNT]; + /*0x0130*/ struct ItemSlot TMsHMs[BAG_TMHM_COUNT]; + /*0x0230*/ struct ItemSlot berries[BAG_BERRIES_COUNT]; /*0x02E8*/ struct MailStruct mail[MAIL_COUNT]; }; +// EWRAM DATA EWRAM_DATA struct SaveBlock2 gSaveblock2 = {0}; EWRAM_DATA u8 gSaveblock2_DMA[SAVEBLOCK_MOVE_RANGE] = {0}; @@ -43,8 +40,13 @@ EWRAM_DATA u8 gSaveblock3_DMA[SAVEBLOCK_MOVE_RANGE] = {0}; EWRAM_DATA struct LoadedSaveData gLoadedSaveData = {0}; EWRAM_DATA u32 gLastEncryptionKey = {0}; -void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey); +// IWRAM common +IWRAM_DATA bool32 gFlashMemoryPresent; +IWRAM_DATA struct SaveBlock1 *gSaveBlock1Ptr; +IWRAM_DATA struct SaveBlock2 *gSaveBlock2Ptr; +IWRAM_DATA struct PokemonStorage *gPokemonStoragePtr; +// code void CheckForFlashMemory(void) { if (!IdentifyFlash()) @@ -53,7 +55,9 @@ void CheckForFlashMemory(void) InitFlashTimer(); } else + { gFlashMemoryPresent = FALSE; + } } void ClearSav2(void) @@ -80,8 +84,6 @@ void SetSaveBlocksPointers(u16 offset) SetDecorationInventoriesPointers(); } -extern u8 gHeap[]; - void MoveSaveBlocks_ResetHeap(void) { void *vblankCB, *hblankCB; @@ -132,13 +134,12 @@ void MoveSaveBlocks_ResetHeap(void) gSaveBlock2Ptr->encryptionKey = encryptionKey; } - -u8 sav2_x1_query_bit1(void) +u32 GetSecretBase2Field_9(void) { return gSaveBlock2Ptr->specialSaveWarp & 1; } -void sav2_x9_clear_bit1(void) +void ClearSecretBase2Field_9(void) { gSaveBlock2Ptr->specialSaveWarp &= ~1; } @@ -159,112 +160,112 @@ void sav2_gender2_inplace_and_xFE(void) gSaveBlock2Ptr->specialSaveWarp &= ~1; } -void copy_player_party_to_sav1(void) // SavePlayerParty +void SavePlayerParty(void) { int i; gSaveBlock1Ptr->playerPartyCount = gPlayerPartyCount; - for (i = 0; i < 6; i++) + for (i = 0; i < PARTY_SIZE; i++) gSaveBlock1Ptr->playerParty[i] = gPlayerParty[i]; } -void copy_player_party_from_sav1(void) // LoadPlayerParty +void LoadPlayerParty(void) { int i; gPlayerPartyCount = gSaveBlock1Ptr->playerPartyCount; - for (i = 0; i < 6; i++) + for (i = 0; i < PARTY_SIZE; i++) gPlayerParty[i] = gSaveBlock1Ptr->playerParty[i]; } -void save_serialize_npcs(void) // SaveMapObjects +void SaveMapObjects(void) { int i; - for (i = 0; i < 16; i++) + for (i = 0; i < MAP_OBJECTS_COUNT; i++) gSaveBlock1Ptr->mapObjects[i] = gMapObjects[i]; } -void save_deserialize_npcs(void) // LoadMapObjects +void LoadMapObjects(void) { int i; - for (i = 0; i < 16; i++) + for (i = 0; i < MAP_OBJECTS_COUNT; i++) gMapObjects[i] = gSaveBlock1Ptr->mapObjects[i]; } void SaveSerializedGame(void) { - copy_player_party_to_sav1(); - save_serialize_npcs(); + SavePlayerParty(); + SaveMapObjects(); } void LoadSerializedGame(void) { - copy_player_party_from_sav1(); - save_deserialize_npcs(); + LoadPlayerParty(); + LoadMapObjects(); } -void copy_bags_and_unk_data_from_save_blocks(void) +void LoadPlayerBag(void) { int i; // load player items. - for (i = 0; i < 30; i++) + for (i = 0; i < BAG_ITEMS_COUNT; i++) gLoadedSaveData.items[i] = gSaveBlock1Ptr->bagPocket_Items[i]; // load player key items. - for (i = 0; i < 30; i++) + for (i = 0; i < BAG_KEYITEMS_COUNT; i++) gLoadedSaveData.keyItems[i] = gSaveBlock1Ptr->bagPocket_KeyItems[i]; // load player pokeballs. - for (i = 0; i < 16; i++) + for (i = 0; i < BAG_POKEBALLS_COUNT; i++) gLoadedSaveData.pokeBalls[i] = gSaveBlock1Ptr->bagPocket_PokeBalls[i]; // load player TMs and HMs. - for (i = 0; i < 64; i++) + for (i = 0; i < BAG_TMHM_COUNT; i++) gLoadedSaveData.TMsHMs[i] = gSaveBlock1Ptr->bagPocket_TMHM[i]; // load player berries. - for (i = 0; i < 46; i++) + for (i = 0; i < BAG_BERRIES_COUNT; i++) gLoadedSaveData.berries[i] = gSaveBlock1Ptr->bagPocket_Berries[i]; // load mail. - for (i = 0; i < 16; i++) + for (i = 0; i < MAIL_COUNT; i++) gLoadedSaveData.mail[i] = gSaveBlock1Ptr->mail[i]; gLastEncryptionKey = gSaveBlock2Ptr->encryptionKey; } -void copy_bags_and_unk_data_to_save_blocks(void) +void SavePlayerBag(void) { int i; u32 encryptionKeyBackup; // save player items. - for (i = 0; i < 30; i++) + for (i = 0; i < BAG_ITEMS_COUNT; i++) gSaveBlock1Ptr->bagPocket_Items[i] = gLoadedSaveData.items[i]; // save player key items. - for (i = 0; i < 30; i++) + for (i = 0; i < BAG_KEYITEMS_COUNT; i++) gSaveBlock1Ptr->bagPocket_KeyItems[i] = gLoadedSaveData.keyItems[i]; // save player pokeballs. - for (i = 0; i < 16; i++) + for (i = 0; i < BAG_POKEBALLS_COUNT; i++) gSaveBlock1Ptr->bagPocket_PokeBalls[i] = gLoadedSaveData.pokeBalls[i]; // save player TMs and HMs. - for (i = 0; i < 64; i++) + for (i = 0; i < BAG_TMHM_COUNT; i++) gSaveBlock1Ptr->bagPocket_TMHM[i] = gLoadedSaveData.TMsHMs[i]; // save player berries. - for (i = 0; i < 46; i++) + for (i = 0; i < BAG_BERRIES_COUNT; i++) gSaveBlock1Ptr->bagPocket_Berries[i] = gLoadedSaveData.berries[i]; // save mail. - for (i = 0; i < 16; i++) + for (i = 0; i < MAIL_COUNT; i++) gSaveBlock1Ptr->mail[i] = gLoadedSaveData.mail[i]; encryptionKeyBackup = gSaveBlock2Ptr->encryptionKey; diff --git a/src/mail.c b/src/mail.c index ac263ac67..8fddc7045 100644 --- a/src/mail.c +++ b/src/mail.c @@ -101,7 +101,7 @@ struct MailRead /*0x021c*/ u8 monIconSprite; /*0x021d*/ u8 language; /*0x021e*/ bool8 playerIsSender; - /*0x0220*/ void (*parserSingle)(u8 *dest, u16 word); + /*0x0220*/ u8 * (*parserSingle)(u8 *dest, u16 word); /*0x0224*/ void (*parserMultiple)(u8 *dest, const u16 *src, u16 length1, u16 length2); /*0x0228*/ const struct MailLayout *layout; /*0x022c*/ u8 bg1TilemapBuffer[0x1000]; @@ -403,11 +403,11 @@ static bool8 MailReadBuildGraphics(void) switch (sMailRead->animsActive) { case 1: - sub_80D2F68(icon); + LoadMonIconPalette(icon); sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x60, 0x80, 0, 0); break; case 2: - sub_80D2F68(icon); + LoadMonIconPalette(icon); sMailRead->monIconSprite = sub_80D2D78(icon, SpriteCallbackDummy, 0x28, 0x80, 0, 0); break; } @@ -540,7 +540,7 @@ static void CB2_ExitMailReadFreeVars(void) { case 1: case 2: - sub_80D2FF0(sub_80D2E84(sMailRead->mail->species)); + FreeMonIconPalette(sub_80D2E84(sMailRead->mail->species)); sub_80D2EF8(&gSprites[sMailRead->monIconSprite]); } memset(sMailRead, 0, sizeof(*sMailRead)); diff --git a/src/main.c b/src/main.c index d4601293b..f04f9b61b 100644 --- a/src/main.c +++ b/src/main.c @@ -1,50 +1,32 @@ #include "global.h" -#include "main.h" +#include "crt0.h" +#include "malloc.h" +#include "link.h" +#include "link_rfu.h" +#include "librfu.h" #include "m4a.h" +#include "bg.h" #include "rtc.h" +#include "scanline_effect.h" +#include "overworld.h" +#include "play_time.h" #include "random.h" #include "dma3.h" #include "gba/flash_internal.h" +#include "load_save.h" +#include "gpu_regs.h" +#include "agb_flash.h" +#include "sound.h" #include "battle.h" +#include "battle_controllers.h" +#include "text.h" +#include "intro.h" +#include "main.h" -extern u16 GetGpuReg(u8); -extern void SetGpuReg(u8, u16); -extern void LinkVSync(void); -extern void sub_800E174(void); extern void sub_800B9B8(void); -extern void InitGpuRegManager(void); -extern void sub_800E6D0(void); -extern void CheckForFlashMemory(void); -extern void InitMapMusic(void); -extern void ResetBgs(void); -extern void SetDefaultFontsPointer(void); -extern void InitHeap(void *heapStart, u32 heapSize); // malloc.h -extern void rfu_REQ_stopMode(void); -extern void rfu_waitREQComplete(void); -extern bool32 sub_8087634(void); -extern bool32 sub_80875C8(void); -extern void ClearSpriteCopyRequests(void); -extern void PlayTimeCounter_Update(void); -extern void MapMusicMain(void); -extern void EnableInterrupts(u16); -extern void sub_8033648(void); -extern u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void)); -extern void ScanlineEffect_Stop(void); - -extern struct SoundInfo gSoundInfo; -extern u32 gFlashMemoryPresent; -extern u32 IntrMain[]; -extern u8 gHeap[]; -extern struct SaveBlock2 gSaveblock2; -extern struct PokemonStorage gPokemonStorage; -extern u32 gBattleTypeFlags; extern u8 gUnknown_03002748; extern u32 *gUnknown_0203CF5C; -void Timer3Intr(void); -bool8 HandleLinkConnection(void); -void c2_copyright_1(void); - static void VBlankIntr(void); static void HBlankIntr(void); static void VCountIntr(void); @@ -79,19 +61,19 @@ const IntrFunc gIntrTableTemplate[] = static u16 gUnknown_03000000; -extern u16 gKeyRepeatStartDelay; -extern u8 gUnknown_030022B4; -extern struct Main gMain; -extern u16 gKeyRepeatContinueDelay; -extern u8 gSoftResetDisabled; -extern IntrFunc gIntrTable[INTR_COUNT]; -extern bool8 gLinkVSyncDisabled; -extern u32 IntrMain_Buffer[0x200]; -extern u8 gPcmDmaCounter; +u16 gKeyRepeatStartDelay; +bool8 gLinkTransferringData; +struct Main gMain; +u16 gKeyRepeatContinueDelay; +bool8 gSoftResetDisabled; +IntrFunc gIntrTable[INTR_COUNT]; +u8 gLinkVSyncDisabled; +u32 IntrMain_Buffer[0x200]; +u8 gPcmDmaCounter; -extern u16 gTrainerId; +static EWRAM_DATA u16 gTrainerId = 0; -EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL; +//EWRAM_DATA void (**gFlashTimerIntrFunc)(void) = NULL; static void UpdateLinkAndCallCallbacks(void); static void InitMainCallbacks(void); @@ -129,7 +111,7 @@ void AgbMain() if (gFlashMemoryPresent != TRUE) SetMainCallback2(NULL); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; gUnknown_03000000 = 0xFC0; for (;;) @@ -147,22 +129,22 @@ void AgbMain() if (sub_8087634() == 1) { - gUnknown_030022B4 = 1; + gLinkTransferringData = TRUE; UpdateLinkAndCallCallbacks(); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; } else { - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; UpdateLinkAndCallCallbacks(); if (sub_80875C8() == 1) { gMain.newKeys = 0; ClearSpriteCopyRequests(); - gUnknown_030022B4 = 1; + gLinkTransferringData = TRUE; UpdateLinkAndCallCallbacks(); - gUnknown_030022B4 = 0; + gLinkTransferringData = FALSE; } } @@ -184,7 +166,7 @@ static void InitMainCallbacks(void) gUnknown_0203CF5C = NULL; gMain.vblankCounter2 = 0; gMain.callback1 = NULL; - SetMainCallback2(c2_copyright_1); + SetMainCallback2(CB2_InitCopyrightScreenAfterBootup); gSaveBlock2Ptr = &gSaveblock2; gPokemonStoragePtr = &gPokemonStorage; } @@ -335,10 +317,10 @@ extern void CopyBufferedValuesToGpuRegs(void); static void VBlankIntr(void) { - if (gLinkVSyncDisabled != FALSE) + if (gWirelessCommType != 0) + RfuVSync(); + else if (gLinkVSyncDisabled == FALSE) LinkVSync(); - else if (gUnknown_03002748 == FALSE) - sub_800B9B8(); gMain.vblankCounter1++; diff --git a/src/main_menu.c b/src/main_menu.c index 8608159c2..3d6c1df76 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -1,15 +1,1977 @@ // Includes #include "global.h" +#include "battle_dome_cards.h" +#include "bg.h" +#include "constants/flags.h" +#include "constants/rgb.h" +#include "constants/songs.h" +#include "constants/species.h" +#include "decompress.h" +#include "event_data.h" +#include "field_effect.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "international_string_util.h" +#include "link.h" +#include "main.h" +#include "menu.h" +#include "menu_indicators.h" +#include "mystery_event_menu.h" +#include "naming_screen.h" +#include "option_menu.h" +#include "overworld.h" +#include "palette.h" +#include "pokeball.h" +#include "pokedex.h" +#include "pokemon_3.h" +#include "random.h" +#include "rtc.h" +#include "save.h" +#include "scanline_effect.h" +#include "sound.h" +#include "sprite.h" +#include "string.h" +#include "strings.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "text_window.h" +#include "title_screen.h" +#include "window.h" // Static type declarations // Static RAM declarations +EWRAM_DATA u8 gUnknown_02022D04 = 0; +EWRAM_DATA u16 gUnknown_02022D06 = 0; + IWRAM_DATA u8 gUnknown_03000DD0; // Static ROM declarations +u32 InitMainMenu(bool8); +void Task_MainMenuCheckSaveFile(u8); +void Task_MainMenuCheckBattery(u8); +void Task_WaitForSaveFileErrorWindow(u8); +void CreateMainMenuErrorWindow(const u8*); +void sub_8032250(const struct WindowTemplate*); +void Task_DisplayMainMenu(u8); +void Task_WaitForBatteryDryErrorWindow(u8); +void fmt_savegame(void); +void HighlightSelectedMainMenuItem(u8, u8, s16); +void Task_HandleMainMenuInput(u8); +void Task_HandleMainMenuAPressed(u8); +void Task_HandleMainMenuBPressed(u8); +void task_new_game_prof_birch_speech_1(u8); +void Task_DisplayMainMenuInvalidActionError(u8); +void AddBirchSpeechObjects(u8); +void task_new_game_prof_birch_speech_2(u8); +void sub_8031BAC(u8, u8); +void sub_8031D34(u8, u8); +void task_new_game_prof_birch_speech_3(u8); +void unknown_rbox_to_vram(u8, u8); +void sub_8032318(u8); +void task_new_game_prof_birch_speech_4(u8); +void task_new_game_prof_birch_speech_5(u8); +void sub_80323A0(struct TextSubPrinter *printer, u16 a); +void task_new_game_prof_birch_speech_6(u8); +void sub_8030B14(u8); +void task_new_game_prof_birch_speech_7(u8); +void sub_8031ACC(u8, u8); +void sub_8031C88(u8, u8); +void task_new_game_prof_birch_speech_8(u8); +void task_new_game_prof_birch_speech_9(u8); +void task_new_game_prof_birch_speech_10(u8); +void task_new_game_prof_birch_speech_11(u8); +void LoadMainMenuWindowFrameTiles(u8, u16); +void DrawMainMenuWindowBorder(const struct WindowTemplate*, u16); +void Task_HighlightSelectedMainMenuItem(u8); +void task_new_game_prof_birch_speech_12(u8); +void task_new_game_prof_birch_speech_13(u8); +void sub_8031D74(void); +s8 sub_8031DB4(void); +void sub_80322E0(u8, u8); +void task_new_game_prof_birch_speech_14(u8); +void sub_8030ED4(u8); +void sub_8030F7C(u8); +void task_new_game_prof_birch_speech_15(u8); +void task_new_game_prof_birch_speech_16(u8); +void task_new_game_prof_birch_speech_17(u8); +void new_game_prof_birch_speech_part2_start(void); +void set_default_player_name(u8); +void task_new_game_prof_birch_speech_part2_3(u8); +void task_new_game_prof_birch_speech_part2_4(u8); +void sub_80323CC(u8, u8, u16, u16, u8, u8); +void task_new_game_prof_birch_speech_part2_5(u8); +void task_new_game_prof_birch_speech_part2_6(u8); +void task_new_game_prof_birch_speech_part2_7(u8); +void task_new_game_prof_birch_speech_part2_8(u8); +void task_new_game_prof_birch_speech_part2_9(u8); +void sub_80318D8(struct Sprite*); +void task_new_game_prof_birch_speech_part2_10(u8); +void task_new_game_prof_birch_speech_part2_11(u8); +void task_new_game_prof_birch_speech_part2_12(u8); +void nullsub_11(); +void task_new_game_prof_birch_speech_part2_1(u8); +void fmt_time(void); +void fmt_pokedex(void); +void fmt_player(void); +void fmt_badges(void); +void sub_8032474(u8, u8, u8, u8, u8, u8); + // .rodata +const u16 gUnknown_082FECFC[][16] = { + INCBIN_U16("graphics/birch_speech/bg0.gbapal"), + INCBIN_U16("graphics/birch_speech/bg1.gbapal") +}; + +const u8 gBirchIntroShadowGfx[] = INCBIN_U8("graphics/birch_speech/shadow.4bpp.lz"); +const u8 gUnknown_082FEEF0[] = INCBIN_U8("graphics/birch_speech/map.bin.lz"); +const u16 gUnknown_082FF018[] = INCBIN_U16("graphics/birch_speech/bg2.gbapal"); +const u16 gUnknown_082FF028[] = {0, 0, 0, 0, 0, 0, 0, 0}; + +const struct WindowTemplate gUnknown_082FF038[] = { + {0, 2, 1, 26, 2, 15, 1}, + {0, 2, 5, 26, 2, 15, 0x35} +}; + +const struct WindowTemplate gUnknown_082FF048[] = { + {0, 2, 1, 26, 6, 15, 1}, + {0, 2, 9, 26, 2, 15, 0x9D}, + {0, 2, 13, 26, 2, 15, 0xD1}, + {0, 2, 17, 26, 2, 15, 0x105}, + {0, 2, 21, 26, 2, 15, 0x139} +}; + +const struct WindowTemplate gUnknown_082FF070[] = { + {0, 2, 15, 26, 4, 15, 0x16D}, + {0xFF, 0, 0, 0, 0, 0, 0} +}; + +const struct WindowTemplate gUnknown_082FF080[] = { + {0, 2, 15, 27, 4, 15, 1}, + {0, 3, 5, 6, 4, 15, 0x6D}, + {0, 3, 2, 9, 10, 15, 0x85}, + {0xFF, 0, 0, 0, 0, 0, 0} +}; + +const u16 gMainMenuBgPal[] = INCBIN_U16("graphics/misc/main_menu_bg.gbapal"); +const u16 gMainMenuTextPal[] = INCBIN_U16("graphics/misc/main_menu_text.gbapal"); + +const u8 gUnknown_082FF0E0[] = {10, 11, 12}; +const u8 gUnknown_082FF0E3[] = {10, 1, 12}; + +const struct BgTemplate gUnknown_082FF0E8[] = { + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 7, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0 + } +}; + +const struct BgTemplate gUnknown_082FF0F0 = { + .bg = 0, + .charBaseIndex = 3, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 +}; + +const struct ArrowStruct gUnknown_082FF0F4 = {2, 0x78, 8, 3, 0x78, 0x98, 3, 4, 1, 1, 0}; + +const union AffineAnimCmd gUnknown_082FF104[] = { + AFFINEANIMCMD_FRAME(-2, -2, 0, 0x30), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd *const gUnknown_082FF114 = gUnknown_082FF104; + +const struct MenuAction gUnknown_082FF118[] = { + {gText_BirchBoy, NULL}, + {gText_BirchGirl, NULL} +}; + +const u8 *const gMalePresetNames[] = { + gText_DefaultNameStu, + gText_DefaultNameMilton, + gText_DefaultNameTom, + gText_DefaultNameKenny, + gText_DefaultNameReid, + gText_DefaultNameJude, + gText_DefaultNameJaxson, + gText_DefaultNameEaston, + gText_DefaultNameWalker, + gText_DefaultNameTeru, + gText_DefaultNameJohnny, + gText_DefaultNameBrett, + gText_DefaultNameSeth, + gText_DefaultNameTerry, + gText_DefaultNameCasey, + gText_DefaultNameDarren, + gText_DefaultNameLandon, + gText_DefaultNameCollin, + gText_DefaultNameStanley, + gText_DefaultNameQuincy +}; + +const u8 *const gFemalePresetNames[] = { + gText_DefaultNameKimmy, + gText_DefaultNameTiara, + gText_DefaultNameBella, + gText_DefaultNameJayla, + gText_DefaultNameAllie, + gText_DefaultNameLianna, + gText_DefaultNameSara, + gText_DefaultNameMonica, + gText_DefaultNameCamila, + gText_DefaultNameAubree, + gText_DefaultNameRuthie, + gText_DefaultNameHazel, + gText_DefaultNameNadine, + gText_DefaultNameTanja, + gText_DefaultNameYasmin, + gText_DefaultNameNicola, + gText_DefaultNameLillie, + gText_DefaultNameTerra, + gText_DefaultNameLucy, + gText_DefaultNameHalie +}; + // .text + +enum +{ + HAS_NO_SAVED_GAME, //NEW GAME, OPTION + HAS_SAVED_GAME, //CONTINUE, NEW GAME, OPTION + HAS_MYSTERY_GIFT, //CONTINUE, NEW GAME, MYSTERY EVENTS, OPTION + HAS_MYSTERY_EVENTS, +}; + +#define MAIN_MENU_BORDER_TILE 0x1D5 + +void CB2_MainMenu(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +void VBlankCB_MainMenu(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_InitMainMenu(void) +{ + InitMainMenu(FALSE); +} + +void CB2_ReinitMainMenu(void) +{ + InitMainMenu(TRUE); +} + +u32 InitMainMenu(bool8 returningFromOptionsMenu) +{ + SetVBlankCallback(NULL); + + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + + DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); + DmaFill32(3, 0, (void *)OAM, OAM_SIZE); + DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); + + ResetPaletteFade(); + LoadPalette(gMainMenuBgPal, 0, 32); + LoadPalette(gMainMenuTextPal, 0xF0, 32); + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + FreeAllSpritePalettes(); + if (returningFromOptionsMenu) + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0x0000); // fade to black + else + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0xFFFF); // fade to white + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, gUnknown_082FF0E8, 2); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + InitWindows(gUnknown_082FF038); + DeactivateAllTextPrinters(); + LoadMainMenuWindowFrameTiles(0, MAIN_MENU_BORDER_TILE); + + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 0); + SetGpuReg(REG_OFFSET_WINOUT, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + + EnableInterrupts(1); + SetVBlankCallback(VBlankCB_MainMenu); + SetMainCallback2(CB2_MainMenu); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + ShowBg(0); + HideBg(1); + CreateTask(Task_MainMenuCheckSaveFile, 0); + + return 0; +} + +void Task_MainMenuCheckSaveFile(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 17); + SetGpuReg(REG_OFFSET_WINOUT, 0x31); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_DARKEN | BLDCNT_TGT1_BG0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 7); + + if (sub_80093CC()) + data[15] = 1; + switch (gSaveFileStatus) + { + case 1: + data[0] = HAS_SAVED_GAME; + if (IsMysteryGiftEnabled()) + data[0]++; + gTasks[taskId].func = Task_MainMenuCheckBattery; + break; + case 2: + CreateMainMenuErrorWindow(gText_SaveFileErased); + data[0] = 0; + gTasks[taskId].func = Task_WaitForSaveFileErrorWindow; + break; + case 0xFF: + CreateMainMenuErrorWindow(gText_SaveFileCorrupted); + gTasks[taskId].func = Task_WaitForSaveFileErrorWindow; + data[0] = HAS_SAVED_GAME; + if (IsMysteryGiftEnabled() == TRUE) + data[0]++; + break; + case 0: + default: + data[0] = HAS_NO_SAVED_GAME; + gTasks[taskId].func = Task_MainMenuCheckBattery; + break; + case 4: + CreateMainMenuErrorWindow(gJPText_No1MSubCircuit); + gTasks[taskId].data[0] = HAS_NO_SAVED_GAME; + gTasks[taskId].func = Task_WaitForSaveFileErrorWindow; + break; + } + if (gUnknown_02022D06 & 0x8000) + { + switch (data[0]) + { + case HAS_NO_SAVED_GAME: + case HAS_SAVED_GAME: + gUnknown_02022D06 = data[0] + 1; + break; + case HAS_MYSTERY_GIFT: + gUnknown_02022D06 = 3; + break; + case 3: + gUnknown_02022D06 = 4; + break; + } + } + gUnknown_02022D06 &= 0x7FFF; + data[1] = gUnknown_02022D06; + data[12] = data[0] + 2; + } +} + +void Task_WaitForSaveFileErrorWindow(u8 taskId) +{ + RunTextPrinters(); + if (!IsTextPrinterActive(7) && (gMain.newKeys & A_BUTTON)) + { + ClearWindowTilemap(7); + sub_8032250(gUnknown_082FF070); + gTasks[taskId].func = Task_MainMenuCheckBattery; + } +} + +void Task_MainMenuCheckBattery(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 17); + SetGpuReg(REG_OFFSET_WINOUT, 0x31); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_DARKEN | BLDCNT_TGT1_BG0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 7); + + if (!(RtcGetErrorStatus() & RTC_ERR_FLAG_MASK)) + { + gTasks[taskId].func = Task_DisplayMainMenu; + } + else + { + CreateMainMenuErrorWindow(gText_BatteryRunDry); + gTasks[taskId].func = Task_WaitForBatteryDryErrorWindow; + } + } +} + +void Task_WaitForBatteryDryErrorWindow(u8 taskId) +{ + RunTextPrinters(); + if (!IsTextPrinterActive(7) && (gMain.newKeys & A_BUTTON)) + { + ClearWindowTilemap(7); + sub_8032250(gUnknown_082FF070); + gTasks[taskId].func = Task_DisplayMainMenu; + } +} + +void Task_DisplayMainMenu(u8 taskId) +{ + s16* data = gTasks[taskId].data; + u16 palette; + + if (!gPaletteFade.active) + { + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 17); + SetGpuReg(REG_OFFSET_WINOUT, 0x31); + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_DARKEN | BLDCNT_TGT1_BG0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 7); + + palette = RGB_BLACK; + LoadPalette(&palette, 254, 2); + + palette = RGB_WHITE; + LoadPalette(&palette, 250, 2); + + palette = RGB(12, 12, 12); + LoadPalette(&palette, 251, 2); + + palette = RGB(26, 26, 25); + LoadPalette(&palette, 252, 2); + + if (gSaveBlock2Ptr->playerGender == MALE) + { + palette = RGB(4, 16, 31); + LoadPalette(&palette, 241, 2); + } + else + { + palette = RGB(31, 3, 21); + LoadPalette(&palette, 241, 2); + } + + switch (gTasks[taskId].data[0]) + { + case HAS_NO_SAVED_GAME: + default: + FillWindowPixelBuffer(0, 0xAA); + FillWindowPixelBuffer(1, 0xAA); + box_print(0, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuNewGame); + box_print(1, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuOption); + PutWindowTilemap(0); + PutWindowTilemap(1); + CopyWindowToVram(0, 2); + CopyWindowToVram(1, 2); + DrawMainMenuWindowBorder(gUnknown_082FF038, MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF038[1], MAIN_MENU_BORDER_TILE); + break; + case HAS_SAVED_GAME: + FillWindowPixelBuffer(2, 0xAA); + FillWindowPixelBuffer(3, 0xAA); + FillWindowPixelBuffer(4, 0xAA); + box_print(2, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuContinue); + box_print(3, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuNewGame); + box_print(4, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuOption); + fmt_savegame(); + PutWindowTilemap(2); + PutWindowTilemap(3); + PutWindowTilemap(4); + CopyWindowToVram(2, 2); + CopyWindowToVram(3, 2); + CopyWindowToVram(4, 2); + DrawMainMenuWindowBorder(gUnknown_082FF048, MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[1], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[2], MAIN_MENU_BORDER_TILE); + break; + case HAS_MYSTERY_GIFT: + FillWindowPixelBuffer(2, 0xAA); + FillWindowPixelBuffer(3, 0xAA); + FillWindowPixelBuffer(4, 0xAA); + FillWindowPixelBuffer(5, 0xAA); + box_print(2, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuContinue); + box_print(3, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuNewGame); + box_print(4, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuMysteryGift); + box_print(5, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuOption); + fmt_savegame(); + PutWindowTilemap(2); + PutWindowTilemap(3); + PutWindowTilemap(4); + PutWindowTilemap(5); + CopyWindowToVram(2, 2); + CopyWindowToVram(3, 2); + CopyWindowToVram(4, 2); + CopyWindowToVram(5, 2); + DrawMainMenuWindowBorder(gUnknown_082FF048, MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[1], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[2], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[3], MAIN_MENU_BORDER_TILE); + break; + case HAS_MYSTERY_EVENTS: + FillWindowPixelBuffer(2, 0xAA); + FillWindowPixelBuffer(3, 0xAA); + FillWindowPixelBuffer(4, 0xAA); + FillWindowPixelBuffer(5, 0xAA); + FillWindowPixelBuffer(6, 0xAA); + box_print(2, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuContinue); + box_print(3, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuNewGame); + box_print(4, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuMysteryGift2); + box_print(5, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuMysteryEvents); + box_print(6, 1, 0, 1, gUnknown_082FF0E0, -1, gText_MainMenuOption); + fmt_savegame(); + PutWindowTilemap(2); + PutWindowTilemap(3); + PutWindowTilemap(4); + PutWindowTilemap(5); + PutWindowTilemap(6); + CopyWindowToVram(2, 2); + CopyWindowToVram(3, 2); + CopyWindowToVram(4, 2); + CopyWindowToVram(5, 2); + CopyWindowToVram(6, 2); + DrawMainMenuWindowBorder(gUnknown_082FF048, MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[1], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[2], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[3], MAIN_MENU_BORDER_TILE); + DrawMainMenuWindowBorder(&gUnknown_082FF048[4], MAIN_MENU_BORDER_TILE); + data[13] = AddScrollIndicatorArrowPair(&gUnknown_082FF0F4, &gUnknown_02022D06); + gTasks[data[13]].func = Task_ScrollIndicatorArrowPairOnMainMenu; + if (gUnknown_02022D06 == 4) + { + ChangeBgY(0, 0x2000, 1); + ChangeBgY(1, 0x2000, 1); + data[14] = 1; + gTasks[data[13]].data[15] = 1; + } + break; + } + gTasks[taskId].func = Task_HighlightSelectedMainMenuItem; + } +} + +void Task_HighlightSelectedMainMenuItem(u8 taskId) +{ + HighlightSelectedMainMenuItem(gTasks[taskId].data[0], gTasks[taskId].data[1], gTasks[taskId].data[14]); + gTasks[taskId].func = Task_HandleMainMenuInput; +} + +bool8 HandleMainMenuInput(u8 taskId) +{ + s16* data = gTasks[taskId].data; + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sub_80093CC(); + BeginNormalPaletteFade(-1, 0, 0, 0x10, RGB_BLACK); + gTasks[taskId].func = Task_HandleMainMenuAPressed; + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + BeginNormalPaletteFade(-1, 0, 0, 0x10, RGB_WHITEALPHA); + SetGpuReg(REG_OFFSET_WIN0H, 0xF0); + SetGpuReg(REG_OFFSET_WIN0V, 0xA0); + gTasks[taskId].func = Task_HandleMainMenuBPressed; + } + else if ((gMain.newKeys & DPAD_UP) && data[1] > 0) + { + if (data[0] == 3 && data[14] == 1 && data[1] == 1) + { + ChangeBgY(0, 0x2000, 2); + ChangeBgY(1, 0x2000, 2); + gTasks[data[13]].data[15] = data[14] = 0; + } + data[1]--; + gUnknown_02022D06 = data[1]; + return TRUE; + } + else if ((gMain.newKeys & DPAD_DOWN) && data[1] < data[12] - 1) + { + if (data[0] == 3 && data[1] == 3 && data[14] == 0) + { + ChangeBgY(0, 0x2000, 1); + ChangeBgY(1, 0x2000, 1); + gTasks[data[13]].data[15] = data[14] = 1; + } + data[1]++; + gUnknown_02022D06 = data[1]; + return TRUE; + } + return FALSE; +} + +void Task_HandleMainMenuInput(u8 taskId) +{ + if (HandleMainMenuInput(taskId)) + gTasks[taskId].func = Task_HighlightSelectedMainMenuItem; +} + +void Task_HandleMainMenuAPressed(u8 taskId) +{ + bool8 r2; + u8 action; + + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[0] == 3) + RemoveScrollIndicatorArrowPair(gTasks[taskId].data[13]); + sub_819746C(0, 1); + sub_819746C(1, 1); + sub_819746C(2, 1); + sub_819746C(3, 1); + sub_819746C(4, 1); + sub_819746C(5, 1); + sub_819746C(6, 1); + sub_819746C(7, 1); + r2 = sub_80093CC(); + switch (gTasks[taskId].data[0]) + { + case HAS_NO_SAVED_GAME: + default: + switch (gTasks[taskId].data[1]) + { + case 0: + default: + action = 0; + break; + case 1: + action = 2; + break; + } + break; + case HAS_SAVED_GAME: + switch (gTasks[taskId].data[1]) + { + case 0: + default: + action = 1; + break; + case 1: + action = 0; + break; + case 2: + action = 2; + break; + } + break; + case HAS_MYSTERY_GIFT: + switch (gTasks[taskId].data[1]) + { + case 0: + default: + action = 1; + break; + case 1: + action = 0; + break; + case 2: + action = 3; + if (r2 == FALSE) + { + action = 6; + gTasks[taskId].data[0] = 0; + } + break; + case 3: + action = 2; + break; + } + break; + case HAS_MYSTERY_EVENTS: + switch (gTasks[taskId].data[1]) + { + case 0: + default: + action = 1; + break; + case 1: + action = 0; + break; + case 2: + if (gTasks[taskId].data[15]) + { + action = 3; + if (r2 == FALSE) + { + action = 6; + gTasks[taskId].data[0] = 0; + } + } + else if (r2) + { + action = 6; + gTasks[taskId].data[0] = 1; + } + else + { + action = 5; + } + break; + case 3: + if (r2) + { + action = 6; + gTasks[taskId].data[0] = 2; + } + else + { + action = 4; + } + break; + case 4: + action = 2; + break; + } + break; + } + ChangeBgY(0, 0, 0); + ChangeBgY(1, 0, 0); + switch (action) + { + case 0: + default: + gPlttBufferUnfaded[0] = RGB_BLACK; + gPlttBufferFaded[0] = RGB_BLACK; + gTasks[taskId].func = task_new_game_prof_birch_speech_1; + break; + case 1: + gPlttBufferUnfaded[0] = RGB_BLACK; + gPlttBufferFaded[0] = RGB_BLACK; + SetMainCallback2(CB2_ContinueSavedGame); + DestroyTask(taskId); + break; + case 2: + gMain.savedCallback = CB2_ReinitMainMenu; + SetMainCallback2(CB2_InitOptionMenu); + DestroyTask(taskId); + break; + case 3: + SetMainCallback2(c2_mystery_gift); + DestroyTask(taskId); + break; + case 4: + SetMainCallback2(CB2_InitMysteryEventMenu); + DestroyTask(taskId); + break; + case 5: + SetMainCallback2(sub_801867C); + DestroyTask(taskId); + break; + case 6: + gTasks[taskId].data[1] = 0; + gTasks[taskId].func = Task_DisplayMainMenuInvalidActionError; + gPlttBufferUnfaded[0xF1] = RGB_WHITE; + gPlttBufferFaded[0xF1] = RGB_WHITE; + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + return; + } + FreeAllWindowBuffers(); + if (action != 2) + gUnknown_02022D06 = 0; + else + gUnknown_02022D06 |= 0x8000; + } +} + +void Task_HandleMainMenuBPressed(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[0] == 3) + RemoveScrollIndicatorArrowPair(gTasks[taskId].data[13]); + gUnknown_02022D06 = 0; + FreeAllWindowBuffers(); + SetMainCallback2(CB2_InitTitleScreen); + DestroyTask(taskId); + } +} + +void Task_DisplayMainMenuInvalidActionError(u8 taskId) +{ + switch (gTasks[taskId].data[1]) + { + case 0: + FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 30, 20); + switch (gTasks[taskId].data[0]) + { + case 0: + CreateMainMenuErrorWindow(gText_WirelessNotConnected); + break; + case 1: + CreateMainMenuErrorWindow(gText_MysteryGiftCantUse); + break; + case 2: + CreateMainMenuErrorWindow(gText_MysteryEventsCantUse); + break; + } + gTasks[taskId].data[1]++; + break; + case 1: + if (!gPaletteFade.active) + gTasks[taskId].data[1]++; + break; + case 2: + RunTextPrinters(); + if (!IsTextPrinterActive(7)) + gTasks[taskId].data[1]++; + break; + case 3: + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + PlaySE(SE_SELECT); + BeginNormalPaletteFade(-1, 0, 0, 16, RGB_BLACK); + gTasks[taskId].func = Task_HandleMainMenuBPressed; + } + } +} + +void HighlightSelectedMainMenuItem(u8 menuType, u8 selectedMenuItem, s16 a) +{ + SetGpuReg(REG_OFFSET_WIN0H, 0x9E7); + + switch (menuType) + { + case HAS_NO_SAVED_GAME: + default: + switch (selectedMenuItem) + { + case 0: + default: + SetGpuReg(REG_OFFSET_WIN0V, 0x11F); + break; + case 1: + SetGpuReg(REG_OFFSET_WIN0V, 0x213F); + break; + } + break; + case HAS_SAVED_GAME: + switch (selectedMenuItem) + { + case 0: + default: + SetGpuReg(REG_OFFSET_WIN0V, 0x13F); + break; + case 1: + SetGpuReg(REG_OFFSET_WIN0V, 0x415F); + break; + case 2: + SetGpuReg(REG_OFFSET_WIN0V, 0x617F); + break; + } + break; + case HAS_MYSTERY_GIFT: + switch (selectedMenuItem) + { + case 0: + default: + SetGpuReg(REG_OFFSET_WIN0V, 0x13F); + break; + case 1: + SetGpuReg(REG_OFFSET_WIN0V, 0x415F); + break; + case 2: + SetGpuReg(REG_OFFSET_WIN0V, 0x617F); + break; + case 3: + SetGpuReg(REG_OFFSET_WIN0V, 0x819F); + break; + } + break; + case HAS_MYSTERY_EVENTS: + switch (selectedMenuItem) + { + case 0: + default: + SetGpuReg(REG_OFFSET_WIN0V, 0x13F); + break; + case 1: + if (a) + SetGpuReg(REG_OFFSET_WIN0V, 0x213F); + else + SetGpuReg(REG_OFFSET_WIN0V, 0x415F); + break; + case 2: + if (a) + SetGpuReg(REG_OFFSET_WIN0V, 0x415F); + else + SetGpuReg(REG_OFFSET_WIN0V, 0x617F); + break; + case 3: + if (a) + SetGpuReg(REG_OFFSET_WIN0V, 0x617F); + else + SetGpuReg(REG_OFFSET_WIN0V, 0x819F); + break; + case 4: + SetGpuReg(REG_OFFSET_WIN0V, 0x819F); + break; + } + break; + } +} + +void task_new_game_prof_birch_speech_1(u8 taskId) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + InitBgFromTemplate(&gUnknown_082FF0F0); + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 0); + SetGpuReg(REG_OFFSET_WINOUT, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + + LZ77UnCompVram(gBirchIntroShadowGfx, (void*)VRAM); + LZ77UnCompVram(gUnknown_082FEEF0, (void*)(VRAM + 0x3800)); + LoadPalette(gUnknown_082FECFC, 0, 64); + LoadPalette(gUnknown_082FF028, 1, 16); + ScanlineEffect_Stop(); + ResetSpriteData(); + FreeAllSpritePalettes(); + dp13_810BB8C(); + AddBirchSpeechObjects(taskId); + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + gTasks[taskId].data[4] = 0; + gTasks[taskId].func = task_new_game_prof_birch_speech_2; + gTasks[taskId].data[2] = 0xFF; + gTasks[taskId].data[3] = 0xFF; + gTasks[taskId].data[7] = 0xD8; + PlayBGM(MUS_DOORO_X4); + ShowBg(0); + ShowBg(1); +} + +void task_new_game_prof_birch_speech_2(u8 taskId) +{ + u8 spriteId; + + if (gTasks[taskId].data[7]) + { + gTasks[taskId].data[7]--; + } + else + { + spriteId = gTasks[taskId].data[8]; + gSprites[spriteId].pos1.x = 0x88; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = 0; + gSprites[spriteId].oam.objMode = 1; + sub_8031BAC(taskId, 10); + sub_8031D34(taskId, 20); + gTasks[taskId].data[7] = 0x50; + gTasks[taskId].func = task_new_game_prof_birch_speech_3; + } +} + +void task_new_game_prof_birch_speech_3(u8 taskId) +{ + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[8]].oam.objMode = 0; + if (gTasks[taskId].data[7]) + { + gTasks[taskId].data[7]--; + } + else + { + InitWindows(gUnknown_082FF080); + LoadMainMenuWindowFrameTiles(0, 0xF3); + copy_textbox_border_tile_patterns_to_vram(0, 0xFC, 0xF0); + unknown_rbox_to_vram(0, 1); + PutWindowTilemap(0); + CopyWindowToVram(0, 2); + sub_8032318(0); + StringExpandPlaceholders(gStringVar4, gText_Birch_Welcome); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_4; + } + } +} + +void task_new_game_prof_birch_speech_4(u8 taskId) +{ + if (!gPaletteFade.active && !sub_8197224()) + { + gTasks[taskId].func = task_new_game_prof_birch_speech_5; + StringExpandPlaceholders(gStringVar4, gText_ThisIsAPokemon); + AddTextPrinterWithCallbackForMessage(1, sub_80323A0); + gUnknown_03000DD0 = taskId; + } +} + +void task_new_game_prof_birch_speech_5(u8 taskId) +{ + if (!sub_8197224()) + { + StringExpandPlaceholders(gStringVar4, gText_Birch_MainSpeech); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_6; + } +} + +void sub_8030A70(u8 taskId) +{ + u8 spriteId = gTasks[gUnknown_03000DD0].data[9]; + + gSprites[spriteId].pos1.x = 0x64; + gSprites[spriteId].pos1.y = 0x4B; + gSprites[spriteId].invisible = 0; + gSprites[spriteId].data[0] = 0; + + CreatePokeballSpriteToReleaseMon(spriteId, gSprites[spriteId].oam.paletteNum, 0x70, 0x3A, 0, 0, 0x20, 0xFFFF, SPECIES_LOTAD); + gTasks[taskId].func = sub_8030B14; + gTasks[gUnknown_03000DD0].data[7] = 0; +} + +void sub_8030B14(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + struct Sprite *sprite = &gSprites[gTasks[gUnknown_03000DD0].data[9]]; + + switch (data[0]) + { + case 0: + if (sprite->callback == SpriteCallbackDummy) + { + sprite->oam.affineMode = 0; + goto _08030B98_inc_data0; + } + break; + case 1: + if (gTasks[gUnknown_03000DD0].data[7] >= 0x60) + { + DestroyTask(taskId); + if (gTasks[gUnknown_03000DD0].data[7] < 0x4000) + gTasks[gUnknown_03000DD0].data[7]++; + } + break; + _08030B98_inc_data0: + default: + data[0]++; + if (gTasks[gUnknown_03000DD0].data[7] < 0x4000) + gTasks[gUnknown_03000DD0].data[7]++; + break; + } +} + +void task_new_game_prof_birch_speech_6(u8 taskId) +{ + if (!sub_8197224()) + { + gUnknown_02022D04 = 0; + StringExpandPlaceholders(gStringVar4, gText_Birch_AndYouAre); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_7; + } +} + +void task_new_game_prof_birch_speech_7(u8 taskId) +{ + if (!sub_8197224()) + { + gSprites[gTasks[taskId].data[8]].oam.objMode = 1; + gSprites[gTasks[taskId].data[9]].oam.objMode = 1; + sub_8031ACC(taskId, 2); + sub_8031C88(taskId, 1); + gTasks[taskId].data[7] = 0x40; + gTasks[taskId].func = task_new_game_prof_birch_speech_8; + } +} + +void task_new_game_prof_birch_speech_8(u8 taskId) +{ + if (gTasks[taskId].data[4] != -60) + { + gTasks[taskId].data[4] -= 2; + SetGpuReg(REG_OFFSET_BG1HOFS, gTasks[taskId].data[4]); + } + else + { + gTasks[taskId].data[4] = -60; + gTasks[taskId].func = task_new_game_prof_birch_speech_9; + } +} + +void task_new_game_prof_birch_speech_9(u8 taskId) +{ + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[8]].invisible = 1; + gSprites[gTasks[taskId].data[9]].invisible = 1; + if (gTasks[taskId].data[7]) + { + gTasks[taskId].data[7]--; + } + else + { + u8 spriteId = gTasks[taskId].data[10]; + + gSprites[spriteId].pos1.x = 0xB4; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = 0; + gSprites[spriteId].oam.objMode = 1; + gTasks[taskId].data[2] = spriteId; + gTasks[taskId].data[6] = 0; + sub_8031BAC(taskId, 2); + sub_8031D34(taskId, 1); + gTasks[taskId].func = task_new_game_prof_birch_speech_10; + } + } +} + +void task_new_game_prof_birch_speech_10(u8 taskId) +{ + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[2]].oam.objMode = 0; + gTasks[taskId].func = task_new_game_prof_birch_speech_11; + } +} + +void task_new_game_prof_birch_speech_11(u8 taskId) +{ + sub_8032318(0); + StringExpandPlaceholders(gStringVar4, gText_Birch_BoyOrGirl); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_12; +} + +void task_new_game_prof_birch_speech_12(u8 taskId) +{ + if (!sub_8197224()) + { + sub_8031D74(); + gTasks[taskId].func = task_new_game_prof_birch_speech_13; + } +} + +void task_new_game_prof_birch_speech_13(u8 taskId) +{ + int gender = sub_8031DB4(); + int r3; + + switch (gender) + { + case MALE: + PlaySE(SE_SELECT); + gSaveBlock2Ptr->playerGender = gender; + sub_80322E0(1, 1); + gTasks[taskId].func = task_new_game_prof_birch_speech_14; + break; + case FEMALE: + PlaySE(SE_SELECT); + gSaveBlock2Ptr->playerGender = gender; + sub_80322E0(1, 1); + gTasks[taskId].func = task_new_game_prof_birch_speech_14; + break; + } + r3 = GetMenuCursorPos(); + if (r3 != gTasks[taskId].data[6]) + { + gTasks[taskId].data[6] = r3; + gSprites[gTasks[taskId].data[2]].oam.objMode = 1; + sub_8031ACC(taskId, 0); + gTasks[taskId].func = sub_8030ED4; + } +} + +void sub_8030ED4(u8 taskId) +{ + u8 spriteId = gTasks[taskId].data[2]; + if (gTasks[taskId].data[5] == 0) + { + gSprites[spriteId].pos1.x += 4; + } + else + { + gSprites[spriteId].invisible = 1; + if (gTasks[taskId].data[6]) + spriteId = gTasks[taskId].data[11]; + else + spriteId = gTasks[taskId].data[10]; + gSprites[spriteId].pos1.x = 0xF0; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = 0; + gTasks[taskId].data[2] = spriteId; + gSprites[spriteId].oam.objMode = 1; + sub_8031BAC(taskId, 0); + gTasks[taskId].func = sub_8030F7C; + } +} + +void sub_8030F7C(u8 taskId) +{ + u8 spriteId = gTasks[taskId].data[2]; + + if (gSprites[spriteId].pos1.x > 0xB4) + { + gSprites[spriteId].pos1.x -= 4; + } + else + { + gSprites[spriteId].pos1.x = 0xB4; + if (gTasks[taskId].data[5]) + { + gSprites[spriteId].oam.objMode = 0; + gTasks[taskId].func = task_new_game_prof_birch_speech_13; + } + } +} + +void task_new_game_prof_birch_speech_14(u8 taskId) +{ + sub_8032318(0); + StringExpandPlaceholders(gStringVar4, gText_Birch_WhatsYourName); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_15; +} + +void task_new_game_prof_birch_speech_15(u8 taskId) +{ + if (!sub_8197224()) + gTasks[taskId].func = task_new_game_prof_birch_speech_16; +} + +void task_new_game_prof_birch_speech_16(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + BeginNormalPaletteFade(-1, 0, 0, 16, RGB_BLACK); + gTasks[taskId].func = task_new_game_prof_birch_speech_17; + } +} + +void task_new_game_prof_birch_speech_17(u8 taskId) +{ + if (!gPaletteFade.active) + { + FreeAllWindowBuffers(); + sub_818D820(gTasks[taskId].data[9]); + set_default_player_name(Random() % 20); + DestroyTask(taskId); + DoNamingScreen(0, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, new_game_prof_birch_speech_part2_start); + } +} + +void task_new_game_prof_birch_speech_part2_2(u8 taskId) +{ + sub_8032318(0); + StringExpandPlaceholders(gStringVar4, gText_Birch_SoItsPlayer); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_3; +} + +void task_new_game_prof_birch_speech_part2_3(u8 taskId) +{ + if (!sub_8197224()) + { + sub_80323CC(2, 1, 0xF3, 0xDF, 2, 15); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_4; + } +} + +void task_new_game_prof_birch_speech_part2_4(u8 taskId) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: + PlaySE(SE_SELECT); + gSprites[gTasks[taskId].data[2]].oam.objMode = 1; + sub_8031ACC(taskId, 2); + sub_8031C88(taskId, 1); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_5; + break; + case -1: + case 1: + PlaySE(SE_SELECT); + gTasks[taskId].func = task_new_game_prof_birch_speech_11; + } +} + +void task_new_game_prof_birch_speech_part2_5(u8 taskId) +{ + if (gTasks[taskId].data[4]) + { + gTasks[taskId].data[4] += 2; + SetGpuReg(REG_OFFSET_BG1HOFS, gTasks[taskId].data[4]); + } + else + { + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_6; + } +} + +void task_new_game_prof_birch_speech_part2_6(u8 taskId) +{ + u8 spriteId; + + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[10]].invisible = TRUE; + gSprites[gTasks[taskId].data[11]].invisible = TRUE; + spriteId = gTasks[taskId].data[8]; + gSprites[spriteId].pos1.x = 0x88; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = FALSE; + gSprites[spriteId].oam.objMode = 1; + spriteId = gTasks[taskId].data[9]; + gSprites[spriteId].pos1.x = 0x64; + gSprites[spriteId].pos1.y = 0x4B; + gSprites[spriteId].invisible = FALSE; + gSprites[spriteId].oam.objMode = 1; + sub_8031BAC(taskId, 2); + sub_8031D34(taskId, 1); + sub_8032318(0); + StringExpandPlaceholders(gStringVar4, gText_Birch_YourePlayer); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_7; + } +} + +void task_new_game_prof_birch_speech_part2_7(u8 taskId) +{ + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[8]].oam.objMode = 0; + gSprites[gTasks[taskId].data[9]].oam.objMode = 0; + if (!sub_8197224()) + { + gSprites[gTasks[taskId].data[8]].oam.objMode = 1; + gSprites[gTasks[taskId].data[9]].oam.objMode = 1; + sub_8031ACC(taskId, 2); + sub_8031C88(taskId, 1); + gTasks[taskId].data[7] = 64; + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_8; + } + } +} + +void task_new_game_prof_birch_speech_part2_8(u8 taskId) +{ + u8 spriteId; + + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[8]].invisible = 1; + gSprites[gTasks[taskId].data[9]].invisible = 1; + if (gTasks[taskId].data[7]) + { + gTasks[taskId].data[7]--; + return; + } + if (gSaveBlock2Ptr->playerGender != MALE) + spriteId = gTasks[taskId].data[11]; + else + spriteId = gTasks[taskId].data[10]; + gSprites[spriteId].pos1.x = 0x78; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = 0; + gSprites[spriteId].oam.objMode = 1; + gTasks[taskId].data[2] = spriteId; + sub_8031BAC(taskId, 2); + sub_8031D34(taskId, 1); + StringExpandPlaceholders(gStringVar4, gText_Birch_AreYouReady); + AddTextPrinterForMessage(1); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_9; + } +} + +void task_new_game_prof_birch_speech_part2_9(u8 taskId) +{ + u8 spriteId; + + if (gTasks[taskId].data[5]) + { + gSprites[gTasks[taskId].data[2]].oam.objMode = 0; + if (!sub_8197224()) + { + spriteId = gTasks[taskId].data[2]; + gSprites[spriteId].oam.affineMode = 1; + gSprites[spriteId].affineAnims = &gUnknown_082FF114; + InitSpriteAffineAnim(&gSprites[spriteId]); + StartSpriteAffineAnim(&gSprites[spriteId], 0); + gSprites[spriteId].callback = sub_80318D8; + BeginNormalPaletteFade(0x0000FFFF, 0, 0, 16, RGB_BLACK); + FadeOutBGM(4); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_10; + } + } +} + +void task_new_game_prof_birch_speech_part2_10(u8 taskId) +{ + u8 spriteId = gTasks[taskId].data[2]; + + if (gSprites[spriteId].affineAnimEnded) + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_11; +} + +void task_new_game_prof_birch_speech_part2_11(u8 taskId) +{ + u8 spriteId; + + if (!gPaletteFade.active) + { + spriteId = gTasks[taskId].data[2]; + gSprites[spriteId].callback = nullsub_11; + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + BeginNormalPaletteFade(0xFFFF0000, 0, 0, 16, RGB_WHITEALPHA); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_12; + } +} + +void task_new_game_prof_birch_speech_part2_12(u8 taskId) +{ + if (!gPaletteFade.active) + { + FreeAllWindowBuffers(); + sub_818D820(gTasks[taskId].data[9]); + dp13_810BB8C(); + SetMainCallback2(CB2_NewGame); + DestroyTask(taskId); + } +} + +void new_game_prof_birch_speech_part2_start(void) +{ + u8 taskId; + u8 spriteId; + u16 savedIme; + + ResetBgsAndClearDma3BusyFlags(0); + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); + InitBgsFromTemplates(0, gUnknown_082FF0E8, 2); + InitBgFromTemplate(&gUnknown_082FF0F0); + SetVBlankCallback(NULL); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + DmaFill16(3, 0, VRAM, VRAM_SIZE); + DmaFill32(3, 0, OAM, OAM_SIZE); + DmaFill16(3, 0, PLTT, PLTT_SIZE); + ResetPaletteFade(); + LZ77UnCompVram(gBirchIntroShadowGfx, (u8*)VRAM); + LZ77UnCompVram(gUnknown_082FEEF0, (u8*)(VRAM + 0x3800)); + LoadPalette(gUnknown_082FECFC, 0, 64); + LoadPalette(&gUnknown_082FF018[1], 1, 16); + ResetTasks(); + taskId = CreateTask(task_new_game_prof_birch_speech_part2_1, 0); + gTasks[taskId].data[7] = 5; + gTasks[taskId].data[4] = -60; + ScanlineEffect_Stop(); + ResetSpriteData(); + FreeAllSpritePalettes(); + dp13_810BB8C(); + AddBirchSpeechObjects(taskId); + if (gSaveBlock2Ptr->playerGender != MALE) + { + gTasks[taskId].data[6] = FEMALE; + spriteId = gTasks[taskId].data[11]; + } + else + { + gTasks[taskId].data[6] = MALE; + spriteId = gTasks[taskId].data[10]; + } + gSprites[spriteId].pos1.x = 0xB4; + gSprites[spriteId].pos1.y = 0x3C; + gSprites[spriteId].invisible = 0; + gTasks[taskId].data[2] = spriteId; + SetGpuReg(REG_OFFSET_BG1HOFS, -60); + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + SetGpuReg(REG_OFFSET_WIN0H, 0); + SetGpuReg(REG_OFFSET_WIN0V, 0); + SetGpuReg(REG_OFFSET_WININ, 0); + SetGpuReg(REG_OFFSET_WINOUT, 0); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + ShowBg(0); + ShowBg(1); + savedIme = REG_IME; + REG_IME = 0; + REG_IE |= 1; + REG_IME = savedIme; + SetVBlankCallback(VBlankCB_MainMenu); + SetMainCallback2(CB2_MainMenu); + InitWindows(gUnknown_082FF080); + LoadMainMenuWindowFrameTiles(0, 0xF3); + copy_textbox_border_tile_patterns_to_vram(0, 0xFC, 0xF0); + PutWindowTilemap(0); + CopyWindowToVram(0, 3); +} + +void nullsub_11(struct Sprite *sprite) +{ +} + +void sub_80318D8(struct Sprite *sprite) +{ + u32 y; + + y = (sprite->pos1.y << 16) + sprite->data[0] + 0xC000; + sprite->pos1.y = y >> 16; + sprite->data[0] = y; +} + +u8 sub_80318F4(u8 a, u8 b) +{ + return sub_818D3E4(SPECIES_LOTAD, 8, 0, 1, a, b, 14, -1); +} + +void AddBirchSpeechObjects(u8 taskId) +{ + u8 spriteId = AddNewGameBirchObject(0x88, 0x3C, 1); + u8 spriteId2; + u8 spriteId3; + u8 spriteId4; + + gSprites[spriteId].callback = nullsub_11; + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].invisible = TRUE; + gTasks[taskId].data[8] = spriteId; + spriteId2 = sub_80318F4(100, 0x4B); + gSprites[spriteId2].callback = nullsub_11; + gSprites[spriteId2].oam.priority = 0; + gSprites[spriteId2].invisible = TRUE; + gTasks[taskId].data[9] = spriteId2; + spriteId3 = CreateTrainerSprite(FacilityClassToPicIndex(0x3C), 0x78, 0x3C, 0, gDecompressionBuffer); + gSprites[spriteId3].callback = nullsub_11; + gSprites[spriteId3].invisible = TRUE; + gSprites[spriteId3].oam.priority = 0; + gTasks[taskId].data[10] = spriteId3; + spriteId4 = CreateTrainerSprite(FacilityClassToPicIndex(0x3F), 0x78, 0x3C, 0, &gDecompressionBuffer[0x800]); + gSprites[spriteId4].callback = nullsub_11; + gSprites[spriteId4].invisible = TRUE; + gSprites[spriteId4].oam.priority = 0; + gTasks[taskId].data[11] = spriteId4; +} + +void sub_8031A5C(u8 taskId) +{ + int alpha; + + if (gTasks[taskId].data[1] == 0) + { + gTasks[gTasks[taskId].data[0]].data[5] = 1; + DestroyTask(taskId); + } + else if (gTasks[taskId].data[4]) + { + gTasks[taskId].data[4]--; + } + else + { + gTasks[taskId].data[4] = gTasks[taskId].data[3]; + gTasks[taskId].data[1]--; + gTasks[taskId].data[2]++; + alpha = gTasks[taskId].data[2] << 8; + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1] + alpha); + } +} + +void sub_8031ACC(u8 taskId, u8 a) +{ + u8 taskId2; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(16, 0)); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[5] = 0; + taskId2 = CreateTask(sub_8031A5C, 0); + gTasks[taskId2].data[0] = taskId; + gTasks[taskId2].data[1] = 16; + gTasks[taskId2].data[2] = 0; + gTasks[taskId2].data[3] = a; + gTasks[taskId2].data[4] = a; +} + +void sub_8031B3C(u8 taskId) +{ + int alpha; + + if (gTasks[taskId].data[1] == 16) + { + gTasks[gTasks[taskId].data[0]].data[5] = 1; + DestroyTask(taskId); + } + else if (gTasks[taskId].data[4]) + { + gTasks[taskId].data[4]--; + } + else + { + gTasks[taskId].data[4] = gTasks[taskId].data[3]; + gTasks[taskId].data[1]++; + gTasks[taskId].data[2]--; + alpha = gTasks[taskId].data[2] << 8; + SetGpuReg(REG_OFFSET_BLDALPHA, gTasks[taskId].data[1] + alpha); + } +} + +void sub_8031BAC(u8 taskId, u8 a) +{ + u8 taskId2; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT2_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT1_OBJ); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetGpuReg(REG_OFFSET_BLDY, 0); + gTasks[taskId].data[5] = 0; + taskId2 = CreateTask(sub_8031B3C, 0); + gTasks[taskId2].data[0] = taskId; + gTasks[taskId2].data[1] = 0; + gTasks[taskId2].data[2] = 16; + gTasks[taskId2].data[3] = a; + gTasks[taskId2].data[4] = a; +} + +void sub_8031C1C(u8 taskId) +{ + if (gTasks[taskId].data[2]) + { + gTasks[taskId].data[2]--; + } + else if (gTasks[taskId].data[1] == 8) + { + DestroyTask(taskId); + } + else if (gTasks[taskId].data[4]) + { + gTasks[taskId].data[4]--; + } + else + { + gTasks[taskId].data[4] = gTasks[taskId].data[3]; + gTasks[taskId].data[1]++; + LoadPalette(&gUnknown_082FF018[gTasks[taskId].data[1]], 1, 16); + } +} + +void sub_8031C88(u8 taskId, u8 a) +{ + u8 taskId2; + + taskId2 = CreateTask(sub_8031C1C, 0); + gTasks[taskId2].data[0] = taskId; + gTasks[taskId2].data[1] = 0; + gTasks[taskId2].data[2] = 8; + gTasks[taskId2].data[3] = a; + gTasks[taskId2].data[4] = a; +} + +void sub_8031CC8(u8 taskId) +{ + if (gTasks[taskId].data[2]) + { + gTasks[taskId].data[2]--; + } + else if (gTasks[taskId].data[1] == 0) + { + DestroyTask(taskId); + } + else if (gTasks[taskId].data[4]) + { + gTasks[taskId].data[4]--; + } + else + { + gTasks[taskId].data[4] = gTasks[taskId].data[3]; + gTasks[taskId].data[1]--; + LoadPalette(&gUnknown_082FF018[gTasks[taskId].data[1]], 1, 16); + } +} + +void sub_8031D34(u8 taskId, u8 a) +{ + u8 taskId2; + + taskId2 = CreateTask(sub_8031CC8, 0); + gTasks[taskId2].data[0] = taskId; + gTasks[taskId2].data[1] = 8; + gTasks[taskId2].data[2] = 8; + gTasks[taskId2].data[3] = a; + gTasks[taskId2].data[4] = a; +} + +void sub_8031D74(void) +{ + DrawMainMenuWindowBorder(&gUnknown_082FF080[1], 0xF3); + FillWindowPixelBuffer(1, 17); + PrintMenuTable(1, 2, gUnknown_082FF118); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(1, 2, 0); + PutWindowTilemap(1); + CopyWindowToVram(1, 3); +} + +s8 sub_8031DB4(void) +{ + return ProcessMenuInputNoWrapAround(); +} + +void set_default_player_name(u8 nameId) +{ + const u8* name; + u8 i; + + if (gSaveBlock2Ptr->playerGender == MALE) + name = gMalePresetNames[nameId]; + else + name = gFemalePresetNames[nameId]; + for (i = 0; i < 7; i++) + gSaveBlock2Ptr->playerName[i] = name[i]; + gSaveBlock2Ptr->playerName[7] = 0xFF; +} + +void CreateMainMenuErrorWindow(const u8* str) +{ + FillWindowPixelBuffer(7, 17); + PrintTextOnWindow(7, 1, str, 0, 1, 2, 0); + PutWindowTilemap(7); + CopyWindowToVram(7, 2); + DrawMainMenuWindowBorder(gUnknown_082FF070, MAIN_MENU_BORDER_TILE); + SetGpuReg(REG_OFFSET_WIN0H, 0x9E7); + SetGpuReg(REG_OFFSET_WIN0V, 0x719F); +} + +void fmt_savegame(void) +{ + fmt_time(); + fmt_pokedex(); + fmt_player(); + fmt_badges(); +} + +void fmt_time(void) +{ + StringExpandPlaceholders(gStringVar4, gText_ContinueMenuPlayer); + box_print(2, 1, 0, 17, gUnknown_082FF0E3, -1, gStringVar4); + box_print(2, 1, GetStringRightAlignXOffset(1, gSaveBlock2Ptr->playerName, 100), 17, gUnknown_082FF0E3, -1, gSaveBlock2Ptr->playerName); +} + +void fmt_player(void) +{ + u8 str[0x20]; + u8* ptr; + + StringExpandPlaceholders(gStringVar4, gText_ContinueMenuTime); + box_print(2, 1, 0x6C, 17, gUnknown_082FF0E3, -1, gStringVar4); + ptr = ConvertIntToDecimalStringN(str, gSaveBlock2Ptr->playTimeHours, 0, 3); + *ptr = 0xF0; + ConvertIntToDecimalStringN(ptr + 1, gSaveBlock2Ptr->playTimeMinutes, 2, 2); + box_print(2, 1, GetStringRightAlignXOffset(1, str, 0xD0), 17, gUnknown_082FF0E3, -1, str); +} + +void fmt_pokedex(void) +{ + u8 str[0x20]; + u16 dexCount; + + if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) + { + if (IsNationalPokedexEnabled()) + dexCount = GetNationalPokedexCount(1); + else + dexCount = GetHoennPokedexCount(1); + StringExpandPlaceholders(gStringVar4, gText_ContinueMenuPokedex); + box_print(2, 1, 0, 33, gUnknown_082FF0E3, -1, gStringVar4); + ConvertIntToDecimalStringN(str, dexCount, 0, 3); + box_print(2, 1, GetStringRightAlignXOffset(1, str, 100), 33, gUnknown_082FF0E3, -1, str); + } +} + +void fmt_badges(void) +{ + u8 str[0x20]; + u8 badgeCount = 0; + u32 i; + + for (i = FLAG_BADGE01_GET; i <= FLAG_BADGE08_GET; i++) + { + if (FlagGet(i)) + badgeCount++; + } + StringExpandPlaceholders(gStringVar4, gText_ContinueMenuBadges); + box_print(2, 1, 0x6C, 33, gUnknown_082FF0E3, -1, gStringVar4); + ConvertIntToDecimalStringN(str, badgeCount, 2, 1); + box_print(2, 1, GetStringRightAlignXOffset(1, str, 0xD0), 33, gUnknown_082FF0E3, -1, str); +} + +void LoadMainMenuWindowFrameTiles(u8 bgId, u16 tileOffset) +{ + LoadBgTiles(bgId, GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType)->tiles, 0x120, tileOffset); + LoadPalette(GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType)->pal, 32, 32); +} + +void DrawMainMenuWindowBorder(const struct WindowTemplate *template, u16 baseTileNum) +{ + u16 r9 = 1 + baseTileNum; + u16 r10 = 2 + baseTileNum; + u16 sp18 = 3 + baseTileNum; + u16 spC = 5 + baseTileNum; + u16 sp10 = 6 + baseTileNum; + u16 sp14 = 7 + baseTileNum; + u16 r6 = 8 + baseTileNum; + + FillBgTilemapBufferRect(template->priority, baseTileNum, template->tilemapLeft - 1, template->tilemapTop - 1, 1, 1, 2); + FillBgTilemapBufferRect(template->priority, r9, template->tilemapLeft, template->tilemapTop - 1, template->width, 1, 2); + FillBgTilemapBufferRect(template->priority, r10, template->tilemapLeft + template->width, template->tilemapTop - 1, 1, 1, 2); + FillBgTilemapBufferRect(template->priority, sp18, template->tilemapLeft - 1, template->tilemapTop, 1, template->height, 2); + FillBgTilemapBufferRect(template->priority, spC, template->tilemapLeft + template->width, template->tilemapTop, 1, template->height, 2); + FillBgTilemapBufferRect(template->priority, sp10, template->tilemapLeft - 1, template->tilemapTop + template->height, 1, 1, 2); + FillBgTilemapBufferRect(template->priority, sp14, template->tilemapLeft, template->tilemapTop + template->height, template->width, 1, 2); + FillBgTilemapBufferRect(template->priority, r6, template->tilemapLeft + template->width, template->tilemapTop + template->height, 1, 1, 2); + CopyBgTilemapBufferToVram(template->priority); +} + +void sub_8032250(const struct WindowTemplate *template) +{ + FillBgTilemapBufferRect(template->priority, 0, template->tilemapLeft - 1, template->tilemapTop - 1, template->tilemapLeft + template->width + 1, template->tilemapTop + template->height + 1, 2); + CopyBgTilemapBufferToVram(template->priority); +} + +void sub_8032298(u8 a, u8 b, u8 c, u8 d, u8 e, u8 unused) +{ + FillBgTilemapBufferRect(a, 0, b + 0xFF, c + 0xFF, d + 2, e + 2, 2); +} + +void sub_80322E0(u8 windowId, u8 a) +{ + CallWindowFunction(windowId, sub_8032298); + FillWindowPixelBuffer(windowId, 0x11); + ClearWindowTilemap(windowId); + if (a == 1) + CopyWindowToVram(windowId, 3); +} + +void sub_8032318(u8 a) +{ + u8 fontAttribute = GetFontAttribute(1, 6); + u8 fontAttribute2 = GetFontAttribute(1, 0); + u8 fontAttribute3 = GetFontAttribute(1, 1); + u8 windowAttribute = GetWindowAttribute(a, 3); + u8 windowAttribute2 = GetWindowAttribute(a, 4); + + FillWindowPixelRect(a, fontAttribute, 0, 0, fontAttribute2 * windowAttribute, fontAttribute3 * windowAttribute2); + CopyWindowToVram(a, 2); +} + +void sub_80323A0(struct TextSubPrinter *printer, u16 a) +{ + if (*(printer->current_text_offset - 2) == 8 && gUnknown_02022D04 == 0) + { + gUnknown_02022D04 = 1; + CreateTask(sub_8030A70, 0); + } +} + +void sub_80323CC(u8 a, u8 b, u16 c, u16 d, u8 e, u8 f) +{ + struct WindowTemplate sp; + + sp = sub_8198A50(0, a + 1, b + 1, 5, 4, f, d); + CreateYesNoMenu(&sp, c, e, 0); +} + +void unknown_rbox_to_vram(u8 windowId, u8 a) +{ + CallWindowFunction(windowId, sub_8032474); + FillWindowPixelBuffer(windowId, 17); + PutWindowTilemap(windowId); + if (a == 1) + CopyWindowToVram(windowId, 3); +} + +void sub_8032474 (u8 a, u8 b, u8 c, u8 d, u8 e, u8 f) +{ + FillBgTilemapBufferRect(a, 0xFD, b-2, c-1, 1, 1, f); + FillBgTilemapBufferRect(a, 0xFF, b-1, c-1, 1, 1, f); + FillBgTilemapBufferRect(a, 0x100, b, c-1, d, 1, f); + FillBgTilemapBufferRect(a, 0x101, b+d-1, c-1, 1, 1, f); + FillBgTilemapBufferRect(a, 0x102, b+d, c-1, 1, 1, f); + FillBgTilemapBufferRect(a, 0x103, b-2, c, 1, 5, f); + FillBgTilemapBufferRect(a, 0x105, b-1, c, d+1, 5, f); + FillBgTilemapBufferRect(a, 0x106, b+d, c, 1, 5, f); + FillBgTilemapBufferRect(a, BG_TILE_V_FLIP(0xFD), b-2, c+e, 1, 1, f); + FillBgTilemapBufferRect(a, BG_TILE_V_FLIP(0xFF), b-1, c+e, 1, 1, f); + FillBgTilemapBufferRect(a, BG_TILE_V_FLIP(0x100), b, c+e, d-1, 1, f); + FillBgTilemapBufferRect(a, BG_TILE_V_FLIP(0x101), b+d-1, c+e, 1, 1, f); + FillBgTilemapBufferRect(a, BG_TILE_V_FLIP(0x102), b+d, c+e, 1, 1, f); +} + +void task_new_game_prof_birch_speech_part2_1(u8 taskId) +{ + if (gTasks[taskId].data[7]-- <= 0) + { + unknown_rbox_to_vram(0, 1); + gTasks[taskId].func = task_new_game_prof_birch_speech_part2_2; + } +} diff --git a/src/map_name_popup.c b/src/map_name_popup.c new file mode 100644 index 000000000..1782e9af8 --- /dev/null +++ b/src/map_name_popup.c @@ -0,0 +1,474 @@ +#include "global.h" +#include "constants/region_map_sections.h" +#include "constants/weather.h" +#include "bg.h" +#include "event_data.h" +#include "gpu_regs.h" +#include "international_string_util.h" +#include "menu.h" +#include "map_name_popup.h" +#include "palette.h" +#include "region_map.h" +#include "rom_818CFC8.h" +#include "start_menu.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + + +// enums +enum MapPopUp_Themes +{ + MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_MARBLE, + MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_STONE2, +}; + +// static functions +static void Task_MapNamePopUpWindow(u8 taskId); +static void ShowMapNamePopUpWindow(void); +static void LoadMapNamePopUpWindowBg(void); + +// EWRAM +static EWRAM_DATA u8 mapNamePopupTaskId = 0; + +// .rodata +static const u8 gMapPopUp_Table[][960] = +{ + INCBIN_U8("graphics/interface/map_popup/wood.4bpp"), + INCBIN_U8("graphics/interface/map_popup/marble.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone.4bpp"), + INCBIN_U8("graphics/interface/map_popup/brick.4bpp"), + INCBIN_U8("graphics/interface/map_popup/underwater.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone2.4bpp"), +}; + +static const u8 gMapPopUp_Outline_Table[][960] = +{ + INCBIN_U8("graphics/interface/map_popup/wood_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/marble_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/brick_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/underwater_outline.4bpp"), + INCBIN_U8("graphics/interface/map_popup/stone2_outline.4bpp"), +}; + +static const u16 gMapPopUp_Palette_Table[][16] = +{ + INCBIN_U16("graphics/interface/map_popup/wood.gbapal"), + INCBIN_U16("graphics/interface/map_popup/marble_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/stone_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/brick_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/underwater_outline.gbapal"), + INCBIN_U16("graphics/interface/map_popup/stone2_outline.gbapal"), +}; + +static const u16 gUnknown_0857F444[16] = INCBIN_U16("graphics/interface/map_popup/857F444.gbapal"); + +static const u8 gRegionMapSectionId_To_PopUpThemeIdMapping[] = +{ + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_BRICK, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, + MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_UNDERWATER, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_MARBLE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_MARBLE, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_WOOD, + MAPPOPUP_THEME_WOOD, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, MAPPOPUP_THEME_STONE2, + MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_STONE, MAPPOPUP_THEME_MARBLE +}; + +static const u8 gText_PyramidFloor1[] = _("PYRAMID FLOOR 1"); +static const u8 gText_PyramidFloor2[] = _("PYRAMID FLOOR 2"); +static const u8 gText_PyramidFloor3[] = _("PYRAMID FLOOR 3"); +static const u8 gText_PyramidFloor4[] = _("PYRAMID FLOOR 4"); +static const u8 gText_PyramidFloor5[] = _("PYRAMID FLOOR 5"); +static const u8 gText_PyramidFloor6[] = _("PYRAMID FLOOR 6"); +static const u8 gText_PyramidFloor7[] = _("PYRAMID FLOOR 7"); +static const u8 gText_Pyramid[] = _("PYRAMID"); + +static const u8 * const gBattlePyramid_MapHeaderStrings[] = +{ + gText_PyramidFloor1, + gText_PyramidFloor2, + gText_PyramidFloor3, + gText_PyramidFloor4, + gText_PyramidFloor5, + gText_PyramidFloor6, + gText_PyramidFloor7, + gText_Pyramid, +}; + +// text +bool8 sub_80D47D4(void) +{ + HideStartMenu(); + ShowMapNamePopup(); + return 1; +} + +void ShowMapNamePopup(void) +{ + if (FlagGet(FLAG_SPECIAL_FLAG_0x4000) != TRUE) + { + if (!FuncIsActiveTask(Task_MapNamePopUpWindow)) + { + mapNamePopupTaskId = CreateTask(Task_MapNamePopUpWindow, 90); + SetGpuReg(REG_OFFSET_BG0VOFS, 40); + gTasks[mapNamePopupTaskId].data[0] = 6; + gTasks[mapNamePopupTaskId].data[2] = 40; + } + else + { + if (gTasks[mapNamePopupTaskId].data[0] != 2) + gTasks[mapNamePopupTaskId].data[0] = 2; + gTasks[mapNamePopupTaskId].data[3] = 1; + } + } +} + +static void Task_MapNamePopUpWindow(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 6: + task->data[4]++; + if (task->data[4] > 30) + { + task->data[0] = 0; + task->data[4] = 0; + ShowMapNamePopUpWindow(); + } + break; + case 0: + task->data[2] -= 2; + if (task->data[2] <= 0 ) + { + task->data[2] = 0; + task->data[0] = 1; + gTasks[mapNamePopupTaskId].data[1] = 0; + } + break; + case 1: + task->data[1]++; + if (task->data[1] > 120 ) + { + task->data[1] = 0; + task->data[0] = 2; + } + break; + case 2: + task->data[2] += 2; + if (task->data[2] > 39) + { + task->data[2] = 40; + if (task->data[3]) + { + task->data[0] = 6; + task->data[4] = 0; + task->data[3] = 0; + } + else + { + task->data[0] = 4; + return; + } + } + break; + case 4: + sub_819746C(GetMapNamePopUpWindowId(), TRUE); + task->data[0] = 5; + break; + case 5: + HideMapNamePopUpWindow(); + return; + } + SetGpuReg(REG_OFFSET_BG0VOFS, task->data[2]); +} + +void HideMapNamePopUpWindow(void) +{ + if (FuncIsActiveTask(Task_MapNamePopUpWindow)) + { + sub_819746C(GetMapNamePopUpWindowId(), TRUE); + RemoveMapNamePopUpWindow(); + SetGpuReg_ForcedBlank(REG_OFFSET_BG0VOFS, 0); + DestroyTask(mapNamePopupTaskId); + } +} + +static void ShowMapNamePopUpWindow(void) +{ + u8 mapDisplayHeader[24]; + u8 *withoutPrefixPtr; + u8 x; + const u8* mapDisplayHeaderSource; + + if(InBattlePyramid()) + { + if(gMapHeader.mapDataId == 0x17A) + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[7]; + } + else + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + mapDisplayHeaderSource = gBattlePyramid_MapHeaderStrings[gSaveBlock2Ptr->battlePyramidWildHeaderId]; + } + StringCopy(withoutPrefixPtr, mapDisplayHeaderSource); + } + else + { + withoutPrefixPtr = &(mapDisplayHeader[3]); + GetMapName(withoutPrefixPtr, gMapHeader.regionMapSectionId, 0); + } + AddMapNamePopUpWindow(); + LoadMapNamePopUpWindowBg(); + x = GetStringCenterAlignXOffset(7, withoutPrefixPtr, 80); + mapDisplayHeader[0] = EXT_CTRL_CODE_BEGIN; + mapDisplayHeader[1] = EXT_CTRL_CODE_HIGHLIGHT; + mapDisplayHeader[2] = TEXT_COLOR_TRANSPARENT; + PrintTextOnWindow(GetMapNamePopUpWindowId(), 7, mapDisplayHeader, x, 3, 0xFF, NULL); + CopyWindowToVram(GetMapNamePopUpWindowId(), 3); +} + +#ifdef NONMATCHING +static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) +{ + s32 i; + + for(i=0; i<=11; i++) + { + FillBgTilemapBufferRect(bg, 0x21D + i, x + i - 1, y - 1, 1, 1, 0xE); + } + FillBgTilemapBufferRect(bg, 0x229 + i, x - 1, y, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22A + i, deltaX + x, y, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22B + i, x - 1, y + 1 , 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22C + i, deltaX + x, y + 1, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22D + i, x - 1, y + 2, 1, 1, 0xE); + FillBgTilemapBufferRect(bg, 0x22E + i, deltaX + x, y + 2, 1, 1, 0xE); + for(i=0; i<=11; i++) + { + FillBgTilemapBufferRect(bg, 0x22F + i, x + i - 1, y + deltaY, 1, 1, 0xE); + } +} +#else +NAKED +static void sub_80D4A78(u8 bg, u8 x, u8 y, u8 deltaX, u8 deltaY, u8 unused) +{ + asm("\n\ + .syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x1C\n\ + ldr r4, [sp, 0x3C]\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r10, r1\n\ + lsls r2, 24\n\ + lsls r3, 24\n\ + lsrs r3, 24\n\ + str r3, [sp, 0x10]\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r4, [sp, 0x14]\n\ + movs r5, 0\n\ + lsls r0, r1, 24\n\ + asrs r1, r0, 24\n\ + lsrs r3, r2, 24\n\ + str r3, [sp, 0xC]\n\ + movs r6, 0xFF\n\ + lsls r6, 24\n\ + adds r6, r2\n\ + mov r8, r6\n\ + str r0, [sp, 0x18]\n\ + subs r4, r1, 0x1\n\ + _080D4AB4:\n\ + ldr r0, =0x0000021d\n\ + adds r1, r5, r0\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + lsls r2, r4, 24\n\ + lsrs r2, 24\n\ + movs r3, 0x1\n\ + str r3, [sp]\n\ + str r3, [sp, 0x4]\n\ + movs r6, 0xE\n\ + mov r9, r6\n\ + str r6, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r6, r8\n\ + lsrs r3, r6, 24\n\ + bl FillBgTilemapBufferRect\n\ + adds r4, 0x1\n\ + adds r5, 0x1\n\ + cmp r5, 0xB\n\ + ble _080D4AB4\n\ + ldr r1, =0x00000229\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + add r0, r10\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + movs r5, 0x1\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r2, r9\n\ + str r2, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + ldr r3, [sp, 0xC]\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022a\n\ + ldr r6, [sp, 0x10]\n\ + add r6, r10\n\ + lsls r6, 24\n\ + lsrs r6, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r3, r9\n\ + str r3, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + ldr r3, [sp, 0xC]\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022b\n\ + ldr r4, [sp, 0xC]\n\ + adds r4, 0x1\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r0, r9\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + movs r1, 0x8B\n\ + lsls r1, 2\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r2, r9\n\ + str r2, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022d\n\ + ldr r4, [sp, 0xC]\n\ + adds r4, 0x2\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r3, r9\n\ + str r3, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + mov r2, r8\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + ldr r1, =0x0000022e\n\ + str r5, [sp]\n\ + str r5, [sp, 0x4]\n\ + mov r0, r9\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + adds r2, r6, 0\n\ + adds r3, r4, 0\n\ + bl FillBgTilemapBufferRect\n\ + movs r5, 0\n\ + ldr r1, [sp, 0xC]\n\ + ldr r2, [sp, 0x14]\n\ + adds r0, r1, r2\n\ + lsls r4, r0, 24\n\ + movs r6, 0x1\n\ + _080D4B8A:\n\ + ldr r3, =0x0000022f\n\ + adds r1, r5, r3\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + subs r0, r5, 0x1\n\ + ldr r3, [sp, 0x18]\n\ + asrs r2, r3, 24\n\ + adds r2, r0\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + str r6, [sp]\n\ + str r6, [sp, 0x4]\n\ + movs r0, 0xE\n\ + str r0, [sp, 0x8]\n\ + adds r0, r7, 0\n\ + lsrs r3, r4, 24\n\ + bl FillBgTilemapBufferRect\n\ + adds r5, 0x1\n\ + cmp r5, 0xB\n\ + ble _080D4B8A\n\ + add sp, 0x1C\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +} +#endif // NONMATCHING + +static void LoadMapNamePopUpWindowBg(void) +{ + u8 popupWindowId; + u16 regionMapSectionId; + u8 popUpThemeId; + + popupWindowId = GetMapNamePopUpWindowId(); + regionMapSectionId = gMapHeader.regionMapSectionId; + if(regionMapSectionId > MAPSEC_DYNAMIC) + { + if(regionMapSectionId > MAPSEC_SPECIAL_AREA) + regionMapSectionId -= (MAPSEC_SPECIAL_AREA - MAPSEC_DYNAMIC); + else + regionMapSectionId = 0; //discard kanto region sections + } + popUpThemeId = gRegionMapSectionId_To_PopUpThemeIdMapping[regionMapSectionId]; + + LoadBgTiles(GetWindowAttribute(popupWindowId, 0), &(gMapPopUp_Outline_Table[popUpThemeId][0]), 0x400, 0x21D); + CallWindowFunction(popupWindowId, sub_80D4A78); + PutWindowTilemap(popupWindowId); + if(gMapHeader.weather == WEATHER_BUBBLES) + LoadPalette(&gUnknown_0857F444, 0xE0, 0x20); + else + LoadPalette(&(gMapPopUp_Palette_Table[popUpThemeId][0]), 0xE0, 0x20); + BlitBitmapToWindow(popupWindowId, &(gMapPopUp_Table[popUpThemeId][0]), 0, 0, 80, 24); +} diff --git a/src/map_obj_lock.c b/src/map_obj_lock.c new file mode 100644 index 000000000..688d0594d --- /dev/null +++ b/src/map_obj_lock.c @@ -0,0 +1,187 @@ +#include "global.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "map_obj_lock.h" +#include "script_movement.h" +#include "task.h" +#include "trainer_see.h" + +bool8 walkrun_is_standing_still(void) +{ + if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION) + return FALSE; + else + return TRUE; +} + +static void sub_80983A4(u8 taskId) +{ + if (walkrun_is_standing_still()) + { + sub_808B864(); + DestroyTask(taskId); + } +} + +bool8 sub_80983C4(void) +{ + if (FuncIsActiveTask(sub_80983A4)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} + + +void ScriptFreezeMapObjects(void) +{ + FreezeMapObjects(); + CreateTask(sub_80983A4, 80); +} + +static void sub_8098400(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (!task->data[0] && walkrun_is_standing_still() == TRUE) + { + sub_808B864(); + task->data[0] = 1; + } + if (!task->data[1] && !gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + task->data[1] = 1; + } + if (task->data[0] && task->data[1]) + DestroyTask(taskId); +} + +bool8 sub_809847C(void) +{ + if (FuncIsActiveTask(sub_8098400)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} + +void LockSelectedMapObject(void) +{ + u8 taskId; + FreezeMapObjectsExceptOne(gSelectedMapObject); + taskId = CreateTask(sub_8098400, 80); + if (!gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + gTasks[taskId].data[1] = 1; + } +} + +void sub_80984F4(void) +{ + u8 objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80D338C(); + UnfreezeMapObjects(); +} + +void sub_8098524(void) +{ + u8 objectId; + + if (gMapObjects[gSelectedMapObject].active) + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedMapObject]); + objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80D338C(); + UnfreezeMapObjects(); +} + +void sub_8098574(void) +{ + FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], gSpecialVar_Facing); +} + +void sub_809859C(void) +{ + FieldObjectClearAnimIfSpecialAnimActive(&gMapObjects[gSelectedMapObject]); +} + +static void sub_80985BC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + u8 mapObjectId = task->data[2]; + + if (!task->data[0] && walkrun_is_standing_still() == TRUE) + { + sub_808B864(); + task->data[0] = 1; + } + if (!task->data[1] && !gMapObjects[mapObjectId].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[mapObjectId]); + task->data[1] = 1; + } + if (task->data[0] && task->data[1]) + DestroyTask(taskId); +} + +void sub_8098630(void) +{ + u8 trainerObjectId1, trainerObjectId2, taskId; + trainerObjectId1 = GetChosenApproachingTrainerMapObjectId(0); + if(gNoOfApproachingTrainers == 2) + { + trainerObjectId2 = GetChosenApproachingTrainerMapObjectId(1); + sub_8098074(trainerObjectId1, trainerObjectId2); + taskId = CreateTask(sub_80985BC, 80); + gTasks[taskId].data[2] = trainerObjectId1; + if(!gMapObjects[trainerObjectId1].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId1]); + gTasks[taskId].data[1] = 1; + } + taskId = CreateTask(sub_80985BC, 81); + gTasks[taskId].data[2] = trainerObjectId2; + if(!gMapObjects[trainerObjectId2].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId2]); + gTasks[taskId].data[1] = 1; + } + } + else + { + FreezeMapObjectsExceptOne(trainerObjectId1); + taskId = CreateTask(sub_80985BC, 80); + gTasks[taskId].data[2] = trainerObjectId1; + if(!gMapObjects[trainerObjectId1].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[trainerObjectId1]); + gTasks[taskId].data[1] = 1; + } + } +} + +bool8 sub_8098734(void) +{ + if (FuncIsActiveTask(sub_80985BC)) + { + return FALSE; + } + else + { + sub_808BCF4(); + return TRUE; + } +} diff --git a/src/match_call.c b/src/match_call.c new file mode 100644 index 000000000..aa6945161 --- /dev/null +++ b/src/match_call.c @@ -0,0 +1,1275 @@ + +// Includes +#include "global.h" +#include "battle_setup.h" +#include "event_data.h" +#include "string_util.h" +#include "battle.h" +#include "battle_frontier_1.h" +#include "gym_leader_rematch.h" + +extern const u8 gTrainerClassNames[][13]; + +// Static type declarations + +typedef struct MatchCallTextDataStruct { + const u8 *text; + u16 flag; + u16 flag2; +} match_call_text_data_t; + +struct MatchCallStructCommon { + u8 type; + u8 v1; + u16 flag; +}; + +struct MatchCallStruct0 { + u8 type; + u8 v1; + u16 flag; + const u8 *desc; + const u8 *name; + const match_call_text_data_t *textData; +}; + +struct MatchCallStruct1 { + u8 type; + u8 v1; + u16 flag; + u16 rematchTableIdx; + const u8 *desc; + const u8 *name; + const match_call_text_data_t *textData; +}; + +struct MatchCallSubstruct2 { + u16 flag; + u8 v2; +}; + +struct MatchCallStruct2 { + u8 type; + u8 v1; + u16 flag; + u16 rematchTableIdx; + const u8 *desc; + const match_call_text_data_t *textData; + const struct MatchCallSubstruct2 *v10; +}; + +struct MatchCallStruct3 { + u8 type; + u8 v1; + u16 flag; + const u8 *desc; + const u8 *name; +}; + +struct MatchCallStruct4 { + u8 type; + u8 gender; + u16 flag; + const u8 *desc; + const u8 *name; + const match_call_text_data_t *textData; +}; + +struct MatchCallStruct5 { + u8 type; + u8 v1; + u16 flag; + u16 v4; + const u8 *desc; + const u8 *name; + const match_call_text_data_t *textData; +}; + +#define MATCHCALLDEF(name, type_, ...) \ +static const struct MatchCallStruct##type_ name = { \ + .type = type_, \ + __VA_ARGS__ \ +}; + +typedef union { + const struct MatchCallStructCommon *common; + const struct MatchCallStruct0 *type0; + const struct MatchCallStruct1 *type1; + const struct MatchCallStruct2 *type2; + const struct MatchCallStruct3 *type3; + const struct MatchCallStruct4 *type4; + const struct MatchCallStruct5 *type5; +} match_call_t; + +struct UnkStruct_08625388 { + u16 idx; + u16 v2; + u16 v4; + const u8 *v8[4]; +}; + +// Static RAM declarations + +// Static ROM declarations + +static bool32 MatchCallGetFlag_Type0(match_call_t); +static bool32 MatchCallGetFlag_Type1(match_call_t); +static bool32 MatchCallGetFlag_Type2(match_call_t); +static bool32 MatchCallGetFlag_Type3(match_call_t); +static bool32 MatchCallGetFlag_Type4(match_call_t); + +static u8 sub_81D1714(match_call_t); +static u8 sub_81D1718(match_call_t); +static u8 sub_81D171C(match_call_t); +static u8 sub_81D1750(match_call_t); +static u8 sub_81D1754(match_call_t); + +static bool32 MatchCall_IsRematchable_Type0(match_call_t); +static bool32 MatchCall_IsRematchable_Type1(match_call_t); +static bool32 MatchCall_IsRematchable_Type2(match_call_t); +static bool32 MatchCall_IsRematchable_Type3(match_call_t); +static bool32 MatchCall_IsRematchable_Type4(match_call_t); + +static bool32 sub_81D1840(match_call_t); +static bool32 sub_81D1844(match_call_t); +static bool32 sub_81D1848(match_call_t); +static bool32 sub_81D184C(match_call_t); +static bool32 sub_81D1850(match_call_t); + +static u32 MatchCall_GetRematchTableIdx_Type0(match_call_t); +static u32 MatchCall_GetRematchTableIdx_Type1(match_call_t); +static u32 MatchCall_GetRematchTableIdx_Type2(match_call_t); +static u32 MatchCall_GetRematchTableIdx_Type3(match_call_t); +static u32 MatchCall_GetRematchTableIdx_Type4(match_call_t); + +static void MatchCall_GetMessage_Type0(match_call_t, u8 *); +static void MatchCall_GetMessage_Type1(match_call_t, u8 *); +static void MatchCall_GetMessage_Type2(match_call_t, u8 *); +static void MatchCall_GetMessage_Type3(match_call_t, u8 *); +static void MatchCall_GetMessage_Type4(match_call_t, u8 *); + +static void MatchCall_GetNameAndDesc_Type0(match_call_t, const u8 **, const u8 **); +static void MatchCall_GetNameAndDesc_Type1(match_call_t, const u8 **, const u8 **); +static void MatchCall_GetNameAndDesc_Type2(match_call_t, const u8 **, const u8 **); +static void MatchCall_GetNameAndDesc_Type3(match_call_t, const u8 **, const u8 **); +static void MatchCall_GetNameAndDesc_Type4(match_call_t, const u8 **, const u8 **); + +static void sub_81D1920(const match_call_text_data_t *, u8 *); +static void sub_81D199C(const match_call_text_data_t *, u16, u8 *); +static void MatchCall_GetNameAndDescByRematchIdx(u32, const u8 **, const u8 **); + +extern const u8 gText_MrStone_Pokenav_2B60C0[]; +extern const u8 gText_MrStone_Pokenav_2B61E6[]; +extern const u8 gText_MrStone_Pokenav_2B6302[]; +extern const u8 gText_MrStone_Pokenav_2B63A0[]; +extern const u8 gText_MrStone_Pokenav_2B64A2[]; +extern const u8 gText_MrStone_Pokenav_2B6526[]; +extern const u8 gText_MrStone_Pokenav_2B65BB[]; +extern const u8 gText_MrStone_Pokenav_2B6664[]; +extern const u8 gText_MrStone_Pokenav_2B66B1[]; +extern const u8 gText_MrStone_Pokenav_2B6703[]; +extern const u8 gText_MrStone_Pokenav_2B67ED[]; + +extern const u8 gMrStoneMatchCallDesc[]; +extern const u8 gMrStoneMatchCallName[]; + +extern const u8 gText_Norman_Pokenav_2B5719[]; +extern const u8 gText_Norman_Pokenav_2B5795[]; +extern const u8 gText_Norman_Pokenav_2B584D[]; +extern const u8 gText_Norman_Pokenav_2B58E3[]; +extern const u8 gText_Norman_Pokenav_2B5979[]; +extern const u8 gText_Norman_Pokenav_2B5A07[]; +extern const u8 gText_Norman_Pokenav_2B5A69[]; +extern const u8 gText_Norman_Pokenav_2B5ACF[]; +extern const u8 gText_Norman_Pokenav_2B5B5E[]; + +extern const u8 gNormanMatchCallDesc[]; +extern const u8 gNormanMatchCallName[]; + +extern const u8 gProfBirchMatchCallDesc[]; +extern const u8 gProfBirchMatchCallName[]; + +extern const u8 gText_Mom_Pokenav_2B227B[]; +extern const u8 gText_Mom_Pokenav_2B2310[]; +extern const u8 gText_Mom_Pokenav_2B23F3[]; + +extern const u8 gMomMatchCallDesc[]; +extern const u8 gMomMatchCallName[]; + +extern const u8 gText_Steven_Pokenav_2B5B95[]; +extern const u8 gText_Steven_Pokenav_2B5C53[]; +extern const u8 gText_Steven_Pokenav_2B5CC9[]; +extern const u8 gText_Steven_Pokenav_2B5DB4[]; +extern const u8 gText_Steven_Pokenav_2B5E26[]; +extern const u8 gText_Steven_Pokenav_2B5EA2[]; +extern const u8 gText_Steven_Pokenav_2B5ED9[]; + +extern const u8 gStevenMatchCallDesc[]; +extern const u8 gStevenMatchCallName[]; + +extern const u8 gText_May_Pokenav_2B3AB3[]; +extern const u8 gText_May_Pokenav_2B3B3F[]; +extern const u8 gText_May_Pokenav_2B3C13[]; +extern const u8 gText_May_Pokenav_2B3CF3[]; +extern const u8 gText_May_Pokenav_2B3D4B[]; +extern const u8 gText_May_Pokenav_2B3DD1[]; +extern const u8 gText_May_Pokenav_2B3E69[]; +extern const u8 gText_May_Pokenav_2B3ECD[]; +extern const u8 gText_May_Pokenav_2B3F2B[]; +extern const u8 gText_May_Pokenav_2B3FFB[]; +extern const u8 gText_May_Pokenav_2B402B[]; +extern const u8 gText_May_Pokenav_2B414B[]; +extern const u8 gText_May_Pokenav_2B4228[]; +extern const u8 gText_May_Pokenav_2B42E0[]; +extern const u8 gText_May_Pokenav_2B4350[]; +extern const u8 gMayBrendanMatchCallDesc[]; +extern const u8 gExpandedPlaceholder_May[]; +extern const u8 gText_Brendan_Pokenav_2B43EF[]; +extern const u8 gText_Brendan_Pokenav_2B4486[]; +extern const u8 gText_Brendan_Pokenav_2B4560[]; +extern const u8 gText_Brendan_Pokenav_2B463F[]; +extern const u8 gText_Brendan_Pokenav_2B46B7[]; +extern const u8 gText_Brendan_Pokenav_2B4761[]; +extern const u8 gText_Brendan_Pokenav_2B47F4[]; +extern const u8 gText_Brendan_Pokenav_2B4882[]; +extern const u8 gText_Brendan_Pokenav_2B4909[]; +extern const u8 gText_Brendan_Pokenav_2B49C4[]; +extern const u8 gText_Brendan_Pokenav_2B4A44[]; +extern const u8 gText_Brendan_Pokenav_2B4B28[]; +extern const u8 gText_Brendan_Pokenav_2B4C15[]; +extern const u8 gText_Brendan_Pokenav_2B4CD8[]; +extern const u8 gText_Brendan_Pokenav_2B4D46[]; +extern const u8 gExpandedPlaceholder_Brendan[]; +extern const u8 gText_Wally_Pokenav_2B4DE2[]; +extern const u8 gText_Wally_Pokenav_2B4E57[]; +extern const u8 gText_Wally_Pokenav_2B4EA5[]; +extern const u8 gText_Wally_Pokenav_2B4F41[]; +extern const u8 gText_Wally_Pokenav_2B4FF3[]; +extern const u8 gText_Wally_Pokenav_2B50B1[]; +extern const u8 gText_Wally_Pokenav_2B5100[]; +extern const u8 gWallyMatchCallDesc[]; +extern const u8 gText_Scott_Pokenav_2B5184[]; +extern const u8 gText_Scott_Pokenav_2B5275[]; +extern const u8 gText_Scott_Pokenav_2B5323[]; +extern const u8 gText_Scott_Pokenav_2B53DB[]; +extern const u8 gText_Scott_Pokenav_2B54A5[]; +extern const u8 gText_Scott_Pokenav_2B5541[]; +extern const u8 gText_Scott_Pokenav_2B56CA[]; +extern const u8 gScottMatchCallDesc[]; +extern const u8 gScottMatchCallName[]; +extern const u8 gText_Roxanne_Pokenav_2B2456[]; +extern const u8 gText_Roxanne_Pokenav_2B250E[]; +extern const u8 gText_Roxanne_Pokenav_2B25C1[]; +extern const u8 gText_Roxanne_Pokenav_2B2607[]; +extern const u8 gRoxanneMatchCallDesc[]; +extern const u8 gText_Brawly_Pokenav_2B2659[]; +extern const u8 gText_Brawly_Pokenav_2B275D[]; +extern const u8 gText_Brawly_Pokenav_2B286F[]; +extern const u8 gText_Brawly_Pokenav_2B28D1[]; +extern const u8 gBrawlyMatchCallDesc[]; +extern const u8 gText_Wattson_Pokenav_2B2912[]; +extern const u8 gText_Wattson_Pokenav_2B29CA[]; +extern const u8 gText_Wattson_Pokenav_2B2AB6[]; +extern const u8 gText_Wattson_Pokenav_2B2B01[]; +extern const u8 gWattsonMatchCallDesc[]; +extern const u8 gText_Flannery_Pokenav_2B2B4D[]; +extern const u8 gText_Flannery_Pokenav_2B2C0E[]; +extern const u8 gText_Flannery_Pokenav_2B2CF1[]; +extern const u8 gText_Flannery_Pokenav_2B2D54[]; +extern const u8 gFlanneryMatchCallDesc[]; +extern const u8 gText_Winona_Pokenav_2B2DA4[]; +extern const u8 gText_Winona_Pokenav_2B2E2B[]; +extern const u8 gText_Winona_Pokenav_2B2EC2[]; +extern const u8 gText_Winona_Pokenav_2B2F16[]; +extern const u8 gWinonaMatchCallDesc[]; +extern const u8 gText_TateLiza_Pokenav_2B2F97[]; +extern const u8 gText_TateLiza_Pokenav_2B306E[]; +extern const u8 gText_TateLiza_Pokenav_2B3158[]; +extern const u8 gText_TateLiza_Pokenav_2B31CD[]; +extern const u8 gTateLizaMatchCallDesc[]; +extern const u8 gText_Juan_Pokenav_2B3249[]; +extern const u8 gText_Juan_Pokenav_2B32EC[]; +extern const u8 gText_Juan_Pokenav_2B33AA[]; +extern const u8 gText_Juan_Pokenav_2B341E[]; +extern const u8 gJuanMatchCallDesc[]; +extern const u8 gText_Sidney_Pokenav_2B34CC[]; +extern const u8 gEliteFourMatchCallDesc[]; +extern const u8 gText_Phoebe_Pokenav_2B3561[]; +extern const u8 gText_Glacia_Pokenav_2B35E4[]; +extern const u8 gText_Drake_Pokenav_2B368B[]; +extern const u8 gText_Wallace_Pokenav_2B3790[]; +extern const u8 gChampionMatchCallDesc[]; +extern const u8 gMatchCallStevenStrategyText[]; +extern const u8 gMatchCall_StevenTrainersPokemonText[]; +extern const u8 gMatchCall_StevenSelfIntroductionText_Line1_BeforeMeteorFallsBattle[]; +extern const u8 gMatchCall_StevenSelfIntroductionText_Line2_BeforeMeteorFallsBattle[]; +extern const u8 gMatchCall_StevenSelfIntroductionText_Line1_AfterMeteorFallsBattle[]; +extern const u8 gMatchCall_StevenSelfIntroductionText_Line2_AfterMeteorFallsBattle[]; +extern const u8 gMatchCall_BrendanStrategyText[]; +extern const u8 gMatchCall_BrendanTrainersPokemonText[]; +extern const u8 gMatchCall_BrendanSelfIntroductionText_Line1[]; +extern const u8 gMatchCall_BrendanSelfIntroductionText_Line2[]; +extern const u8 gMatchCall_MayStrategyText[]; +extern const u8 gMatchCall_MayTrainersPokemonText[]; +extern const u8 gMatchCall_MaySelfIntroductionText_Line1[]; +extern const u8 gMatchCall_MaySelfIntroductionText_Line2[]; +// .rodata + +static const match_call_text_data_t sMrStoneTextScripts[] = { + { gText_MrStone_Pokenav_2B60C0, 0xFFFF, FLAG_0x158 }, + { gText_MrStone_Pokenav_2B61E6, FLAG_0x158, 0xFFFF }, + { gText_MrStone_Pokenav_2B6302, FLAG_0x0BD, 0xFFFF }, + { gText_MrStone_Pokenav_2B63A0, FLAG_0x110, 0xFFFF }, + { gText_MrStone_Pokenav_2B64A2, FLAG_0x06A, 0xFFFF }, + { gText_MrStone_Pokenav_2B6526, FLAG_0x4F4, 0xFFFF }, + { gText_MrStone_Pokenav_2B65BB, FLAG_0x097, 0xFFFF }, + { gText_MrStone_Pokenav_2B6664, FLAG_0x06F, 0xFFFF }, + { gText_MrStone_Pokenav_2B66B1, FLAG_0x070, 0xFFFF }, + { gText_MrStone_Pokenav_2B6703, FLAG_0x4F7, 0xFFFF }, + { gText_MrStone_Pokenav_2B67ED, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sMrStoneMatchCallHeader, 0, 10, 0xffff, gMrStoneMatchCallDesc, gMrStoneMatchCallName, sMrStoneTextScripts); + +static const match_call_text_data_t sNormanTextScripts[] = { + { gText_Norman_Pokenav_2B5719, FLAG_0x132, 0xFFFF }, + { gText_Norman_Pokenav_2B5795, FLAG_0x4F1, 0xFFFF }, + { gText_Norman_Pokenav_2B584D, FLAG_0x4F3, 0xFFFF }, + { gText_Norman_Pokenav_2B58E3, FLAG_0x4F4, 0xFFFF }, + { gText_Norman_Pokenav_2B5979, FLAG_0x0D4, 0xFFFF }, + { gText_Norman_Pokenav_2B5A07, 0xFFFE, 0xFFFF }, + { gText_Norman_Pokenav_2B5A69, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { gText_Norman_Pokenav_2B5ACF, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { gText_Norman_Pokenav_2B5B5E, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sNormanMatchCallHeader, 5, 7, FLAG_0x132, 0x45, gNormanMatchCallDesc, gNormanMatchCallName, sNormanTextScripts); + +MATCHCALLDEF(sProfBirchMatchCallHeader, 3, 0, FLAG_0x119, gProfBirchMatchCallDesc, gProfBirchMatchCallName) + +static const match_call_text_data_t sMomTextScripts[] = { + { gText_Mom_Pokenav_2B227B, 0xffff, 0xffff }, + { gText_Mom_Pokenav_2B2310, FLAG_0x4F4, 0xffff }, + { gText_Mom_Pokenav_2B23F3, FLAG_SYS_GAME_CLEAR, 0xffff }, + { NULL, 0xffff, 0xffff } +}; + +MATCHCALLDEF(sMomMatchCallHeader, 0, 0, FLAG_0x0D8, gMomMatchCallDesc, gMomMatchCallName, sMomTextScripts); + +static const match_call_text_data_t sStevenTextScripts[] = { + { gText_Steven_Pokenav_2B5B95, 0xffff, 0xffff }, + { gText_Steven_Pokenav_2B5C53, FLAG_0x0C7, 0xffff }, + { gText_Steven_Pokenav_2B5CC9, FLAG_0x0D4, 0xffff }, + { gText_Steven_Pokenav_2B5DB4, FLAG_0x070, 0xffff }, + { gText_Steven_Pokenav_2B5E26, FLAG_0x4F6, 0xffff }, + { gText_Steven_Pokenav_2B5EA2, FLAG_0x081, 0xffff }, + { gText_Steven_Pokenav_2B5ED9, FLAG_SYS_GAME_CLEAR, 0xffff }, + { NULL, 0xffff, 0xffff }, +}; + +MATCHCALLDEF(sStevenMatchCallHeader, 0, 0xd5, FLAG_0x131, gStevenMatchCallDesc, gStevenMatchCallName, sStevenTextScripts); + +static const match_call_text_data_t sMayTextScripts[] = { + { gText_May_Pokenav_2B3AB3, 0xFFFF, 0xFFFF }, + { gText_May_Pokenav_2B3B3F, FLAG_0x4F1, 0xFFFF }, + { gText_May_Pokenav_2B3C13, FLAG_0x095, 0xFFFF }, + { gText_May_Pokenav_2B3CF3, FLAG_0x324, 0xFFFF }, + { gText_May_Pokenav_2B3D4B, FLAG_0x06A, 0xFFFF }, + { gText_May_Pokenav_2B3DD1, FLAG_0x4F3, 0xFFFF }, + { gText_May_Pokenav_2B3E69, FLAG_0x4F4, 0xFFFF }, + { gText_May_Pokenav_2B3ECD, FLAG_0x097, 0xFFFF }, + { gText_May_Pokenav_2B3F2B, FLAG_0x0D4, 0xFFFF }, + { gText_May_Pokenav_2B3FFB, FLAG_0x06F, 0xFFFF }, + { gText_May_Pokenav_2B402B, FLAG_0x061, 0xFFFF }, + { gText_May_Pokenav_2B414B, FLAG_0x070, 0xFFFF }, + { gText_May_Pokenav_2B4228, FLAG_0x081, 0xFFFF }, + { gText_May_Pokenav_2B42E0, FLAG_0x4F7, 0xFFFF }, + { gText_May_Pokenav_2B4350, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sMayMatchCallHeader, 4, MALE, FLAG_0x0FD, gMayBrendanMatchCallDesc, gExpandedPlaceholder_May, sMayTextScripts); + +static const match_call_text_data_t sBrendanTextScripts[] = { + { gText_Brendan_Pokenav_2B43EF, 0xFFFF, 0xFFFF }, + { gText_Brendan_Pokenav_2B4486, FLAG_0x4F1, 0xFFFF }, + { gText_Brendan_Pokenav_2B4560, FLAG_0x095, 0xFFFF }, + { gText_Brendan_Pokenav_2B463F, FLAG_0x324, 0xFFFF }, + { gText_Brendan_Pokenav_2B46B7, FLAG_0x06A, 0xFFFF }, + { gText_Brendan_Pokenav_2B4761, FLAG_0x4F3, 0xFFFF }, + { gText_Brendan_Pokenav_2B47F4, FLAG_0x4F4, 0xFFFF }, + { gText_Brendan_Pokenav_2B4882, FLAG_0x097, 0xFFFF }, + { gText_Brendan_Pokenav_2B4909, FLAG_0x0D4, 0xFFFF }, + { gText_Brendan_Pokenav_2B49C4, FLAG_0x06F, 0xFFFF }, + { gText_Brendan_Pokenav_2B4A44, FLAG_0x061, 0xFFFF }, + { gText_Brendan_Pokenav_2B4B28, FLAG_0x070, 0xFFFF }, + { gText_Brendan_Pokenav_2B4C15, FLAG_0x081, 0xFFFF }, + { gText_Brendan_Pokenav_2B4CD8, FLAG_0x4F7, 0xFFFF }, + { gText_Brendan_Pokenav_2B4D46, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sBrendanMatchCallHeader, 4, FEMALE, FLAG_0x0FD, gMayBrendanMatchCallDesc, gExpandedPlaceholder_Brendan, sBrendanTextScripts); + +static const match_call_text_data_t sWallyTextScripts[] = { + { gText_Wally_Pokenav_2B4DE2, 0xFFFF, 0xFFFF }, + { gText_Wally_Pokenav_2B4E57, FLAG_0x0C7, 0xFFFF }, + { gText_Wally_Pokenav_2B4EA5, FLAG_0x4F3, 0xFFFF }, + { gText_Wally_Pokenav_2B4F41, FLAG_0x097, 0xFFFF }, + { gText_Wally_Pokenav_2B4FF3, FLAG_0x06F, 0xFFFF }, + { gText_Wally_Pokenav_2B50B1, FLAG_0x081, 0xFFFF }, + { gText_Wally_Pokenav_2B5100, FLAG_0x07E, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +const struct MatchCallSubstruct2 sWallyAdditionalData[] = { + { FLAG_0x324, 0x05 }, + { FLAG_0x06F, 0xD5 }, + { FLAG_0x35A, 0x46 }, + { 0xFFFF, 0xD5 } +}; + +MATCHCALLDEF(sWallyMatchCallHeader, 2, 0, FLAG_0x0D6, REMATCH_WALLY_3, gWallyMatchCallDesc, sWallyTextScripts, sWallyAdditionalData); + +static const match_call_text_data_t sScottTextScripts[] = { + { gText_Scott_Pokenav_2B5184, 0xFFFF, 0xFFFF }, + { gText_Scott_Pokenav_2B5275, FLAG_0x08B, 0xFFFF }, + { gText_Scott_Pokenav_2B5323, FLAG_0x097, 0xFFFF }, + { gText_Scott_Pokenav_2B53DB, FLAG_0x0D4, 0xFFFF }, + { gText_Scott_Pokenav_2B54A5, FLAG_0x070, 0xFFFF }, + { gText_Scott_Pokenav_2B5541, FLAG_0x4F7, 0xFFFF }, + { gText_Scott_Pokenav_2B56CA, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + + +MATCHCALLDEF(sScottMatchCallHeader, 0, 0xD5, FLAG_0x0D7, gScottMatchCallDesc, gScottMatchCallName, sScottTextScripts); + +static const match_call_text_data_t sRoxanneTextScripts[] = { + { gText_Roxanne_Pokenav_2B2456, 0xFFFE, 0xFFFF }, + { gText_Roxanne_Pokenav_2B250E, 0xFFFF, 0xFFFF }, + { gText_Roxanne_Pokenav_2B25C1, 0xFFFF, 0xFFFF }, + { gText_Roxanne_Pokenav_2B2607, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sRoxanneMatchCallHeader, 5, 10, FLAG_0x1D3, 0x41, gRoxanneMatchCallDesc, NULL, sRoxanneTextScripts); + +static const match_call_text_data_t sBrawlyTextScripts[] = { + { gText_Brawly_Pokenav_2B2659, 0xFFFE, 0xFFFF }, + { gText_Brawly_Pokenav_2B275D, 0xFFFF, 0xFFFF }, + { gText_Brawly_Pokenav_2B286F, 0xFFFF, 0xFFFF }, + { gText_Brawly_Pokenav_2B28D1, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sBrawlyMatchCallHeader, 5, 2, FLAG_0x1D4, 0x42, gBrawlyMatchCallDesc, NULL, sBrawlyTextScripts); + +static const match_call_text_data_t sWattsonTextScripts[] = { + { gText_Wattson_Pokenav_2B2912, 0xFFFE, 0xFFFF }, + { gText_Wattson_Pokenav_2B29CA, 0xFFFF, 0xFFFF }, + { gText_Wattson_Pokenav_2B2AB6, 0xFFFF, 0xFFFF }, + { gText_Wattson_Pokenav_2B2B01, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sWattsonMatchCallHeader, 5, 9, FLAG_0x1D5, 0x43, gWattsonMatchCallDesc, NULL, sWattsonTextScripts); + +static const match_call_text_data_t sFlanneryTextScripts[] = { + { gText_Flannery_Pokenav_2B2B4D, 0xFFFE, 0xFFFF }, + { gText_Flannery_Pokenav_2B2C0E, 0xFFFF, 0xFFFF }, + { gText_Flannery_Pokenav_2B2CF1, 0xFFFF, 0xFFFF }, + { gText_Flannery_Pokenav_2B2D54, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sFlanneryMatchCallHeader, 5, 3, FLAG_0x1D6, 0x44, gFlanneryMatchCallDesc, NULL, sFlanneryTextScripts); + +static const match_call_text_data_t sWinonaTextScripts[] = { + { gText_Winona_Pokenav_2B2DA4, 0xFFFE, 0xFFFF }, + { gText_Winona_Pokenav_2B2E2B, 0xFFFF, 0xFFFF }, + { gText_Winona_Pokenav_2B2EC2, 0xFFFF, 0xFFFF }, + { gText_Winona_Pokenav_2B2F16, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sWinonaMatchCallHeader, 5, 11, FLAG_0x1D7, 0x46, gWinonaMatchCallDesc, NULL, sWinonaTextScripts); + +static const match_call_text_data_t sTateLizaTextScripts[] = { + { gText_TateLiza_Pokenav_2B2F97, 0xFFFE, 0xFFFF }, + { gText_TateLiza_Pokenav_2B306E, 0xFFFF, 0xFFFF }, + { gText_TateLiza_Pokenav_2B3158, 0xFFFF, 0xFFFF }, + { gText_TateLiza_Pokenav_2B31CD, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sTateLizaMatchCallHeader, 5, 13, FLAG_0x1D8, 0x47, gTateLizaMatchCallDesc, NULL, sTateLizaTextScripts); + +static const match_call_text_data_t sJuanTextScripts[] = { + { gText_Juan_Pokenav_2B3249, 0xFFFE, 0xFFFF }, + { gText_Juan_Pokenav_2B32EC, 0xFFFF, 0xFFFF }, + { gText_Juan_Pokenav_2B33AA, 0xFFFF, 0xFFFF }, + { gText_Juan_Pokenav_2B341E, FLAG_SYS_GAME_CLEAR, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sJuanMatchCallHeader, 5, 14, FLAG_0x1D9, 0x48, gJuanMatchCallDesc, NULL, sJuanTextScripts); + +static const match_call_text_data_t sSidneyTextScripts[] = { + { gText_Sidney_Pokenav_2B34CC, 0xFFFF, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sSidneyMatchCallHeader, 5, 15, FLAG_0x1A5, 0x49, gEliteFourMatchCallDesc, NULL, sSidneyTextScripts); + +static const match_call_text_data_t sPhoebeTextScripts[] = { + { gText_Phoebe_Pokenav_2B3561, 0xFFFF, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sPhoebeMatchCallHeader, 5, 15, FLAG_0x1A6, 0x4A, gEliteFourMatchCallDesc, NULL, sPhoebeTextScripts); + +static const match_call_text_data_t sGlaciaTextScripts[] = { + { gText_Glacia_Pokenav_2B35E4, 0xFFFF, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sGlaciaMatchCallHeader, 5, 15, FLAG_0x1A7, 0x4B, gEliteFourMatchCallDesc, NULL, sGlaciaTextScripts); + +static const match_call_text_data_t sDrakeTextScripts[] = { + { gText_Drake_Pokenav_2B368B, 0xFFFF, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sDrakeMatchCallHeader, 5, 15, FLAG_0x1A8, 0x4C, gEliteFourMatchCallDesc, NULL, sDrakeTextScripts); + +static const match_call_text_data_t sWallaceTextScripts[] = { + { gText_Wallace_Pokenav_2B3790, 0xFFFF, 0xFFFF }, + { NULL, 0xFFFF, 0xFFFF } +}; + +MATCHCALLDEF(sWallaceMatchCallHeader, 5, 15, FLAG_0x1A9, 0x4D, gChampionMatchCallDesc, NULL, sWallaceTextScripts); + +static const match_call_t sMatchCallHeaders[] = { + {.type0 = &sMrStoneMatchCallHeader}, + {.type3 = &sProfBirchMatchCallHeader}, + {.type4 = &sBrendanMatchCallHeader}, + {.type4 = &sMayMatchCallHeader}, + {.type2 = &sWallyMatchCallHeader}, + {.type5 = &sNormanMatchCallHeader}, + {.type0 = &sMomMatchCallHeader}, + {.type0 = &sStevenMatchCallHeader}, + {.type0 = &sScottMatchCallHeader}, + {.type5 = &sRoxanneMatchCallHeader}, + {.type5 = &sBrawlyMatchCallHeader}, + {.type5 = &sWattsonMatchCallHeader}, + {.type5 = &sFlanneryMatchCallHeader}, + {.type5 = &sWinonaMatchCallHeader}, + {.type5 = &sTateLizaMatchCallHeader}, + {.type5 = &sJuanMatchCallHeader}, + {.type5 = &sSidneyMatchCallHeader}, + {.type5 = &sPhoebeMatchCallHeader}, + {.type5 = &sGlaciaMatchCallHeader}, + {.type5 = &sDrakeMatchCallHeader}, + {.type5 = &sWallaceMatchCallHeader} +}; + +static bool32 (*const sMatchCallGetFlagFuncs[])(match_call_t) = { + MatchCallGetFlag_Type0, + MatchCallGetFlag_Type1, + MatchCallGetFlag_Type2, + MatchCallGetFlag_Type3, + MatchCallGetFlag_Type4 +}; + +static u8 (*const gUnknown_08625310[])(match_call_t) = { + sub_81D1714, + sub_81D1718, + sub_81D171C, + sub_81D1750, + sub_81D1754 +}; + +static bool32 (*const sMatchCall_IsRematchableFunctions[])(match_call_t) = { + MatchCall_IsRematchable_Type0, + MatchCall_IsRematchable_Type1, + MatchCall_IsRematchable_Type2, + MatchCall_IsRematchable_Type3, + MatchCall_IsRematchable_Type4 +}; + +static bool32 (*const gUnknown_08625338[])(match_call_t) = { + sub_81D1840, + sub_81D1844, + sub_81D1848, + sub_81D184C, + sub_81D1850 +}; + +static u32 (*const sMatchCall_GetRematchTableIdxFunctions[])(match_call_t) = { + MatchCall_GetRematchTableIdx_Type0, + MatchCall_GetRematchTableIdx_Type1, + MatchCall_GetRematchTableIdx_Type2, + MatchCall_GetRematchTableIdx_Type3, + MatchCall_GetRematchTableIdx_Type4 +}; + +static void (*const sMatchCall_GetMessageFunctions[])(match_call_t, u8 *) = { + MatchCall_GetMessage_Type0, + MatchCall_GetMessage_Type1, + MatchCall_GetMessage_Type2, + MatchCall_GetMessage_Type3, + MatchCall_GetMessage_Type4 +}; + +static void (*const sMatchCall_GetNameAndDescFunctions[])(match_call_t, const u8 **, const u8 **) = { + MatchCall_GetNameAndDesc_Type0, + MatchCall_GetNameAndDesc_Type1, + MatchCall_GetNameAndDesc_Type2, + MatchCall_GetNameAndDesc_Type3, + MatchCall_GetNameAndDesc_Type4 +}; + +static const struct UnkStruct_08625388 sMatchCallCheckPageOverrides[] = { + { 7, 0x4B, 0xffff, { gMatchCallStevenStrategyText, gMatchCall_StevenTrainersPokemonText, gMatchCall_StevenSelfIntroductionText_Line1_BeforeMeteorFallsBattle, gMatchCall_StevenSelfIntroductionText_Line2_BeforeMeteorFallsBattle } }, // STEVEN + { 7, 0x4B, FLAG_0x4F6, { gMatchCallStevenStrategyText, gMatchCall_StevenTrainersPokemonText, gMatchCall_StevenSelfIntroductionText_Line1_AfterMeteorFallsBattle, gMatchCall_StevenSelfIntroductionText_Line2_AfterMeteorFallsBattle } }, // STEVEN + { 2, 0x3c, 0xffff, { gMatchCall_BrendanStrategyText, gMatchCall_BrendanTrainersPokemonText, gMatchCall_BrendanSelfIntroductionText_Line1, gMatchCall_BrendanSelfIntroductionText_Line2 } }, // Brendan + { 3, 0x3f, 0xffff, { gMatchCall_MayStrategyText, gMatchCall_MayTrainersPokemonText, gMatchCall_MaySelfIntroductionText_Line1, gMatchCall_MaySelfIntroductionText_Line2 } } // May +}; + +// .text + +static u32 MatchCallGetFunctionIndex(match_call_t matchCall) +{ + switch (matchCall.common->type) + { + case 0: + default: + return 0; + case 1: + case 5: + return 1; + case 2: + return 2; + case 4: + return 3; + case 3: + return 4; + } +} + +u32 GetTrainerIdxByRematchIdx(u32 rematchIdx) +{ + return gRematchTable[rematchIdx].trainerIds[0]; +} + +s32 GetRematchIdxByTrainerIdx(s32 trainerIdx) +{ + s32 rematchIdx; + + for (rematchIdx = 0; rematchIdx < REMATCH_TABLE_ENTRIES; rematchIdx++) + { + if (gRematchTable[rematchIdx].trainerIds[0] == trainerIdx) + return rematchIdx; + } + return -1; +} + +bool32 MatchCallFlagGetByIndex(u32 idx) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return FALSE; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + return sMatchCallGetFlagFuncs[i](matchCall); +} + +static bool32 MatchCallGetFlag_Type0(match_call_t matchCall) +{ + if (matchCall.type0->flag == 0xffff) + return TRUE; + return FlagGet(matchCall.type0->flag); +} + +static bool32 MatchCallGetFlag_Type1(match_call_t matchCall) +{ + if (matchCall.type1->flag == 0xffff) + return TRUE; + return FlagGet(matchCall.type1->flag); +} + +static bool32 MatchCallGetFlag_Type2(match_call_t matchCall) +{ + if (matchCall.type2->flag == 0xffff) + return TRUE; + return FlagGet(matchCall.type2->flag); +} + +static bool32 MatchCallGetFlag_Type3(match_call_t matchCall) +{ + if (matchCall.type4->gender != gSaveBlock2Ptr->playerGender) + return FALSE; + if (matchCall.type4->flag == 0xffff) + return TRUE; + return FlagGet(matchCall.type4->flag); +} + +static bool32 MatchCallGetFlag_Type4(match_call_t matchCall) +{ + return FlagGet(matchCall.type3->flag); +} + +u8 sub_81D16DC(u32 idx) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return 0; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + return gUnknown_08625310[i](matchCall); +} + +static u8 sub_81D1714(match_call_t matchCall) +{ + return matchCall.type0->v1; +} + +static u8 sub_81D1718(match_call_t matchCall) +{ + return matchCall.type1->v1; +} + +static u8 sub_81D171C(match_call_t matchCall) +{ + s32 i; + + for (i = 0; matchCall.type2->v10[i].flag != 0xffff; i++) + { + if (!FlagGet(matchCall.type2->v10[i].flag)) + break; + } + return matchCall.type2->v10[i].v2; +} + +static u8 sub_81D1750(match_call_t matchCall) +{ + return 0xd5; +} + +static u8 sub_81D1754(match_call_t matchCall) +{ + return 0xd5; +} + +bool32 MatchCall_IsRematchable(u32 idx) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return 0; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + return sMatchCall_IsRematchableFunctions[i](matchCall); +} + +static bool32 MatchCall_IsRematchable_Type0(match_call_t matchCall) +{ + return FALSE; +} + +static bool32 MatchCall_IsRematchable_Type1(match_call_t matchCall) +{ + if (matchCall.type1->rematchTableIdx >= REMATCH_ELITE_FOUR_ENTRIES) + return FALSE; + return gSaveBlock1Ptr->trainerRematches[matchCall.type1->rematchTableIdx] ? TRUE : FALSE; +} + +static bool32 MatchCall_IsRematchable_Type2(match_call_t matchCall) +{ + return gSaveBlock1Ptr->trainerRematches[matchCall.type2->rematchTableIdx] ? TRUE : FALSE; +} + +static bool32 MatchCall_IsRematchable_Type3(match_call_t matchCall) +{ + return FALSE; +} + +static bool32 MatchCall_IsRematchable_Type4(match_call_t matchCall) +{ + return FALSE; +} + +bool32 sub_81D17E8(u32 idx) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return FALSE; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + if (gUnknown_08625338[i](matchCall)) + return TRUE; + for (i = 0; i < 4; i++) + { + if (sMatchCallCheckPageOverrides[i].idx == idx) + return TRUE; + } + return FALSE; +} + +static bool32 sub_81D1840(match_call_t matchCall) +{ + return FALSE; +} + +static bool32 sub_81D1844(match_call_t matchCall) +{ + return TRUE; +} + +static bool32 sub_81D1848(match_call_t matchCall) +{ + return TRUE; +} + +static bool32 sub_81D184C(match_call_t matchCall) +{ + return FALSE; +} + +static bool32 sub_81D1850(match_call_t matchCall) +{ + return FALSE; +} + +u32 MatchCall_GetRematchTableIdx(u32 idx) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return REMATCH_TABLE_ENTRIES; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + return sMatchCall_GetRematchTableIdxFunctions[i](matchCall); +} + +static u32 MatchCall_GetRematchTableIdx_Type0(match_call_t matchCall) +{ + return REMATCH_TABLE_ENTRIES; +} + +static u32 MatchCall_GetRematchTableIdx_Type1(match_call_t matchCall) +{ + return matchCall.type1->rematchTableIdx; +} + +static u32 MatchCall_GetRematchTableIdx_Type2(match_call_t matchCall) +{ + return matchCall.type2->rematchTableIdx; +} + +static u32 MatchCall_GetRematchTableIdx_Type3(match_call_t matchCall) +{ + return REMATCH_TABLE_ENTRIES; +} + +static u32 MatchCall_GetRematchTableIdx_Type4(match_call_t matchCall) +{ + return REMATCH_TABLE_ENTRIES; +} + +void MatchCall_GetMessage(u32 idx, u8 *dest) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + sMatchCall_GetMessageFunctions[i](matchCall, dest); +} + +static void MatchCall_GetMessage_Type0(match_call_t matchCall, u8 *dest) +{ + sub_81D1920(matchCall.type0->textData, dest); +} + +static void MatchCall_GetMessage_Type1(match_call_t matchCall, u8 *dest) +{ + if (matchCall.common->type != 5) + sub_81D1920(matchCall.type5->textData, dest); + else + sub_81D199C(matchCall.type1->textData, matchCall.type1->rematchTableIdx, dest); +} + +static void MatchCall_GetMessage_Type2(match_call_t matchCall, u8 *dest) +{ + sub_81D1920(matchCall.type2->textData, dest); +} + +static void MatchCall_GetMessage_Type3(match_call_t matchCall, u8 *dest) +{ + sub_81D1920(matchCall.type4->textData, dest); +} + +static void MatchCall_GetMessage_Type4(match_call_t matchCall, u8 *dest) +{ + sub_8197080(dest); +} + +void sub_81D1920(const match_call_text_data_t *sub0, u8 *dest) +{ + u32 i; + for (i = 0; sub0[i].text != NULL; i++) + ; + if (i) + i--; + while (i) + { + if (sub0[i].flag != 0xffff && FlagGet(sub0[i].flag) == TRUE) + break; + i--; + } + if (sub0[i].flag2 != 0xffff) + FlagSet(sub0[i].flag2); + StringExpandPlaceholders(dest, sub0[i].text); +} + +#ifdef NONMATCHING +// There's some weird upmerge going on that I cannot replicate at this time. +static void sub_81D199C(const match_call_text_data_t *sub0, u16 idx, u8 *dest) +{ + u32 i; + for (i = 0; sub0[i].text != NULL; i++) + { + if (sub0[i].flag == 0xfffe) + break; + if (sub0[i].flag == 0xffff && !FlagGet(sub0[i].flag)) + break; + } + if (sub0[i].flag != 0xfffe) + { + if (i) + i--; + if (sub0[i].flag2 != 0xffff) + FlagSet(sub0[i].flag2); + StringExpandPlaceholders(dest, sub0[i].text); + } + else + { + if (!FlagGet(FLAG_SYS_GAME_CLEAR)) + ; + else if (gSaveBlock1Ptr->trainerRematches[idx]) + i += 2; + else if (CountBattledRematchTeams(idx) >= 2) + i += 3; + else + i++; + StringExpandPlaceholders(dest, sub0[i].text); + } +} +#else +static NAKED void sub_81D199C(const match_call_text_data_t *sub0, u16 idx, u8 *dest) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tadds r6, r0, 0\n" + "\tmov r10, r2\n" + "\tlsls r1, 16\n" + "\tlsrs r7, r1, 16\n" + "\tmovs r5, 0\n" + "\tldr r0, [r6]\n" + "\tcmp r0, 0\n" + "\tbeq _081D19E6\n" + "\tldrh r0, [r6, 0x4]\n" + "\tldr r1, =0x0000fffe\n" + "\tcmp r0, r1\n" + "\tbeq _081D1A24\n" + "\tldr r0, =0x0000ffff\n" + "\tmov r9, r0\n" + "\tmov r8, r1\n" + "\tadds r4, r6, 0\n" + "_081D19C6:\n" + "\tldrh r0, [r4, 0x4]\n" + "\tcmp r0, r9\n" + "\tbeq _081D19D6\n" + "\tbl FlagGet\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _081D19E6\n" + "_081D19D6:\n" + "\tadds r4, 0x8\n" + "\tadds r5, 0x1\n" + "\tldr r0, [r4]\n" + "\tcmp r0, 0\n" + "\tbeq _081D19E6\n" + "\tldrh r0, [r4, 0x4]\n" + "\tcmp r0, r8\n" + "\tbne _081D19C6\n" + "_081D19E6:\n" + "\tlsls r0, r5, 3\n" + "\tadds r0, r6\n" + "\tldrh r1, [r0, 0x4]\n" + "\tldr r0, =0x0000fffe\n" + "\tcmp r1, r0\n" + "\tbeq _081D1A24\n" + "\tcmp r5, 0\n" + "\tbeq _081D19F8\n" + "\tsubs r5, 0x1\n" + "_081D19F8:\n" + "\tlsls r0, r5, 3\n" + "\tadds r4, r0, r6\n" + "\tldrh r1, [r4, 0x6]\n" + "\tldr r0, =0x0000ffff\n" + "\tcmp r1, r0\n" + "\tbeq _081D1A0A\n" + "\tadds r0, r1, 0\n" + "\tbl FlagSet\n" + "_081D1A0A:\n" + "\tldr r1, [r4]\n" + "\tmov r0, r10\n" + "\tbl StringExpandPlaceholders\n" + "\tb _081D1A5C\n" + "\t.pool\n" + "_081D1A1C:\n" + "\tadds r5, 0x2\n" + "\tb _081D1A50\n" + "_081D1A20:\n" + "\tadds r5, 0x3\n" + "\tb _081D1A50\n" + "_081D1A24:\n" + "\tldr r0, =0x00000864\n" + "\tbl FlagGet\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _081D1A50\n" + "\tldr r0, =gSaveBlock1Ptr\n" + "\tldr r0, [r0]\n" + "\tldr r1, =0x000009ca\n" + "\tadds r0, r1\n" + "\tadds r0, r7\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _081D1A1C\n" + "\tadds r0, r7, 0\n" + "\tbl CountBattledRematchTeams\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tcmp r0, 0x1\n" + "\tbhi _081D1A20\n" + "\tadds r5, 0x1\n" + "_081D1A50:\n" + "\tlsls r0, r5, 3\n" + "\tadds r0, r6\n" + "\tldr r1, [r0]\n" + "\tmov r0, r10\n" + "\tbl StringExpandPlaceholders\n" + "_081D1A5C:\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.pool"); +} +#endif + +void sub_81D1A78(u32 idx, const u8 **desc, const u8 **name) +{ + match_call_t matchCall; + u32 i; + + if (idx > 20) + return; + matchCall = sMatchCallHeaders[idx]; + i = MatchCallGetFunctionIndex(matchCall); + sMatchCall_GetNameAndDescFunctions[i](matchCall, desc, name); +} + +static void MatchCall_GetNameAndDesc_Type0(match_call_t matchCall, const u8 **desc, const u8 **name) +{ + *desc = matchCall.type0->desc; + *name = matchCall.type0->name; +} + +static void MatchCall_GetNameAndDesc_Type1(match_call_t matchCall, const u8 **desc, const u8 **name) +{ + match_call_t _matchCall = matchCall; + if (_matchCall.type1->name == NULL) + MatchCall_GetNameAndDescByRematchIdx(_matchCall.type1->rematchTableIdx, desc, name); + else + *name = _matchCall.type1->name; + *desc = _matchCall.type1->desc; +} + +static void MatchCall_GetNameAndDesc_Type2(match_call_t matchCall, const u8 **desc, const u8 **name) +{ + MatchCall_GetNameAndDescByRematchIdx(matchCall.type2->rematchTableIdx, desc, name); + *desc = matchCall.type2->desc; +} + +static void MatchCall_GetNameAndDesc_Type3(match_call_t matchCall, const u8 **desc, const u8 **name) +{ + *desc = matchCall.type4->desc; + *name = matchCall.type4->name; +} + +static void MatchCall_GetNameAndDesc_Type4(match_call_t matchCall, const u8 **desc, const u8 **name) +{ + *desc = matchCall.type3->desc; + *name = matchCall.type3->name; +} + +static void MatchCall_GetNameAndDescByRematchIdx(u32 idx, const u8 **desc, const u8 **name) +{ + const struct Trainer *trainer = gTrainers + GetTrainerIdxByRematchIdx(idx); + *desc = gTrainerClassNames[trainer->trainerClass]; + *name = trainer->trainerName; +} + +#ifdef NONMATCHING +const u8 *sub_81D1B40(u32 idx, u32 offset) +{ + u32 i; + + for (i = 0; i < 4; i++) + { + if (sMatchCallCheckPageOverrides[i].idx == idx) + { + for (; i + 1 < 4 && sMatchCallCheckPageOverrides[i + 1].idx == idx; i++) + { + if (!FlagGet(sMatchCallCheckPageOverrides[i + 1].v4)) + break; + } + return sMatchCallCheckPageOverrides[i].v8[offset]; + } + } + return NULL; +} +#else +NAKED const u8 *sub_81D1B40(u32 idx, u32 offset) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r9\n" + "\tmov r6, r8\n" + "\tpush {r6,r7}\n" + "\tadds r6, r0, 0\n" + "\tmovs r5, 0\n" + "\tldr r2, =sMatchCallCheckPageOverrides\n" + "\tmovs r0, 0x8\n" + "\tadds r0, r2\n" + "\tmov r9, r0\n" + "_081D1B54:\n" + "\tlsls r0, r5, 1\n" + "\tadds r0, r5\n" + "\tlsls r0, 3\n" + "\tadds r0, r2\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, r6\n" + "\tbne _081D1BBC\n" + "\tadds r4, r5, 0x1\n" + "\tlsls r1, 2\n" + "\tmov r8, r1\n" + "\tcmp r4, 0x3\n" + "\tbhi _081D1BA8\n" + "\tlsls r0, r4, 1\n" + "\tadds r0, r4\n" + "\tlsls r0, 3\n" + "\tadds r0, r2\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, r6\n" + "\tbne _081D1BA8\n" + "\tldr r7, =sMatchCallCheckPageOverrides\n" + "_081D1B7C:\n" + "\tlsls r0, r4, 1\n" + "\tadds r0, r4\n" + "\tlsls r0, 3\n" + "\tadds r1, r7, 0x4\n" + "\tadds r0, r1\n" + "\tldrh r0, [r0]\n" + "\tbl FlagGet\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _081D1BA8\n" + "\tadds r5, r4, 0\n" + "\tadds r4, r5, 0x1\n" + "\tcmp r4, 0x3\n" + "\tbhi _081D1BA8\n" + "\tlsls r0, r4, 1\n" + "\tadds r0, r4\n" + "\tlsls r0, 3\n" + "\tadds r0, r7\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, r6\n" + "\tbeq _081D1B7C\n" + "_081D1BA8:\n" + "\tlsls r0, r5, 1\n" + "\tadds r0, r5\n" + "\tlsls r0, 3\n" + "\tadd r0, r8\n" + "\tadd r0, r9\n" + "\tldr r0, [r0]\n" + "\tb _081D1BC4\n" + "\t.pool\n" + "_081D1BBC:\n" + "\tadds r5, 0x1\n" + "\tcmp r5, 0x3\n" + "\tbls _081D1B54\n" + "\tmovs r0, 0\n" + "_081D1BC4:\n" + "\tpop {r3,r4}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1"); +} +#endif + +s32 sub_81D1BD0(u32 idx) +{ + u32 i; + + for (i = 0; i < 4; i++) + { + if (sMatchCallCheckPageOverrides[i].idx == idx) + return sMatchCallCheckPageOverrides[i].v2; + } + return -1; +} + +bool32 sub_81D1BF8(u32 idx) +{ + s32 i; + + for (i = 0; i < 21; i++) + { + u32 r0 = MatchCall_GetRematchTableIdx(i); + if (r0 != REMATCH_TABLE_ENTRIES && r0 == idx) + return TRUE; + } + return FALSE; +} + +void SetMatchCallRegisteredFlag(void) +{ + s32 r0 = GetRematchIdxByTrainerIdx(gSpecialVar_0x8004); + if (r0 >= 0) + FlagSet(FLAG_MATCH_CALL_REGISTERED + r0); +} diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c new file mode 100644 index 000000000..5c8be1581 --- /dev/null +++ b/src/mauville_old_man.c @@ -0,0 +1,1247 @@ +#include "global.h" +#include "main.h" +#include "constants/songs.h" +#include "constants/easy_chat.h" +#include "constants/map_objects.h" +#include "constants/vars.h" +#include "mauville_old_man.h" +#include "event_data.h" +#include "string_util.h" +#include "text.h" +#include "easy_chat.h" +#include "script.h" +#include "random.h" +#include "event_scripts.h" +#include "task.h" +#include "menu.h" +#include "m4a.h" +#include "bard_music.h" +#include "sound.h" +#include "strings.h" +#include "overworld.h" +#include "field_message_box.h" +#include "script_menu.h" +#include "trader.h" + +#define CHAR_SONG_WORD_SEPARATOR 0x37 + +extern struct MusicPlayerInfo gMPlayInfo_SE2; + +static void InitGiddyTaleList(void); +static void StartBardSong(bool8 useTemporaryLyrics); +static void Task_BardSong(u8 taskId); +static void StorytellerSetup(void); +static void Storyteller_ResetFlag(void); + +IWRAM_DATA u8 sSelectedStory; + +struct BardSong gBardSong; + +static EWRAM_DATA u16 sUnknownBardRelated = 0; +static EWRAM_DATA struct MauvilleManStoryteller * sStorytellerPtr = NULL; +static EWRAM_DATA u8 sStorytellerWindowId = 0; + +static const u16 sDefaultBardSongLyrics[6] = { + EC_WORD_SHAKE, + EC_WORD_IT, + EC_WORD_DO, + EC_WORD_THE, + EC_WORD_DIET, + EC_WORD_DANCE +}; + +static const u8 * const sGiddyAdjectives[] = { + gText_SoPretty, + gText_SoDarling, + gText_SoRelaxed, + gText_SoSunny, + gText_SoDesirable, + gText_SoExciting, + gText_SoAmusing, + gText_SoMagical +}; + +static const u8 * const sGiddyQuestions[] = { + gUnknown_08294313, + gUnknown_08294359, + gUnknown_08294398, + gUnknown_082943DA, + gUnknown_0829441C, + gUnknown_08294460, + gUnknown_082944A0, + gUnknown_082944D5 +}; + +static void SetupBard(void) +{ + u16 i; + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + + bard->id = MAUVILLE_MAN_BARD; + bard->hasChangedSong = FALSE; + bard->language = gGameLanguage; + for (i = 0; i < 6; i++) + bard->songLyrics[i] = sDefaultBardSongLyrics[i]; +} + +static void SetupHipster(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; + + hipster->id = MAUVILLE_MAN_HIPSTER; + hipster->alreadySpoken = FALSE; + hipster->language = gGameLanguage; +} + +static void SetupStoryteller(void) +{ + StorytellerSetup(); +} + +static void SetupGiddy(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1Ptr->oldMan.giddy; + + giddy->id = MAUVILLE_MAN_GIDDY; + giddy->taleCounter = 0; + giddy->language = gGameLanguage; +} + +static void SetupTrader(void) +{ + TraderSetup(); +} + +void SetMauvilleOldMan(void) +{ + u16 trainerId = (gSaveBlock2Ptr->playerTrainerId[1] << 8) | gSaveBlock2Ptr->playerTrainerId[0]; + + + // Determine man based on the last digit of the player's trainer ID. + switch ((trainerId % 10) / 2) + { + case MAUVILLE_MAN_BARD: + SetupBard(); + break; + case MAUVILLE_MAN_HIPSTER: + SetupHipster(); + break; + case MAUVILLE_MAN_TRADER: + SetupTrader(); + break; + case MAUVILLE_MAN_STORYTELLER: + SetupStoryteller(); + break; + case MAUVILLE_MAN_GIDDY: + SetupGiddy(); + break; + } + ScrSpecial_SetMauvilleOldManMapObjGfx(); +} + +u8 GetCurrentMauvilleOldMan(void) +{ + struct MauvilleManCommon *common = &gSaveBlock1Ptr->oldMan.common; + + return common->id; +} + +void ScrSpecial_GetCurrentMauvilleMan(void) +{ + gSpecialVar_Result = GetCurrentMauvilleOldMan(); +} + +void ScrSpecial_HasBardSongBeenChanged(void) +{ + u16 *scriptResult = &gSpecialVar_Result; // why?? + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + + *scriptResult = bard->hasChangedSong; +} + +void ScrSpecial_SaveBardSongLyrics(void) +{ + u16 i; + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + + StringCopy(bard->playerName, gSaveBlock2Ptr->playerName); + + for (i = 0; i < 4; i++) + bard->playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i]; + + for (i = 0; i < 6; i++) + bard->songLyrics[i] = bard->temporaryLyrics[i]; + + bard->hasChangedSong = TRUE; +} + +// Copies lyrics into gStringVar4 +static void PrepareSongText(void) +{ + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + u16 * lyrics = gSpecialVar_0x8004 == 0 ? bard->songLyrics : bard->temporaryLyrics; + u8 * wordEnd = gStringVar4; + u8 * str = wordEnd; + u16 lineNum; + + // Put three words on each line + for (lineNum = 0; lineNum < 2; lineNum++) + { + wordEnd = CopyEasyChatWord(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + str++; + *(wordEnd++) = CHAR_SPACE; + + wordEnd = CopyEasyChatWord(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + str++; + *(wordEnd++) = CHAR_NEWLINE; + + wordEnd = CopyEasyChatWord(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + if (lineNum == 0) + { + *(wordEnd++) = EXT_CTRL_CODE_BEGIN; + *(wordEnd++) = 15; + } + } +} + +void ScrSpecial_PlayBardSong(void) +{ + StartBardSong(gSpecialVar_0x8004); + ScriptContext1_Stop(); +} + +void ScrSpecial_GetHipsterSpokenFlag(void) +{ + u16 *scriptResult = &gSpecialVar_Result; // again?? + struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; + + *scriptResult = hipster->alreadySpoken; +} + +void ScrSpecial_SetHipsterSpokenFlag(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; + + hipster->alreadySpoken = TRUE; +} + +void ScrSpecial_HipsterTeachWord(void) +{ + u16 var = sub_811F01C(); + + if (var == 0xFFFF) + { + gSpecialVar_Result = FALSE; + } + else + { + CopyEasyChatWord(gStringVar1, var); + gSpecialVar_Result = TRUE; + } +} + +void ScrSpecial_GiddyShouldTellAnotherTale(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1Ptr->oldMan.giddy; + + if (giddy->taleCounter == 10) + { + gSpecialVar_Result = FALSE; + giddy->taleCounter = 0; + } + else + { + gSpecialVar_Result = TRUE; + } +} + +void ScrSpecial_GenerateGiddyLine(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1Ptr->oldMan.giddy; + + if (giddy->taleCounter == 0) + InitGiddyTaleList(); + + if (giddy->randomWords[giddy->taleCounter] != 0xFFFF) // is not the last element of the array? + { + u8 *stringPtr; + u32 adjective = Random(); + + adjective %= 8; + stringPtr = CopyEasyChatWord(gStringVar4, giddy->randomWords[giddy->taleCounter]); + stringPtr = StringCopy(stringPtr, gOtherText_Is); + stringPtr = StringCopy(stringPtr, sGiddyAdjectives[adjective]); + StringCopy(stringPtr, gOtherText_DontYouAgree); + } + else + { + StringCopy(gStringVar4, sGiddyQuestions[giddy->questionList[giddy->questionNum++]]); + } + + if (!(Random() % 10)) + giddy->taleCounter = 10; + else + giddy->taleCounter++; + + gSpecialVar_Result = TRUE; +} + +static void InitGiddyTaleList(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1Ptr->oldMan.giddy; + u16 arr[][2] = { + {EC_GROUP_POKEMON, 0}, + {EC_GROUP_LIFESTYLE, 0}, + {EC_GROUP_HOBBIES, 0}, + {EC_GROUP_MOVE_1, 0}, + {EC_GROUP_MOVE_2, 0}, + {EC_GROUP_POKEMON_2, 0} + }; + u16 i; + u16 r10; + u16 r7; + u16 r1; + + for (i = 0; i < 8; i++) + giddy->questionList[i] = i; + + for (i = 0; i < 8; i++) + { + r1 = Random() % (i + 1); + r7 = giddy->questionList[i]; + giddy->questionList[i] = giddy->questionList[r1]; + giddy->questionList[r1] = r7; + } + + r10 = 0; + for (i = 0; i < 6; i++) + { + arr[i][1] = EasyChat_GetNumWordsInGroup(arr[i][0]); + r10 += arr[i][1]; + } + + giddy->questionNum = 0; + r7 = 0; + for (i = 0; i < 10; i++) + { + r1 = Random() % 10; + if (r1 < 3 && r7 < 8) + { + giddy->randomWords[i] = 0xFFFF; + r7++; + } + else + { + s16 r2 = Random() % r10; + for (r1 = 0; i < 6; r1++) + if ((r2 -= arr[r1][1]) <= 0) + break; + if (r1 == 6) + r1 = 0; + giddy->randomWords[i] = sub_811EE90(arr[r1][0]); + } + } +} +static void ResetBardFlag(void) +{ + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + + bard->hasChangedSong = FALSE; +} + +static void ResetHipsterFlag(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1Ptr->oldMan.hipster; + + hipster->alreadySpoken = FALSE; +} + +static void ResetTraderFlag(void) +{ + Trader_ResetFlag(); +} + +static void ResetStorytellerFlag(void) +{ + Storyteller_ResetFlag(); +} + +void ResetMauvilleOldManFlag(void) +{ + switch (GetCurrentMauvilleOldMan()) + { + case MAUVILLE_MAN_BARD: + ResetBardFlag(); + break; + case MAUVILLE_MAN_HIPSTER: + ResetHipsterFlag(); + break; + case MAUVILLE_MAN_STORYTELLER: + ResetStorytellerFlag(); + break; + case MAUVILLE_MAN_TRADER: + ResetTraderFlag(); + break; + case MAUVILLE_MAN_GIDDY: + break; + } + ScrSpecial_SetMauvilleOldManMapObjGfx(); +} + + +#define tState data[0] +#define tCharIndex data[3] +#define tCurrWord data[4] +#define tUseTemporaryLyrics data[5] + +#define MACRO1(a) (((a) & 3) + (((a) / 8) & 1)) +#define MACRO2(a) (((a) % 4) + (((a) / 8) & 1)) + +static void StartBardSong(bool8 useTemporaryLyrics) +{ + u8 taskId = CreateTask(Task_BardSong, 80); + + gTasks[taskId].tUseTemporaryLyrics = useTemporaryLyrics; +} + +static void sub_81206F0(void) +{ + gUnknown_03002F84 = FALSE; +} + +static void BardSong_TextSubPrinter(struct TextSubPrinter * printer, u16 a1) +{ + gUnknown_03002F84 = TRUE; +} + +static void sub_8120708(const u8 * src) +{ + NewMenuHelpers_DrawDialogueFrame(0, 0); + PrintTextOnWindow(0, 1, src, 0, 1, 1, BardSong_TextSubPrinter); + gUnknown_03002F84 = TRUE; + CopyWindowToVram(0, 3); +} + +static void BardSing(struct Task *task, struct BardSong *song) +{ + switch (task->tState) + { + case 0: // Initialize song + { + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + u16 *lyrics; + s32 i; + + // Copy lyrics + if (gSpecialVar_0x8004 == 0) + lyrics = bard->songLyrics; + else + lyrics = bard->temporaryLyrics; + for (i = 0; i < 6; i++) + song->lyrics[i] = lyrics[i]; + song->currWord = 0; + } + break; + case 1: // Wait for BGM to end + break; + case 2: // Initialize word + { + u16 word = song->lyrics[song->currWord]; + song->sound = GetWordSounds(word); + GetWordPhonemes(song, MACRO1(word)); + song->currWord++; + if (song->sound->var00 != 0xFF) + song->state = 0; + else + { + song->state = 3; + song->phonemeTimer = 2; + } + break; + } + case 3: + case 4: + { + const struct BardSound *sound = &song->sound[song->currPhoneme]; + + switch (song->state) + { + case 0: + song->phonemeTimer = song->phonemes[song->currPhoneme].length; + if (sound->var00 <= 50) + { + u8 num = sound->var00 / 3; + m4aSongNumStart(PH_TRAP_HELD + 3 * num); + } + song->state = 2; + song->phonemeTimer--; + break; + case 2: + song->state = 1; + if (sound->var00 <= 50) + { + song->volume = 0x100 + sound->volume * 16; + m4aMPlayVolumeControl(&gMPlayInfo_SE2, 0xFFFF, song->volume); + song->pitch = 0x200 + song->phonemes[song->currPhoneme].pitch; + m4aMPlayPitchControl(&gMPlayInfo_SE2, 0xFFFF, song->pitch); + } + break; + case 1: + if (song->voiceInflection > 10) + song->volume -= 2; + if (song->voiceInflection & 1) + song->pitch += 64; + else + song->pitch -= 64; + m4aMPlayVolumeControl(&gMPlayInfo_SE2, 0xFFFF, song->volume); + m4aMPlayPitchControl(&gMPlayInfo_SE2, 0xFFFF, song->pitch); + song->voiceInflection++; + song->phonemeTimer--; + if (song->phonemeTimer == 0) + { + song->currPhoneme++; + if (song->currPhoneme != 6 && song->sound[song->currPhoneme].var00 != 0xFF) + song->state = 0; + else + { + song->state = 3; + song->phonemeTimer = 2; + } + } + break; + case 3: + song->phonemeTimer--; + if (song->phonemeTimer == 0) + { + m4aMPlayStop(&gMPlayInfo_SE2); + song->state = 4; + } + break; + } + } + break; + case 5: + break; + } +} + +static void Task_BardSong(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; // r5 + + BardSing(task, &gBardSong); + switch (task->tState) + { + case 0: // Initialize song + PrepareSongText(); + sub_8120708(gStringVar4); + task->data[1] = 0; + task->data[2] = 0; + task->tCharIndex = 0; + task->tCurrWord = 0; + FadeOutBGMTemporarily(4); + task->tState = 1; + break; + case 1: // Wait for BGM to end + if (IsBGMPausedOrStopped()) + task->tState = 2; + break; + case 2: // Initialize word + { + struct MauvilleManBard *bard = &gSaveBlock1Ptr->oldMan.bard; + u8 *str = gStringVar4 + task->tCharIndex; + u16 wordLen = 0; + // Can't get it to match without hacking + u32 temp; + register s16 zero asm("r1"); + + while (*str != CHAR_SPACE + && *str != CHAR_NEWLINE + && *str != EXT_CTRL_CODE_BEGIN + && *str != EOS) + { + str++; + wordLen++; + } + if (!task->tUseTemporaryLyrics) + sUnknownBardRelated = MACRO2(bard->songLyrics[task->tCurrWord]); + else + sUnknownBardRelated = MACRO2(bard->temporaryLyrics[task->tCurrWord]); + temp = gBardSong.length / wordLen; + zero = 0; + gBardSong.length = temp; + if (gBardSong.length <= 0) + gBardSong.length = 1; + task->tCurrWord++; + if (task->data[2] == 0) + task->tState = 3; + else + task->tState = 5; + task->data[1] = zero; + } + break; + case 5: + if (task->data[2] == 0) + task->tState = 3; + else + task->data[2]--; + break; + case 3: + if (gStringVar4[task->tCharIndex] == EOS) + { + FadeInBGM(6); + m4aMPlayFadeOutTemporarily(&gMPlayInfo_SE2, 2); + EnableBothScriptContexts(); + DestroyTask(taskId); + } + else if (gStringVar4[task->tCharIndex] == CHAR_SPACE) + { + + sub_81206F0(); + task->tCharIndex++; + task->tState = 2; + task->data[2] = 0; + } + else if (gStringVar4[task->tCharIndex] == CHAR_NEWLINE) + { + task->tCharIndex++; + task->tState = 2; + task->data[2] = 0; + } + else if (gStringVar4[task->tCharIndex] == EXT_CTRL_CODE_BEGIN) + { + task->tCharIndex += 2; // skip over control codes + task->tState = 2; + task->data[2] = 8; + } + else if (gStringVar4[task->tCharIndex] == CHAR_SONG_WORD_SEPARATOR) + { + gStringVar4[task->tCharIndex] = CHAR_SPACE; // restore it back to a space + sub_81206F0(); + task->tCharIndex++; + task->data[2] = 0; + } + else + { + switch (task->data[1]) + { + case 0: + sub_81206F0(); + task->data[1]++; + break; + case 1: + task->data[1]++; + break; + case 2: + task->tCharIndex++; + task->data[1] = 0; + task->data[2] = gBardSong.length; + task->tState = 4; + break; + } + } + break; + case 4: + task->data[2]--; + if (task->data[2] == 0) + task->tState = 3; + break; + } + sub_8197224(); +} + +void ScrSpecial_SetMauvilleOldManMapObjGfx(void) +{ + VarSet(VAR_0x4010, MAP_OBJ_GFX_BARD); +} + +// Language fixers? + +void sub_8120B70(union OldMan * oldMan) +{ + s32 i; + u8 sp00[8]; + + switch (oldMan->common.id) + { + case MAUVILLE_MAN_TRADER: + { + struct MauvilleOldManTrader * trader = &oldMan->trader; + for (i = 0; i < 4; i++) + { + if (trader->language[i] == LANGUAGE_JAPANESE) + { + ConvertInternationalString(trader->playerNames[i], LANGUAGE_JAPANESE); + } + } + } + break; + case MAUVILLE_MAN_STORYTELLER: + { + struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; + for (i = 0; i < 4; i++) + { + if (storyteller->gameStatIDs[i] != 0) + { + memcpy(sp00, storyteller->trainerNames[i], 7); + sp00[7] = EOS; + if (IsStringJapanese(sp00)) + { + memset(sp00, CHAR_SPACE, 8); + StringCopy(sp00, gText_Friend); + memcpy(storyteller->trainerNames[i], sp00, 7); + storyteller->language[i] = GAME_LANGUAGE; + } + } + } + } + break; + } +} + +void sub_8120C0C(union OldMan * oldMan, u32 r8, u32 r7, u32 r3) +{ + s32 i; + + switch (oldMan->common.id) + { + case MAUVILLE_MAN_TRADER: + { + struct MauvilleOldManTrader * trader = &oldMan->trader; + + for (i = 0; i < 4; i++) + { + if (IsStringJapanese(trader->playerNames[i])) + { + trader->language[i] = r8; + } + else + { + trader->language[i] = r7; + } + } + } + break; + case MAUVILLE_MAN_STORYTELLER: + { + struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; + + for (i = 0; i < 4; i++) + { + if (IsStringJapanese(storyteller->trainerNames[i])) + { + storyteller->language[i] = r8; + } + else + { + storyteller->language[i] = r7; + } + } + } + break; + case MAUVILLE_MAN_BARD: + { + struct MauvilleManBard * bard = &oldMan->bard; + + if (r3 == LANGUAGE_JAPANESE) + bard->language = r8; + else + bard->language = r7; + } + break; + case MAUVILLE_MAN_HIPSTER: + { + struct MauvilleManHipster * hipster = &oldMan->hipster; + + if (r3 == LANGUAGE_JAPANESE) + hipster->language = r8; + else + hipster->language = r7; + } + break; + case MAUVILLE_MAN_GIDDY: + { + struct MauvilleManGiddy * giddy = &oldMan->giddy; + + if (r3 == LANGUAGE_JAPANESE) + giddy->language = r8; + else + giddy->language = r7; + } + break; + } +} + +void sub_8120CD0(union OldMan * oldMan, u32 unused, u32 a2) +{ + u8 sp00[8]; + s32 i; + if (oldMan->common.id == MAUVILLE_MAN_STORYTELLER && a2 == LANGUAGE_JAPANESE) + { + struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; + + for (i = 0; i < 4; i++) + { + if (storyteller->gameStatIDs[i] != 0) + { + memcpy(sp00, storyteller->trainerNames[i], 7); + sp00[7] = EOS; + if (IsStringJapanese(sp00)) + storyteller->language[i] = LANGUAGE_JAPANESE; + else + storyteller->language[i] = GAME_LANGUAGE; + } + } + } +} + +void sub_8120D34(union OldMan * oldMan, u32 r1, u32 r6) +{ + u32 r2 = (r1 == LANGUAGE_JAPANESE || r1 == LANGUAGE_ENGLISH) ? 1 : 0; + switch (oldMan->common.id) + { + case MAUVILLE_MAN_TRADER: + { + struct MauvilleOldManTrader * trader = &oldMan->trader; + s32 i; + + if (r2) + { + for (i = 0; i < 4; i++) + { + u8 * str = trader->playerNames[i]; + if (str[0] == EXT_CTRL_CODE_BEGIN && str[1] == EXT_CTRL_CODE_JPN) + { + StripExtCtrlCodes(str); + trader->language[i] = LANGUAGE_JAPANESE; + } + else + trader->language[i] = r6; + } + } + else + { + for (i = 0; i < 4; i++) + { + if (trader->language[i] == LANGUAGE_JAPANESE) + { + StripExtCtrlCodes(trader->playerNames[i]); + } + } + } + } + break; + case MAUVILLE_MAN_STORYTELLER: + { + + struct MauvilleManStoryteller * storyteller = &oldMan->storyteller; + s32 i; + + if (r2) + { + for (i = 0; i < 4; i++) + { + if (storyteller->gameStatIDs[i] != 0) + storyteller->language[i] = r6; + } + } + } + break; + case MAUVILLE_MAN_BARD: + { + struct MauvilleManBard * bard = &oldMan->bard; + + if (r2) + { + bard->language = r6; + } + } + break; + case MAUVILLE_MAN_HIPSTER: + { + struct MauvilleManHipster * hipster = &oldMan->hipster; + + if (r2) + { + hipster->language = r6; + } + } + break; + case MAUVILLE_MAN_GIDDY: + { + struct MauvilleManGiddy * giddy = &oldMan->giddy; + + if (r2) + { + giddy->language = r6; + } + } + break; + } +} + +struct Story +{ + u8 stat; + u8 minVal; + const u8 *title; + const u8 *action; + const u8 *fullText; +}; + +static const struct Story sStorytellerStories[] = { + {GAME_STAT_50, 1, MauvilleCity_PokemonCenter_1F_Text_28E930, MauvilleCity_PokemonCenter_1F_Text_28E947, MauvilleCity_PokemonCenter_1F_Text_28E956}, + {GAME_STAT_STARTED_TRENDS, 1, MauvilleCity_PokemonCenter_1F_Text_28E9D7, MauvilleCity_PokemonCenter_1F_Text_28E9EF, MauvilleCity_PokemonCenter_1F_Text_28E9FE}, + {GAME_STAT_PLANTED_BERRIES, 1, MauvilleCity_PokemonCenter_1F_Text_28EA7D, MauvilleCity_PokemonCenter_1F_Text_28EA98, MauvilleCity_PokemonCenter_1F_Text_28EAA8}, + {GAME_STAT_TRADED_BIKES, 1, MauvilleCity_PokemonCenter_1F_Text_28EB19, MauvilleCity_PokemonCenter_1F_Text_28EB31, MauvilleCity_PokemonCenter_1F_Text_28EB3E}, + {GAME_STAT_GOT_INTERVIEWED, 1, MauvilleCity_PokemonCenter_1F_Text_28EBB5, MauvilleCity_PokemonCenter_1F_Text_28EBCD, MauvilleCity_PokemonCenter_1F_Text_28EBDD}, + {GAME_STAT_TRAINER_BATTLES, 1, MauvilleCity_PokemonCenter_1F_Text_28EC60, MauvilleCity_PokemonCenter_1F_Text_28EC79, MauvilleCity_PokemonCenter_1F_Text_28EC81}, + {GAME_STAT_POKEMON_CAPTURES, 1, MauvilleCity_PokemonCenter_1F_Text_28ED04, MauvilleCity_PokemonCenter_1F_Text_28ED21, MauvilleCity_PokemonCenter_1F_Text_28ED30}, + {GAME_STAT_FISHING_CAPTURES, 1, MauvilleCity_PokemonCenter_1F_Text_28EDA1, MauvilleCity_PokemonCenter_1F_Text_28EDB5, MauvilleCity_PokemonCenter_1F_Text_28EDCF}, + {GAME_STAT_HATCHED_EGGS, 1, MauvilleCity_PokemonCenter_1F_Text_28EE45, MauvilleCity_PokemonCenter_1F_Text_28EE5D, MauvilleCity_PokemonCenter_1F_Text_28EE6A}, + {GAME_STAT_EVOLVED_POKEMON, 1, MauvilleCity_PokemonCenter_1F_Text_28EEDD, MauvilleCity_PokemonCenter_1F_Text_28EEF1, MauvilleCity_PokemonCenter_1F_Text_28EF01}, + {GAME_STAT_USED_POKECENTER, 1, MauvilleCity_PokemonCenter_1F_Text_28EF73, MauvilleCity_PokemonCenter_1F_Text_28EF95, MauvilleCity_PokemonCenter_1F_Text_28EFAA}, + {GAME_STAT_RESTED_AT_HOME, 1, MauvilleCity_PokemonCenter_1F_Text_28F045, MauvilleCity_PokemonCenter_1F_Text_28F05A, MauvilleCity_PokemonCenter_1F_Text_28F071}, + {GAME_STAT_ENTERED_SAFARI_ZONE, 1, MauvilleCity_PokemonCenter_1F_Text_28F0F3, MauvilleCity_PokemonCenter_1F_Text_28F10D, MauvilleCity_PokemonCenter_1F_Text_28F125}, + {GAME_STAT_USED_CUT, 1, MauvilleCity_PokemonCenter_1F_Text_28F1BE, MauvilleCity_PokemonCenter_1F_Text_28F1D5, MauvilleCity_PokemonCenter_1F_Text_28F1DE}, + {GAME_STAT_USED_ROCK_SMASH, 1, MauvilleCity_PokemonCenter_1F_Text_28F24F, MauvilleCity_PokemonCenter_1F_Text_28F269, MauvilleCity_PokemonCenter_1F_Text_28F277}, + {GAME_STAT_MOVED_SECRET_BASE, 1, MauvilleCity_PokemonCenter_1F_Text_28F2FC, MauvilleCity_PokemonCenter_1F_Text_28F314, MauvilleCity_PokemonCenter_1F_Text_28F32A}, + {GAME_STAT_USED_SPLASH, 1, MauvilleCity_PokemonCenter_1F_Text_28F3AD, MauvilleCity_PokemonCenter_1F_Text_28F3C6, MauvilleCity_PokemonCenter_1F_Text_28F3D2}, + {GAME_STAT_USED_STRUGGLE, 1, MauvilleCity_PokemonCenter_1F_Text_28F44B, MauvilleCity_PokemonCenter_1F_Text_28F461, MauvilleCity_PokemonCenter_1F_Text_28F47C}, + {GAME_STAT_SLOT_JACKPOTS, 1, MauvilleCity_PokemonCenter_1F_Text_28F50C, MauvilleCity_PokemonCenter_1F_Text_28F51B, MauvilleCity_PokemonCenter_1F_Text_28F538}, + {GAME_STAT_CONSECUTIVE_ROULETTE_WINS, 2, MauvilleCity_PokemonCenter_1F_Text_28F5BE, MauvilleCity_PokemonCenter_1F_Text_28F5D1, MauvilleCity_PokemonCenter_1F_Text_28F5F2}, + {GAME_STAT_ENTERED_BATTLE_TOWER, 1, MauvilleCity_PokemonCenter_1F_Text_28F678, MauvilleCity_PokemonCenter_1F_Text_28F694, MauvilleCity_PokemonCenter_1F_Text_28F6B4}, + {GAME_STAT_POKEBLOCKS, 1, MauvilleCity_PokemonCenter_1F_Text_28F751, MauvilleCity_PokemonCenter_1F_Text_28F76A, MauvilleCity_PokemonCenter_1F_Text_28F776}, + {GAME_STAT_ENTERED_CONTEST, 1, MauvilleCity_PokemonCenter_1F_Text_28F7F6, MauvilleCity_PokemonCenter_1F_Text_28F811, MauvilleCity_PokemonCenter_1F_Text_28F822}, + {GAME_STAT_WON_CONTEST, 1, MauvilleCity_PokemonCenter_1F_Text_28F89C, MauvilleCity_PokemonCenter_1F_Text_28F8AF, MauvilleCity_PokemonCenter_1F_Text_28F8BC}, + {GAME_STAT_SHOPPED, 1, MauvilleCity_PokemonCenter_1F_Text_28F92F, MauvilleCity_PokemonCenter_1F_Text_28F941, MauvilleCity_PokemonCenter_1F_Text_28F949}, + {GAME_STAT_USED_ITEMFINDER, 1, MauvilleCity_PokemonCenter_1F_Text_28F9D1, MauvilleCity_PokemonCenter_1F_Text_28F9EA, MauvilleCity_PokemonCenter_1F_Text_28F9FD}, + {GAME_STAT_GOT_RAINED_ON, 1, MauvilleCity_PokemonCenter_1F_Text_28FA81, MauvilleCity_PokemonCenter_1F_Text_28FA99, MauvilleCity_PokemonCenter_1F_Text_28FAA7}, + {GAME_STAT_CHECKED_POKEDEX, 1, MauvilleCity_PokemonCenter_1F_Text_28FB1D, MauvilleCity_PokemonCenter_1F_Text_28FB35, MauvilleCity_PokemonCenter_1F_Text_28FB47}, + {GAME_STAT_RECEIVED_RIBBONS, 1, MauvilleCity_PokemonCenter_1F_Text_28FBC4, MauvilleCity_PokemonCenter_1F_Text_28FBD9, MauvilleCity_PokemonCenter_1F_Text_28FBEA}, + {GAME_STAT_JUMPED_DOWN_LEDGES, 1, MauvilleCity_PokemonCenter_1F_Text_28FC6B, MauvilleCity_PokemonCenter_1F_Text_28FC85, MauvilleCity_PokemonCenter_1F_Text_28FC98}, + {GAME_STAT_WATCHED_TV, 1, MauvilleCity_PokemonCenter_1F_Text_28FD1D, MauvilleCity_PokemonCenter_1F_Text_28FD35, MauvilleCity_PokemonCenter_1F_Text_28FD40}, + {GAME_STAT_CHECKED_CLOCK, 1, MauvilleCity_PokemonCenter_1F_Text_28FDA2, MauvilleCity_PokemonCenter_1F_Text_28FDBD, MauvilleCity_PokemonCenter_1F_Text_28FDCE}, + {GAME_STAT_WON_POKEMON_LOTTERY, 1, MauvilleCity_PokemonCenter_1F_Text_28FE57, MauvilleCity_PokemonCenter_1F_Text_28FE72, MauvilleCity_PokemonCenter_1F_Text_28FE88}, + {GAME_STAT_USED_DAYCARE, 1, MauvilleCity_PokemonCenter_1F_Text_28FF0C, MauvilleCity_PokemonCenter_1F_Text_28FF27, MauvilleCity_PokemonCenter_1F_Text_28FF44}, + {GAME_STAT_RODE_CABLE_CAR, 1, MauvilleCity_PokemonCenter_1F_Text_28FFDD, MauvilleCity_PokemonCenter_1F_Text_28FFFA, MauvilleCity_PokemonCenter_1F_Text_29000D}, + {GAME_STAT_ENTERED_HOT_SPRINGS, 1, MauvilleCity_PokemonCenter_1F_Text_290097, MauvilleCity_PokemonCenter_1F_Text_2900B5, MauvilleCity_PokemonCenter_1F_Text_2900CB} +}; + +static void StorytellerSetup(void) +{ + s32 i; + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + + sStorytellerPtr->id = MAUVILLE_MAN_STORYTELLER; + sStorytellerPtr->alreadyRecorded = FALSE; + for (i = 0; i < 4; i++) + { + sStorytellerPtr->gameStatIDs[i] = 0; + sStorytellerPtr->trainerNames[0][i] = EOS; // Maybe they meant storyteller->trainerNames[i][0] instead? + } +} + +static void Storyteller_ResetFlag(void) +{ + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + + sStorytellerPtr->id = MAUVILLE_MAN_STORYTELLER; + sStorytellerPtr->alreadyRecorded = FALSE; +} + +static u32 StorytellerGetGameStat(u8 stat) +{ + if (stat == 50) + stat = 0; + return GetGameStat(stat); +} + +static const struct Story *GetStoryByStat(u32 stat) +{ + s32 i; + + for (i = 0; i < 36; i++) + { + if (sStorytellerStories[i].stat == stat) + return &sStorytellerStories[i]; + } + return &sStorytellerStories[35]; +} + +static const u8 *GetStoryTitleByStat(u32 stat) +{ + return GetStoryByStat(stat)->title; +} + +static const u8 *GetStoryTextByStat(u32 stat) +{ + return GetStoryByStat(stat)->fullText; +} + +static const u8 *GetStoryActionByStat(u32 stat) +{ + return GetStoryByStat(stat)->action; +} + +static u8 GetFreeStorySlot(void) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + if (sStorytellerPtr->gameStatIDs[i] == 0) + break; + } + return i; +} + +static u32 StorytellerGetRecordedTrainerStat(u32 trainer) +{ + u8 *ptr = sStorytellerPtr->statValues[trainer]; + + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static void StorytellerSetRecordedTrainerStat(u32 trainer, u32 val) +{ + u8 *ptr = sStorytellerPtr->statValues[trainer]; + + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; +} + +static bool32 HasTrainerStatIncreased(u32 trainer) +{ + if (StorytellerGetGameStat(sStorytellerPtr->gameStatIDs[trainer]) > StorytellerGetRecordedTrainerStat(trainer)) + return TRUE; + else + return FALSE; +} + +static void GetStoryByStattellerPlayerName(u32 player, void *dst) +{ + u8 *name = sStorytellerPtr->trainerNames[player]; + + memset(dst, EOS, 8); + memcpy(dst, name, 7); +} + +static void StorytellerSetPlayerName(u32 player, const u8 * src) +{ + u8 * name = sStorytellerPtr->trainerNames[player]; + memset(name, EOS, 7); + memcpy(name, src, 7); +} + + +static void StorytellerRecordNewStat(u32 player, u32 stat) +{ + sStorytellerPtr->gameStatIDs[player] = stat; + StorytellerSetPlayerName(player, gSaveBlock2Ptr->playerName); + StorytellerSetRecordedTrainerStat(player, StorytellerGetGameStat(stat)); + ConvertIntToDecimalStringN(gStringVar1, StorytellerGetGameStat(stat), STR_CONV_MODE_LEFT_ALIGN, 10); + StringCopy(gStringVar2, GetStoryActionByStat(stat)); + sStorytellerPtr->language[player] = gGameLanguage; +} + +static void ScrambleStatList(u8 * arr, s32 count) +{ + s32 i; + + for (i = 0; i < count; i++) + arr[i] = i; + for (i = 0; i < count; i++) + { + u32 a = Random() % count; + u32 b = Random() % count; + u8 temp = arr[a]; + arr[a] = arr[b]; + arr[b] = temp; + } +} + +struct UnknownStruct_0859F288 +{ + s32 length; + u32 unused2; +}; + +static const struct UnknownStruct_0859F288 sStorytellerStuff = { + ARRAY_COUNT(sStorytellerStories), + sizeof(sStorytellerStuff) +}; + +static bool8 StorytellerInitializeRandomStat(void) +{ + u8 arr[sStorytellerStuff.length]; + s32 i; + s32 j; + + ScrambleStatList(arr, ARRAY_COUNT(sStorytellerStories)); + for (i = 0; i < (s32)ARRAY_COUNT(sStorytellerStories); i++) + { + u8 stat = sStorytellerStories[arr[i]].stat; + u8 minVal = sStorytellerStories[arr[i]].minVal; + + for (j = 0; j < 4; j++) + { + if (sStorytellerPtr->gameStatIDs[j] == stat) + break; + } + if (j == 4 && StorytellerGetGameStat(stat) >= minVal) + { + sStorytellerPtr->alreadyRecorded = TRUE; + if (GetFreeStorySlot() == 4) + StorytellerRecordNewStat(sSelectedStory, stat); + else + StorytellerRecordNewStat(GetFreeStorySlot(), stat); + return TRUE; + } + } + return FALSE; +} + +static void StorytellerDisplayStory(u32 player) +{ + u8 stat = sStorytellerPtr->gameStatIDs[player]; + + ConvertIntToDecimalStringN(gStringVar1, StorytellerGetRecordedTrainerStat(player), 0, 10); + StringCopy(gStringVar2, GetStoryActionByStat(stat)); + GetStoryByStattellerPlayerName(player, gStringVar3); + ConvertInternationalString(gStringVar3, sStorytellerPtr->language[player]); + ShowFieldMessage(GetStoryTextByStat(stat)); +} + +static void PrintStoryList(void) +{ + s32 i; + s32 width = GetStringWidth(1, gText_Exit, 0); + u8 tileWidth; + for (i = 0; i < 4; i++) + { + s32 curWidth; + u16 gameStatID = sStorytellerPtr->gameStatIDs[i]; + + if (gameStatID == 0) + break; + curWidth = GetStringWidth(1, GetStoryTitleByStat(gameStatID), 0); + if (curWidth > width) + width = curWidth; + } + sStorytellerWindowId = CreateWindowFromRect(0, 0, convert_pixel_width_to_tile_width(width), GetFreeStorySlot() * 2 + 2); + SetStandardWindowBorderStyle(sStorytellerWindowId, 0); + for (i = 0; i < 4; i++) + { + u16 gameStatID = sStorytellerPtr->gameStatIDs[i]; + if (gameStatID == 0) + break; + PrintTextOnWindow(sStorytellerWindowId, 1, GetStoryTitleByStat(gameStatID), 8, 16 * i + 1, 0xFF, NULL); + } + PrintTextOnWindow(sStorytellerWindowId, 1, gText_Exit, 8, 16 * i + 1, 0xFF, NULL); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(sStorytellerWindowId, GetFreeStorySlot() + 1, 0); + CopyWindowToVram(sStorytellerWindowId, 3); +} + +static void Task_StoryListMenu(u8 taskId) // Task_StoryListMenu +{ + struct Task *task = &gTasks[taskId]; + s32 selection; + + switch (task->data[0]) + { + case 0: + PrintStoryList(); + task->data[0]++; + break; + case 1: + selection = ProcessMenuInput(); + if (selection == -2) + break; + if (selection == -1 || selection == GetFreeStorySlot()) + { + gSpecialVar_Result = 0; + } + else + { + gSpecialVar_Result = 1; + sSelectedStory = selection; + } + sub_80E2A78(sStorytellerWindowId); + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } +} + +// Sets gSpecialVar_Result to TRUE if player selected a story +void ScrSpecial_StorytellerStoryListMenu(void) +{ + CreateTask(Task_StoryListMenu, 80); +} + +void ScrSpecial_StorytellerDisplayStory(void) +{ + StorytellerDisplayStory(sSelectedStory); +} + +u8 ScrSpecial_StorytellerGetFreeStorySlot(void) +{ + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + return GetFreeStorySlot(); +} + +// Returns TRUE if stat has increased +bool8 ScrSpecial_StorytellerUpdateStat(void) +{ + u8 r4; + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + r4 = sStorytellerPtr->gameStatIDs[sSelectedStory]; + + if (HasTrainerStatIncreased(sSelectedStory) == TRUE) + { + StorytellerRecordNewStat(sSelectedStory, r4); + return TRUE; + } + return FALSE; +} + +bool8 ScrSpecial_HasStorytellerAlreadyRecorded(void) +{ + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + + if (sStorytellerPtr->alreadyRecorded == FALSE) + return FALSE; + else + return TRUE; +} + +bool8 ScrSpecial_StorytellerInitializeRandomStat(void) +{ + sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; + return StorytellerInitializeRandomStat(); +} + diff --git a/src/menu.c b/src/menu.c index d06f950d3..dedfcc3be 100644 --- a/src/menu.c +++ b/src/menu.c @@ -25,11 +25,11 @@ #define STD_WINDOW_PALETTE_NUM 14 #define STD_WINDOW_BASE_TILE_NUM 0x214 -struct SomeUnkStruct_60F0D4 +struct MoveMenuInfoIcon { - u8 unk1; - u8 unk2; - u16 unk3; + u8 width; + u8 height; + u16 offset; }; struct Menu @@ -48,7 +48,7 @@ struct Menu bool8 APressMuted; }; -static EWRAM_DATA u8 gUnknown_0203CD8C = 0; +static EWRAM_DATA u8 gStartMenuWindowId = 0; static EWRAM_DATA u8 gUnknown_0203CD8D = 0; static EWRAM_DATA struct Menu gUnknown_0203CD90 = {0}; static EWRAM_DATA u16 gUnknown_0203CD9C = 0; @@ -63,7 +63,7 @@ static EWRAM_DATA void *gUnknown_0203CDAC[0x20] = {NULL}; const u16 gUnknown_0860F074[] = INCBIN_U16("graphics/interface/860F074.gbapal"); static const u8 gUnknown_0860F094[] = { 8, 4, 1 }; -static const struct WindowTemplate gUnknown_0860F098[] = +static const struct WindowTemplate gUnknown_0860F098[] = { { 0x00, 0x02, 0x0F, 0x1B, 0x04, 0x0F, 0x194 }, DUMMY_WIN_TEMPLATE @@ -76,34 +76,36 @@ static const struct WindowTemplate gUnknown_0860F0A8 = const u16 gUnknown_0860F0B0[] = INCBIN_U16("graphics/interface/860F0B0.gbapal"); const u8 gUnknown_0860F0D0[] = { 15, 1, 2 }; -const struct SomeUnkStruct_60F0D4 gUnknown_0860F0D4[] = -{ - { 12, 12, 0x00 }, - { 32, 12, 0x20 }, - { 32, 12, 0x64 }, - { 32, 12, 0x60 }, - { 32, 12, 0x80 }, - { 32, 12, 0x48 }, - { 32, 12, 0x44 }, - { 32, 12, 0x6C }, - { 32, 12, 0x68 }, - { 32, 12, 0x88 }, - { 32, 12, 0xA4 }, - { 32, 12, 0x24 }, - { 32, 12, 0x28 }, - { 32, 12, 0x2C }, - { 32, 12, 0x40 }, - { 32, 12, 0x84 }, - { 32, 12, 0x4C }, - { 32, 12, 0xA0 }, - { 32, 12, 0x8C }, - { 42, 12, 0xA8 }, - { 42, 12, 0xC0 }, - { 42, 12, 0xC8 }, - { 42, 12, 0xE0 }, - { 42, 12, 0xE8 }, - { 8, 8, 0xAE }, - { 8, 8, 0xAF }, + +// Table of move info icon offsets in graphics/interface_fr/menu.png +const struct MoveMenuInfoIcon gMoveMenuInfoIcons[] = +{ // { width, height, offset } + { 12, 12, 0x00 }, // Unused + { 32, 12, 0x20 }, // Normal icon + { 32, 12, 0x64 }, // Fight icon + { 32, 12, 0x60 }, // Flying icon + { 32, 12, 0x80 }, // Poison icon + { 32, 12, 0x48 }, // Ground icon + { 32, 12, 0x44 }, // Rock icon + { 32, 12, 0x6C }, // Bug icon + { 32, 12, 0x68 }, // Ghost icon + { 32, 12, 0x88 }, // Steel icon + { 32, 12, 0xA4 }, // ??? (Mystery) icon + { 32, 12, 0x24 }, // Fire icon + { 32, 12, 0x28 }, // Water icon + { 32, 12, 0x2C }, // Grass icon + { 32, 12, 0x40 }, // Electric icon + { 32, 12, 0x84 }, // Psychic icon + { 32, 12, 0x4C }, // Ice icon + { 32, 12, 0xA0 }, // Dragon icon + { 32, 12, 0x8C }, // Dark icon + { 42, 12, 0xA8 }, // -Type- icon + { 42, 12, 0xC0 }, // -Power- icon + { 42, 12, 0xC8 }, // -Accuracy- icon + { 42, 12, 0xE0 }, // -PP- icon + { 42, 12, 0xE8 }, // -Effect- icon + { 8, 8, 0xAE }, // Unused (Small white pokeball) + { 8, 8, 0xAF }, // Unused (Small dark pokeball) }; // Forward declarations @@ -125,7 +127,7 @@ extern void task_free_buf_after_copying_tile_data_to_vram(u8 taskId); void sub_81971D0(void) { InitWindows(gUnknown_0860F098); - gUnknown_0203CD8C = 0xFF; + gStartMenuWindowId = 0xFF; gUnknown_0203CD8D = 0xFF; } @@ -151,7 +153,7 @@ u16 sub_8197224(void) u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 speed, void (*callback)(struct TextSubPrinter *, u16), u8 fgColor, u8 bgColor, u8 shadowColor) { struct TextSubPrinter printer; - + printer.current_text_offset = str; printer.windowId = windowId; printer.fontId = fontId; @@ -165,9 +167,9 @@ u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 speed, printer.fgColor = fgColor; printer.bgColor = bgColor; printer.shadowColor = shadowColor; - + gTextFlags.flag_1 = 0; - return AddTextPrinter(&printer, speed, callback); + return AddTextPrinter(&printer, speed, callback); } void AddTextPrinterForMessage(bool8 allowSkippingDelayWithButtonPress) @@ -234,7 +236,7 @@ void sub_819746C(u8 windowId, bool8 copyToVram) void DrawStandardFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 paletteNum) { int i; - + FillBgTilemapBufferRect(bg, STD_WINDOW_BASE_TILE_NUM + 0, tilemapLeft - 1, @@ -256,7 +258,7 @@ void DrawStandardFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height 1, 1, STD_WINDOW_PALETTE_NUM); - + for (i = tilemapTop; i < tilemapTop + height; i++) { FillBgTilemapBufferRect(bg, @@ -274,7 +276,7 @@ void DrawStandardFrame(u8 bg, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height 1, STD_WINDOW_PALETTE_NUM); } - + FillBgTilemapBufferRect(bg, STD_WINDOW_BASE_TILE_NUM + 6, tilemapLeft - 1, @@ -471,22 +473,22 @@ u8 GetPlayerTextSpeed(void) u8 sub_81979C4(u8 a1) { - if (gUnknown_0203CD8C == 0xFF) - gUnknown_0203CD8C = sub_8198AA4(0, 0x16, 1, 7, (a1 * 2) + 2, 0xF, 0x139); - return gUnknown_0203CD8C; + if (gStartMenuWindowId == 0xFF) + gStartMenuWindowId = sub_8198AA4(0, 0x16, 1, 7, (a1 * 2) + 2, 0xF, 0x139); + return gStartMenuWindowId; } u8 GetStartMenuWindowId(void) { - return gUnknown_0203CD8C; + return gStartMenuWindowId; } -void remove_start_menu_window_maybe(void) +void RemoveStartMenuWindow(void) { - if (gUnknown_0203CD8C != 0xFF) + if (gStartMenuWindowId != 0xFF) { - RemoveWindow(gUnknown_0203CD8C); - gUnknown_0203CD8C = 0xFF; + RemoveWindow(gStartMenuWindowId); + gStartMenuWindowId = 0xFF; } } @@ -1941,7 +1943,7 @@ void box_print(u8 windowId, u8 fontId, u8 left, u8 top, const u8 *color, s8 spee printer.fgColor = color[1]; printer.bgColor = color[0]; printer.shadowColor = color[2]; - + AddTextPrinter(&printer, speed, NULL); } @@ -1962,7 +1964,7 @@ void AddTextPrinterParameterized2(u8 windowId, u8 fontId, u8 left, u8 top, u8 le printer.fgColor = color[1]; printer.bgColor = color[0]; printer.shadowColor = color[2]; - + AddTextPrinter(&printer, speed, NULL); } @@ -1988,7 +1990,7 @@ void sub_8199F74(u8 windowId, u8 fontId, const u8 *str, u8 left, u8 top, u8 spee AddTextPrinter(&printer, speed, callback); } -void sub_819A024(u8 windowId, const u8 *src, u16 a2, u16 a3) +void PrintPlayerNameOnWindow(u8 windowId, const u8 *src, u16 x, u16 y) { int count = 0; while (gSaveBlock2Ptr->playerName[count] != EOS) @@ -1996,7 +1998,7 @@ void sub_819A024(u8 windowId, const u8 *src, u16 a2, u16 a3) StringExpandPlaceholders(gStringVar4, src); - PrintTextOnWindow(windowId, 1, gStringVar4, a2, a3, 0xFF, 0); + PrintTextOnWindow(windowId, 1, gStringVar4, x, y, 0xFF, 0); } //Screw this function, it's long and unreferenced and ugh @@ -2078,7 +2080,7 @@ void sub_819A080(struct UnkStruct_819A080 *a0, struct UnkStruct_819A080 *a1, u16 } } #else -__attribute__((naked)) +NAKED void sub_819A080(struct UnkStruct_819A080 *a0, struct UnkStruct_819A080 *a1, u16 a2, u16 a3, u16 a4, u16 a5, u16 a6, u16 a7) { asm("push {r4-r7,lr}\n\ @@ -2364,23 +2366,23 @@ void sub_819A2BC(u8 palOffset, u8 palId) void blit_move_info_icon(u8 windowId, u8 iconId, u16 x, u16 y) { - BlitBitmapRectToWindow(windowId, gFireRedMenuElements_Gfx + gUnknown_0860F0D4[iconId].unk3 * 32, 0, 0, 128, 128, x, y, gUnknown_0860F0D4[iconId].unk1, gUnknown_0860F0D4[iconId].unk2); + BlitBitmapRectToWindow(windowId, gFireRedMenuElements_Gfx + gMoveMenuInfoIcons[iconId].offset * 32, 0, 0, 128, 128, x, y, gMoveMenuInfoIcons[iconId].width, gMoveMenuInfoIcons[iconId].height); } -void sub_819A344(u8 a0, u8 *a1, u8 a2) +void sub_819A344(u8 a0, u8 *dest, u8 color) { s32 curFlag; s32 flagCount; u8 *endOfString; - u8 *string = a1; - + u8 *string = dest; + *(string++) = EXT_CTRL_CODE_BEGIN; *(string++) = EXT_CTRL_CODE_COLOR; - *(string++) = a2; + *(string++) = color; *(string++) = EXT_CTRL_CODE_BEGIN; *(string++) = EXT_CTRL_CODE_SHADOW; - *(string++) = a2 + 1; - + *(string++) = color + 1; + switch (a0) { case 0: @@ -2388,9 +2390,9 @@ void sub_819A344(u8 a0, u8 *a1, u8 a2) break; case 1: if (IsNationalPokedexEnabled()) - string = ConvertIntToDecimalStringN(string, pokedex_count(1), 0, 3); + string = ConvertIntToDecimalStringN(string, GetNationalPokedexCount(1), 0, 3); else - string = ConvertIntToDecimalStringN(string, sub_80C0844(1), 0, 3); + string = ConvertIntToDecimalStringN(string, GetHoennPokedexCount(1), 0, 3); *string = EOS; break; case 2: diff --git a/src/menu_helpers.c b/src/menu_helpers.c new file mode 100644 index 000000000..178fbb5fa --- /dev/null +++ b/src/menu_helpers.c @@ -0,0 +1,455 @@ +#include "global.h" +#include "task.h" +#include "window.h" +#include "menu.h" +#include "menu_helpers.h" +#include "gpu_regs.h" +#include "bg.h" +#include "main.h" +#include "text.h" +#include "link.h" +#include "string_util.h" +#include "sound.h" +#include "mail.h" +#include "overworld.h" +#include "decompress.h" +#include "constants/songs.h" +#include "constants/items.h" +#include "constants/maps.h" + +extern bool32 sub_800B504(void); + +extern const u8 gBagSwapLineGfx[]; +extern const u8 gBagSwapLinePal[]; + +// this file's functions +static void Task_ContinueTaskAfterMessagePrints(u8 taskId); +static void Task_CallYesOrNoCallback(u8 taskId); + +// EWRAM vars +EWRAM_DATA static struct YesNoFuncTable gUnknown_0203A138 = {0}; +EWRAM_DATA static u8 gUnknown_0203A140 = 0; + +// IWRAM bss vars +IWRAM_DATA static TaskFunc gUnknown_0300117C; + +// const rom data +static const struct OamData sOamData_859F4E8 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0 +}; + +static const union AnimCmd sSpriteAnim_859F4F0[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_859F4F8[] = +{ + ANIMCMD_FRAME(4, 0), + ANIMCMD_END +}; + +static const union AnimCmd sSpriteAnim_859F500[] = +{ + ANIMCMD_FRAME(0, 0, 1, 0), + ANIMCMD_END +}; + +static const union AnimCmd *const sSpriteAnimTable_859F508[] = +{ + sSpriteAnim_859F4F0, + sSpriteAnim_859F4F8, + sSpriteAnim_859F500 +}; + +static const struct CompressedSpriteSheet gUnknown_0859F514 = +{ + gBagSwapLineGfx, 0x100, 109 +}; + +static const struct CompressedSpritePalette gUnknown_0859F51C = +{ + gBagSwapLinePal, 109 +}; + +static const struct SpriteTemplate gUnknown_0859F524 = +{ + .tileTag = 109, + .paletteTag = 109, + .oam = &sOamData_859F4E8, + .anims = sSpriteAnimTable_859F508, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +// code +void ResetVramOamAndBgCntRegs(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + CpuFill16(0, (void*) VRAM, VRAM_SIZE); + CpuFill32(0, (void*) OAM, OAM_SIZE); + CpuFill16(0, (void*) PLTT, PLTT_SIZE); +} + +void ResetAllBgsCoordinates(void) +{ + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); +} + +void SetVBlankHBlankCallbacksToNull(void) +{ + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +void DisplayMessageAndContinueTask(u8 taskId, u8 windowId, u16 arg2, u8 arg3, u8 fontId, u8 textSpeed, const u8 *string, void *taskFunc) +{ + gUnknown_0203A140 = windowId; + sub_8197B1C(windowId, TRUE, arg2, arg3); + + if (string != gStringVar4) + StringExpandPlaceholders(gStringVar4, string); + + gTextFlags.flag_0 = 1; + AddTextPrinterParameterized(windowId, fontId, gStringVar4, textSpeed, NULL, 2, 1, 3); + gUnknown_0300117C = taskFunc; + gTasks[taskId].func = Task_ContinueTaskAfterMessagePrints; +} + +bool16 RunTextPrintersRetIsActive(u8 textPrinterId) +{ + RunTextPrinters(); + return IsTextPrinterActive(textPrinterId); +} + +static void Task_ContinueTaskAfterMessagePrints(u8 taskId) +{ + if (!RunTextPrintersRetIsActive(gUnknown_0203A140)) + gUnknown_0300117C(taskId); +} + +void sub_8121F68(u8 taskId, const struct YesNoFuncTable *data) +{ + gUnknown_0203A138 = *data; + gTasks[taskId].func = Task_CallYesOrNoCallback; +} + +void CreateYesNoMenuWithCallbacks(u8 taskId, const struct WindowTemplate *template, u8 arg2, u8 arg3, u8 arg4, u16 tileStart, u8 palette, const struct YesNoFuncTable *yesNo) +{ + CreateYesNoMenu(template, tileStart, palette, 0); + gUnknown_0203A138 = *yesNo; + gTasks[taskId].func = Task_CallYesOrNoCallback; +} + +static void Task_CallYesOrNoCallback(u8 taskId) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: + PlaySE(SE_SELECT); + gUnknown_0203A138.yesFunc(taskId); + break; + case 1: + case MENU_B_PRESSED: + PlaySE(SE_SELECT); + gUnknown_0203A138.noFunc(taskId); + break; + } +} + +bool8 AdjustQuantityAccordingToDPadInput(s16 *arg0, u16 arg1) +{ + s16 valBefore = (*arg0); + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + (*arg0)++; + if ((*arg0) > arg1) + (*arg0) = 1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + (*arg0)--; + if ((*arg0) <= 0) + (*arg0) = arg1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_RIGHT) + { + (*arg0) += 10; + if ((*arg0) > arg1) + (*arg0) = arg1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_LEFT) + { + (*arg0) -= 10; + if ((*arg0) <= 0) + (*arg0) = 1; + + if ((*arg0) == valBefore) + { + return FALSE; + } + else + { + PlaySE(SE_SELECT); + return TRUE; + } + } + + return FALSE; +} + +u8 GetLRKeysState(void) +{ + if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newKeys & L_BUTTON) + return 1; + if (gMain.newKeys & R_BUTTON) + return 2; + } + + return 0; +} + +u8 sub_812210C(void) +{ + if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newAndRepeatedKeys & L_BUTTON) + return 1; + if (gMain.newAndRepeatedKeys & R_BUTTON) + return 2; + } + + return 0; +} + +bool8 sub_8122148(u16 itemId) +{ + if (itemId != ITEM_ENIGMA_BERRY) + return TRUE; + else if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(TRADE_CENTER) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(TRADE_CENTER)) + return FALSE; + else if (InUnionRoom() != TRUE) + return TRUE; + else + return FALSE; +} + +bool8 itemid_80BF6D8_mail_related(u16 itemId) +{ + if (is_c1_link_related_active() != TRUE && InUnionRoom() != TRUE) + return TRUE; + else if (ItemIsMail(itemId) != TRUE) + return TRUE; + else + return FALSE; +} + +bool8 sub_81221AC(void) +{ + if (is_c1_link_related_active() == TRUE || gReceivedRemoteLinkPlayers == 1) + return TRUE; + else + return FALSE; +} + +static bool8 sub_81221D0(void) +{ + if (!sub_81221AC()) + return FALSE; + else + return sub_8087598(); +} + +bool8 sub_81221EC(void) +{ + if (sub_81221D0() == TRUE) + return TRUE; + else if (sub_800B504() != TRUE) + return FALSE; + else + return TRUE; +} + +void sub_812220C(struct ItemSlot *slots, u8 count, u8 *arg2, u8 *usedSlotsCount, u8 maxUsedSlotsCount) +{ + u16 i; + struct ItemSlot *slots_ = slots; + + (*usedSlotsCount) = 0; + for (i = 0; i < count; i++) + { + if (slots_[i].itemId != ITEM_NONE) + (*usedSlotsCount)++; + } + + (*usedSlotsCount)++; + if ((*usedSlotsCount) > maxUsedSlotsCount) + *arg2 = maxUsedSlotsCount; + else + *arg2 = (*usedSlotsCount); +} + +void sub_812225C(u16 *arg0, u16 *arg1, u8 arg2, u8 arg3) +{ + if ((*arg0) != 0 && (*arg0) + arg2 > arg3) + (*arg0) = arg3 - arg2; + + if ((*arg0) + (*arg1) >= arg3) + { + if (arg3 == 0) + (*arg1) = 0; + else + (*arg1) = arg3 - 1; + } +} + +void sub_8122298(u16 *arg0, u16 *arg1, u8 arg2, u8 arg3, u8 arg4) +{ + u8 i; + + if (arg4 % 2 != 0) + { + if ((*arg1) >= arg4 / 2) + { + for (i = 0; i < (*arg1) - (arg4 / 2); i++) + { + if ((*arg0) + arg2 == arg3) + break; + (*arg1)--; + (*arg0)++; + } + } + } + else + { + if ((*arg1) >= (arg4 / 2) + 1) + { + for (i = 0; i <= (*arg1) - (arg4 / 2); i++) + { + if ((*arg0) + arg2 == arg3) + break; + (*arg1)--; + (*arg0)++; + } + } + } +} + +void LoadListMenuArrowsGfx(void) +{ + LoadCompressedObjectPic(&gUnknown_0859F514); + LoadCompressedObjectPalette(&gUnknown_0859F51C); +} + +void sub_8122344(u8 *spriteIds, u8 count) +{ + u8 i; + + for (i = 0; i < count; i++) + { + spriteIds[i] = CreateSprite(&gUnknown_0859F524, i * 16, 0, 0); + if (i != 0) + StartSpriteAnim(&gSprites[spriteIds[i]], 1); + + gSprites[spriteIds[i]].invisible = 1; + } +} + +void sub_81223B0(u8 *spriteIds, u8 count) +{ + u8 i; + + for (i = 0; i < count; i++) + { + if (i == count - 1) + DestroySpriteAndFreeResources(&gSprites[spriteIds[i]]); + else + DestroySprite(&gSprites[spriteIds[i]]); + } +} + +void sub_81223FC(u8 *spriteIds, u8 count, bool8 invisible) +{ + u8 i; + + for (i = 0; i < count; i++) + { + gSprites[spriteIds[i]].invisible = invisible; + } +} + +void sub_8122448(u8 *spriteIds, u8 count, s16 x, u16 y) +{ + u8 i; + bool8 unknownBit = count & 0x80; + count &= ~(0x80); + + for (i = 0; i < count; i++) + { + if (i == count - 1 && unknownBit) + gSprites[spriteIds[i]].pos2.x = x - 8; + else + gSprites[spriteIds[i]].pos2.x = x; + + gSprites[spriteIds[i]].pos1.y = 1 + y; + } +} diff --git a/src/mon_markings.c b/src/mon_markings.c new file mode 100644 index 000000000..147872ab6 --- /dev/null +++ b/src/mon_markings.c @@ -0,0 +1,611 @@ +#include "global.h" +#include "dma3.h" +#include "graphics.h" +#include "main.h" +#include "menu_indicators.h" +#include "mon_markings.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" +#include "text_window.h" + +#define MENU_TEXT_SPRITE_X_OFFSET 32 + +// static functions +static void sub_811FC80(s16, s16, u16, u16); +static void TaskDummy7(struct Sprite *); +static void sub_811FF40(struct Sprite *); +static void sub_811FF7C(struct Sprite *); +static struct Sprite *sub_811FFD4(u16, u16, const u16 *, u16); + +// .rodata +static const u16 gUnknown_0859E65C[] = INCBIN_U16("graphics/misc/mon_markings.gbapal"); +static const u8 gUnknown_0859E67C[] = INCBIN_U8("graphics/misc/mon_markings.4bpp"); + +static const struct OamData gUnknown_0859EE7C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct OamData gUnknown_0859EE84 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EE8C[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE94[] = +{ + ANIMCMD_FRAME(1, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE9C[] = +{ + ANIMCMD_FRAME(2, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEA4[] = +{ + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEAC[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEB4[] = +{ + ANIMCMD_FRAME(5, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEBC[] = +{ + ANIMCMD_FRAME(6, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEC4[] = +{ + ANIMCMD_FRAME(7, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EECC[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EED4[] = +{ + ANIMCMD_FRAME(9, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EEDC[] = +{ + gUnknown_0859EE8C, + gUnknown_0859EE94, + gUnknown_0859EE9C, + gUnknown_0859EEA4, + gUnknown_0859EEAC, + gUnknown_0859EEB4, + gUnknown_0859EEBC, + gUnknown_0859EEC4, + gUnknown_0859EECC, + gUnknown_0859EED4, +}; + +static const union AnimCmd gUnknown_0859EF04[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF0C[] = +{ + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EF14[] = +{ + gUnknown_0859EF04, + gUnknown_0859EF0C, +}; + +static const struct OamData gUnknown_0859EF1C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 1, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EF24[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF2C[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF34[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF3C[] = +{ + ANIMCMD_FRAME(12, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF44[] = +{ + ANIMCMD_FRAME(16, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF4C[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF54[] = +{ + ANIMCMD_FRAME(24, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF5C[] = +{ + ANIMCMD_FRAME(28, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF64[] = +{ + ANIMCMD_FRAME(32, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF6C[] = +{ + ANIMCMD_FRAME(36, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF74[] = +{ + ANIMCMD_FRAME(40, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF7C[] = +{ + ANIMCMD_FRAME(44, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF84[] = +{ + ANIMCMD_FRAME(48, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF8C[] = +{ + ANIMCMD_FRAME(52, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF94[] = +{ + ANIMCMD_FRAME(56, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF9C[] = +{ + ANIMCMD_FRAME(60, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EFA4[] = +{ + gUnknown_0859EF24, + gUnknown_0859EF2C, + gUnknown_0859EF34, + gUnknown_0859EF3C, + gUnknown_0859EF44, + gUnknown_0859EF4C, + gUnknown_0859EF54, + gUnknown_0859EF5C, + gUnknown_0859EF64, + gUnknown_0859EF6C, + gUnknown_0859EF74, + gUnknown_0859EF7C, + gUnknown_0859EF84, + gUnknown_0859EF8C, + gUnknown_0859EF94, + gUnknown_0859EF9C, +}; + +static EWRAM_DATA struct PokemonMarkMenu *sMenu = NULL; + +void sub_811F90C(struct PokemonMarkMenu *ptr) +{ + sMenu = ptr; +} + +void sub_811F918(void) +{ + const struct TilesPal *frame = GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType); + sMenu->frameTiles = frame->tiles; + sMenu->framePalette = frame->pal; + sMenu->tileLoadState = 0; + CpuFill16(0, sMenu->menuWindowSpriteTiles, sizeof(sMenu->menuWindowSpriteTiles)); +} + +bool8 sub_811F960(void) +{ + u16 i; + u8 *dest = sMenu->menuWindowSpriteTiles + sMenu->tileLoadState * 0x100; + + switch (sMenu->tileLoadState) + { + case 0: + CpuFastCopy(sMenu->frameTiles, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 2, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + default: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 3, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 4, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 5, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + case 13: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 6, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 7, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 8, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + return FALSE; + case 14: + return FALSE; + } + + return TRUE; +} + +void sub_811FA90(void) +{ + sub_811F918(); + while (sub_811F960()); +} + +void sub_811FAA4(u8 markings, s16 x, s16 y) +{ + u16 i; + sMenu->cursorPos = 0; + sMenu->markings = markings; + for (i = 0; i < 4; i++) + sMenu->markingsArray[i] = (sMenu->markings >> i) & 1; + sub_811FC80(x, y, sMenu->baseTileTag, sMenu->basePaletteTag); +} + +void sub_811FAF8(void) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + FreeSpriteTilesByTag(sMenu->baseTileTag + i); + FreeSpritePaletteByTag(sMenu->basePaletteTag + i); + } + for (i = 0; i < 2; i++) + { + if (!sMenu->menuWindowSprites[i]) + return; + DestroySprite(sMenu->menuWindowSprites[i]); + sMenu->menuWindowSprites[i] = NULL; + } + for (i = 0; i < 4; i++) + { + if (!sMenu->menuMarkingSprites[i]) + return; + DestroySprite(sMenu->menuMarkingSprites[i]); + sMenu->menuMarkingSprites[i] = NULL; + } + if (sMenu->unkSprite) + { + DestroySprite(sMenu->unkSprite); + sMenu->unkSprite = NULL; + } + if (sMenu->menuTextSprite) + { + DestroySprite(sMenu->menuTextSprite); + sMenu->menuTextSprite = NULL; + } +} + + +bool8 sub_811FBA4(void) +{ + u16 i; + + if (gMain.newKeys & DPAD_UP) + { + s8 pos; + PlaySE(SE_SELECT); + pos = --sMenu->cursorPos; + if (pos < 0) + sMenu->cursorPos = 5; + return TRUE; + } + + if (gMain.newKeys & DPAD_DOWN) + { + s8 pos; + PlaySE(SE_SELECT); + pos = ++sMenu->cursorPos; + if (pos > 5) + sMenu->cursorPos = 0; + return TRUE; + } + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + + switch (sMenu->cursorPos) + { + case 4: + sMenu->markings = 0; + for (i = 0; i < 4; i++) + sMenu->markings |= sMenu->markingsArray[i] << i; + return FALSE; + case 5: + return FALSE; + } + + sMenu->markingsArray[sMenu->cursorPos] = !sMenu->markingsArray[sMenu->cursorPos]; + return TRUE; + } + + if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + return FALSE; + } + + return TRUE; +} + +static void sub_811FC80(s16 x, s16 y, u16 baseTileTag, u16 basePaletteTag) +{ + u16 i; + u8 spriteId; + + struct SpriteSheet sheets[] = + { + { sMenu->menuWindowSpriteTiles, 0x1000, baseTileTag }, + { gPokenavConditionMarker_Gfx, 0x320, baseTileTag + 1 }, + { NULL, 0 } + }; + + struct SpritePalette palettes[] = + { + { sMenu->framePalette, basePaletteTag }, + { gPokenavConditionMarker_Pal, basePaletteTag + 1}, + { NULL, 0 } + }; + + struct SpriteTemplate sprTemplate = + { + baseTileTag, + basePaletteTag, + &gUnknown_0859EE7C, + gUnknown_0859EF14, + NULL, + gDummySpriteAffineAnimTable, + TaskDummy7, + }; + + LoadSpriteSheets(sheets); + LoadSpritePalettes(palettes); + + for (i = 0; i < 2; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 32, 1); + if (spriteId != 64) + { + sMenu->menuWindowSprites[i] = &gSprites[spriteId]; + StartSpriteAnim(&gSprites[spriteId], i); + } + else + { + sMenu->menuWindowSprites[i] = NULL; + return; + } + } + + sMenu->menuWindowSprites[1]->pos1.y = y + 96; + + sprTemplate.tileTag++; + sprTemplate.paletteTag++; + sprTemplate.anims = gUnknown_0859EEDC; + sprTemplate.callback = sub_811FF40; + sprTemplate.oam = &gUnknown_0859EE84; + + for (i = 0; i < 4; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 16 + 16 * i, 0); + if (spriteId != 64) + { + sMenu->menuMarkingSprites[i] = &gSprites[spriteId]; + gSprites[spriteId].data[0] = i; + } + else + { + sMenu->menuMarkingSprites[i] = NULL; + return; + } + } + + sprTemplate.callback = SpriteCallbackDummy; + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + + if (spriteId != 64) + { + sMenu->menuTextSprite = &gSprites[spriteId]; + sMenu->menuTextSprite->oam.shape = ST_OAM_SQUARE; + sMenu->menuTextSprite->oam.size = 2; + StartSpriteAnim(sMenu->menuTextSprite, 9); + sMenu->menuTextSprite->pos1.x = x + MENU_TEXT_SPRITE_X_OFFSET; + sMenu->menuTextSprite->pos1.y = y + 80; + CalcCenterToCornerVec(sMenu->menuTextSprite, 1, 2, 0); + } + else + { + sMenu->menuTextSprite = NULL; + } + + sprTemplate.callback = sub_811FF7C; + spriteId = CreateSprite(&sprTemplate, x + 12, 0, 0); + if(spriteId != 64) + { + sMenu->unkSprite = &gSprites[spriteId]; + sMenu->unkSprite->data[0] = y + 16; + StartSpriteAnim(sMenu->unkSprite, 8); + } + else + { + sMenu->unkSprite = NULL; + } + +} + +static void TaskDummy7(struct Sprite *sprite) +{ +} + +static void sub_811FF40(struct Sprite *sprite) +{ + if (sMenu->markingsArray[sprite->data[0]]) + StartSpriteAnim(sprite, 2 * sprite->data[0] + 1); + else + StartSpriteAnim(sprite, 2 * sprite->data[0]); +} + +static void sub_811FF7C(struct Sprite *sprite) +{ + sprite->pos1.y = (16 * sMenu->cursorPos) + sprite->data[0]; +} + +struct Sprite *sub_811FF94(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 16); +} + +struct Sprite *sub_811FFB4(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 1); +} + +static struct Sprite *sub_811FFD4(u16 tileTag, u16 paletteTag, const u16 *palette, u16 size) +{ + u8 spriteId; + struct SpriteTemplate sprTemplate; + struct SpriteSheet sheet = { gUnknown_0859E67C, 0x80, tileTag }; + struct SpritePalette sprPalette = { palette, paletteTag }; + + sprTemplate.tileTag = tileTag; + sprTemplate.paletteTag = paletteTag; + sprTemplate.oam = &gUnknown_0859EF1C; + sprTemplate.anims = gUnknown_0859EFA4; + sprTemplate.images = NULL; + sprTemplate.affineAnims = gDummySpriteAffineAnimTable; + sprTemplate.callback = TaskDummy7; + + sheet.size = size * 0x80; + + LoadSpriteSheet(&sheet); + LoadSpritePalette(&sprPalette); + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + if (spriteId != 64) + return &gSprites[spriteId]; + else + return NULL; +} + +void sub_8120084(u8 markings, void *dest) +{ + RequestDma3Copy(gUnknown_0859E67C + markings * 0x80, dest, 0x80, 0x10); +} diff --git a/src/mystery_event_menu.c b/src/mystery_event_menu.c index 31b366ae9..8a7671c5b 100644 --- a/src/mystery_event_menu.c +++ b/src/mystery_event_menu.c @@ -189,7 +189,7 @@ static void CB2_MysteryEventMenu(void) { if (gReceivedRemoteLinkPlayers != 0) { - if (sub_800A0C8(2, 2) == 3) + if (GetLinkPlayerDataExchangeStatusTimed(2, 2) == 3) { sub_800AC34(); GetEventLoadMessage(gStringVar4, 1); @@ -241,7 +241,7 @@ static void CB2_MysteryEventMenu(void) u16 unkVal = RunMysteryEventScript(gDecompressionBuffer); CpuFill32(0, gDecompressionBuffer, 0x7D4); if (!GetEventLoadMessage(gStringVar4, unkVal)) - TrySavingData(NORMAL_SAVE); + TrySavingData(SAVE_NORMAL); gMain.state++; } break; diff --git a/src/naming_screen.c b/src/naming_screen.c index 47d8b8ad1..0e350aa35 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -75,7 +75,7 @@ static const u8 gSpriteImage_858BCB8[] = INCBIN_U8("graphics/naming_screen/pc_ic static const u16 gUnknown_0858BD78[] = INCBIN_U16("graphics/naming_screen/0.gbapal"); static const u16 gUnknown_0858BD98[] = INCBIN_U16("graphics/naming_screen/1.gbapal"); -static const u8 *const gUnknown_0858BDB8[] = +static const u8 *const gUnknown_0858BDB8[] = { gText_PkmnTransferredSomeonesPC, gText_PkmnTransferredLanettesPC, @@ -85,7 +85,7 @@ static const u8 *const gUnknown_0858BDB8[] = static const u8 gUnknown_0858BDC8[] = _("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"); -static const struct BgTemplate gUnknown_0858BE00[] = +static const struct BgTemplate gUnknown_0858BE00[] = { { .bg = 0, @@ -226,10 +226,10 @@ void DoNamingScreen(u8 templateNum, u8 *destBuffer, u16 monSpecies, u16 monGende gNamingScreenData->monPersonality = monPersonality; gNamingScreenData->destBuffer = destBuffer; gNamingScreenData->returnCallback = returnCallback; - + if (templateNum == 0) StartTimer1(); - + SetMainCallback2(C2_NamingScreen); } } @@ -316,15 +316,15 @@ static void sub_80E2FA4(void) static void NamingScreen_InitBGs(void) { u8 i; - + DmaClearLarge16(3, (void *)VRAM, VRAM_SIZE, 0x1000); DmaClear32(3, (void *)OAM, OAM_SIZE); DmaClear16(3, (void *)PLTT, PLTT_SIZE); - + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, gUnknown_0858BE00, 4); - + ChangeBgX(0, 0, 0); ChangeBgY(0, 0, 0); ChangeBgX(1, 0, 0); @@ -333,21 +333,21 @@ static void NamingScreen_InitBGs(void) ChangeBgY(2, 0, 0); ChangeBgX(3, 0, 0); ChangeBgY(3, 0, 0); - + sub_81971D0(); sub_8197200(); - + for (i = 0; i < 5; i++) gNamingScreenData->windows[i] = AddWindow(&gUnknown_0858BE10[i]); - + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0xC, 0x8)); - + SetBgTilemapBuffer(1, gNamingScreenData->tilemapBuffer1); SetBgTilemapBuffer(2, gNamingScreenData->tilemapBuffer2); SetBgTilemapBuffer(3, gNamingScreenData->tilemapBuffer3); - + FillBgTilemapBufferRect_Palette0(1, 0, 0, 0, 0x20, 0x20); FillBgTilemapBufferRect_Palette0(2, 0, 0, 0, 0x20, 0x20); FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 0x20, 0x20); @@ -511,7 +511,7 @@ static bool8 MainState_WaitFadeOutAndExit(void) static void DisplaySentToPCMessage(void) { u8 stringToDisplay = 0; - + if (!sub_813B260()) { StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN))); @@ -524,10 +524,10 @@ static void DisplaySentToPCMessage(void) StringCopy(gStringVar3, GetBoxNamePtr(get_unknown_box_id())); stringToDisplay = 2; } - + if (FlagGet(FLAG_SYS_PC_LANETTE)) stringToDisplay++; - + StringExpandPlaceholders(gStringVar4, gUnknown_0858BDB8[stringToDisplay]); NewMenuHelpers_DrawDialogueFrame(0, 0); gTextFlags.flag_0 = TRUE; @@ -538,10 +538,10 @@ static void DisplaySentToPCMessage(void) static bool8 sub_80E3604(void) { RunTextPrinters(); - + if (!IsTextPrinterActive(0) && (gMain.newKeys & A_BUTTON)) gNamingScreenData->state = MAIN_STATE_BEGIN_FADE_OUT; - + return FALSE; } @@ -562,17 +562,17 @@ static bool8 MainState_WaitPageSwap(void) s16 cursorX; s16 cursorY; bool32 var3; - + if (IsPageSwapAnimNotInProgress()) { - + GetCursorPos(&cursorX, &cursorY); var3 = (cursorX == GetCurrentPageColumnCount()); - + gNamingScreenData->state = MAIN_STATE_HANDLE_INPUT; gNamingScreenData->currentPage++; gNamingScreenData->currentPage %= 3; - + if (var3) { cursorX = GetCurrentPageColumnCount(); @@ -582,7 +582,7 @@ static bool8 MainState_WaitPageSwap(void) if (cursorX >= GetCurrentPageColumnCount()) cursorX = GetCurrentPageColumnCount() - 1; } - + SetCursorPos(cursorX, cursorY); sub_80E4E5C(); SetInputState(INPUT_STATE_ENABLED); @@ -603,7 +603,7 @@ static bool8 PageSwapAnimState_1(struct Task *); static bool8 PageSwapAnimState_2(struct Task *); static bool8 PageSwapAnimState_Done(struct Task *); -static bool8 (*const sPageSwapAnimStateFuncs[])(struct Task *) = +static bool8 (*const sPageSwapAnimStateFuncs[])(struct Task *) = { PageSwapAnimState_Init, PageSwapAnimState_1, @@ -754,7 +754,7 @@ static void Task_80E39BC(u8 taskId) task->data[3] += task->data[4]; task->data[6] += task->data[4]; } - + if (task->data[3] == 16 && task->data[6] == 22) { task->data[4] = -4; @@ -893,7 +893,7 @@ static void CursorInit(void) static void SetCursorPos(s16 x, s16 y) { struct Sprite *cursorSprite = &gSprites[gNamingScreenData->cursorSpriteId]; - + if (x < gUnknown_0858BEA0[sub_80E3274()]) cursorSprite->pos1.x = gUnknown_0858BEA3[x + sub_80E3274() * 8] + 38; else @@ -909,7 +909,7 @@ static void SetCursorPos(s16 x, s16 y) static void GetCursorPos(s16 *x, s16 *y) { struct Sprite *cursorSprite = &gSprites[gNamingScreenData->cursorSpriteId]; - + *x = cursorSprite->data[0]; *y = cursorSprite->data[1]; } @@ -1133,7 +1133,7 @@ static void CreateInputTargetIcon(void) static void TaskDummy2(void) { - + } static void NamingScreen_CreatePlayerIcon(void) @@ -1160,7 +1160,7 @@ static void NamingScreen_CreateMonIcon(void) { u8 spriteId; - sub_80D2F04(); + LoadMonIconPalettes(); spriteId = CreateMonIcon(gNamingScreenData->monSpecies, SpriteCallbackDummy, 0x38, 0x28, 0, gNamingScreenData->monPersonality, 1); gSprites[spriteId].oam.priority = 3; } @@ -1331,7 +1331,7 @@ static void InputState_Disabled(struct Task *task) static void InputState_Enabled(struct Task *task) { task->tKeyboardEvent = 0; - + if (gMain.newKeys & A_BUTTON) task->tKeyboardEvent = KBEVENT_PRESSED_A; else if (gMain.newKeys & B_BUTTON) @@ -1454,7 +1454,7 @@ static void sub_80E4894(void) static void sub_80E48E8(void) { u8 buffer[0x20]; - + StringCopy(buffer, gSpeciesNames[gNamingScreenData->monSpecies]); StringAppendN(buffer, gNamingScreenData->template->title, 15); FillWindowPixelBuffer(gNamingScreenData->windows[3], 0x11); @@ -1492,10 +1492,10 @@ static void sub_80E498C(void) static void TaskDummy3(void) { - + } -static const u8 sGenderColors[2][3] = +static const u8 sGenderColors[2][3] = { {0, 9, 8}, {0, 5, 4} @@ -1505,7 +1505,7 @@ static void sub_80E49BC(void) { u8 genderSymbol[2]; bool8 isFemale = FALSE; - + StringCopy(genderSymbol, gText_MaleSymbol); if (gNamingScreenData->monGender != MON_GENDERLESS) @@ -1575,7 +1575,7 @@ static bool8 sub_80E4B54(void) sub_80E4D10(); CopyBgTilemapBufferToVram(3); PlaySE(SE_SELECT); - + if (GetPreviousTextCaretPosition() != gNamingScreenData->template->maxChars - 1) return FALSE; else @@ -1633,7 +1633,7 @@ static void sub_80E4CF8(u8 bg, const void *src) static void nullsub_10(u8 a1, u8 a2) { - + } static void sub_80E4D10(void) @@ -1643,18 +1643,18 @@ static void sub_80E4D10(void) u16 unk2; u8 maxChars = gNamingScreenData->template->maxChars; u16 unk = gNamingScreenData->inputCharBaseXPos - 0x40; - + FillWindowPixelBuffer(gNamingScreenData->windows[2], 0x11); - + for (i = 0; i < maxChars; i++) { temp[0] = gNamingScreenData->textBuffer[i]; temp[1] = gExpandedPlaceholder_Empty[0]; unk2 = (sub_80E503C(temp[0]) == 1) ? 2 : 0; - + PrintTextOnWindow(gNamingScreenData->windows[2], 1, temp, i * 8 + unk + unk2, 1, 0xFF, NULL); } - + sub_80E498C(); CopyWindowToVram(gNamingScreenData->windows[2], 2); PutWindowTilemap(gNamingScreenData->windows[2]); @@ -1674,12 +1674,12 @@ static const struct TextColorThing sUnkColorStruct = } }; -static const u8 sFillValues[3] = +static const u8 sFillValues[3] = { 0xEE, 0xDD, 0xFF }; -static const u8 *const sUnkColors[3] = +static const u8 *const sUnkColors[3] = { sUnkColorStruct.colors[1], sUnkColorStruct.colors[0], @@ -1689,18 +1689,18 @@ static const u8 *const sUnkColors[3] = static void sub_80E4DE4(u8 window, u8 a1) { u8 i; - + FillWindowPixelBuffer(window, sFillValues[a1]); - + for (i = 0; i < 4; i++) { box_print(window, 1, 0, i * 16 + 1, sUnkColors[a1], 0, gUnknown_0858C198[a1][i]); } - + PutWindowTilemap(window); } -static const u8 *const gUnknown_0858BF98[] = +static const u8 *const gUnknown_0858BF98[] = { gUnknown_08DD4620, gUnknown_08DD46E0, @@ -1714,7 +1714,7 @@ static void sub_80E4E5C(void) u8 unk3; u8 bg1Priority = GetGpuReg(REG_OFFSET_BG1CNT) & 3; u8 bg2Priority = GetGpuReg(REG_OFFSET_BG2CNT) & 3; - + if (bg1Priority > bg2Priority) { unk1 = 1; @@ -1727,7 +1727,7 @@ static void sub_80E4E5C(void) unk2 = 2; unk3 = gNamingScreenData->windows[1]; } - + sub_80E4CF8(unk1, gUnknown_0858BF98[gNamingScreenData->currentPage]); sub_80E4DE4(unk3, sub_80E3254()); nullsub_10(unk1, sub_80E3254()); @@ -1737,7 +1737,7 @@ static void sub_80E4E5C(void) static void sub_80E4EF0(void) { const u8 color[3] = { 15, 1, 2 }; - + FillWindowPixelBuffer(gNamingScreenData->windows[4], 0xFF); box_print(gNamingScreenData->windows[4], 0, 2, 1, color, 0, gText_MoveOkBack); PutWindowTilemap(gNamingScreenData->windows[4]); @@ -1787,7 +1787,7 @@ static void sub_80E501C(void) static bool8 sub_80E503C(u8 character) { u8 i; - + for (i = 0; gUnknown_0858BDC8[i] != EOS; i++) { if (character == gUnknown_0858BDC8[i]) @@ -1798,22 +1798,22 @@ static bool8 sub_80E503C(u8 character) static void sub_80E5074(void) { - DoNamingScreen(0, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, sub_8086194); + DoNamingScreen(0, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu); } static void sub_80E509C(void) { - DoNamingScreen(1, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, sub_8086194); + DoNamingScreen(1, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu); } static void sub_80E50C4(void) { - DoNamingScreen(2, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, sub_8086194); + DoNamingScreen(2, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu); } static void sub_80E50EC(void) { - DoNamingScreen(3, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, sub_8086194); + DoNamingScreen(3, gSaveBlock2Ptr->playerName, gSaveBlock2Ptr->playerGender, 0, 0, CB2_ReturnToFieldWithOpenMenu); } //-------------------------------------------------- @@ -1987,20 +1987,20 @@ static const struct SpriteFrameImage gUnknown_0858C080[] = {gSpriteImage_858BCB8, sizeof(gSpriteImage_858BCB8)}, }; -static const union AnimCmd gSpriteAnim_858C090[] = +static const union AnimCmd gSpriteAnim_858C090[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_JUMP(0) }; -static const union AnimCmd gSpriteAnim_858C098[] = +static const union AnimCmd gSpriteAnim_858C098[] = { ANIMCMD_FRAME(4, 8), ANIMCMD_FRAME(8, 8), ANIMCMD_END }; -static const union AnimCmd gSpriteAnim_858C0A4[] = +static const union AnimCmd gSpriteAnim_858C0A4[] = { ANIMCMD_FRAME(0, 2), ANIMCMD_FRAME(1, 2), @@ -2023,7 +2023,7 @@ static const union AnimCmd *const gSpriteAnimTable_858C0BC[] = gSpriteAnim_858C0A4 }; -static const struct SpriteTemplate gUnknown_0858C0C0 = +static const struct SpriteTemplate gUnknown_0858C0C0 = { .tileTag = 0x0002, .paletteTag = 0x0004, @@ -2034,7 +2034,7 @@ static const struct SpriteTemplate gUnknown_0858C0C0 = .callback = sub_80E4084 }; -static const struct SpriteTemplate gUnknown_0858C0D8 = +static const struct SpriteTemplate gUnknown_0858C0D8 = { .tileTag = 0x0003, .paletteTag = 0x0001, @@ -2045,7 +2045,7 @@ static const struct SpriteTemplate gUnknown_0858C0D8 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C0F0 = +static const struct SpriteTemplate gUnknown_0858C0F0 = { .tileTag = 0x0004, .paletteTag = 0x0004, @@ -2056,7 +2056,7 @@ static const struct SpriteTemplate gUnknown_0858C0F0 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C108 = +static const struct SpriteTemplate gUnknown_0858C108 = { .tileTag = 0x0000, .paletteTag = 0x0006, @@ -2067,7 +2067,7 @@ static const struct SpriteTemplate gUnknown_0858C108 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C120 = +static const struct SpriteTemplate gUnknown_0858C120 = { .tileTag = 0x0001, .paletteTag = 0x0007, @@ -2078,7 +2078,7 @@ static const struct SpriteTemplate gUnknown_0858C120 = .callback = SpriteCallbackDummy }; -static const struct SpriteTemplate gUnknown_0858C138 = +static const struct SpriteTemplate gUnknown_0858C138 = { .tileTag = 0x0007, .paletteTag = 0x0005, @@ -2089,7 +2089,7 @@ static const struct SpriteTemplate gUnknown_0858C138 = .callback = sub_80E3B30 }; -static const struct SpriteTemplate sSpriteTemplate_InputArrow = +static const struct SpriteTemplate sSpriteTemplate_InputArrow = { .tileTag = 0x000A, .paletteTag = 0x0003, @@ -2100,7 +2100,7 @@ static const struct SpriteTemplate sSpriteTemplate_InputArrow = .callback = sub_80E3C20 }; -static const struct SpriteTemplate sSpriteTemplate_Underscore = +static const struct SpriteTemplate sSpriteTemplate_Underscore = { .tileTag = 0x000B, .paletteTag = 0x0003, @@ -2111,7 +2111,7 @@ static const struct SpriteTemplate sSpriteTemplate_Underscore = .callback = sub_80E3C6C }; -static const struct SpriteTemplate gUnknown_0858C180 = +static const struct SpriteTemplate gUnknown_0858C180 = { .tileTag = 0xFFFF, .paletteTag = 0x0000, @@ -2122,7 +2122,7 @@ static const struct SpriteTemplate gUnknown_0858C180 = .callback = SpriteCallbackDummy }; -static const u8* const gUnknown_0858C198[][4] = +static const u8* const gUnknown_0858C198[][4] = { { gUnknown_0862B88D, diff --git a/src/new_game.c b/src/new_game.c index 89771e92b..37336016e 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -20,8 +20,10 @@ #include "tv.h" #include "coins.h" #include "text.h" +#include "overworld.h" +#include "mail.h" +#include "battle_records.h" -extern u8 gPlayerPartyCount; extern u8 gDifferentSaveFile; extern u16 gSaveFileStatus; extern u8 gUnknown_030060B0; @@ -29,19 +31,15 @@ extern u8 gUnknown_030060B0; // TODO: replace those declarations with file headers extern u16 GetGeneratedTrainerIdLower(void); extern void ClearContestWinnerPicsInContestHall(void); -extern void Overworld_SetWarpDestination(s8 mapBank, s8 mapNo, s8 warpNo, s8 xPos, s8 yPos); extern void warp_in(void); extern void sub_80BB358(void); extern void ResetBagScrollPositions(void); extern void ResetPokedex(void); extern void sub_8084400(void); -extern void ClearMailData(void); extern void ResetGabbyAndTy(void); extern void ResetSecretBases(void); extern void ResetLinkContestBoolean(void); -extern void ResetGameStats(void); extern void sub_8052DA8(void); -extern void InitLinkBattleRecords(void); extern void ResetPokemonStorageSystem(void); extern void ClearBag(void); extern void NewGameInitPCItems(void); @@ -58,7 +56,7 @@ extern void ResetContestLinkResults(void); extern void ResetPokeJumpResults(void); extern void SetBerryPowder(u32* powder, u32 newValue); -extern u8 EventScript_2715DE[]; +extern const u8 EventScript_2715DE[]; void WriteUnalignedWord(u32 var, u8 *dataPtr) { @@ -178,7 +176,7 @@ void NewGameInitData(void) ResetLinkContestBoolean(); ResetGameStats(); ClearAllContestWinnerPics(); - InitLinkBattleRecords(); + ClearPlayerLinkBattleRecords(); InitSeedotSizeRecord(); InitLotadSizeRecord(); gPlayerPartyCount = 0; diff --git a/src/option_menu.c b/src/option_menu.c index cbbe14b77..de9a216a6 100644 --- a/src/option_menu.c +++ b/src/option_menu.c @@ -146,23 +146,7 @@ void CB2_InitOptionMenu(void) gMain.state++; break; case 1: - { - u8 *addr; - u32 size; - - addr = (u8 *)VRAM; - size = 0x18000; - while (1) - { - DmaFill16(3, 0, addr, 0x1000); - addr += 0x1000; - size -= 0x1000; - if (size <= 0x1000) - { - DmaFill16(3, 0, addr, size); - break; - } - } + DmaClearLarge16(3, (void*)(VRAM), VRAM_SIZE, 0x1000); DmaClear32(3, OAM, OAM_SIZE); DmaClear16(3, PLTT, PLTT_SIZE); SetGpuReg(REG_OFFSET_DISPCNT, 0); @@ -189,7 +173,6 @@ void CB2_InitOptionMenu(void) ShowBg(0); ShowBg(1); gMain.state++; - } break; case 2: ResetPaletteFade(); diff --git a/src/overworld.c b/src/overworld.c index c538595f2..3d9a1bdc2 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1,19 +1,3181 @@ - -// Includes #include "global.h" +#include "overworld.h" +#include "main.h" +#include "battle_setup.h" +#include "berry.h" +// #include "cable_club.h" +#include "clock.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_control_avatar.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_ground_effect.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_screen_effect.h" +// #include "field_special_scene.h" +#include "field_specials.h" +#include "field_tasks.h" +#include "field_weather.h" +#include "fieldmap.h" +// #include "fldeff_flash.h" +#include "heal_location.h" +#include "link.h" +#include "load_save.h" +#include "main.h" +#include "m4a.h" +#include "constants/maps.h" +#include "map_name_popup.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "new_game.h" +#include "palette.h" +#include "play_time.h" +#include "random.h" +#include "roamer.h" +// #include "rotating_gate.h" +#include "safari_zone.h" +#include "save.h" +#include "script.h" +// #include "script_pokemon_80C4.h" +#include "secret_base.h" +#include "constants/songs.h" +#include "sound.h" +#include "constants/species.h" +#include "start_menu.h" +#include "task.h" +// #include "tileset_anim.h" +#include "time_events.h" +#include "tv.h" +#include "scanline_effect.h" +#include "wild_encounter.h" +#include "bg.h" +#include "money.h" +#include "save_location.h" +#include "constants/abilities.h" +#include "malloc.h" +#include "gpu_regs.h" +#include "link_rfu.h" + +// event scripts +extern const u8 EventScript_WhiteOut[]; +extern const u8 EventScript_271862[]; +extern const u8 EventScript_277513[]; +extern const u8 EventScript_TradeRoom_TooBusyToNotice[]; +extern const u8 EventScript_TradeRoom_ReadTrainerCard1[]; +extern const u8 EventScript_TradeRoom_ReadTrainerCard2[]; +extern const u8 gUnknown_08277388[]; +extern const u8 gUnknown_082773A3[]; +extern const u8 gUnknown_082773BE[]; +extern const u8 gUnknown_082773D9[]; +extern const u8 gUnknown_0827741D[]; +extern const u8 gUnknown_08277432[]; +extern const u8 gUnknown_08277447[]; +extern const u8 gUnknown_0827745C[]; +extern const u8 gUnknown_08277374[]; +extern const u8 gUnknown_0827737E[]; +extern const u8 gUnknown_082773FF[]; +extern const u8 gUnknown_082773F5[]; +extern const u8 gUnknown_082774EF[]; +extern const u8 gUnknown_08277509[]; + +// vars +extern const struct MapData *const gMapAttributes[]; +extern const struct MapHeader *const *const gMapGroups[]; +extern const s32 gMaxFlashLevel; +extern const u16 gUnknown_82EC7C4[]; + +u16 gUnknown_03005DA8; +MainCallback gFieldCallback; +bool8 (*gUnknown_03005DB0)(void); +u8 gUnknown_03005DB4; +u8 gFieldLinkPlayerCount; + +// functions +extern void HealPlayerParty(void); +extern void move_tilemap_camera_to_upper_left_corner(void); +extern void cur_mapheader_run_tileset_funcs_after_some_cpuset(void); +extern void DrawWholeMapView(void); +extern void copy_map_tileset1_tileset2_to_vram(const struct MapData *); +extern void apply_map_tileset1_tileset2_palette(const struct MapData *); +extern void ResetCyclingRoadChallengeData(void); +extern void ApplyNewEncryptionKeyToWord(u32 *word, u32 newKey); +extern void mapheader_run_script_with_tag_x5(void); +extern void ResetFieldTasksArgs(void); +extern void sub_80A0A2C(void); +extern void not_trainer_hill_battle_pyramid(void); +extern void apply_map_tileset2_palette(const struct MapData *); +extern void copy_map_tileset2_to_vram_2(const struct MapData *); +extern void prev_quest_postbuffer_cursor_backup_reset(void); +extern void ShowMapNamePopup(void); +extern bool32 InTrainerHill(void); +extern bool32 sub_808651C(void); +extern bool8 sub_80AF6A4(void); +extern bool8 sub_81A9E6C(void); +extern bool8 sub_80E909C(void); +extern void sub_81AA1D8(void); +extern void c2_change_map(void); +extern void sub_81D5DF8(void); +extern void sub_80EB218(void); +extern void sub_81BE72C(void); +extern void sub_80AF3C8(void); +extern void sub_81971F4(void); +extern void sub_808B578(void); +extern void sub_80AF314(void); +extern void sub_80AF214(void); +extern void sub_80AF188(void); +extern void door_upload_tiles(void); +extern void RotatingGate_InitPuzzleAndGraphics(void); +extern void sub_80AF168(void); +extern void sub_80AF3C8(void); +extern void ExecuteTruckSequence(void); +extern void sub_80A0A38(void); +extern void trainer_hill_map_load_related(void); +extern void sub_8087D74(void); +extern void battle_pyramid_map_load_related(u8); +extern void sub_80B00E8(u8); +extern void sub_80E9238(u8); +extern void sub_81A3908(void); +extern void sub_81AA2F8(void); +extern void sub_8195E10(void); +extern void sub_80EDB44(void); +extern void sub_81D64C0(void); +extern void sub_81BE6AC(void); +extern void sub_8098128(void); +extern void copy_map_tileset1_to_vram(const struct MapData *); +extern void copy_map_tileset2_to_vram(const struct MapData *); +extern void FieldUpdateBgTilemapScroll(void); +extern void TransferTilesetAnimsBuffer(void); +extern bool32 sub_81D5F48(void); +extern u8 GetCurrentTrainerHillMapId(void); +extern bool8 warp0_in_pokecenter(void); +extern void dp13_810BB8C(void); +extern void FieldEffectActiveListClear(void); +extern void SetUpFieldTasks(void); +extern void sub_81BE6B8(void); +extern void sub_80AAFA4(void); +extern void ShowStartMenu(void); +extern void sub_80AEE84(void); +extern void mapldr_default(void); +extern void npc_paltag_set_load(u8); +extern void sub_8088B3C(u16, u16); +extern bool32 sub_800F0B8(void); +extern bool32 sub_8009F3C(void); +extern void sub_8010198(void); +extern u32 sub_800B4DC(void); +extern bool32 sub_80B39D4(u8); +extern const u8* sub_809C2C8(struct MapPosition *a1, u8, u8); +extern u8 *sub_809D0F4(void*); +extern u8 sub_808BD6C(u8); +extern u8 sub_808BD7C(u8); +extern void sub_80979D4(struct Sprite*, u8); + +// this file's functions +static void Overworld_ResetStateAfterWhiteOut(void); +static void c2_80567AC(void); +static void CB2_LoadMap2(void); +static void VBlankCB_Field(void); +static void SpriteCB_LinkPlayer(struct Sprite *sprite); +static void ChooseAmbientCrySpecies(void); +static void do_load_map_stuff_loop(u8 *state); +static bool32 map_loading_iteration_3(u8 *state); +static bool32 sub_8086638(u8 *state); +static bool32 load_map_stuff(u8 *state, u32); +static bool32 map_loading_iteration_2_link(u8 *state); +static void mli4_mapscripts_and_other(void); +static void map_loading_lcd_reset(void); +static u8 sub_8087858(u8); +static u16 sub_80871C0(u32 a1); +static void sub_80867C8(void); +static void sub_80867D8(void); +static void sub_8086AE4(void); +static void sub_80869DC(void); +static void sub_8086B14(void); +static void sub_8086AAC(void); +static void sub_8086988(bool32 arg0); +static void sub_8086A80(void); +static void sub_8086A68(void); +static void sub_8086860(void); +static void sub_8086AC8(void); +static void sub_8086B9C(void); +static void sub_8086C40(void); +static void sub_8086C90(void); +static void sub_8086FA0(u16); +static void sub_8086F38(u16*, s32); +static u8 npc_something3(u8 a1, u8 a2); +static u8 LinkPlayerDetectCollision(u8 selfMapObjId, u8 a2, s16 x, s16 y); +static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion); +static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y); +static u8 sub_80878A0(u8 linkPlayerId); +static u8 sub_80878C0(u8 linkPlayerId); +static s32 sub_80878E4(u8 linkPlayerId); +static u8 GetLinkPlayerIdAt(s16 x, s16 y); +static void sub_808796C(u8 linkPlayerId, u8 a2); +static void ZeroMapObject(struct MapObject *mapObj); +static void SpawnLinkPlayerMapObject(u8 linkPlayerId, s16 x, s16 y, u8 a4); +static void InitLinkPlayerMapObjectPos(struct MapObject *mapObj, s16 x, s16 y); +static void sub_80877DC(u8 linkPlayerId, u8 a2); +static void sub_808780C(u8 linkPlayerId); +static u8 sub_8087858(u8 linkPlayerId); +static void sub_8087584(void); +static u32 sub_8087690(void); +static void ZeroLinkPlayerMapObject(struct LinkPlayerMapObject *linkPlayerMapObj); +static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1); +static u16 sub_8087480(const u8 *script); +static void sub_8087510(void); +static void sub_808751C(void); +static void sub_8087530(const u8 *script); +static void sub_808754C(void); +static void sub_8087568(const u8 *script); +static void sub_80872D8(s32 linkPlayerId, s32 a2, struct UnkStruct_8054FF8 *a3); +static bool32 sub_8087340(struct UnkStruct_8054FF8 *a1); +static bool32 sub_8087358(struct UnkStruct_8054FF8 *a1); +static u8 *sub_8087370(struct UnkStruct_8054FF8 *a1); +static bool32 sub_8087388(struct UnkStruct_8054FF8 *a1); +static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1); +static u16 sub_808711C(u32); +static u16 sub_8087140(u32); +static void sub_808709C(u16 *a1); +static u16 sub_80870B0(u32 a1); +static u16 sub_80870F8(u32 a1); +static u16 sub_8087068(u16 a1); +static void c1_link_related(void); +static void c1_link_related_func_set(u16 (*func)(u32)); +static void SetFieldVBlankCallback(void); +static void FieldClearVBlankHBlankCallbacks(void); +static void sub_8085810(void); +static u8 sub_808532C(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3); +static u8 sub_808538C(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4); +static u16 cur_mapdata_block_role_at_screen_center_acc_to_sav1(void); + +// IWRAM bss vars +IWRAM_DATA static void *sUnknown_03000E0C; +IWRAM_DATA static u8 sUnknown_03000E10[4]; +IWRAM_DATA static u16 (*sUnknown_03000E14)(u32); +IWRAM_DATA static u8 sUnknown_03000E18; +IWRAM_DATA static u8 sUnknown_03000E19; +IWRAM_DATA static u32 sUnusedVar; + +// EWRAM vars +EWRAM_DATA static u8 sUnknown_020322D8 = 0; +EWRAM_DATA struct WarpData gUnknown_020322DC = {0}; +EWRAM_DATA static struct WarpData sWarpDestination = {0}; // new warp position +EWRAM_DATA static struct WarpData sUnknown_020322EC = {0}; +EWRAM_DATA static struct WarpData sUnknown_020322F4 = {0}; +EWRAM_DATA static u16 sLastMapSectionId = 0; +EWRAM_DATA static struct UnkPlayerStruct sUnknown_02032300 = {0}; +EWRAM_DATA static u16 sAmbientCrySpecies = 0; +EWRAM_DATA static bool8 sIsAmbientCryWaterMon = FALSE; +EWRAM_DATA struct LinkPlayerMapObject gLinkPlayerMapObjects[4] = {0}; + +// const rom data +static const struct WarpData sDummyWarpData = +{ + .mapGroup = -1, + .mapNum = -1, + .warpId = -1, + .x = -1, + .y = -1, +}; + +static const u8 sUnusedData[] = +{ + 0xB0, 0x04, 0x00, 0x00, + 0x10, 0x0E, 0x00, 0x00, + 0xB0, 0x04, 0x00, 0x00, + 0x60, 0x09, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, + 0xD4, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x00, 0x00, +}; + +const struct UCoords32 gUnknown_08339D64[] = +{ + { 0, 0}, + { 0, 1}, + { 0, -1}, + {-1, 0}, + { 1, 0}, + {-1, 1}, + { 1, 1}, + {-1, -1}, + { 1, -1}, +}; + +static const struct BgTemplate gUnknown_08339DAC[] = +{ + { + .bg = 0, + .charBaseIndex = 2, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0 + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 29, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0 + }, + { + .bg = 2, + .charBaseIndex = 0, + .mapBaseIndex = 28, + .screenSize = 0, + .paletteMode = 0, + .priority = 2, + .baseTile = 0 + }, + { + .bg = 3, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 3, + .baseTile = 0 + } +}; + +static const struct ScanlineEffectParams gUnknown_08339DBC = +{ + (void *)REG_ADDR_WIN0H, + ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, + 1, + 0, +}; + +static u8 sub_80879D8(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_80879F8(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_80879FC(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_08339DC8[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_80879D8, + sub_80879F8, + sub_80879FC, +}; + +static u8 sub_8087A1C(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8087A20(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8087A88(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_08339DD4[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_8087A1C, + sub_8087A20, + sub_8087A20, + sub_8087A20, + sub_8087A20, + sub_8087A1C, + sub_8087A1C, + sub_8087A88, + sub_8087A88, + sub_8087A88, + sub_8087A88, +}; + +static void sub_8087AA0(struct LinkPlayerMapObject *, struct MapObject *); +static void sub_8087AA8(struct LinkPlayerMapObject *, struct MapObject *); + +static void (*const gUnknown_08339E00[])(struct LinkPlayerMapObject *, struct MapObject *) = +{ + sub_8087AA0, + sub_8087AA8, +}; + +// code +void DoWhiteOut(void) +{ + ScriptContext2_RunNewScript(EventScript_WhiteOut); + SetMoney(&gSaveBlock1Ptr->money, GetMoney(&gSaveBlock1Ptr->money) / 2); + HealPlayerParty(); + Overworld_ResetStateAfterWhiteOut(); + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); +} + +void Overworld_ResetStateAfterFly(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); +} + +void Overworld_ResetStateAfterTeleport(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); + ScriptContext2_RunNewScript(EventScript_271862); +} + +void Overworld_ResetStateAfterDigEscRope(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); +} + +static void Overworld_ResetStateAfterWhiteOut(void) +{ + player_avatar_init_params_reset(); + FlagClear(FLAG_SYS_CYCLING_ROAD); + FlagClear(FLAG_SYS_CRUISE_MODE); + FlagClear(FLAG_SYS_SAFARI_MODE); + FlagClear(FLAG_SYS_USE_STRENGTH); + FlagClear(FLAG_SYS_USE_FLASH); + if (VarGet(VAR_0x4039) == 1) + { + VarSet(VAR_0x4039, 0); + VarSet(VAR_0x4037, 0); + } +} + +static void sub_8084788(void) +{ + FlagClear(FLAG_SYS_SAFARI_MODE); + ChooseAmbientCrySpecies(); + ResetCyclingRoadChallengeData(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); +} + +void ResetGameStats(void) +{ + s32 i; + + for (i = 0; i < NUM_GAME_STATS; i++) + SetGameStat(i, 0); +} + +void IncrementGameStat(u8 index) +{ + if (index < NUM_USED_GAME_STATS) + { + u32 statVal = GetGameStat(index); + if (statVal < 0xFFFFFF) + statVal++; + else + statVal = 0xFFFFFF; + + SetGameStat(index, statVal); + } +} + +u32 GetGameStat(u8 index) +{ + if (index >= NUM_USED_GAME_STATS) + return 0; + + return gSaveBlock1Ptr->gameStats[index] ^ gSaveBlock2Ptr->encryptionKey; +} + +void SetGameStat(u8 index, u32 value) +{ + if (index < NUM_USED_GAME_STATS) + gSaveBlock1Ptr->gameStats[index] = value ^ gSaveBlock2Ptr->encryptionKey; +} + +void ApplyNewEncryptionKeyToGameStats(u32 newKey) +{ + u8 i; + + for (i = 0; i < NUM_GAME_STATS; i++) + ApplyNewEncryptionKeyToWord(&gSaveBlock1Ptr->gameStats[i], newKey); +} + +void LoadMapObjTemplatesFromHeader(void) +{ + // Clear map object templates + CpuFill32(0, gSaveBlock1Ptr->mapObjectTemplates, sizeof(gSaveBlock1Ptr->mapObjectTemplates)); + + // Copy map header events to save block + CpuCopy32(gMapHeader.events->mapObjects, + gSaveBlock1Ptr->mapObjectTemplates, + gMapHeader.events->mapObjectCount * sizeof(struct MapObjectTemplate)); +} + +void LoadSaveblockMapObjScripts(void) +{ + struct MapObjectTemplate *mapHeaderObjTemplates = gMapHeader.events->mapObjects; + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + s32 i; + + for (i = 0; i < 64; i++) + savObjTemplates[i].script = mapHeaderObjTemplates[i].script; +} + +void Overworld_SetMapObjTemplateCoords(u8 localId, s16 x, s16 y) +{ + s32 i; + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->x = x; + mapObjectTemplate->y = y; + return; + } + } +} + +void Overworld_SetMapObjTemplateMovementType(u8 localId, u8 movementType) +{ + s32 i; + + struct MapObjectTemplate *savObjTemplates = gSaveBlock1Ptr->mapObjectTemplates; + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &savObjTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->movementType = movementType; + return; + } + } +} + +static void mapdata_load_assets_to_gpu_and_full_redraw(void) +{ + move_tilemap_camera_to_upper_left_corner(); + copy_map_tileset1_tileset2_to_vram(gMapHeader.mapData); + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + DrawWholeMapView(); + cur_mapheader_run_tileset_funcs_after_some_cpuset(); +} + +const struct MapData *get_mapdata_header(void) +{ + u16 mapDataId = gSaveBlock1Ptr->mapDataId; + if (mapDataId) + return gMapAttributes[mapDataId - 1]; + return NULL; +} + +void ApplyCurrentWarp(void) +{ + gUnknown_020322DC = gSaveBlock1Ptr->location; + gSaveBlock1Ptr->location = sWarpDestination; + sUnknown_020322EC = sDummyWarpData; + sUnknown_020322F4 = sDummyWarpData; +} + +void set_warp2_warp3_to_neg_1(void) +{ + sUnknown_020322EC = sDummyWarpData; + sUnknown_020322F4 = sDummyWarpData; +} + +void SetWarpData(struct WarpData *warp, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + warp->mapGroup = mapGroup; + warp->mapNum = mapNum; + warp->warpId = warpId; + warp->x = x; + warp->y = y; +} + +bool32 warp_data_is_not_neg_1(struct WarpData *warp) +{ + if (warp->mapGroup != -1) + return FALSE; + else if (warp->mapNum != -1) + return FALSE; + else if (warp->warpId != -1) + return FALSE; + else if (warp->x != -1) + return FALSE; + else if (warp->y != -1) + return FALSE; + else + return TRUE; +} + +struct MapHeader const *const Overworld_GetMapHeaderByGroupAndId(u16 mapGroup, u16 mapNum) +{ + return gMapGroups[mapGroup][mapNum]; +} + +struct MapHeader const *const warp1_get_mapheader(void) +{ + return Overworld_GetMapHeaderByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); +} + +void set_current_map_header_from_sav1_save_old_name(void) +{ + sLastMapSectionId = gMapHeader.regionMapSectionId; + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gSaveBlock1Ptr->mapDataId = gMapHeader.mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +void LoadSaveblockMapHeader(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + gMapHeader.mapData = get_mapdata_header(); +} + +void update_camera_pos_from_warpid(void) +{ + if (gSaveBlock1Ptr->location.warpId >= 0 && gSaveBlock1Ptr->location.warpId < gMapHeader.events->warpCount) + { + gSaveBlock1Ptr->pos.x = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].x; + gSaveBlock1Ptr->pos.y = gMapHeader.events->warps[gSaveBlock1Ptr->location.warpId].y; + } + else if (gSaveBlock1Ptr->location.x >= 0 && gSaveBlock1Ptr->location.y >= 0) + { + gSaveBlock1Ptr->pos.x = gSaveBlock1Ptr->location.x; + gSaveBlock1Ptr->pos.y = gSaveBlock1Ptr->location.y; + } + else + { + gSaveBlock1Ptr->pos.x = gMapHeader.mapData->width / 2; + gSaveBlock1Ptr->pos.y = gMapHeader.mapData->height / 2; + } +} + +void warp_in(void) +{ + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + update_camera_pos_from_warpid(); +} + +void Overworld_SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sWarpDestination, mapGroup, mapNum, warpId, x, y); +} + +void warp1_set_2(s8 mapGroup, s8 mapNum, s8 warpId) +{ + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, -1, -1); +} + +void saved_warp2_set(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId) +{ + SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y); +} + +void saved_warp2_set_2(s32 unused, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp2, mapGroup, mapNum, warpId, x, y); +} + +void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused) +{ + sWarpDestination = gSaveBlock1Ptr->warp2; +} + +void sub_8084CCC(u8 a1) +{ + const struct HealLocation *warp = GetHealLocationPointer(a1); + + if (warp) + Overworld_SetWarpDestination(warp->group, warp->map, -1, warp->x, warp->y); +} + +void Overworld_SetWarpDestToLastHealLoc(void) +{ + sWarpDestination = gSaveBlock1Ptr->lastHealLocation; +} + +void Overworld_SetHealLocationWarp(u8 healLocationId) +{ + const struct HealLocation *healLocation = GetHealLocationPointer(healLocationId); + + if (healLocation != NULL) + SetWarpData(&gSaveBlock1Ptr->lastHealLocation, healLocation->group, healLocation->map, -1, healLocation->x, healLocation->y); +} + +void sub_8084D5C(s16 a1, s16 a2) +{ + u8 currMapType = Overworld_GetMapTypeOfSaveblockLocation(); + u8 destMapType = GetMapTypeByGroupAndId(sWarpDestination.mapGroup, sWarpDestination.mapNum); + if (is_map_type_1_2_3_5_or_6(currMapType) && is_map_type_1_2_3_5_or_6(destMapType) != TRUE) + sub_8084DD4(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, a1 - 7, a2 - 6); +} + +void sub_8084DD4(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp4, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084E14(void) +{ + sWarpDestination = gSaveBlock1Ptr->warp4; +} + +void sub_8084E2C(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sUnknown_020322EC, mapGroup, mapNum, warpId, x, y); +} + +void warp1_set_to_warp2(void) +{ + sWarpDestination = sUnknown_020322EC; +} + +void sub_8084E80(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&sUnknown_020322F4, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084EBC(s16 x, s16 y) +{ + if (warp_data_is_not_neg_1(&sUnknown_020322F4) == TRUE) + sWarpDestination = gUnknown_020322DC; + else + Overworld_SetWarpDestination(sUnknown_020322F4.mapGroup, sUnknown_020322F4.mapNum, -1, x, y); +} + +void warp1_set_to_sav1w(void) +{ + sWarpDestination = gSaveBlock1Ptr->warp1; +} + +void sub_8084F2C(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1Ptr->warp1, mapGroup, mapNum, warpId, x, y); +} + +void sub_8084F6C(u8 a1) +{ + const struct HealLocation *warp = GetHealLocationPointer(a1); + if (warp) + SetWarpData(&gSaveBlock1Ptr->warp1, warp->group, warp->map, -1, warp->x, warp->y); +} + +void sub_8084FAC(void) +{ + gSaveBlock1Ptr->warp1 = gSaveBlock1Ptr->warp2; +} + +const struct MapConnection *GetMapConnection(u8 dir) +{ + s32 i; + s32 count = gMapHeader.connections->count; + const struct MapConnection *connection = gMapHeader.connections->connections; + + if (connection == NULL) + return NULL; + + for(i = 0; i < count; i++, connection++) + if (connection->direction == dir) + return connection; + + return NULL; +} + +bool8 sub_8084FF8(u8 dir, u16 x, u16 y) +{ + const struct MapConnection *connection = GetMapConnection(dir); + + if (connection != NULL) + { + Overworld_SetWarpDestination(connection->mapGroup, connection->mapNum, -1, x, y); + } + else + { + mapheader_run_script_with_tag_x6(); + if (warp_data_is_not_neg_1(&sUnknown_020322EC)) + return FALSE; + warp1_set_to_warp2(); + } + return TRUE; +} + +bool8 sub_8085058(u16 x, u16 y) +{ + return sub_8084FF8(CONNECTION_EMERGE, x, y); +} + +bool8 sub_8085078(u16 x, u16 y) +{ + return sub_8084FF8(CONNECTION_DIVE, x, y); +} + +void mliX_load_map(u8 mapGroup, u8 mapNum) +{ + s32 paletteIndex; + + Overworld_SetWarpDestination(mapGroup, mapNum, -1, -1, -1); + if (gMapHeader.regionMapSectionId != 0x3A) + sub_8085810(); + + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + LoadMapObjTemplatesFromHeader(); + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + TryUpdateRandomTrainerRematches(mapGroup, mapNum); + DoTimeBasedEvents(); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + not_trainer_hill_battle_pyramid(); + copy_map_tileset2_to_vram_2(gMapHeader.mapData); + apply_map_tileset2_palette(gMapHeader.mapData); + + for (paletteIndex = 6; paletteIndex < 13; paletteIndex++) + ApplyWeatherGammaShiftToPal(paletteIndex); + + sub_80A0A2C(); + UpdateLocationHistoryForRoamer(); + RoamerMove(); + DoCurrentWeather(); + ResetFieldTasksArgs(); + mapheader_run_script_with_tag_x5(); + + if (gMapHeader.regionMapSectionId != 0x3A || gMapHeader.regionMapSectionId != sLastMapSectionId) + ShowMapNamePopup(); +} + +static void mli0_load_map(u32 a1) +{ + bool8 v2; + bool8 indoors; + + set_current_map_header_from_sav1_save_old_name(); + if (!(sUnknown_020322D8 & 1)) + { + if (gMapHeader.mapDataId == 0x169) + sub_81AA1D8(); + else if (InTrainerHill()) + sub_81D5DF8(); + else + LoadMapObjTemplatesFromHeader(); + } + + v2 = is_map_type_1_2_3_5_or_6(gMapHeader.mapType); + indoors = Overworld_MapTypeIsIndoors(gMapHeader.mapType); + + sub_80EB218(); + TrySetMapSaveWarpStatus(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + TryUpdateRandomTrainerRematches(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum); + if (a1 != 1) + DoTimeBasedEvents(); + SetSav1WeatherFromCurrMapHeader(); + ChooseAmbientCrySpecies(); + if (v2) + FlagClear(FLAG_SYS_USE_FLASH); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); + if (gMapHeader.mapDataId == 0x169) + battle_pyramid_map_load_related(0); + else if (InTrainerHill()) + trainer_hill_map_load_related(); + else + not_trainer_hill_battle_pyramid(); + + if (a1 != 1 && indoors) + { + UpdateTVScreensOnMap(gUnknown_03005DC0.width, gUnknown_03005DC0.height); + sub_80E9238(1); + } +} + +void player_avatar_init_params_reset(void) +{ + sUnknown_02032300.player_field_1 = 1; + sUnknown_02032300.player_field_0 = 1; +} + +void walkrun_find_lowest_active_bit_in_bitfield(void) +{ + sUnknown_02032300.player_field_1 = player_get_direction_lower_nybble(); + + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE)) + sUnknown_02032300.player_field_0 = 2; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE)) + sUnknown_02032300.player_field_0 = 4; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + sUnknown_02032300.player_field_0 = 8; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_4)) + sUnknown_02032300.player_field_0 = 16; + else + sUnknown_02032300.player_field_0 = 1; +} + +static struct UnkPlayerStruct *sub_80852D4(void) +{ + struct UnkPlayerStruct playerStruct; + u8 mapType = Overworld_GetMapTypeOfSaveblockLocation(); + u16 v2 = cur_mapdata_block_role_at_screen_center_acc_to_sav1(); + u8 v4 = sub_808532C(&sUnknown_02032300, v2, mapType); + playerStruct.player_field_0 = v4; + playerStruct.player_field_1 = sub_808538C(&sUnknown_02032300, v4, v2, mapType); + sUnknown_02032300 = playerStruct; + return &sUnknown_02032300; +} + +static u8 sub_808532C(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3) +{ + if (a3 != 8 && FlagGet(FLAG_SYS_CRUISE_MODE)) + return 1; + else if (a3 == 5) + return 16; + else if (MetatileBehavior_IsSurfableWaterOrUnderwater(a2) == 1) + return 8; + else if (Overworld_IsBikingAllowed() != TRUE) + return 1; + else if (playerStruct->player_field_0 == 2) + return 2; + else if (playerStruct->player_field_0 != 4) + return 1; + else + return 4; +} + +static u8 sub_808538C(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4) +{ + if (FlagGet(FLAG_SYS_CRUISE_MODE) && a4 == 6) + return 4; + else if (MetatileBehavior_IsDeepSouthWarp(a3) == TRUE) + return 2; + else if (MetatileBehavior_IsNonAnimDoor(a3) == TRUE || MetatileBehavior_IsDoor(a3) == TRUE) + return 1; + else if (MetatileBehavior_IsSouthArrowWarp(a3) == TRUE) + return 2; + else if (MetatileBehavior_IsNorthArrowWarp(a3) == TRUE) + return 1; + else if (MetatileBehavior_IsWestArrowWarp(a3) == TRUE) + return 4; + else if (MetatileBehavior_IsEastArrowWarp(a3) == TRUE) + return 3; + else if ((playerStruct->player_field_0 == 16 && a2 == 8) + || (playerStruct->player_field_0 == 8 && a2 == 16)) + return playerStruct->player_field_1; + else if (MetatileBehavior_IsLadder(a3) == TRUE) + return playerStruct->player_field_1; + else + return 1; +} + +static u16 cur_mapdata_block_role_at_screen_center_acc_to_sav1(void) +{ + return MapGridGetMetatileBehaviorAt(gSaveBlock1Ptr->pos.x + 7, gSaveBlock1Ptr->pos.y + 7); +} + +bool32 Overworld_IsBikingAllowed(void) +{ + if (!(gMapHeader.flags & 1)) + return FALSE; + else + return TRUE; +} + +void SetDefaultFlashLevel(void) +{ + if (!gMapHeader.cave) + gSaveBlock1Ptr->flashLevel = 0; + else if (FlagGet(FLAG_SYS_USE_FLASH)) + gSaveBlock1Ptr->flashLevel = 1; + else + gSaveBlock1Ptr->flashLevel = gMaxFlashLevel - 1; +} + +void Overworld_SetFlashLevel(s32 flashLevel) +{ + if (flashLevel < 0 || flashLevel > gMaxFlashLevel) + flashLevel = 0; + gSaveBlock1Ptr->flashLevel = flashLevel; +} + +u8 Overworld_GetFlashLevel(void) +{ + return gSaveBlock1Ptr->flashLevel; +} + +void sub_8085524(u16 mapDataId) +{ + gSaveBlock1Ptr->mapDataId = mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +void sub_8085540(u8 var) +{ + sUnknown_020322D8 = var; +} + +u8 sub_808554C(void) +{ + return sUnknown_020322D8; +} + +static bool16 ShouldLegendaryMusicPlayAtLocation(struct WarpData *warp) +{ + if (!FlagGet(FLAG_SYS_WEATHER_CTRL)) + return FALSE; + if (warp->mapGroup == 0) + { + switch (warp->mapNum) + { + case MAP_NUM(LILYCOVE_CITY): + case MAP_NUM(MOSSDEEP_CITY): + case MAP_NUM(SOOTOPOLIS_CITY): + case MAP_NUM(EVER_GRANDE_CITY): + case MAP_NUM(ROUTE124): + case MAP_NUM(ROUTE125): + case MAP_NUM(ROUTE126): + case MAP_NUM(ROUTE127): + case MAP_NUM(ROUTE128): + return TRUE; + default: + if (VarGet(VAR_0x405E) < 4) + return FALSE; + switch (warp->mapNum) + { + case MAP_NUM(ROUTE129): + case MAP_NUM(ROUTE130): + case MAP_NUM(ROUTE131): + return TRUE; + } + } + } + return FALSE; +} + +static bool16 NoMusicInSotopolisWithLegendaries(struct WarpData *warp) +{ + if (VarGet(VAR_0x40CA) != 1) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(SOOTOPOLIS_CITY)) + return FALSE; + else if (warp->mapNum == MAP_NUM(SOOTOPOLIS_CITY)) + return TRUE; + else + return FALSE; +} + +static bool16 IsInfiltratedWeatherInstitute(struct WarpData *warp) +{ + if (VarGet(VAR_WEATHER_INSTITUTE_STATE)) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(ROUTE119_WEATHER_INSTITUTE_1F)) + return FALSE; + else if (warp->mapNum == MAP_NUM(ROUTE119_WEATHER_INSTITUTE_1F) + || warp->mapNum == MAP_NUM(ROUTE119_WEATHER_INSTITUTE_2F)) + return TRUE; + else + return FALSE; +} + +static bool16 IsInflitratedSpaceCenter(struct WarpData *warp) +{ + if (VarGet(VAR_0x405D) == 0) + return FALSE; + else if (VarGet(VAR_0x405D) > 2) + return FALSE; + else if (warp->mapGroup != MAP_GROUP(MOSSDEEP_CITY_SPACE_CENTER_1F)) + return FALSE; + else if (warp->mapNum == MAP_NUM(MOSSDEEP_CITY_SPACE_CENTER_1F) + || warp->mapNum == MAP_NUM(MOSSDEEP_CITY_SPACE_CENTER_2F)) + return TRUE; + return FALSE; +} + +u16 GetLocationMusic(struct WarpData *warp) +{ + if (NoMusicInSotopolisWithLegendaries(warp) == TRUE) + return 0xFFFF; + else if (ShouldLegendaryMusicPlayAtLocation(warp) == TRUE) + return MUS_OOAME; + else if (IsInflitratedSpaceCenter(warp) == TRUE) + return MUS_MGM0; + else if (IsInfiltratedWeatherInstitute(warp) == TRUE) + return MUS_TOZAN; + else + return Overworld_GetMapHeaderByGroupAndId(warp->mapGroup, warp->mapNum)->music; +} + +u16 GetCurrLocationDefaultMusic(void) +{ + u16 music; + + // Play the desert music only when the sandstorm is active on Route 111. + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE111) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE111) + && GetSav1Weather() == 8) + return MUS_ASHROAD; + + music = GetLocationMusic(&gSaveBlock1Ptr->location); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1Ptr->pos.x < 24) + return MUS_DOORO_X1; + else + return MUS_GRANROAD; + } +} + +u16 GetWarpDestinationMusic(void) +{ + u16 music = GetLocationMusic(&sWarpDestination); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(MAUVILLE_CITY) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(MAUVILLE_CITY)) + return MUS_DOORO_X1; + else + return MUS_GRANROAD; + } +} + +void Overworld_ResetMapMusic(void) +{ + ResetMapMusic(); +} + +void Overworld_PlaySpecialMapMusic(void) +{ + u16 music = GetCurrLocationDefaultMusic(); + + if (music != MUS_OOAME && music != 0xFFFF) + { + if (gSaveBlock1Ptr->savedMusic) + music = gSaveBlock1Ptr->savedMusic; + else if (Overworld_GetMapTypeOfSaveblockLocation() == MAP_TYPE_UNDERWATER) + music = MUS_DEEPDEEP; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + music = MUS_NAMINORI; + } + + if (music != GetCurrentMapMusic()) + PlayNewMapMusic(music); +} + +void Overworld_SetSavedMusic(u16 songNum) +{ + gSaveBlock1Ptr->savedMusic = songNum; +} + +void Overworld_ClearSavedMusic(void) +{ + gSaveBlock1Ptr->savedMusic = 0; +} + +static void sub_8085810(void) +{ + if (FlagGet(FLAG_SPECIAL_FLAG_0x4001) != TRUE) + { + u16 newMusic = GetWarpDestinationMusic(); + u16 currentMusic = GetCurrentMapMusic(); + if (newMusic != MUS_OOAME && newMusic != 0xFFFF) + { + if (currentMusic == MUS_DEEPDEEP || currentMusic == MUS_NAMINORI) + return; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + newMusic = MUS_NAMINORI; + } + if (newMusic != currentMusic) + { + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + FadeOutAndFadeInNewMapMusic(newMusic, 4, 4); + else + FadeOutAndPlayNewMapMusic(newMusic, 8); + } + } +} + +void Overworld_ChangeMusicToDefault(void) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != GetCurrLocationDefaultMusic()) + FadeOutAndPlayNewMapMusic(GetCurrLocationDefaultMusic(), 8); +} + +void Overworld_ChangeMusicTo(u16 newMusic) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != newMusic && currentMusic != MUS_OOAME) + FadeOutAndPlayNewMapMusic(newMusic, 8); +} + +u8 GetMapMusicFadeoutSpeed(void) +{ + const struct MapHeader *mapHeader = warp1_get_mapheader(); + if (Overworld_MapTypeIsIndoors(mapHeader->mapType) == TRUE) + return 2; + else + return 4; +} + +void music_something(void) +{ + u16 currentMusic = GetCurrentMapMusic(); + u16 warpMusic = GetWarpDestinationMusic(); + if (FlagGet(FLAG_SPECIAL_FLAG_0x4001) != TRUE && warpMusic != GetCurrentMapMusic()) + { + if (currentMusic == MUS_NAMINORI + && VarGet(VAR_0x40CA) == 2 + && gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(SOOTOPOLIS_CITY) + && sWarpDestination.mapGroup == MAP_GROUP(SOOTOPOLIS_CITY) + && sWarpDestination.mapNum == MAP_NUM(SOOTOPOLIS_CITY) + && sWarpDestination.x == 0x1D + && sWarpDestination.y == 0x35) + return; + FadeOutMapMusic(GetMapMusicFadeoutSpeed()); + } +} + +bool8 sub_80859A0(void) +{ + return IsNotWaitingForBGMStop(); +} + +void Overworld_FadeOutMapMusic(void) +{ + FadeOutMapMusic(4); +} + +static void PlayAmbientCry(void) +{ + s16 x, y; + s8 pan; + s8 volume; + + PlayerGetDestCoords(&x, &y); + if (sIsAmbientCryWaterMon == TRUE + && !MetatileBehavior_IsSurfableWaterOrUnderwater(MapGridGetMetatileBehaviorAt(x, y))) + return; + pan = (Random() % 88) + 212; + volume = (Random() % 30) + 50; + PlayCry2(sAmbientCrySpecies, pan, volume, 1); +} + +void UpdateAmbientCry(s16 *state, u16 *delayCounter) +{ + u8 i, monsCount, divBy; + + switch (*state) + { + case 0: + if (sAmbientCrySpecies == SPECIES_NONE) + *state = 4; + else + *state = 1; + break; + case 1: + *delayCounter = (Random() % 2400) + 1200; + *state = 3; + break; + case 2: + divBy = 1; + monsCount = CalculatePlayerPartyCount(); + for (i = 0; i < monsCount; i++) + { + if (!GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT3) + && GetMonAbility(&gPlayerParty[0]) == ABILITY_SWARM) + { + divBy = 2; + break; + } + } + *delayCounter = ((Random() % 1200) + 1200) / divBy; + *state = 3; + break; + case 3: + (*delayCounter)--; + if (*delayCounter == 0) + { + PlayAmbientCry(); + *state = 2; + } + break; + case 4: + break; + } +} + +static void ChooseAmbientCrySpecies(void) +{ + if ((gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE130) + && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE130)) + && !IsMirageIslandPresent()) + { + // Only play water pokemon cries on this route + // when Mirage Island is not present + sIsAmbientCryWaterMon = TRUE; + sAmbientCrySpecies = GetLocalWaterMon(); + } + else + { + sAmbientCrySpecies = GetLocalWildMon(&sIsAmbientCryWaterMon); + } +} + +u8 GetMapTypeByGroupAndId(s8 mapGroup, s8 mapNum) +{ + return Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum)->mapType; +} + +u8 GetMapTypeByWarpData(struct WarpData *warp) +{ + return GetMapTypeByGroupAndId(warp->mapGroup, warp->mapNum); +} + +u8 Overworld_GetMapTypeOfSaveblockLocation(void) +{ + return GetMapTypeByWarpData(&gSaveBlock1Ptr->location); +} + +u8 get_map_light_from_warp0(void) +{ + return GetMapTypeByWarpData(&gUnknown_020322DC); +} + +bool8 is_map_type_1_2_3_5_or_6(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_UNDERWATER + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_6) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeAllowsTeleportAndFly(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_6 + || mapType == MAP_TYPE_CITY) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeIsIndoors(u8 mapType) +{ + if (mapType == MAP_TYPE_INDOOR + || mapType == MAP_TYPE_SECRET_BASE) + return TRUE; + else + return FALSE; +} + +u8 sav1_saved_warp2_map_get_name(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->warp2.mapGroup, gSaveBlock1Ptr->warp2.mapNum)->regionMapSectionId; +} + +u8 sav1_map_get_name(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->regionMapSectionId; +} + +u8 GetCurrentMapBattleScene(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)->battleType; +} + +static void overworld_bg_setup(void) +{ + InitBgsFromTemplates(0, gUnknown_08339DAC, ARRAY_COUNT(gUnknown_08339DAC)); + SetBgAttribute(1, BG_CTRL_ATTR_PALETTEMODE, 1); + SetBgAttribute(2, BG_CTRL_ATTR_PALETTEMODE, 1); + SetBgAttribute(3, BG_CTRL_ATTR_PALETTEMODE, 1); + gBGTilemapBuffers2 = AllocZeroed(0x800); + gBGTilemapBuffers1 = AllocZeroed(0x800); + gBGTilemapBuffers3 = AllocZeroed(0x800); + SetBgTilemapBuffer(1, gBGTilemapBuffers2); + SetBgTilemapBuffer(2, gBGTilemapBuffers1); + SetBgTilemapBuffer(3, gBGTilemapBuffers3); + sub_81971D0(); +} + +void overworld_free_bg_tilemaps(void) +{ + sub_81BE72C(); + sub_81971F4(); + if (gBGTilemapBuffers3 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers3); + if (gBGTilemapBuffers1 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers1); + if (gBGTilemapBuffers2 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers2); +} + +static void ResetSafariZoneFlag_(void) +{ + ResetSafariZoneFlag(); +} + +bool32 is_c1_link_related_active(void) +{ + if (gMain.callback1 == c1_link_related) + return TRUE; + else + return FALSE; +} + +static void DoCB1_Overworld(u16 newKeys, u16 heldKeys) +{ + struct FieldInput inputStruct; + + sub_808B578(); + FieldClearPlayerInput(&inputStruct); + FieldGetPlayerInput(&inputStruct, newKeys, heldKeys); + if (!ScriptContext2_IsEnabled()) + { + if (sub_809C014(&inputStruct) == 1) + { + ScriptContext2_Enable(); + HideMapNamePopUpWindow(); + } + else + { + player_step(inputStruct.dpadDirection, newKeys, heldKeys); + } + } +} + +void CB1_Overworld(void) +{ + if (gMain.callback2 == CB2_Overworld) + DoCB1_Overworld(gMain.newKeys, gMain.heldKeys); +} + +static void OverworldBasic(void) +{ + ScriptContext2_RunScript(); + RunTasks(); + AnimateSprites(); + CameraUpdate(); + UpdateCameraPanning(); + BuildOamBuffer(); + UpdatePaletteFade(); + sub_80A0A38(); + do_scheduled_bg_tilemap_copies_to_vram(); +} + +// This CB2 is used when starting +void CB2_OverworldBasic(void) +{ + OverworldBasic(); +} + +void CB2_Overworld(void) +{ + bool32 fading = (gPaletteFade.active != 0); + if (fading) + SetVBlankCallback(NULL); + OverworldBasic(); + if (fading) + SetFieldVBlankCallback(); +} + +void SetMainCallback1(MainCallback cb) +{ + gMain.callback1 = cb; +} + +void sub_8085E94(void *a0) +{ + sUnknown_03000E0C = a0; +} + +static bool8 map_post_load_hook_exec(void) +{ + if (gUnknown_03005DB0 != NULL) + { + if (!gUnknown_03005DB0()) + { + return FALSE; + } + else + { + gUnknown_03005DB0 = NULL; + gFieldCallback = NULL; + } + } + else + { + if (gFieldCallback != NULL) + gFieldCallback(); + else + mapldr_default(); + + gFieldCallback = NULL; + } + + return TRUE; +} + +void CB2_NewGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + NewGameInitData(); + player_avatar_init_params_reset(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = ExecuteTruckSequence; + gUnknown_03005DB0 = NULL; + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); +} + +void CB2_WhiteOut(void) +{ + u8 val; + + if (++gMain.state >= 120) + { + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + DoWhiteOut(); + player_avatar_init_params_reset(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = sub_80AF3C8; + val = 0; + do_load_map_stuff_loop(&val); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_LoadMap(void) +{ + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + SetMainCallback2(c2_change_map); + gMain.savedCallback = CB2_LoadMap2; +} + +static void CB2_LoadMap2(void) +{ + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); +} + +void sub_8086024(void) +{ + if (!gMain.state) + { + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + SetMainCallback1(NULL); + } + if (load_map_stuff(&gMain.state, 1)) + { + SetFieldVBlankCallback(); + SetMainCallback1(CB1_Overworld); + SetMainCallback2(CB2_Overworld); + } +} + +void sub_8086074(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF314; + SetMainCallback2(c2_80567AC); +} + +static void c2_80567AC(void) +{ + if (map_loading_iteration_3(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback1(c1_link_related); + sub_8086C2C(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToField(void) +{ + if (is_c1_link_related_active() == TRUE) + { + SetMainCallback2(CB2_ReturnToFieldLink); + } + else + { + FieldClearVBlankHBlankCallbacks(); + SetMainCallback2(CB2_ReturnToFieldLocal); + } +} + +void CB2_ReturnToFieldLocal(void) +{ + if (sub_8086638(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback2(CB2_Overworld); + } +} + +void CB2_ReturnToFieldLink(void) +{ + if (!sub_8087598() && map_loading_iteration_2_link(&gMain.state)) + SetMainCallback2(CB2_Overworld); +} + +void c2_8056854(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + SetMainCallback1(c1_link_related); + sub_8086C2C(); + + if (gWirelessCommType != 0) + gFieldCallback = sub_80AF314; + else + gFieldCallback = sub_80AF214; + + ScriptContext1_Init(); + ScriptContext2_Disable(); + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldWithOpenMenu(void) +{ + FieldClearVBlankHBlankCallbacks(); + gUnknown_03005DB0 = sub_80AF6A4; + CB2_ReturnToField(); +} + +void sub_80861B0(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF188; + CB2_ReturnToField(); +} + +void CB2_ReturnToFieldContinueScript(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF168; + CB2_ReturnToField(); +} + +void sub_80861E8(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80AF3C8; + CB2_ReturnToField(); +} + +static void sub_8086204(void) +{ + if ((gMapHeader.flags & 0xF8) == 8 && sub_80E909C() == TRUE) + ShowMapNamePopup(); + sub_80AF3C8(); +} + +void CB2_ContinueSavedGame(void) +{ + u8 trainerHillMapId; + + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + if (gSaveFileStatus == 0xFF) + sub_81A3908(); + + LoadSaveblockMapHeader(); + set_warp2_warp3_to_neg_1(); + trainerHillMapId = GetCurrentTrainerHillMapId(); + if (gMapHeader.mapDataId == 0x169) + sub_81AA2F8(); + else if (trainerHillMapId != 0 && trainerHillMapId != 6) + sub_81D5F48(); + else + LoadSaveblockMapObjScripts(); + + UnfreezeMapObjects(); + DoTimeBasedEvents(); + sub_8084788(); + if (gMapHeader.mapDataId == 0x169) + battle_pyramid_map_load_related(1); + else if (trainerHillMapId != 0) + trainer_hill_map_load_related(); + else + sub_8087D74(); + + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + sub_8195E10(); + if (GetSecretBase2Field_9() == 1) + { + ClearSecretBase2Field_9(); + warp1_set_to_sav1w(); + warp_in(); + sub_80EDB44(); + SetMainCallback2(CB2_LoadMap); + } + else + { + sub_80EDB44(); + gFieldCallback = sub_8086204; + SetMainCallback1(CB1_Overworld); + CB2_ReturnToField(); + } +} + +static void FieldClearVBlankHBlankCallbacks(void) +{ + if (warp0_in_pokecenter() == TRUE) + CloseLink(); + + if (gWirelessCommType != 0) + { + EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_TIMER3 | INTR_FLAG_SERIAL); + DisableInterrupts(INTR_FLAG_HBLANK); + } + else + { + u16 savedIme = REG_IME; + REG_IME = 0; + REG_IE &= ~INTR_FLAG_HBLANK; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + } + + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +static void SetFieldVBlankCallback(void) +{ + SetVBlankCallback(VBlankCB_Field); +} + +static void VBlankCB_Field(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + ScanlineEffect_InitHBlankDmaTransfer(); + FieldUpdateBgTilemapScroll(); + TransferPlttBuffer(); + TransferTilesetAnimsBuffer(); +} + +static void sub_80863B0(void) +{ + u8 val; + + if (sub_81A9E6C()) + { + door_upload_tiles(); + ScanlineEffect_SetParams(gUnknown_08339DBC); + } + else if ((val = Overworld_GetFlashLevel())) + { + sub_80B00E8(val); + ScanlineEffect_SetParams(gUnknown_08339DBC); + } +} + +static bool32 map_loading_iteration_3(u8 *state) +{ + switch (*state) + { + case 0: + overworld_bg_setup(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 1: + mli0_load_map(1); + (*state)++; + break; + case 2: + sub_8086988(TRUE); + (*state)++; + break; + case 3: + sub_8086AE4(); + sub_80869DC(); + sub_8086B14(); + sub_8086AAC(); + (*state)++; + break; + case 4: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 8: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + sub_800E0E8(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + return TRUE; + } + + return FALSE; +} + +static bool32 load_map_stuff(u8 *state, u32 a2) +{ + switch (*state) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + mli0_load_map(a2); + (*state)++; + break; + case 1: + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 2: + sub_8086988(a2); + (*state)++; + break; + case 3: + mli4_mapscripts_and_other(); + sub_8086A80(); + (*state)++; + break; + case 4: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 6: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 8: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 9: + DrawWholeMapView(); + (*state)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if ((gMapHeader.flags & 0xF8) == 8 && sub_80E909C() == 1) + ShowMapNamePopup(); + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 13: + return TRUE; + } + + return FALSE; +} + +static bool32 sub_8086638(u8 *state) +{ + switch (*state) + { + case 0: + sub_80867C8(); + sub_80867D8(); + sub_8086988(0); + sub_8086A68(); + sub_8086A80(); + (*state)++; + break; + case 1: + sub_8086860(); + sub_81D64C0(); + (*state)++; + break; + case 2: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 3: + return TRUE; + } + + return FALSE; +} + +static bool32 map_loading_iteration_2_link(u8 *state) +{ + switch (*state) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + sub_80867C8(); + sub_80867D8(); + (*state)++; + break; + case 1: + sub_8086988(1); + (*state)++; + break; + case 2: + sub_8086B9C(); + sub_8086A68(); + sub_8086AC8(); + (*state)++; + break; + case 3: + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + (*state)++; + break; + case 4: + move_tilemap_camera_to_upper_left_corner(); + (*state)++; + break; + case 5: + copy_map_tileset1_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 6: + copy_map_tileset2_to_vram(gMapHeader.mapData); + (*state)++; + break; + case 7: + if (free_temp_tile_data_buffers_if_possible() != TRUE) + { + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*state)++; + } + break; + case 8: + DrawWholeMapView(); + (*state)++; + break; + case 9: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*state)++; + break; + case 11: + if (gWirelessCommType != 0) + { + sub_800E0E8(); + CreateWirelessStatusIndicatorSprite(0, 0); + } + (*state)++; + break; + case 12: + if (map_post_load_hook_exec()) + (*state)++; + break; + case 10: + (*state)++; + break; + case 13: + SetFieldVBlankCallback(); + (*state)++; + return TRUE; + } + + return FALSE; +} + +static void do_load_map_stuff_loop(u8 *state) +{ + while (!load_map_stuff(state, 0)); +} + +static void sub_80867C8(void) +{ + sub_81BE6AC(); + MoveSaveBlocks_ResetHeap(); +} + +static void sub_80867D8(void) +{ + SetGpuReg(REG_OFFSET_DISPCNT, 0); + ScanlineEffect_Stop(); + + DmaClear16(3, PLTT + 2, PLTT_SIZE - 2); + DmaFillLarge16(3, 0, (void *)(VRAM + 0x0), 0x18000, 0x1000); + ResetOamRange(0, 128); + LoadOam(); +} + +static void sub_8086860(void) +{ + sub_80863B0(); + map_loading_lcd_reset(); + sub_8197200(); + mapdata_load_assets_to_gpu_and_full_redraw(); +} + +static void map_loading_lcd_reset(void) +{ + clear_scheduled_bg_copies_to_vram(); + reset_temp_tile_data_buffers(); + SetGpuReg(REG_OFFSET_MOSAIC, 0); + SetGpuReg(REG_OFFSET_WININ, 0x1F1F); + SetGpuReg(REG_OFFSET_WINOUT, 0x101); + SetGpuReg(REG_OFFSET_WIN0H, 0xFF); + SetGpuReg(REG_OFFSET_WIN0V, 0xFF); + SetGpuReg(REG_OFFSET_WIN1H, 0xFFFF); + SetGpuReg(REG_OFFSET_WIN1V, 0xFFFF); + SetGpuReg(REG_OFFSET_BLDCNT, gUnknown_82EC7C4[1] | gUnknown_82EC7C4[2] | gUnknown_82EC7C4[3] + | BLDCNT_TGT2_OBJ | BLDCNT_EFFECT_BLEND); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(13, 7)); + overworld_bg_setup(); + schedule_bg_copy_tilemap_to_vram(1); + schedule_bg_copy_tilemap_to_vram(2); + schedule_bg_copy_tilemap_to_vram(3); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + ChangeBgX(1, 0, 0); + ChangeBgY(1, 0, 0); + ChangeBgX(2, 0, 0); + ChangeBgY(2, 0, 0); + ChangeBgX(3, 0, 0); + ChangeBgY(3, 0, 0); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON + | DISPCNT_OBJ_1D_MAP | DISPCNT_HBLANK_INTERVAL); + ShowBg(0); + ShowBg(1); + ShowBg(2); + ShowBg(3); + sub_8098128(); +} + +static void sub_8086988(u32 a1) +{ + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + ScanlineEffect_Clear(); + dp13_810BB8C(); + ResetCameraUpdateInfo(); + InstallCameraPanAheadCallback(); + if (!a1) + npc_paltag_set_load(0); + else + npc_paltag_set_load(1); + + FieldEffectActiveListClear(); + sub_80AAFA4(); + sub_80AEE84(); + if (!a1) + SetUpFieldTasks(); + mapheader_run_script_with_tag_x5(); + sub_81BE6B8(); +} + +static void sub_80869DC(void) +{ + gUnknown_03005DEC = 0; + gUnknown_03005DE8 = 0; + sub_808D438(); + SpawnFieldObjectsInView(0, 0); + mapheader_run_first_tag4_script_list_match(); +} + +static void mli4_mapscripts_and_other(void) +{ + s16 x, y; + struct UnkPlayerStruct *player; + + gUnknown_03005DEC = 0; + gUnknown_03005DE8 = 0; + sub_808D438(); + sav1_camera_get_focus_coords(&x, &y); + player = sub_80852D4(); + InitPlayerAvatar(x, y, player->player_field_1, gSaveBlock2Ptr->playerGender); + SetPlayerAvatarTransitionFlags(player->player_field_0); + player_avatar_init_params_reset(); + SpawnFieldObjectsInView(0, 0); + mapheader_run_first_tag4_script_list_match(); +} + +static void sub_8086A68(void) +{ + sub_808E16C(0, 0); + RotatingGate_InitPuzzleAndGraphics(); + mapheader_run_script_with_tag_x7(); +} + +static void sub_8086A80(void) +{ + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_15 = 1; + InitCameraUpdateCallback(gPlayerAvatar.spriteId); +} + +static void sub_8086AAC(void) +{ + InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4)); +} + +static void sub_8086AC8(void) +{ + InitCameraUpdateCallback(sub_8087858(gUnknown_03005DB4)); +} + +static void sub_8086AE4(void) +{ + u16 x, y; + sav1_camera_get_focus_coords(&x, &y); + sub_8088B3C(x + gUnknown_03005DB4, y); +} + +static void sub_8086B14(void) +{ + u16 i; + u16 x, y; + + sav1_camera_get_focus_coords(&x, &y); + x -= gUnknown_03005DB4; + + for (i = 0; i < gFieldLinkPlayerCount; i++) + { + SpawnLinkPlayerMapObject(i, i + x, y, gLinkPlayers[i].gender); + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); + } + + sub_8086C40(); +} + +static void sub_8086B9C(void) +{ + u16 i; + for (i = 0; i < gFieldLinkPlayerCount; i++) + CreateLinkPlayerSprite(i, gLinkPlayers[i].version); +} + +static void c1_link_related(void) +{ + if (gWirelessCommType == 0 || !sub_800F0B8() || !sub_8009F3C()) + { + u8 var = gUnknown_03005DB4; + sub_8086F38(gLinkPartnersHeldKeys, var); + sub_8086FA0(sUnknown_03000E14(var)); + sub_8086C40(); + } +} + +void sub_8086C2C(void) +{ + sub_8086C90(); + c1_link_related_func_set(sub_80870B0); +} + +static void sub_8086C40(void) +{ + sub_808709C(gLinkPartnersHeldKeys); +} + +static void c1_link_related_func_set(u16 (*func)(u32)) +{ + sUnknown_03000E19 = 0; + sUnknown_03000E14 = func; +} + +static void sub_8086C64(void) +{ + if (gWirelessCommType != 0 && ++sUnknown_03000E19 > 60) + sub_8010198(); +} + +static void sub_8086C90(void) +{ + s32 i; + for (i = 0; i < 4; i++) + sUnknown_03000E10[i] = 0x80; +} + +static bool32 sub_8086CA8(u16 a1) +{ + s32 i; + s32 count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (sUnknown_03000E10[i] != a1) + return FALSE; + return TRUE; +} + +static bool32 sub_8086CE0(u16 a1) +{ + s32 i; + s32 count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (sUnknown_03000E10[i] == a1) + return TRUE; + return FALSE; +} + +static void sub_8086D18(u32 a1, u16 a2, struct UnkStruct_8054FF8 *a3, u16 *a4) +{ + const u8 *script; + + if (sUnknown_03000E10[a1] == 0x80) + { + script = sub_8087370(a3); + if (script) + { + *a4 = sub_8087480(script); + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087530(script); + } + return; + } + if (sub_8086CE0(0x83) == 1) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087584(); + } + return; + } + switch (a2) + { + case 24: + if (sub_8087358(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_808751C(); + } + } + break; + case 18: + if (sub_8087388(a3) == TRUE) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_808754C(); + } + } + break; + case 25: + script = sub_80873B4(a3); + if (script) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_80870F8); + sub_8087568(script); + } + } + break; + case 27: + if (sub_8087340(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_808711C); + sub_8087510(); + } + } + break; + case 28: + if (sub_8087340(a3)) + { + sUnknown_03000E10[a1] = 0x81; + if (a3->b) + { + c1_link_related_func_set(sub_8087140); + sub_8087510(); + } + } + break; + } + } + + switch (a2) + { + case 23: + sUnknown_03000E10[a1] = 0x83; + break; + case 22: + sUnknown_03000E10[a1] = 0x82; + break; + case 26: + sUnknown_03000E10[a1] = 0x80; + if (a3->b) + c1_link_related_func_set(sub_80870B0); + break; + case 29: + if (sUnknown_03000E10[a1] == 0x82) + sUnknown_03000E10[a1] = 0x81; + break; + } +} + +static void sub_8086F38(u16 *a1, s32 a2) +{ + struct UnkStruct_8054FF8 st; + s32 i; + + for (i = 0; i < 4; i++) + { + u8 v5 = a1[i]; + u16 v8 = 0; + sub_80872D8(i, a2, &st); + sub_8086D18(i, v5, &st, &v8); + if (sUnknown_03000E10[i] == 0x80) + v8 = sub_8087068(v5); + sub_808796C(i, v8); + } +} + +static void sub_8086FA0(u16 a1) +{ + if (a1 >= 17 && a1 < 30) + gUnknown_03005DA8 = a1; + else + gUnknown_03005DA8 = 17; + + if (gWirelessCommType != 0 + && sub_8087690() > 1 + && is_c1_link_related_active() == TRUE + && sub_8009F3C() == TRUE) + { + switch (a1) + { + case 17: + case 18: + case 19: + case 20: + case 21: + case 24: + case 25: + gUnknown_03005DA8 = 0; + break; + } + } +} + +static u16 sub_808700C(u32 a1) +{ + if (gMain.heldKeys & DPAD_UP) + return 19; + else if (gMain.heldKeys & DPAD_DOWN) + return 18; + else if (gMain.heldKeys & DPAD_LEFT) + return 20; + else if (gMain.heldKeys & DPAD_RIGHT) + return 21; + else if (gMain.newKeys & START_BUTTON) + return 24; + else if (gMain.newKeys & A_BUTTON) + return 25; + else + return 17; +} + +static u16 sub_8087068(u16 a1) +{ + switch (a1) + { + case 21: + return 4; + case 20: + return 3; + case 19: + return 1; + case 18: + return 2; + default: + return 0; + } +} + +static void sub_808709C(u16 *a1) +{ + s32 i; + for (i = 0; i < 4; i++) + a1[i] = 17; +} + +static u16 sub_80870B0(u32 a1) +{ + if (ScriptContext2_IsEnabled() == 1) + return 17; + if (sub_800B4DC() > 4) + return 27; + if (sub_8087690() <= 4) + return sub_808700C(a1); + return 28; +} + +static u16 sub_80870EC(u32 a1) +{ + sub_8086C64(); + return 17; +} + +static u16 sub_80870F8(u32 a1) +{ + u16 retVal; + if (ScriptContext2_IsEnabled() == TRUE) + { + retVal = 17; + } + else + { + retVal = 26; + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_808711C(u32 a1) +{ + u16 retVal; + if (sub_800B4DC() > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_8087140(u32 a1) +{ + u16 retVal; + if (sub_8087690() > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + c1_link_related_func_set(sub_80870EC); + } + return retVal; +} + +static u16 sub_8087164(u32 a1) +{ + sub_8086C64(); + return 17; +} + +static u16 sub_8087170(u32 linkPlayerId) +{ + if (sUnknown_03000E10[linkPlayerId] == 0x82) + { + if (gMain.newKeys & B_BUTTON) + { + c1_link_related_func_set(sub_8087164); + return 29; + } + else + { + return 17; + } + } + else + { + sub_8086C64(); + return 17; + } +} + +static u16 sub_80871AC(u32 a1) +{ + c1_link_related_func_set(sub_8087170); + return 22; +} + +static u16 sub_80871C0(u32 a1) +{ + return 17; +} + +static u16 sub_80871C4(u32 a1) +{ + if (sUnknown_03000E10[a1] != 0x83) + sub_8086C64(); + if (sub_8086CA8(0x83) == TRUE) + { + ScriptContext1_SetupScript(EventScript_277513); + c1_link_related_func_set(sub_80871C0); + } + return 17; +} + +static u16 sub_80871FC(u32 a1) +{ + c1_link_related_func_set(sub_80871C4); + return 23; +} + +static u16 sub_8087210(u32 a1) +{ + return 17; +} + +u32 sub_8087214(void) +{ + if (sub_8086CE0(0x83) == TRUE) + return 2; + if (sUnknown_03000E14 == sub_8087170 && sUnknown_03000E10[gUnknown_03005DB4] != 0x82) + return 0; + if (sUnknown_03000E14 == sub_8087164 && sUnknown_03000E10[gUnknown_03005DB4] == 0x81) + return 2; + if (sub_8086CA8(0x82) != 0) + return 1; + return 0; +} + +bool32 sub_808727C(void) +{ + return sub_8086CE0(0x83); +} + +u16 sub_8087288(void) +{ + c1_link_related_func_set(sub_80871AC); + return 0; +} + +u16 sub_808729C(void) +{ + c1_link_related_func_set(sub_80870F8); + return 0; +} + +u16 sub_80872B0(void) +{ + c1_link_related_func_set(sub_80871FC); + return 0; +} + +u16 sub_80872C4(void) +{ + c1_link_related_func_set(sub_8087210); + return 0; +} + +static void sub_80872D8(s32 linkPlayerId, s32 a2, struct UnkStruct_8054FF8 *a3) +{ + s16 x, y; + + a3->a = linkPlayerId; + a3->b = (linkPlayerId == a2) ? 1 : 0; + a3->c = gLinkPlayerMapObjects[linkPlayerId].mode; + a3->d = sub_80878A0(linkPlayerId); + sub_8087878(linkPlayerId, &x, &y); + a3->sub.x = x; + a3->sub.y = y; + a3->sub.height = sub_80878C0(linkPlayerId); + a3->field_C = MapGridGetMetatileBehaviorAt(x, y); +} + +static bool32 sub_8087340(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +static bool32 sub_8087358(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +static u8 *sub_8087370(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2) + return 0; + return sub_809D0F4(&a1->sub); +} + +static bool32 sub_8087388(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2 && a1->c != 0) + return FALSE; + else if (!MetatileBehavior_IsSouthArrowWarp(a1->field_C)) + return FALSE; + else if (a1->d != 1) + return FALSE; + else + return TRUE; +} + +static const u8 *sub_80873B4(struct UnkStruct_8054FF8 *a1) +{ + struct MapPosition unkStruct; + u8 linkPlayerId; + + if (a1->c && a1->c != 2) + return 0; + + unkStruct = a1->sub; + unkStruct.x += gUnknown_08339D64[a1->d].x; + unkStruct.y += gUnknown_08339D64[a1->d].y; + unkStruct.height = 0; + linkPlayerId = GetLinkPlayerIdAt(unkStruct.x, unkStruct.y); + + if (linkPlayerId != 4) + { + if (!a1->b) + return EventScript_TradeRoom_TooBusyToNotice; + else if (sUnknown_03000E10[linkPlayerId] != 0x80) + return EventScript_TradeRoom_TooBusyToNotice; + else if (!sub_80B39D4(linkPlayerId)) + return EventScript_TradeRoom_ReadTrainerCard1; + else + return EventScript_TradeRoom_ReadTrainerCard2; + } + + return sub_809C2C8(&unkStruct, a1->field_C, a1->d); +} + +static u16 sub_8087480(const u8 *script) +{ + if (script == gUnknown_08277388) + return 10; + else if (script == gUnknown_082773A3) + return 9; + else if (script == gUnknown_082773BE) + return 10; + else if (script == gUnknown_082773D9) + return 9; + else if (script == gUnknown_0827741D) + return 10; + else if (script == gUnknown_08277432) + return 9; + else if (script == gUnknown_08277447) + return 10; + else if (script == gUnknown_0827745C) + return 9; + else if (script == gUnknown_08277374) + return 10; + else if (script == gUnknown_0827737E) + return 9; + else if (script == gUnknown_082773F5) + return 10; + else if (script == gUnknown_082773FF) + return 9; + else + return 0; +} + +static void sub_8087510(void) +{ + ScriptContext2_Enable(); +} + +static void sub_808751C(void) +{ + PlaySE(SE_WIN_OPEN); + ShowStartMenu(); + ScriptContext2_Enable(); +} + +static void sub_8087530(const u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +static void sub_808754C(void) +{ + PlaySE(SE_WIN_OPEN); + ScriptContext1_SetupScript(gUnknown_082774EF); + ScriptContext2_Enable(); +} + +static void sub_8087568(const u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +static void sub_8087584(void) +{ + ScriptContext1_SetupScript(gUnknown_08277509); + ScriptContext2_Enable(); +} + +bool32 sub_8087598(void) +{ + if (!is_c1_link_related_active()) + return 0; + if (sub_800B4DC() >= 3) + sUnknown_03000E18 = 1; + else + sUnknown_03000E18 = 0; + return sUnknown_03000E18; +} + +bool32 sub_80875C8(void) +{ + u8 temp; + + if (sub_800B4DC() < 2) + return FALSE; + else if (is_c1_link_related_active() != TRUE) + return FALSE; + else if (sub_8009F3C() != TRUE) + return FALSE; + else if (sUnknown_03000E14 == sub_808711C) + return TRUE; + else if (sUnknown_03000E14 != sub_80870F8) + return FALSE; + + temp = sUnknown_03000E18; + sUnknown_03000E18 = 0; + + if (temp == TRUE) + return TRUE; + else if (gPaletteFade.active && gPaletteFade.softwareFadeFinishing) + return TRUE; + else + return FALSE; +} + +bool32 sub_8087634(void) +{ + if (sub_8087690() < 2) + return FALSE; + else if (is_c1_link_related_active() != TRUE) + return FALSE; + else if (sub_8009F3C() != TRUE) + return FALSE; + else if (sUnknown_03000E14 == sub_8087140) + return TRUE; + else + return FALSE; +} + +bool32 sub_808766C(void) +{ + if (gWirelessCommType != 0) + return FALSE; + else if (!sub_8009F3C()) + return FALSE; + else + return TRUE; +} + +static u32 sub_8087690(void) +{ + if (gWirelessCommType != 0) + return gUnknown_03005000.unk_9e8.unk_232; + else + return gLink.sendQueue.count; +} + +static void ZeroLinkPlayerMapObject(struct LinkPlayerMapObject *linkPlayerMapObj) +{ + memset(linkPlayerMapObj, 0, sizeof(struct LinkPlayerMapObject)); +} + +void ZeroAllLinkPlayerMapObjects(void) +{ + memset(gLinkPlayerMapObjects, 0, sizeof(gLinkPlayerMapObjects)); +} + +static void ZeroMapObject(struct MapObject *mapObj) +{ + memset(mapObj, 0, sizeof(struct MapObject)); +} + +static void SpawnLinkPlayerMapObject(u8 linkPlayerId, s16 x, s16 y, u8 a4) +{ + u8 mapObjId = sub_808D4F4(); + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + ZeroLinkPlayerMapObject(linkPlayerMapObj); + ZeroMapObject(mapObj); + + linkPlayerMapObj->active = 1; + linkPlayerMapObj->linkPlayerId = linkPlayerId; + linkPlayerMapObj->mapObjId = mapObjId; + linkPlayerMapObj->mode = 0; + + mapObj->active = 1; + mapObj->mapobj_bit_1 = a4; + mapObj->range.as_byte = 2; + mapObj->spriteId = 64; + + InitLinkPlayerMapObjectPos(mapObj, x, y); +} + +static void InitLinkPlayerMapObjectPos(struct MapObject *mapObj, s16 x, s16 y) +{ + mapObj->coords2.x = x; + mapObj->coords2.y = y; + mapObj->coords3.x = x; + mapObj->coords3.y = y; + sub_8093038(x, y, &mapObj->coords1.x, &mapObj->coords1.y); + mapObj->coords1.x += 8; + FieldObjectUpdateZCoord(mapObj); +} + +static void sub_80877DC(u8 linkPlayerId, u8 a2) +{ + if (gLinkPlayerMapObjects[linkPlayerId].active) + { + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + mapObj->range.as_byte = a2; + } +} + +static void sub_808780C(u8 linkPlayerId) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + if (mapObj->spriteId != 64 ) + DestroySprite(&gSprites[mapObj->spriteId]); + linkPlayerMapObj->active = 0; + mapObj->active = 0; +} + +static u8 sub_8087858(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->spriteId; +} + +static void sub_8087878(u8 linkPlayerId, u16 *x, u16 *y) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + *x = mapObj->coords2.x; + *y = mapObj->coords2.y; +} + +static u8 sub_80878A0(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->range.as_byte; +} + +static u8 sub_80878C0(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->mapobj_unk_0B_0; +} + +static s32 sub_80878E4(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return 16 - (s8)mapObj->mapobj_unk_21; +} + +static u8 GetLinkPlayerIdAt(s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 4; i++) + { + if (gLinkPlayerMapObjects[i].active + && (gLinkPlayerMapObjects[i].mode == 0 || gLinkPlayerMapObjects[i].mode == 2)) + { + struct MapObject *mapObj = &gMapObjects[gLinkPlayerMapObjects[i].mapObjId]; + if (mapObj->coords2.x == x && mapObj->coords2.y == y) + return i; + } + } + return 4; +} + +static void sub_808796C(u8 linkPlayerId, u8 a2) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + if (linkPlayerMapObj->active) + { + if (a2 > 10) + mapObj->mapobj_bit_2 = 1; + else + gUnknown_08339E00[gUnknown_08339DC8[linkPlayerMapObj->mode](linkPlayerMapObj, mapObj, a2)](linkPlayerMapObj, mapObj); + } +} + +static u8 sub_80879D8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_08339DD4[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_80879F8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 1; +} + +static u8 sub_80879FC(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_08339DD4[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_8087A1C(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 0; +} + +static u8 sub_8087A20(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + s16 x, y; + + mapObj->range.as_byte = npc_something3(a3, mapObj->range.as_byte); + FieldObjectMoveDestCoords(mapObj, mapObj->range.as_byte, &x, &y); + + if (LinkPlayerDetectCollision(linkPlayerMapObj->mapObjId, mapObj->range.as_byte, x, y)) + { + return 0; + } + else + { + mapObj->mapobj_unk_21 = 16; + npc_coords_shift(mapObj, x, y); + FieldObjectUpdateZCoord(mapObj); + return 1; + } +} + +static u8 sub_8087A88(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + mapObj->range.as_byte = npc_something3(a3, mapObj->range.as_byte); + return 0; +} + +static void sub_8087AA0(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + linkPlayerMapObj->mode = 0; +} + +static void sub_8087AA8(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + mapObj->mapobj_unk_21--; + linkPlayerMapObj->mode = 1; + MoveCoords(mapObj->range.as_byte, &mapObj->coords1.x, &mapObj->coords1.y); + if (!mapObj->mapobj_unk_21) + { + npc_coords_shift_still(mapObj); + linkPlayerMapObj->mode = 2; + } +} + +static u8 npc_something3(u8 a1, u8 a2) +{ + switch (a1 - 1) + { + case 0: + case 6: + return 2; + case 1: + case 7: + return 1; + case 2: + case 8: + return 3; + case 3: + case 9: + return 4; + } + return a2; +} + +static u8 LinkPlayerDetectCollision(u8 selfMapObjId, u8 a2, s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 16; i++) + { + if (i != selfMapObjId) + { + if ((gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y) + || (gMapObjects[i].coords3.x == x && gMapObjects[i].coords3.y == y)) + { + return 1; + } + } + } + return MapGridIsImpassableAt(x, y); +} + +static void CreateLinkPlayerSprite(u8 linkPlayerId, u8 gameVersion) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + struct Sprite *sprite; -// Static type declarations + if (linkPlayerMapObj->active) + { + switch (gameVersion) + { + case VERSION_FIRE_RED: + case VERSION_LEAF_GREEN: + mapObj->spriteId = AddPseudoFieldObject(sub_808BD6C(mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + case VERSION_RUBY: + case VERSION_SAPPHIRE: + mapObj->spriteId = AddPseudoFieldObject(sub_808BD7C(mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + case VERSION_EMERALD: + mapObj->spriteId = AddPseudoFieldObject(GetRivalAvatarGraphicsIdByStateIdAndGender(0, mapObj->mapobj_bit_1), SpriteCB_LinkPlayer, 0, 0, 0); + break; + } -// Static RAM declarations -IWRAM_DATA void *gUnknown_03000E0C; -IWRAM_DATA u8 gUnknown_03000E10[4]; -IWRAM_DATA u8 (*gUnknown_03000E14)(u32); -IWRAM_DATA u8 gUnknown_03000E18; -IWRAM_DATA u8 gUnknown_03000E19; -IWRAM_DATA void *rom4_c_unused_03000e1c; + sprite = &gSprites[mapObj->spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->data[0] = linkPlayerId; + mapObj->mapobj_bit_2 = 0; + } +} -// Static ROM declarations +static void SpriteCB_LinkPlayer(struct Sprite *sprite) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[sprite->data[0]]; + struct MapObject *mapObj = &gMapObjects[linkPlayerMapObj->mapObjId]; + sprite->pos1.x = mapObj->coords1.x; + sprite->pos1.y = mapObj->coords1.y; + SetObjectSubpriorityByZCoord(mapObj->elevation, sprite, 1); + sprite->oam.priority = ZCoordToPriority(mapObj->elevation); -// .rodata + if (!linkPlayerMapObj->mode) + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObj->range.as_byte)); + else + StartSpriteAnimIfDifferent(sprite, get_go_image_anim_num(mapObj->range.as_byte)); -// .text + sub_80979D4(sprite, 0); + if (mapObj->mapobj_bit_2) + { + sprite->invisible = ((sprite->data[7] & 4) >> 2); + sprite->data[7]++; + } +} diff --git a/src/player_pc.c b/src/player_pc.c new file mode 100644 index 000000000..2bdf527e7 --- /dev/null +++ b/src/player_pc.c @@ -0,0 +1,1364 @@ +#include "global.h" +#include "constants/songs.h" +#include "bg.h" +#include "decoration.h" +#include "event_scripts.h" +#include "field_fadetransition.h" +#include "field_map_obj.h" +#include "field_screen.h" +#include "field_weather.h" +#include "international_string_util.h" +#include "item.h" +#include "item_icon.h" +#include "item_menu.h" +#include "constants/items.h" +#include "list_menu.h" +#include "mail.h" +#include "main.h" +#include "malloc.h" +#include "menu.h" +#include "menu_helpers.h" +#include "menu_indicators.h" +#include "overworld.h" +#include "palette.h" +#include "party_menu.h" +#include "pokenav.h" +#include "player_pc.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "window.h" + +// structures +struct Struct203BCC4 +{ + struct ListMenuItem unk0[51]; + u8 unk198[51][0x18]; + u8 windowIds[6]; + u8 unk666; + u8 spriteId; + u8 spriteIds[7]; +}; + +// extern offset +void (*gFieldCallback)(void); + +// static functions +static void InitPlayerPCMenu(u8 taskId); +static void PlayerPCProcessMenuInput(u8 taskId); +static void InitItemStorageMenu(u8 taskId, u8 var); + +static u8 GetMailboxMailCount(void); +static void Mailbox_UpdateMailList(void); +static void Mailbox_DrawMailboxMenu(u8 taskId); +static void Mailbox_ProcessInput(u8 taskId); +static void Mailbox_PrintWhatToDoWithPlayerMailText(u8 taskId); +static void Mailbox_ReturnToPlayerPC(u8); +static void Mailbox_PrintMailOptions(u8 taskId); +static void Mailbox_MailOptionsProcessInput(u8 taskId); + +static void PlayerPC_ItemStorage(u8 taskId); +static void PlayerPC_Mailbox(u8 taskId); +static void PlayerPC_Decoration(u8 var); +static void PlayerPC_TurnOff(u8 taskId); + +static void Mailbox_DoMailMoveToBag(u8 taskId); +static void Mailbox_DoMailRead(u8 taskId); +static void Mailbox_MoveToBag(u8 taskId); +static void Mailbox_Give(u8 taskId); +static void Mailbox_Cancel(u8 taskId); + +static void Mailbox_CancelMoveToBag(u8 taskId); +static void Mailbox_MoveToBagYesNoPrompt(u8 taskId); +static void Mailbox_DrawYesNoBeforeMove(u8 taskId); +static void Mailbox_DoGiveMailPokeMenu(u8 taskId); +static void Mailbox_NoPokemonForMail(u8 taskId); + +static void Mailbox_FadeAndReadMail(u8 taskId); +static void Mailbox_ReturnToFieldFromReadMail(void); +static void Mailbox_DoRedrawMailboxMenuAfterReturn(void); +static void pal_fill_for_maplights_or_black(void); +static void Mailbox_HandleReturnToProcessInput(u8 taskId); +static void Mailbox_UpdateMailListAfterDeposit(void); + +static void ItemStorage_Withdraw(u8 taskId); +static void ItemStorage_Deposit(u8 taskId); +static void ItemStorage_Toss(u8 taskId); +static void ItemStorage_Exit(u8 taskId); +static void ItemStorage_ResumeInputFromYesToss(u8 taskId); +static void ItemStorage_ResumeInputFromNoToss(u8 taskId); + +static void ItemStorageMenuPrint(const u8 *); +static void ItemStorageMenuProcessInput(u8 taskId); +static void ItemStorage_ProcessWithdrawTossInput(u8 taskId); +static void ItemStorage_SetItemAndMailCount(u8); +static void ItemStorage_HandleReturnToProcessInput(u8 taskId); + +static void ItemStorage_WithdrawToss_Helper(u8 taskId, bool8 toss); +static void Task_ItemStorage_Deposit(u8 taskId); +static void ItemStorage_DoItemWithdraw(u8 taskId); +static void ItemStorage_DoItemToss(u8 taskid); +static void ItemStorage_HandleQuantityRolling(u8 taskid); +static void ItemStorage_GoBackToPlayerPCMenu(u8 taskId); +static void ItemStorage_ItemSwapChoosePrompt(u8 taskId); +static void ItemStorage_DoItemAction(u8 taskId); +static void ItemStorage_ProcessInput(u8 taskId); +static void ItemStorage_DoItemSwap(u8 taskId, bool8 a); +static void ItemStorage_HandleRemoveItem(u8 taskId); +static void ItemStorage_WaitPressHandleResumeProcessInput(u8 taskId); +static void ItemStorage_StartScrollIndicatorAndProcessInput(u8 taskId); + +static const u8* ItemStorage_GetItemPcResponse(u16); +static void CopyItemName_PlayerPC(u8 *string, u16 itemId); + +static void sub_816BC14(void); +static void sub_816BFE0(u8 y, u8, u8 speed); +static void sub_816BCC4(u8); +static void sub_816C690(u8); +static void sub_816C4FC(u8 taskId); +static void sub_816C0C8(void); +static void sub_816C060(u16 itemId); +static void sub_816BEF0(s32 id); +static void sub_816B4DC(u8 taskId); +static void ItemStorage_MoveCursor(s32 id, bool8 b, struct ListMenu * thisMenu); +static void fish4_goto_x5_or_x6(u8 windowId, s32 id, u8 yOffset); + +// EWRAM +static EWRAM_DATA const u8 *gPcItemMenuOptionOrder = NULL; +static EWRAM_DATA u8 gPcItemMenuOptionsNum = 0; +EWRAM_DATA struct PlayerPCItemPageStruct playerPCItemPageInfo = {0, 0, 0, 0, {0, 0, 0}, 0}; +static EWRAM_DATA struct Struct203BCC4 *gUnknown_0203BCC4 = NULL; + +// .rodata +static const u8 *const gPCText_OptionDescList[] = +{ + gText_TakeOutItemsFromPC, + gText_StoreItemsInPC, + gText_ThrowAwayItemsInPC, + gText_GoBackPrevMenu, +}; + +static const struct MenuAction sPlayerPCMenuActions[] = +{ + { gText_ItemStorage, PlayerPC_ItemStorage }, + { gText_Mailbox, PlayerPC_Mailbox }, + { gText_Decoration, PlayerPC_Decoration }, + { gText_TurnOff, PlayerPC_TurnOff } +}; + +static const u8 gBedroomPC_OptionOrder[] = +{ + PLAYERPC_MENU_ITEMSTORAGE, + PLAYERPC_MENU_MAILBOX, + PLAYERPC_MENU_DECORATION, + PLAYERPC_MENU_TURNOFF +}; + +static const u8 gPlayerPC_OptionOrder[] = +{ + PLAYERPC_MENU_ITEMSTORAGE, + PLAYERPC_MENU_MAILBOX, + PLAYERPC_MENU_TURNOFF +}; + +static const struct MenuAction gPCText_ItemPCOptionsText[] = +{ + { gText_WithdrawItem, ItemStorage_Withdraw }, + { gText_DepositItem, ItemStorage_Deposit }, + { gText_TossItem, ItemStorage_Toss }, + { gText_Cancel, ItemStorage_Exit } +}; + +static const struct ItemSlot gNewGamePCItems[] = +{ + { ITEM_POTION, 1 }, + { ITEM_NONE, 0 } +}; + +const struct MenuAction gMailboxMailOptions[] = +{ + { gText_Read, Mailbox_DoMailRead }, + { gText_MoveToBag, Mailbox_MoveToBag }, + { gText_Give2, Mailbox_Give }, + { gText_Cancel2, Mailbox_Cancel } +}; + +static const struct WindowTemplate gUnknown_085DFF24[3] = +{ + {0x00, 0x01, 0x01, 0x09, 0x06, 0x0F, 0x0001}, + {0x00, 0x01, 0x01, 0x09, 0x08, 0x0F, 0x0001}, + {0x00, 0x01, 0x01, 0x0A, 0x08, 0x0F, 0x0001} +}; + +static const struct YesNoFuncTable ResumeFromWithdrawYesNoFuncList = // ResumeFromWithdrawYesNoFuncList +{ + ItemStorage_ResumeInputFromYesToss, + ItemStorage_ResumeInputFromNoToss +}; + +static const struct ListMenuTemplate gUnknown_085DFF44 = { + NULL, + ItemStorage_MoveCursor, + fish4_goto_x5_or_x6, + 0, 0, + 0, 0, 8, 0, + 9, 2, 1, 3, FALSE, 0, FALSE, 7 +}; + +static const struct WindowTemplate gUnknown_085DFF5C[5] = +{ + {0x00, 0x10, 0x01, 0x0D, 0x12, 0x0F, 0x0001}, + {0x00, 0x01, 0x0D, 0x0D, 0x06, 0x0F, 0x00EB}, + {0x00, 0x01, 0x08, 0x03, 0x03, 0x0F, 0x0153}, + {0x00, 0x01, 0x01, 0x0D, 0x02, 0x0F, 0x0139}, + {0x00, 0x08, 0x09, 0x06, 0x02, 0x0F, 0x015C} +}; + +static const struct WindowTemplate gUnknown_085DFF84 = +{ + 0x00, 0x09, 0x07, 0x05, 0x04, 0x0F, 0x0168 +}; + +static const u8 gUnknown_085DFF8C[] = {0x01, 0x03, 0x02, 0x00}; + +// text +void NewGameInitPCItems(void) +{ + u8 i; + + // because Game Freak don't know how to use a struct or a 2d array + for(i = 0, ClearItemSlots(gSaveBlock1Ptr->pcItems, ARRAY_COUNT(gSaveBlock1Ptr->pcItems)); NEW_GAME_PC_ITEMS(i, PC_ITEM_ID) && NEW_GAME_PC_ITEMS(i, PC_QUANTITY) && + AddPCItem(NEW_GAME_PC_ITEMS(i, PC_ITEM_ID), NEW_GAME_PC_ITEMS(i, PC_QUANTITY)) == TRUE; i++); +} + +void BedroomPC(void) +{ + gPcItemMenuOptionOrder = gBedroomPC_OptionOrder; + gPcItemMenuOptionsNum = 4; + DisplayItemMessageOnField(CreateTask(TaskDummy, 0), gText_WhatWouldYouLike, InitPlayerPCMenu); +} + +void PlayerPC(void) +{ + gPcItemMenuOptionOrder = gPlayerPC_OptionOrder; + gPcItemMenuOptionsNum = 3; + DisplayItemMessageOnField(CreateTask(TaskDummy, 0), gText_WhatWouldYouLike, InitPlayerPCMenu); +} + +static void InitPlayerPCMenu(u8 taskId) +{ + u16 *data; + struct WindowTemplate windowTemplate; + + data = gTasks[taskId].data; + if(gPcItemMenuOptionsNum == 3) + windowTemplate = gUnknown_085DFF24[0]; + else + windowTemplate = gUnknown_085DFF24[1]; + windowTemplate.width = sub_81DB3D8(sPlayerPCMenuActions, gPcItemMenuOptionOrder, gPcItemMenuOptionsNum); + data[4] = AddWindow(&windowTemplate); + SetStandardWindowBorderStyle(data[4], 0); + sub_81995E4(data[4], gPcItemMenuOptionsNum, sPlayerPCMenuActions, gPcItemMenuOptionOrder); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(data[4], gPcItemMenuOptionsNum, 0); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = PlayerPCProcessMenuInput; +} + +static void PlayerPCProcessMenuInput(u8 taskId) +{ + u16 *data; + s8 inputOptionId; + + data = gTasks[taskId].data; + if(gPcItemMenuOptionsNum > 3) + inputOptionId = ProcessMenuInput(); + else + inputOptionId = ProcessMenuInputNoWrapAround(); + + switch(inputOptionId) + { + case -2: + break; + case -1: + PlaySE(SE_SELECT); + sub_8198070(data[4], FALSE); + ClearWindowTilemap(data[4]); + RemoveWindow(data[4]); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = PlayerPC_TurnOff; + break; + default: + sub_8198070(data[4], FALSE); + ClearWindowTilemap(data[4]); + RemoveWindow(data[4]); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = sPlayerPCMenuActions[gPcItemMenuOptionOrder[inputOptionId]].func.void_u8; + break; + } +} + +void ReshowPlayerPC(u8 var) +{ + DisplayItemMessageOnField(var, gText_WhatWouldYouLike, InitPlayerPCMenu); +} + +static void PlayerPC_ItemStorage(u8 taskId) +{ + InitItemStorageMenu(taskId, ITEMPC_MENU_WITHDRAW); + gTasks[taskId].func = ItemStorageMenuProcessInput; +} + +static void PlayerPC_Mailbox(u8 taskId) +{ + playerPCItemPageInfo.count = GetMailboxMailCount(); + + if (playerPCItemPageInfo.count == 0) + DisplayItemMessageOnField(taskId, gText_NoMailHere, ReshowPlayerPC); + else + { + playerPCItemPageInfo.cursorPos = 0; + playerPCItemPageInfo.itemsAbove = 0; + playerPCItemPageInfo.scrollIndicatorId = 0xFF; + Mailbox_UpdateMailList(); + ItemStorage_SetItemAndMailCount(taskId); + if(sub_81D1C44(playerPCItemPageInfo.count) == TRUE) + { + sub_8197434(0, 0); + Mailbox_DrawMailboxMenu(taskId); + gTasks[taskId].func = Mailbox_ProcessInput; + } + else + DisplayItemMessageOnField(taskId, gText_NoMailHere, ReshowPlayerPC); + } +} + +static void PlayerPC_Decoration(u8 var) +{ + sub_8126B2C(var); //DoPlayerPCDecoration(var); +} + +static void PlayerPC_TurnOff(u8 taskId) +{ + if (gPcItemMenuOptionsNum == 4) // if the option count is 4, we are at the bedroom PC and not player PC, so do gender specific handling. + { + if (gSaveBlock2Ptr->playerGender == MALE) + ScriptContext1_SetupScript(LittlerootTown_BrendansHouse_2F_EventScript_1F863F); + else + ScriptContext1_SetupScript(LittlerootTown_MaysHouse_2F_EventScript_1F958F); + } + else + { + EnableBothScriptContexts(); + } + DestroyTask(taskId); +} + +static void InitItemStorageMenu(u8 taskId, u8 var) +{ + u16 *data; + struct WindowTemplate windowTemplate; + + data = gTasks[taskId].data; + windowTemplate = gUnknown_085DFF24[2]; + windowTemplate.width = GetMaxWidthInMenuTable(gPCText_ItemPCOptionsText, 4); + data[4] = AddWindow(&windowTemplate); + SetStandardWindowBorderStyle(data[4], 0); + PrintMenuTable(data[4], 4, gPCText_ItemPCOptionsText); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(data[4], 4, var); + schedule_bg_copy_tilemap_to_vram(0); + ItemStorageMenuPrint(gPCText_OptionDescList[var]); +} + +static void ItemStorageMenuPrint(const u8 *textPtr) +{ + NewMenuHelpers_DrawDialogueFrame(0, 0); + PrintTextOnWindow(0, 1, textPtr, 0, 1, 0, 0); +} + +static void ItemStorageMenuProcessInput(u8 taskId) +{ + s8 r5; + s8 r2; + s8 inputOptionId; + + r5 = GetMenuCursorPos(); + inputOptionId = ProcessMenuInput(); + r2 = GetMenuCursorPos(); + switch(inputOptionId) + { + case -2: + if (r5 != r2) + ItemStorageMenuPrint(gPCText_OptionDescList[r2]); + break; + case -1: + PlaySE(SE_SELECT); + ItemStorage_Exit(taskId); + break; + default: + PlaySE(SE_SELECT); + gPCText_ItemPCOptionsText[inputOptionId].func.void_u8(taskId); + break; + } +} + +static void ItemStorage_Deposit(u8 taskId) +{ + gTasks[taskId].func = Task_ItemStorage_Deposit; + FadeScreen(1, 0); +} + +static void Task_ItemStorage_Deposit(u8 taskId) +{ + if (!gPaletteFade.active) + { + overworld_free_bg_tilemaps(); + sub_81AAC14(); + DestroyTask(taskId); + } +} + +void sub_816B31C(void) +{ + gFieldCallback = Mailbox_DoRedrawMailboxMenuAfterReturn; + SetMainCallback2(CB2_ReturnToField); +} + +void Mailbox_DoRedrawMailboxMenuAfterReturn(void) +{ + sub_81973A4(); + NewMenuHelpers_DrawDialogueFrame(0, 1); + InitItemStorageMenu(CreateTask(ItemStorage_HandleReturnToProcessInput, 0), 1); + pal_fill_black(); +} + +static void ItemStorage_HandleReturnToProcessInput(u8 taskId) +{ + if (IsWeatherNotFadingIn() == TRUE) + gTasks[taskId].func = ItemStorageMenuProcessInput; +} + +static void ItemStorage_Withdraw(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + NUM_ITEMS = CountUsedPCItemSlots(); + if (NUM_ITEMS != 0) + ItemStorage_WithdrawToss_Helper(taskId, FALSE); + else + { + sub_816B4DC(taskId); + DisplayItemMessageOnField(taskId, gText_NoItems, PlayerPC_ItemStorage); + } + +} + +static void ItemStorage_Toss(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + NUM_ITEMS = CountUsedPCItemSlots(); + if (NUM_ITEMS != 0) + ItemStorage_WithdrawToss_Helper(taskId, TRUE); + else + { + sub_816B4DC(taskId); + DisplayItemMessageOnField(taskId, gText_NoItems, PlayerPC_ItemStorage); + } +} + +static void ItemStorage_WithdrawToss_Helper(u8 taskId, bool8 toss) +{ + u16 *data = gTasks[taskId].data; + + data[3] = toss; + sub_816B4DC(taskId); + playerPCItemPageInfo.cursorPos = 0; + playerPCItemPageInfo.itemsAbove = 0; + playerPCItemPageInfo.scrollIndicatorId = 0xFF; + ItemStorage_SetItemAndMailCount(taskId); + sub_816BC14(); + gpu_pal_allocator_reset__manage_upper_four(); + LoadListMenuArrowsGfx(); + sub_8122344(gUnknown_0203BCC4->spriteIds, 7); + sub_8197434(0,0); + gTasks[taskId].func = ItemStorage_ProcessWithdrawTossInput; +} + +static void ItemStorage_Exit(u8 taskId) +{ + sub_816B4DC(taskId); + ReshowPlayerPC(taskId); +} + + +static void ItemStorage_SetItemAndMailCount(u8 taskId) +{ + if (playerPCItemPageInfo.count > 7) + playerPCItemPageInfo.pageItems = 8; + else + playerPCItemPageInfo.pageItems = playerPCItemPageInfo.count + 1; +} + +static void sub_816B4DC(u8 taskId) +{ + u16 *data = gTasks[taskId].data; + + sub_8198070(data[4], FALSE); + ClearWindowTilemap(data[4]); + RemoveWindow(data[4]); + schedule_bg_copy_tilemap_to_vram(0); +} + +static u8 GetMailboxMailCount(void) +{ + u8 i, j; + + for(i = 0, j = 6; j < 16; j++) + if(gSaveBlock1Ptr->mail[j].itemId != 0) + i++; + + return i; +} + +static void Mailbox_UpdateMailList(void) +{ + struct MailStruct mailBuffer; + u8 i, j; + + for (i=6; i<15; i++) + { + for (j=i+1; j<16; j++) + { + if (gSaveBlock1Ptr->mail[i].itemId == 0) + { + mailBuffer = gSaveBlock1Ptr->mail[i]; + gSaveBlock1Ptr->mail[i] = gSaveBlock1Ptr->mail[j]; + gSaveBlock1Ptr->mail[j] = mailBuffer; + } + } + } +} + +static void Mailbox_DrawMailboxMenu(u8 taskId) +{ + u8 windowId; + + windowId = sub_81D1C84(0); + sub_81D1C84(1); + PrintTextOnWindow(windowId, 1, gText_Mailbox, GetStringCenterAlignXOffset(1, gText_Mailbox, 0x40), 1, 0, NULL); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].data[5] = sub_81D1DC0(&playerPCItemPageInfo); + sub_81D1E90(&playerPCItemPageInfo); +} + +static void Mailbox_ProcessInput(u8 taskId) +{ + u16 *data = gTasks[taskId].data; + s32 inputOptionId; + + if(!gPaletteFade.active) + { + inputOptionId = ListMenuHandleInputGetItemId(data[5]); + ListMenuGetScrollAndRow(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + + switch(inputOptionId) + { + case -1: + break; + case -2: + PlaySE(SE_SELECT); + RemoveScrollIndicatorArrowPair(playerPCItemPageInfo.scrollIndicatorId); + Mailbox_ReturnToPlayerPC(taskId); + break; + default: + PlaySE(SE_SELECT); + sub_81D1D04(0); + sub_81D1D04(1); + DestroyListMenuTask(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + schedule_bg_copy_tilemap_to_vram(0); + RemoveScrollIndicatorArrowPair(playerPCItemPageInfo.scrollIndicatorId); + gTasks[taskId].func = Mailbox_PrintWhatToDoWithPlayerMailText; + break; + } + } +} + +static void Mailbox_PrintWhatToDoWithPlayerMailText(u8 taskId) +{ + StringCopy(gStringVar1, gSaveBlock1Ptr->mail[playerPCItemPageInfo.itemsAbove + 6 + playerPCItemPageInfo.cursorPos].playerName); + sub_81DB554(gStringVar1, 0); + StringExpandPlaceholders(gStringVar4, gText_WhatToDoWithVar1sMail); + DisplayItemMessageOnField(taskId, gStringVar4, Mailbox_PrintMailOptions); +} + +static void Mailbox_ReturnToPlayerPC(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + sub_81D1D04(0); + sub_81D1D04(1); + DestroyListMenuTask(data[5], NULL, NULL); + schedule_bg_copy_tilemap_to_vram(0); + sub_81D1EC0(); + ReshowPlayerPC(taskId); +} + +static void Mailbox_PrintMailOptions(u8 taskId) +{ + u8 r4 = sub_81D1C84(2); + PrintMenuTable(r4, 4, gMailboxMailOptions); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(r4, 4, 0); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = Mailbox_MailOptionsProcessInput; +} + +static void Mailbox_MailOptionsProcessInput(u8 taskId) +{ + s8 inputOptionId = ProcessMenuInput_other(); + + switch(inputOptionId) + { + case -2: + break; + case -1: + PlaySE(SE_SELECT); + Mailbox_Cancel(taskId); + break; + + default: + PlaySE(SE_SELECT); + gMailboxMailOptions[inputOptionId].func.void_u8(taskId); + break; + } +} + +static void Mailbox_DoMailRead(u8 taskId) +{ + FadeScreen(1, 0); + gTasks[taskId].func = Mailbox_FadeAndReadMail; +} + +static void Mailbox_FadeAndReadMail(u8 taskId) +{ + if(!gPaletteFade.active) + { + sub_81D1EC0(); + overworld_free_bg_tilemaps(); + ReadMail(&(gSaveBlock1Ptr->mail[playerPCItemPageInfo.itemsAbove + 6 + playerPCItemPageInfo.cursorPos]), Mailbox_ReturnToFieldFromReadMail, TRUE); + DestroyTask(taskId); + } +} + +static void Mailbox_ReturnToFieldFromReadMail(void) +{ + gFieldCallback = pal_fill_for_maplights_or_black; + SetMainCallback2(CB2_ReturnToField); +} + +static void pal_fill_for_maplights_or_black(void) +{ + u8 taskId; + + sub_81973A4(); + taskId = CreateTask(Mailbox_HandleReturnToProcessInput, 0); + if(sub_81D1C44(playerPCItemPageInfo.count) == TRUE) + Mailbox_DrawMailboxMenu(taskId); + else + DestroyTask(taskId); + pal_fill_black(); +} + +static void Mailbox_HandleReturnToProcessInput(u8 taskId) +{ + if(IsWeatherNotFadingIn() == TRUE) + gTasks[taskId].func = Mailbox_ProcessInput; +} + +static void Mailbox_MoveToBag(u8 taskId) +{ + DisplayItemMessageOnField(taskId, gText_MessageWillBeLost, Mailbox_DrawYesNoBeforeMove); +} + +static void Mailbox_DrawYesNoBeforeMove(u8 taskId) +{ + sub_8197930(); + gTasks[taskId].func = Mailbox_MoveToBagYesNoPrompt; +} + +static void Mailbox_MoveToBagYesNoPrompt(u8 taskId) +{ + switch(ProcessMenuInputNoWrap_()) + { + case 0: + Mailbox_DoMailMoveToBag(taskId); + break; + case -1: + PlaySE(SE_SELECT); + case 1: + Mailbox_CancelMoveToBag(taskId); + break; + case -2: + default: + break; + } +} + +static void Mailbox_DoMailMoveToBag(u8 taskId) +{ + struct MailStruct *mailStruct = &(gSaveBlock1Ptr->mail[playerPCItemPageInfo.itemsAbove + 6 + playerPCItemPageInfo.cursorPos]); + if(!AddBagItem(mailStruct->itemId, 1)) + { + DisplayItemMessageOnField(taskId, gText_BagIsFull, Mailbox_Cancel); + } + else + { + DisplayItemMessageOnField(taskId, gText_MailToBagMessageErased, Mailbox_Cancel); + ClearMailStruct(mailStruct); + Mailbox_UpdateMailList(); + playerPCItemPageInfo.count--; + if(playerPCItemPageInfo.count < (playerPCItemPageInfo.pageItems + playerPCItemPageInfo.itemsAbove) && playerPCItemPageInfo.itemsAbove != 0) + playerPCItemPageInfo.itemsAbove--; + ItemStorage_SetItemAndMailCount(taskId); + } +} + +static void Mailbox_CancelMoveToBag(u8 taskId) +{ + Mailbox_Cancel(taskId); +} + +static void Mailbox_Give(u8 taskId) +{ + if(CalculatePlayerPartyCount() == 0) + Mailbox_NoPokemonForMail(taskId); + else + { + FadeScreen(1, 0); + gTasks[taskId].func = Mailbox_DoGiveMailPokeMenu; + } +} + +static void Mailbox_DoGiveMailPokeMenu(u8 taskId) +{ + if(!gPaletteFade.active) + { + sub_81D1EC0(); + overworld_free_bg_tilemaps(); + sub_81B8448(); + DestroyTask(taskId); + } +} + +void Mailbox_ReturnToMailListAfterDeposit(void) +{ + gFieldCallback = Mailbox_UpdateMailListAfterDeposit; + SetMainCallback2(CB2_ReturnToField); +} + +static void Mailbox_UpdateMailListAfterDeposit(void) +{ + u8 taskId; + u8 prevCount; + taskId = CreateTask(Mailbox_HandleReturnToProcessInput, 0); + prevCount = playerPCItemPageInfo.count; + playerPCItemPageInfo.count = GetMailboxMailCount(); + Mailbox_UpdateMailList(); + if(prevCount != playerPCItemPageInfo.count && (playerPCItemPageInfo.count < (playerPCItemPageInfo.pageItems + playerPCItemPageInfo.itemsAbove)) + && playerPCItemPageInfo.itemsAbove != 0) + playerPCItemPageInfo.itemsAbove--; + ItemStorage_SetItemAndMailCount(taskId); + sub_81973A4(); + if(sub_81D1C44(playerPCItemPageInfo.count) == TRUE) + Mailbox_DrawMailboxMenu(taskId); + else + DestroyTask(taskId); + pal_fill_black(); +} + +static void Mailbox_NoPokemonForMail(u8 taskId) +{ + DisplayItemMessageOnField(taskId, gText_NoPokemon, Mailbox_Cancel); +} + +static void Mailbox_Cancel(u8 taskId) +{ + sub_81D1D04(2); + sub_8197434(0, 0); + Mailbox_DrawMailboxMenu(taskId); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = Mailbox_ProcessInput; +} + +static void sub_816BC14(void) +{ + gUnknown_0203BCC4 = AllocZeroed(sizeof(struct Struct203BCC4)); + memset(gUnknown_0203BCC4->windowIds, 0xFF, 0x6); + gUnknown_0203BCC4->unk666 = 0xFF; + gUnknown_0203BCC4->spriteId = 0xFF; +} + +static void sub_816BC58(void) +{ + u32 i; + + for(i = 0; i < 6; i++) + sub_816BCC4(i); + Free(gUnknown_0203BCC4); +} + +static u8 sub_816BC7C(u8 a) +{ + u8 *windowIdLoc = &(gUnknown_0203BCC4->windowIds[a]); + if(*windowIdLoc == 0xFF) + { + *windowIdLoc = AddWindow(&gUnknown_085DFF5C[a]); + SetWindowBorderStyle(*windowIdLoc, FALSE, 0x214, 0xE); + schedule_bg_copy_tilemap_to_vram(0); + } + return *windowIdLoc; +} + +static void sub_816BCC4(u8 a) +{ + u8 *windowIdLoc = &(gUnknown_0203BCC4->windowIds[a]); + if(*windowIdLoc != 0xFF) + { + sub_8198070(*windowIdLoc, FALSE); + ClearWindowTilemap(*windowIdLoc); + schedule_bg_copy_tilemap_to_vram(0); + RemoveWindow(*windowIdLoc); + *windowIdLoc = 0xFF; + } +} + +void ItemStorage_RefreshListMenu(void) +{ + u16 i; + + for(i = 0; i < playerPCItemPageInfo.count - 1; i++) + { + CopyItemName_PlayerPC(&(gUnknown_0203BCC4->unk198[i][0]), gSaveBlock1Ptr->pcItems[i].itemId); + gUnknown_0203BCC4->unk0[i].name = &(gUnknown_0203BCC4->unk198[i][0]); + gUnknown_0203BCC4->unk0[i].id = i; + } + StringCopy(&(gUnknown_0203BCC4->unk198[i][0]) ,gText_Cancel2); + gUnknown_0203BCC4->unk0[i].name = &(gUnknown_0203BCC4->unk198[i][0]); + gUnknown_0203BCC4->unk0[i].id = -2; + gMultiuseListMenuTemplate = gUnknown_085DFF44; + gMultiuseListMenuTemplate.windowId = sub_816BC7C(0); + gMultiuseListMenuTemplate.totalItems = playerPCItemPageInfo.count; + gMultiuseListMenuTemplate.items = gUnknown_0203BCC4->unk0; + gMultiuseListMenuTemplate.maxShowed = playerPCItemPageInfo.pageItems; +} + +void CopyItemName_PlayerPC(u8 *string, u16 itemId) +{ + CopyItemName(itemId, string); +} + +static void ItemStorage_MoveCursor(s32 id, bool8 b, struct ListMenu *thisMenu) +{ + if(b != TRUE) + PlaySE(SE_SELECT); + if(gUnknown_0203BCC4->unk666 == 0xFF) + { + sub_816C0C8(); + if(id != -2) + sub_816C060(gSaveBlock1Ptr->pcItems[id].itemId); + else + sub_816C060(ITEMPC_GO_BACK_TO_PREV); + sub_816BEF0(id); + } +} + +static void fish4_goto_x5_or_x6(u8 windowId, s32 id, u8 yOffset) +{ + if(id != -2) + { + if(gUnknown_0203BCC4->unk666 != 0xFF) + { + if(gUnknown_0203BCC4->unk666 == (u8)id) + sub_816BFE0(yOffset, 0, 0xFF); + else + sub_816BFE0(yOffset, 0xFF, 0xFF); + } + ConvertIntToDecimalStringN(gStringVar1, gSaveBlock1Ptr->pcItems[id].quantity, STR_CONV_MODE_RIGHT_ALIGN, 3); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + PrintTextOnWindow(windowId, 7, gStringVar4, GetStringRightAlignXOffset(7, gStringVar4, 104), yOffset, 0xFF, NULL); + } +} + +static void sub_816BEF0(s32 id) +{ + const u8* description; + u8 windowId = gUnknown_0203BCC4->windowIds[1]; + + if(id != -2) + description = (u8 *)ItemId_GetDescription(gSaveBlock1Ptr->pcItems[id].itemId); + else + description = ItemStorage_GetItemPcResponse(ITEMPC_GO_BACK_TO_PREV); + FillWindowPixelBuffer(windowId, 17); + PrintTextOnWindow(windowId, 1, description, 0, 1, 0, NULL); +} + +static void ItemStorage_StartScrollIndicator(void) +{ + if(playerPCItemPageInfo.scrollIndicatorId == 0xFF) + playerPCItemPageInfo.scrollIndicatorId = AddScrollIndicatorArrowPairParametrized(0x2, 0xB0, 0xC, 0x94, playerPCItemPageInfo.count - playerPCItemPageInfo.pageItems, 0x13F8, 0x13F8, &(playerPCItemPageInfo.itemsAbove)); +} + +static void ItemStorage_RemoveScrollIndicator(void) +{ + if(playerPCItemPageInfo.scrollIndicatorId != 0xFF) + { + RemoveScrollIndicatorArrowPair(playerPCItemPageInfo.scrollIndicatorId); + playerPCItemPageInfo.scrollIndicatorId = 0xFF; + } +} + +static void sub_816BFB8(u8 a, u8 b, u8 speed) +{ + sub_816BFE0(ListMenuGetYCoordForPrintingArrowCursor(a), b, speed); +} + +static void sub_816BFE0(u8 y, u8 b, u8 speed) +{ + u8 windowId = gUnknown_0203BCC4->windowIds[0]; + if(b == 0xFF) + FillWindowPixelRect(windowId, 17, 0, y, GetMenuCursorDimensionByFont(1, 0), GetMenuCursorDimensionByFont(1, 1)); + else + AddTextPrinterParameterized2(windowId, 1, 0, y, 0, 0, gUnknown_085DFF8C, speed, gText_SelectorArrow2); +} + +static void sub_816C060(u16 itemId) +{ + u8 spriteId; + u8* spriteIdLoc = &(gUnknown_0203BCC4->spriteId); + + if(*spriteIdLoc == 0xFF) + { + FreeSpriteTilesByTag(0x13F6); + FreeSpritePaletteByTag(0x13F6); + spriteId = AddItemIconSprite(0x13F6, 0x13F6, itemId); + if(spriteId != 64) + { + *spriteIdLoc = spriteId; + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].pos2.x = 24; + gSprites[spriteId].pos2.y = 80; + } + } +} + +static void sub_816C0C8(void) +{ + u8* spriteIdLoc = &(gUnknown_0203BCC4->spriteId); + if(*spriteIdLoc != 0xFF) + { + FreeSpriteTilesByTag(0x13F6); + FreeSpritePaletteByTag(0x13F6); + DestroySprite(&(gSprites[*spriteIdLoc])); + *spriteIdLoc = 0xFF; + } +} + +static void sub_816C110(void) +{ + CompactPCItems(); + sub_812220C(gSaveBlock1Ptr->pcItems, 50, &(playerPCItemPageInfo.pageItems), &(playerPCItemPageInfo.count), 0x8); +} + +static void sub_816C140(void) +{ + sub_812225C(&(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos), playerPCItemPageInfo.pageItems, playerPCItemPageInfo.count); +} + +static void ItemStorage_ProcessWithdrawTossInput(u8 taskId) +{ + s16 *data; + bool32 toss; + u32 i, x; + u8 windowId; + const u8* text; + + data = gTasks[taskId].data; + for(i = 0; i <=3; i++) + sub_816BC7C(i); + toss = data[3]; + text = gText_TossItem; + if(!toss) + text = gText_WithdrawItem; + x = GetStringCenterAlignXOffset(1, text, 104); + PrintTextOnWindow(gUnknown_0203BCC4->windowIds[3], 1, text, x, 1, 0, NULL); + CopyWindowToVram(gUnknown_0203BCC4->windowIds[2], 2); + sub_816C110(); + sub_816C140(); + ItemStorage_RefreshListMenu(); + data[5] = ListMenuInit(&gMultiuseListMenuTemplate, playerPCItemPageInfo.itemsAbove, playerPCItemPageInfo.cursorPos); + ItemStorage_StartScrollIndicator(); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = ItemStorage_ProcessInput; +} + +static const u8* ItemStorage_GetItemPcResponse(u16 itemId) +{ + const u8 *string; + + switch(itemId) + { + case ITEMPC_GO_BACK_TO_PREV: + string = gText_GoBackPrevMenu; + break; + case ITEMPC_HOW_MANY_TO_WITHDRAW: + string = gText_WithdrawHowManyItems; + break; + case ITEMPC_WITHDREW_THING: + string = gText_WithdrawXItems; + break; + case ITEMPC_HOW_MANY_TO_TOSS: + string = gText_TossHowManyVar1s; + break; + case ITEMPC_THREW_AWAY_ITEM: + string = gText_ThrewAwayVar2Var1s; + break; + case ITEMPC_NO_MORE_ROOM: + string = gText_NoRoomInBag; + break; + case ITEMPC_TOO_IMPORTANT: + string = gText_TooImportantToToss; + break; + case ITEMPC_OKAY_TO_THROW_AWAY: + string = gText_ConfirmTossItems; + break; + case ITEMPC_SWITCH_WHICH_ITEM: + string = gText_MoveVar1Where; + break; + default: + string = ItemId_GetDescription(itemId); + break; + } + return string; +} + +static void ItemStorage_PrintItemPcResponse(const u8 *string) +{ + u8 windowId = gUnknown_0203BCC4->windowIds[1]; + FillWindowPixelBuffer(windowId, 0x11); + StringExpandPlaceholders(gStringVar4, string); + PrintTextOnWindow(windowId, 1, gStringVar4, 0, 1, 0, NULL); +} + +static void ItemStorage_ProcessInput(u8 taskId) +{ + s16 *data; + s32 id; + + data = gTasks[taskId].data; + if(gMain.newKeys & SELECT_BUTTON) + { + ListMenuGetScrollAndRow(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + if((playerPCItemPageInfo.itemsAbove + playerPCItemPageInfo.cursorPos) != (playerPCItemPageInfo.count - 1)) + { + PlaySE(SE_SELECT); + ItemStorage_ItemSwapChoosePrompt(taskId); + } + } + else + { + id = ListMenuHandleInputGetItemId(data[5]); + ListMenuGetScrollAndRow(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + switch(id) + { + case -1: + break; + case -2: + PlaySE(SE_SELECT); + ItemStorage_GoBackToPlayerPCMenu(taskId); + break; + default: + PlaySE(SE_SELECT); + ItemStorage_DoItemAction(taskId); + break; + } + } +} + +static void ItemStorage_GoBackToPlayerPCMenu_InitStorage(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + if(!IsDma3ManagerBusyWithBgCopy()) + { + NewMenuHelpers_DrawDialogueFrame(0, 0); + if(!data[3]) + InitItemStorageMenu(taskId, ITEMPC_MENU_WITHDRAW); + else + InitItemStorageMenu(taskId, ITEMPC_MENU_TOSS); + gTasks[taskId].func = ItemStorageMenuProcessInput; + } +} + +static void ItemStorage_GoBackToPlayerPCMenu(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + sub_816C0C8(); + ItemStorage_RemoveScrollIndicator(); + DestroyListMenuTask(data[5], NULL, NULL); + sub_81223B0(gUnknown_0203BCC4->spriteIds, 7); + sub_816BC58(); + gTasks[taskId].func = ItemStorage_GoBackToPlayerPCMenu_InitStorage; +} + +static void ItemStorage_ItemSwapChoosePrompt(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + sub_81AF15C(data[5], 16, 1); + gUnknown_0203BCC4->unk666 = (playerPCItemPageInfo.itemsAbove + playerPCItemPageInfo.cursorPos); + sub_816BFB8(data[5], 0, 0); + sub_816C690(gUnknown_0203BCC4->unk666); + CopyItemName(gSaveBlock1Ptr->pcItems[gUnknown_0203BCC4->unk666].itemId, gStringVar1); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_SWITCH_WHICH_ITEM)); + gTasks[taskId].func = sub_816C4FC; +} + +static void sub_816C4FC(u8 taskId) +{ + s16 *data; + s32 id; + + data = gTasks[taskId].data; + if(gMain.newKeys & SELECT_BUTTON) + { + ListMenuGetScrollAndRow(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + ItemStorage_DoItemSwap(taskId, FALSE); + return; + } + id = ListMenuHandleInputGetItemId(data[5]); + ListMenuGetScrollAndRow(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + sub_81223FC(gUnknown_0203BCC4->spriteIds, 7, 0); + sub_816C690(playerPCItemPageInfo.cursorPos); + switch(id) + { + case -1: + break; + case -2: + if(gMain.newKeys & A_BUTTON) + { + ItemStorage_DoItemSwap(taskId, FALSE); + } + else + ItemStorage_DoItemSwap(taskId, TRUE); + break; + default: + ItemStorage_DoItemSwap(taskId, FALSE); + break; + } +} + +static void ItemStorage_DoItemSwap(u8 taskId, bool8 a) +{ + s16 *data; + u16 b; + u8 c; + + data = gTasks[taskId].data; + b = (playerPCItemPageInfo.itemsAbove + playerPCItemPageInfo.cursorPos); + PlaySE(SE_SELECT); + DestroyListMenuTask(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + if(!a) + { + c = gUnknown_0203BCC4->unk666; + if(c != b) + { + if(c != b - 1) + { + MoveItemSlotInList(gSaveBlock1Ptr->pcItems, c, b); + ItemStorage_RefreshListMenu(); + } + } + else + goto LABEL_SKIP_CURSOR_DECREMENT; + } + if (gUnknown_0203BCC4->unk666 < b) + playerPCItemPageInfo.cursorPos--; + LABEL_SKIP_CURSOR_DECREMENT: + sub_81223FC(gUnknown_0203BCC4->spriteIds, 7, 1); + gUnknown_0203BCC4->unk666 = 0xFF; + data[5] = ListMenuInit(&gMultiuseListMenuTemplate, playerPCItemPageInfo.itemsAbove, playerPCItemPageInfo.cursorPos); + schedule_bg_copy_tilemap_to_vram(0); + gTasks[taskId].func = ItemStorage_ProcessInput; +} + +static void sub_816C690(u8 a) +{ + sub_8122448(gUnknown_0203BCC4->spriteIds, 7, 128, ((a+1) * 16)); +} + +static void sub_816C6BC(u8 windowId, u16 value, u32 mode, u8 x, u8 y, u8 n) +{ + ConvertIntToDecimalStringN(gStringVar1, value, mode, n); + StringExpandPlaceholders(gStringVar4, gText_xVar1); + PrintTextOnWindow(windowId, 1, gStringVar4, GetStringCenterAlignXOffset(1, gStringVar4, 48), y, 0, NULL); +} + +static void ItemStorage_DoItemAction(u8 taskId) +{ + s16 *data; + u16 b; + + data = gTasks[taskId].data; + b = (playerPCItemPageInfo.cursorPos + playerPCItemPageInfo.itemsAbove); + ItemStorage_RemoveScrollIndicator(); + data[2] = 1; + if(!data[3]) + { + if(gSaveBlock1Ptr->pcItems[b].quantity == 1) + { + ItemStorage_DoItemWithdraw(taskId); + return; + } + CopyItemName(gSaveBlock1Ptr->pcItems[b].itemId, gStringVar1); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_HOW_MANY_TO_WITHDRAW)); + } + else + { + if(gSaveBlock1Ptr->pcItems[b].quantity == 1) + { + ItemStorage_DoItemToss(taskId); + return; + } + CopyItemName(gSaveBlock1Ptr->pcItems[b].itemId, gStringVar1); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_HOW_MANY_TO_TOSS)); + } + sub_816C6BC(sub_816BC7C(4), data[2], STR_CONV_MODE_LEADING_ZEROS, 8, 1, 3); + gTasks[taskId].func = ItemStorage_HandleQuantityRolling; +} + +static void ItemStorage_HandleQuantityRolling(u8 taskId) +{ + s16 *data; + u16 b; + + data = gTasks[taskId].data; + b = (playerPCItemPageInfo.cursorPos + playerPCItemPageInfo.itemsAbove); + if(AdjustQuantityAccordingToDPadInput(&(data[2]), gSaveBlock1Ptr->pcItems[b].quantity) == TRUE) + sub_816C6BC(sub_816BC7C(4), data[2], STR_CONV_MODE_LEADING_ZEROS, 8, 1, 3); + else + { + if(gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sub_816BCC4(4); + if(!data[3]) + ItemStorage_DoItemWithdraw(taskId); + else + ItemStorage_DoItemToss(taskId); + } + else if(gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_816BCC4(4); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(gSaveBlock1Ptr->pcItems[b].itemId)); + ItemStorage_StartScrollIndicatorAndProcessInput(taskId); + } + } +} + +static void ItemStorage_DoItemWithdraw(u8 taskId) +{ + s16 *data; + u16 b; + + data = gTasks[taskId].data; + b = (playerPCItemPageInfo.cursorPos + playerPCItemPageInfo.itemsAbove); + if(AddBagItem(gSaveBlock1Ptr->pcItems[b].itemId, data[2]) == TRUE) + { + CopyItemName(gSaveBlock1Ptr->pcItems[b].itemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, data[2], STR_CONV_MODE_LEFT_ALIGN, 3); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_WITHDREW_THING)); + gTasks[taskId].func = ItemStorage_HandleRemoveItem; + } + else + { + data[2] = 0; + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_NO_MORE_ROOM)); + gTasks[taskId].func = ItemStorage_WaitPressHandleResumeProcessInput; + } +} + +static void ItemStorage_DoItemToss(u8 taskId) +{ + s16 *data; + u16 b; + + data = gTasks[taskId].data; + b = (playerPCItemPageInfo.cursorPos + playerPCItemPageInfo.itemsAbove); + if(!ItemId_GetImportance(gSaveBlock1Ptr->pcItems[b].itemId)) + { + CopyItemName(gSaveBlock1Ptr->pcItems[b].itemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, data[2], STR_CONV_MODE_LEFT_ALIGN, 3); + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_OKAY_TO_THROW_AWAY)); + CreateYesNoMenuWithCallbacks(taskId, &gUnknown_085DFF84, 1, 0, 1, 0x214, 0xE, &ResumeFromWithdrawYesNoFuncList); + } + else + { + data[2] = 0; + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_TOO_IMPORTANT)); + gTasks[taskId].func = ItemStorage_WaitPressHandleResumeProcessInput; + } +} + +static void ItemStorage_ResumeInputFromYesToss(u8 taskId) +{ + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(ITEMPC_THREW_AWAY_ITEM)); + gTasks[taskId].func = ItemStorage_HandleRemoveItem; +} + +static void ItemStorage_ResumeInputFromNoToss(u8 taskId) +{ + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(gSaveBlock1Ptr->pcItems[(playerPCItemPageInfo.itemsAbove + playerPCItemPageInfo.cursorPos)].itemId)); + ItemStorage_StartScrollIndicatorAndProcessInput(taskId); +} + +static void ItemStorage_HandleRemoveItem(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + if(gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + RemovePCItem((playerPCItemPageInfo.cursorPos + playerPCItemPageInfo.itemsAbove), data[2]); + DestroyListMenuTask(data[5], &(playerPCItemPageInfo.itemsAbove), &(playerPCItemPageInfo.cursorPos)); + sub_816C110(); + sub_816C140(); + ItemStorage_RefreshListMenu(); + data[5] = ListMenuInit(&gMultiuseListMenuTemplate, playerPCItemPageInfo.itemsAbove, playerPCItemPageInfo.cursorPos); + ItemStorage_StartScrollIndicatorAndProcessInput(taskId); + } +} + +static void ItemStorage_WaitPressHandleResumeProcessInput(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + if(gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + ItemStorage_PrintItemPcResponse(ItemStorage_GetItemPcResponse(gSaveBlock1Ptr->pcItems[(playerPCItemPageInfo.itemsAbove + playerPCItemPageInfo.cursorPos)].itemId)); + ItemStorage_StartScrollIndicatorAndProcessInput(taskId); + } +} + +static void ItemStorage_StartScrollIndicatorAndProcessInput(u8 taskId) +{ + ItemStorage_StartScrollIndicator(); + gTasks[taskId].func = ItemStorage_ProcessInput; +} diff --git a/src/pokeball.c b/src/pokeball.c index 795a33827..8173c4a90 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -43,7 +43,7 @@ static void sub_80768F0(struct Sprite *sprite); static void sub_80769A8(struct Sprite *sprite); static void sub_80769CC(struct Sprite *sprite); static void SpriteCB_HitAnimHealthoxEffect(struct Sprite *sprite); -static u16 GetBankPokeballItemId(u8 bank); +static u16 GetBattlerPokeballItemId(u8 battlerId); // rom const data @@ -317,11 +317,11 @@ const struct SpriteTemplate gBallSpriteTemplates[POKEBALL_COUNT] = }, }; -#define tFrames data[0] -#define tPan data[1] -#define tThrowId data[2] -#define tBank data[3] -#define tOpponentBank data[4] +#define tFrames data[0] +#define tPan data[1] +#define tThrowId data[2] +#define tBattler data[3] +#define tOpponentBattler data[4] u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow) { @@ -333,17 +333,17 @@ u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow) taskId = CreateTask(Task_DoPokeballSendOutAnim, 5); gTasks[taskId].tPan = pan; gTasks[taskId].tThrowId = kindOfThrow; - gTasks[taskId].tBank = gActiveBattler; + gTasks[taskId].tBattler = gActiveBattler; return 0; } -#define sBank data[6] +#define sBattler data[6] static void Task_DoPokeballSendOutAnim(u8 taskId) { u16 throwCaseId; - u8 bank; + u8 battlerId; u16 itemId, ballId; u8 ballSpriteId; bool8 notSendOut = FALSE; @@ -355,12 +355,12 @@ static void Task_DoPokeballSendOutAnim(u8 taskId) } throwCaseId = gTasks[taskId].tThrowId; - bank = gTasks[taskId].tBank; + battlerId = gTasks[taskId].tBattler; - if (GetBattlerSide(bank) != B_SIDE_PLAYER) - itemId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_POKEBALL); + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + itemId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL); else - itemId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_POKEBALL); + itemId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL); ballId = ItemIdToBallId(itemId); LoadBallGfx(ballId); @@ -372,15 +372,15 @@ static void Task_DoPokeballSendOutAnim(u8 taskId) switch (throwCaseId) { case POKEBALL_PLAYER_SENDOUT: - gBattlerTarget = bank; + gBattlerTarget = battlerId; gSprites[ballSpriteId].pos1.x = 24; gSprites[ballSpriteId].pos1.y = 68; gSprites[ballSpriteId].callback = SpriteCB_PlayerMonSendOut_1; break; case POKEBALL_OPPONENT_SENDOUT: - gSprites[ballSpriteId].pos1.x = GetBattlerSpriteCoord(bank, BANK_X_POS); - gSprites[ballSpriteId].pos1.y = GetBattlerSpriteCoord(bank, BANK_Y_POS) + 24; - gBattlerTarget = bank; + gSprites[ballSpriteId].pos1.x = GetBattlerSpriteCoord(battlerId, BANK_X_POS); + gSprites[ballSpriteId].pos1.y = GetBattlerSpriteCoord(battlerId, BANK_Y_POS) + 24; + gBattlerTarget = battlerId; gSprites[ballSpriteId].data[0] = 0; gSprites[ballSpriteId].callback = SpriteCB_OpponentMonSendOut; break; @@ -390,7 +390,7 @@ static void Task_DoPokeballSendOutAnim(u8 taskId) break; } - gSprites[ballSpriteId].sBank = gBattlerTarget; + gSprites[ballSpriteId].sBattler = gBattlerTarget; if (!notSendOut) { DestroyTask(taskId); @@ -404,7 +404,7 @@ static void Task_DoPokeballSendOutAnim(u8 taskId) gSprites[ballSpriteId].data[5] = -40; sub_80A68D4(&gSprites[ballSpriteId]); gSprites[ballSpriteId].oam.affineParam = taskId; - gTasks[taskId].tOpponentBank = gBattlerTarget; + gTasks[taskId].tOpponentBattler = gBattlerTarget; gTasks[taskId].func = TaskDummy; PlaySE(SE_NAGERU); } @@ -415,7 +415,7 @@ static void SpriteCB_TestBallThrow(struct Sprite *sprite) { u16 ballId; u8 taskId = sprite->oam.affineParam; - u8 opponentBank = gTasks[taskId].tOpponentBank; + u8 opponentBattler = gTasks[taskId].tOpponentBattler; u8 noOfShakes = gTasks[taskId].tThrowId; StartSpriteAnim(sprite, 1); @@ -425,10 +425,10 @@ static void SpriteCB_TestBallThrow(struct Sprite *sprite) sprite->pos2.x = 0; sprite->pos2.y = 0; sprite->data[5] = 0; - ballId = ItemIdToBallId(GetBankPokeballItemId(opponentBank)); + ballId = ItemIdToBallId(GetBattlerPokeballItemId(opponentBattler)); LaunchBallStarsTask(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); - sprite->data[0] = LaunchBallFadeMonTask(FALSE, opponentBank, 14, ballId); - sprite->sBank = opponentBank; + sprite->data[0] = LaunchBallFadeMonTask(FALSE, opponentBattler, 14, ballId); + sprite->sBattler = opponentBattler; sprite->data[7] = noOfShakes; DestroyTask(taskId); sprite->callback = sub_80756D4; @@ -438,8 +438,8 @@ static void SpriteCB_TestBallThrow(struct Sprite *sprite) #undef tFrames #undef tPan #undef tThrowId -#undef tBank -#undef tOpponentBank +#undef tBattler +#undef tOpponentBattler static void sub_80756D4(struct Sprite *sprite) { @@ -452,9 +452,9 @@ static void sub_80756E0(struct Sprite *sprite) { sprite->data[5] = 0; sprite->callback = sub_807574C; - StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[sprite->sBank]], 2); - AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBank]]); - gSprites[gBattlerSpriteIds[sprite->sBank]].data[1] = 0; + StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[sprite->sBattler]], 2); + AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBattler]]); + gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] = 0; } } @@ -463,17 +463,17 @@ static void sub_807574C(struct Sprite *sprite) sprite->data[5]++; if (sprite->data[5] == 11) PlaySE(SE_SUIKOMU); - if (gSprites[gBattlerSpriteIds[sprite->sBank]].affineAnimEnded) + if (gSprites[gBattlerSpriteIds[sprite->sBattler]].affineAnimEnded) { StartSpriteAnim(sprite, 2); - gSprites[gBattlerSpriteIds[sprite->sBank]].invisible = TRUE; + gSprites[gBattlerSpriteIds[sprite->sBattler]].invisible = TRUE; sprite->data[5] = 0; sprite->callback = sub_80757E4; } else { - gSprites[gBattlerSpriteIds[sprite->sBank]].data[1] += 0x60; - gSprites[gBattlerSpriteIds[sprite->sBank]].pos2.y = -gSprites[gBattlerSpriteIds[sprite->sBank]].data[1] >> 8; + gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] += 0x60; + gSprites[gBattlerSpriteIds[sprite->sBattler]].pos2.y = -gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] >> 8; } } @@ -641,7 +641,7 @@ static void sub_8075970(struct Sprite *sprite) #define tCryTaskSpecies data[0] #define tCryTaskPan data[1] #define tCryTaskWantedCry data[2] -#define tCryTaskBank data[3] +#define tCryTaskBattler data[3] #define tCryTaskMonSpriteId data[4] #define tCryTaskMonPtr1 data[5] #define tCryTaskMonPtr2 data[6] @@ -653,7 +653,7 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId) u8 wantedCry = gTasks[taskId].tCryTaskWantedCry; s8 pan = gTasks[taskId].tCryTaskPan; u16 species = gTasks[taskId].tCryTaskSpecies; - u8 bank = gTasks[taskId].tCryTaskBank; + u8 battlerId = gTasks[taskId].tCryTaskBattler; u8 monSpriteId = gTasks[taskId].tCryTaskMonSpriteId; struct Pokemon *mon = (void*)(u32)((gTasks[taskId].tCryTaskMonPtr1 << 0x10) | (u16)(gTasks[taskId].tCryTaskMonPtr2)); @@ -669,7 +669,7 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId) PlayCry3(species, pan, 0); else PlayCry3(species, pan, 11); - gBattleSpritesDataPtr->healthBoxesData[bank].field_1_x40 = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].field_1_x40 = 0; DestroyTask(taskId); break; case 2: @@ -685,7 +685,7 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId) else PlayCry4(species, pan, 12); - gBattleSpritesDataPtr->healthBoxesData[bank].field_1_x40 = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].field_1_x40 = 0; DestroyTask(taskId); } else @@ -724,7 +724,7 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId) else PlayCry4(species, pan, 11); - gBattleSpritesDataPtr->healthBoxesData[bank].field_1_x40 = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].field_1_x40 = 0; DestroyTask(taskId); break; } @@ -732,13 +732,13 @@ static void Task_PlayCryWhenReleasedFromBall(u8 taskId) static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite) { - u8 bank = sprite->sBank; + u8 battlerId = sprite->sBattler; u32 ballId; StartSpriteAnim(sprite, 1); - ballId = ItemIdToBallId(GetBankPokeballItemId(bank)); + ballId = ItemIdToBallId(GetBattlerPokeballItemId(battlerId)); LaunchBallStarsTask(sprite->pos1.x, sprite->pos1.y - 5, 1, 0x1C, ballId); - sprite->data[0] = LaunchBallFadeMonTask(1, sprite->sBank, 14, ballId); + sprite->data[0] = LaunchBallFadeMonTask(1, sprite->sBattler, 14, ballId); sprite->callback = HandleBallAnimEnd; if (gMain.inBattle) @@ -749,19 +749,19 @@ static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite) u16 wantedCryCase; u8 taskId; - if (GetBattlerSide(bank) != B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) { - mon = &gEnemyParty[gBattlerPartyIndexes[bank]]; + mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]]; pan = 25; } else { - mon = &gPlayerParty[gBattlerPartyIndexes[bank]]; + mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]]; pan = -25; } species = GetMonData(mon, MON_DATA_SPECIES); - if ((bank == GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) || bank == GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) + if ((battlerId == GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) || battlerId == GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) && IsDoubleBattle() && gBattleSpritesDataPtr->animationData->field_9_x1) { if (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK) @@ -777,39 +777,39 @@ static void SpriteCB_ReleaseMonFromBall(struct Sprite *sprite) if (!IsDoubleBattle() || !gBattleSpritesDataPtr->animationData->field_9_x1) wantedCryCase = 0; - else if (bank == GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) || bank == GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) + else if (battlerId == GetBattlerAtPosition(B_POSITION_PLAYER_LEFT) || battlerId == GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT)) wantedCryCase = 1; else wantedCryCase = 2; - gBattleSpritesDataPtr->healthBoxesData[bank].field_1_x40 = 1; + gBattleSpritesDataPtr->healthBoxesData[battlerId].field_1_x40 = 1; taskId = CreateTask(Task_PlayCryWhenReleasedFromBall, 3); gTasks[taskId].tCryTaskSpecies = species; gTasks[taskId].tCryTaskPan = pan; gTasks[taskId].tCryTaskWantedCry = wantedCryCase; - gTasks[taskId].tCryTaskBank = bank; - gTasks[taskId].tCryTaskMonSpriteId = gBattlerSpriteIds[sprite->sBank]; + gTasks[taskId].tCryTaskBattler = battlerId; + gTasks[taskId].tCryTaskMonSpriteId = gBattlerSpriteIds[sprite->sBattler]; gTasks[taskId].tCryTaskMonPtr1 = (u32)(mon) >> 0x10; gTasks[taskId].tCryTaskMonPtr2 = (u32)(mon); gTasks[taskId].tCryTaskState = 0; } - StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[sprite->sBank]], 1); + StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[sprite->sBattler]], 1); - if (GetBattlerSide(sprite->sBank) == B_SIDE_OPPONENT) - gSprites[gBattlerSpriteIds[sprite->sBank]].callback = sub_8039B58; + if (GetBattlerSide(sprite->sBattler) == B_SIDE_OPPONENT) + gSprites[gBattlerSpriteIds[sprite->sBattler]].callback = sub_8039B58; else - gSprites[gBattlerSpriteIds[sprite->sBank]].callback = sub_8039E44; + gSprites[gBattlerSpriteIds[sprite->sBattler]].callback = sub_8039E44; - AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBank]]); - gSprites[gBattlerSpriteIds[sprite->sBank]].data[1] = 0x1000; + AnimateSprite(&gSprites[gBattlerSpriteIds[sprite->sBattler]]); + gSprites[gBattlerSpriteIds[sprite->sBattler]].data[1] = 0x1000; } #undef tCryTaskSpecies #undef tCryTaskPan #undef tCryTaskWantedCry -#undef tCryTaskBank +#undef tCryTaskBattler #undef tCryTaskMonSpriteId #undef tCryTaskMonPtr1 #undef tCryTaskMonPtr2 @@ -828,37 +828,37 @@ static void sub_8075FB4(struct Sprite *sprite) static void HandleBallAnimEnd(struct Sprite *sprite) { bool8 affineAnimEnded = FALSE; - u8 bank = sprite->sBank; + u8 battlerId = sprite->sBattler; - gSprites[gBattlerSpriteIds[bank]].invisible = FALSE; + gSprites[gBattlerSpriteIds[battlerId]].invisible = FALSE; if (sprite->animEnded) sprite->invisible = TRUE; - if (gSprites[gBattlerSpriteIds[bank]].affineAnimEnded) + if (gSprites[gBattlerSpriteIds[battlerId]].affineAnimEnded) { - StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[bank]], 0); + StartSpriteAffineAnim(&gSprites[gBattlerSpriteIds[battlerId]], 0); affineAnimEnded = TRUE; } else { - gSprites[gBattlerSpriteIds[bank]].data[1] -= 288; - gSprites[gBattlerSpriteIds[bank]].pos2.y = gSprites[gBattlerSpriteIds[bank]].data[1] >> 8; + gSprites[gBattlerSpriteIds[battlerId]].data[1] -= 288; + gSprites[gBattlerSpriteIds[battlerId]].pos2.y = gSprites[gBattlerSpriteIds[battlerId]].data[1] >> 8; } if (sprite->animEnded && affineAnimEnded) { - s32 i, doneBanks; + s32 i, doneBattlers; - gSprites[gBattlerSpriteIds[bank]].pos2.y = 0; + gSprites[gBattlerSpriteIds[battlerId]].pos2.y = 0; gDoingBattleAnim = FALSE; - gBattleSpritesDataPtr->healthBoxesData[bank].ballAnimActive = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].ballAnimActive = 0; FreeSpriteOamMatrix(sprite); DestroySprite(sprite); - for (doneBanks = 0, i = 0; i < MAX_BATTLERS_COUNT; i++) + for (doneBattlers = 0, i = 0; i < MAX_BATTLERS_COUNT; i++) { if (gBattleSpritesDataPtr->healthBoxesData[i].ballAnimActive == 0) - doneBanks++; + doneBattlers++; } - if (doneBanks == MAX_BATTLERS_COUNT) + if (doneBattlers == MAX_BATTLERS_COUNT) { for (i = 0; i < POKEBALL_COUNT; i++) FreeBallGfx(i); @@ -868,7 +868,7 @@ static void HandleBallAnimEnd(struct Sprite *sprite) static void sub_80760F8(struct Sprite *sprite) { - u8 bank = sprite->sBank; + u8 battlerId = sprite->sBattler; sprite->data[4]++; if (sprite->data[4] == 40) @@ -883,21 +883,21 @@ static void sub_80760F8(struct Sprite *sprite) } else if (sprite->data[4] == 315) { - FreeOamMatrix(gSprites[gBattlerSpriteIds[sprite->sBank]].oam.matrixNum); - DestroySprite(&gSprites[gBattlerSpriteIds[sprite->sBank]]); + FreeOamMatrix(gSprites[gBattlerSpriteIds[sprite->sBattler]].oam.matrixNum); + DestroySprite(&gSprites[gBattlerSpriteIds[sprite->sBattler]]); DestroySpriteAndFreeResources(sprite); if (gMain.inBattle) - gBattleSpritesDataPtr->healthBoxesData[bank].ballAnimActive = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].ballAnimActive = 0; } } static void SpriteCB_PlayerMonSendOut_1(struct Sprite *sprite) { sprite->data[0] = 25; - sprite->data[2] = GetBattlerSpriteCoord(sprite->sBank, 2); - sprite->data[4] = GetBattlerSpriteCoord(sprite->sBank, 3) + 24; + sprite->data[2] = GetBattlerSpriteCoord(sprite->sBattler, 2); + sprite->data[4] = GetBattlerSpriteCoord(sprite->sBattler, 3) + 24; sprite->data[5] = -30; - sprite->oam.affineParam = sprite->sBank; + sprite->oam.affineParam = sprite->sBattler; sub_80A68D4(sprite); sprite->callback = SpriteCB_PlayerMonSendOut_2; } @@ -923,7 +923,7 @@ static void SpriteCB_PlayerMonSendOut_2(struct Sprite *sprite) } r4 = sprite->data[0]; sub_80A6F3C(sprite); - sprite->data[7] += sprite->sBank / 3; + sprite->data[7] += sprite->sBattler / 3; sprite->pos2.y += Sin(HIBYTE(sprite->data[7]), sprite->data[5]); sprite->oam.affineParam += 0x100; if ((sprite->oam.affineParam >> 8) % 3 != 0) @@ -946,11 +946,11 @@ static void SpriteCB_PlayerMonSendOut_2(struct Sprite *sprite) sprite->pos1.y += sprite->pos2.y; sprite->pos2.y = 0; sprite->pos2.x = 0; - sprite->sBank = sprite->oam.affineParam & 0xFF; + sprite->sBattler = sprite->oam.affineParam & 0xFF; sprite->data[0] = 0; if (IsDoubleBattle() && gBattleSpritesDataPtr->animationData->field_9_x1 - && sprite->sBank == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)) + && sprite->sBattler == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)) sprite->callback = SpriteCB_ReleaseMon2FromBall; else sprite->callback = SpriteCB_ReleaseMonFromBall; @@ -976,26 +976,26 @@ static void SpriteCB_OpponentMonSendOut(struct Sprite *sprite) { sprite->data[0] = 0; if (IsDoubleBattle() && gBattleSpritesDataPtr->animationData->field_9_x1 - && sprite->sBank == GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)) + && sprite->sBattler == GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)) sprite->callback = SpriteCB_ReleaseMon2FromBall; else sprite->callback = SpriteCB_ReleaseMonFromBall; } } -#undef sBank +#undef sBattler static u8 LaunchBallStarsTaskForPokeball(u8 x, u8 y, u8 kindOfStars, u8 d) { return LaunchBallStarsTask(x, y, kindOfStars, d, BALL_POKE); } -static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 bank, u32 arg2) +static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 battlerId, u32 arg2) { - return LaunchBallFadeMonTask(unFadeLater, bank, arg2, BALL_POKE); + return LaunchBallFadeMonTask(unFadeLater, battlerId, arg2, BALL_POKE); } -void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 bank, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 g, u32 h, u16 species) +void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 battlerId, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 g, u32 h, u16 species) { u8 spriteId; @@ -1012,7 +1012,7 @@ void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 bank, u8 x, u8 y, u8 oa gSprites[monSpriteId].data[7] = species; gSprites[spriteId].data[1] = g; - gSprites[spriteId].data[2] = bank; + gSprites[spriteId].data[2] = battlerId; gSprites[spriteId].data[3] = h; gSprites[spriteId].data[4] = h >> 0x10; gSprites[spriteId].oam.priority = oamPriority; @@ -1027,7 +1027,7 @@ static void sub_8076524(struct Sprite *sprite) { u8 r5; u8 r7 = sprite->data[0]; - u8 bank = sprite->data[2]; + u8 battlerId = sprite->data[2]; u32 r4 = (u16)sprite->data[3] | ((u16)sprite->data[4] << 16); if (sprite->subpriority != 0) @@ -1037,7 +1037,7 @@ static void sub_8076524(struct Sprite *sprite) StartSpriteAnim(sprite, 1); LaunchBallStarsTaskForPokeball(sprite->pos1.x, sprite->pos1.y - 5, sprite->oam.priority, r5); - sprite->data[1] = LaunchBallFadeMonTaskForPokeball(1, bank, r4); + sprite->data[1] = LaunchBallFadeMonTaskForPokeball(1, battlerId, r4); sprite->callback = sub_80765E0; gSprites[r7].invisible = FALSE; StartSpriteAffineAnim(&gSprites[r7], 1); @@ -1175,16 +1175,16 @@ static void DestroySpriteAndFreeResources_(struct Sprite *sprite) DestroySpriteAndFreeResources(sprite); } -void sub_8076918(u8 bank) +void sub_8076918(u8 battlerId) { - struct Sprite *healthboxSprite = &gSprites[gHealthboxSpriteIds[bank]]; + struct Sprite *healthboxSprite = &gSprites[gHealthboxSpriteIds[battlerId]]; healthboxSprite->data[0] = 5; healthboxSprite->data[1] = 0; healthboxSprite->pos2.x = 0x73; healthboxSprite->pos2.y = 0; healthboxSprite->callback = sub_80769CC; - if (GetBattlerSide(bank) != B_SIDE_PLAYER) + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) { healthboxSprite->data[0] = -healthboxSprite->data[0]; healthboxSprite->data[1] = -healthboxSprite->data[1]; @@ -1192,7 +1192,7 @@ void sub_8076918(u8 bank) healthboxSprite->pos2.y = -healthboxSprite->pos2.y; } gSprites[healthboxSprite->data[5]].callback(&gSprites[healthboxSprite->data[5]]); - if (GetBattlerPosition(bank) == B_POSITION_PLAYER_RIGHT) + if (GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT) healthboxSprite->callback = sub_80769A8; } @@ -1214,13 +1214,13 @@ static void sub_80769CC(struct Sprite *sprite) sprite->callback = SpriteCallbackDummy; } -void DoHitAnimHealthboxEffect(u8 bank) +void DoHitAnimHealthboxEffect(u8 battlerId) { u8 spriteId; spriteId = CreateInvisibleSpriteWithCallback(SpriteCB_HitAnimHealthoxEffect); gSprites[spriteId].data[0] = 1; - gSprites[spriteId].data[1] = gHealthboxSpriteIds[bank]; + gSprites[spriteId].data[1] = gHealthboxSpriteIds[battlerId]; gSprites[spriteId].callback = SpriteCB_HitAnimHealthoxEffect; } @@ -1267,10 +1267,10 @@ void FreeBallGfx(u8 ballId) FreeSpritePaletteByTag(gBallSpritePalettes[ballId].tag); } -static u16 GetBankPokeballItemId(u8 bank) +static u16 GetBattlerPokeballItemId(u8 battlerId) { - if (GetBattlerSide(bank) == B_SIDE_PLAYER) - return GetMonData(&gPlayerParty[gBattlerPartyIndexes[bank]], MON_DATA_POKEBALL); + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + return GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL); else - return GetMonData(&gEnemyParty[gBattlerPartyIndexes[bank]], MON_DATA_POKEBALL); + return GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_POKEBALL); } diff --git a/src/pokeblock.c b/src/pokeblock.c index b9d1d94c6..f57b2f0c2 100644 --- a/src/pokeblock.c +++ b/src/pokeblock.c @@ -29,6 +29,7 @@ #include "battle_message.h" #include "safari_zone.h" #include "lilycove_lady.h" +#include "overworld.h" #define POKEBLOCK_MAX_FEEL 99 #define FIELD_E75_COUNT 7 @@ -70,11 +71,10 @@ enum }; extern u16 gSpecialVar_ItemId; -extern void (*gFieldCallback)(void); extern const u16 gUnknown_0860F074[]; -extern void c2_exit_to_overworld_2_switch(void); +extern void CB2_ReturnToField(void); extern bool8 sub_81221EC(void); extern void sub_809882C(u8, u16, u8); extern void copy_textbox_border_tile_patterns_to_vram(u8, u16, u8); @@ -91,7 +91,7 @@ static void sub_81362E0(void); static void sub_8136344(void); static void HandlePokeblockListMenuItems(void); static void sub_81363BC(void); -static void MovePokeblockMenuCursor(u32 pkblId, bool8 arg1, struct ListMenu *arg2); +static void MovePokeblockMenuCursor(s32 pkblId, bool8 arg1, struct ListMenu *arg2); static void PutPokeblockInfoText(void); static void HandlePokeblockMenuCursor(u16 cursorPos, u16 arg1); static void PutPokeblockListMenuString(u8 *dst, u16 pkblId); @@ -319,18 +319,18 @@ static const struct ListMenuTemplate sPokeblockListMenuTemplate = .unk_08 = NULL, .totalItems = 0, .maxShowed = 0, - .unk_10 = 1, + .windowId = 1, .unk_11 = 0, .unk_12 = 1, - .cursor_Y = 0, + .cursor_X = 0, .upText_Y = 1, - .cursorColor = 2, - .fillColor = 0, - .cursorShadowColor = 3, - .unk_16_0 = FALSE, - .spaceBetweenItems = 32, - .unk_16_7 = FALSE, - .unk_17_0 = 1, + .cursorPal = 2, + .fillValue = 0, + .cursorShadowPal = 3, + .lettersSpacing = 0, + .unk_16_3 = 0, + .scrollMultiple = LIST_MULTIPLE_SCROLL_DPAD, + .fontId = 1, .cursorKind = 1 }; @@ -374,7 +374,7 @@ void OpenPokeblockCaseInBattle(void) void OpenPokeblockCaseOnFeeder(void) { - OpenPokeblockCase(PBLOCK_CASE_FEEDER, c2_exit_to_overworld_2_switch); + OpenPokeblockCase(PBLOCK_CASE_FEEDER, CB2_ReturnToField); } static void CB2_PokeblockMenu(void) @@ -460,7 +460,7 @@ static bool8 InitPokeblockMenu(void) gMain.state++; break; case 10: - sub_8122344(&sPokeblockMenu->field_E75, FIELD_E75_COUNT); + sub_8122344(sPokeblockMenu->field_E75, FIELD_E75_COUNT); gMain.state++; break; case 11: @@ -589,7 +589,7 @@ static void PutPokeblockInfoText(void) { u8 i; - const u8 *itemName = ItemId_GetItem(ITEM_POKEBLOCK_CASE)->name; + const u8 *itemName = ItemId_GetName(ITEM_POKEBLOCK_CASE); PrintOnPokeblockWindow(0, itemName, GetStringCenterAlignXOffset(1, itemName, 0x48)); PrintOnPokeblockWindow(2, gText_Spicy, 0); @@ -620,7 +620,7 @@ static void HandlePokeblockListMenuItems(void) sPokeblockMenu->items[i].id = LIST_B_PRESSED; gMultiuseListMenuTemplate = sPokeblockListMenuTemplate; - gMultiuseListMenuTemplate.unk_17_0 = 7; + gMultiuseListMenuTemplate.fontId = 7; gMultiuseListMenuTemplate.totalItems = sPokeblockMenu->itemsNo; gMultiuseListMenuTemplate.items = sPokeblockMenu->items; gMultiuseListMenuTemplate.maxShowed = sPokeblockMenu->maxShowed; @@ -639,7 +639,7 @@ static void PutPokeblockListMenuString(u8 *dst, u16 pkblId) StringExpandPlaceholders(txtPtr, gText_LvVar1); } -static void MovePokeblockMenuCursor(u32 pkblId, bool8 arg1, struct ListMenu *arg2) +static void MovePokeblockMenuCursor(s32 pkblId, bool8 arg1, struct ListMenu *arg2) { if (arg1 != TRUE) { @@ -869,7 +869,7 @@ static void Task_FreeDataAndExitPokeblockCase(u8 taskId) if (sPokeblockMenu->caseId == PBLOCK_CASE_FEEDER || sPokeblockMenu->caseId == PBLOCK_CASE_GIVE) gFieldCallback = sub_80AF168; - sub_81AE6C8(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + DestroyListMenuTask(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); sub_8136418(); ResetSpriteData(); FreeAllSpritePalettes(); @@ -893,7 +893,7 @@ static void Task_HandlePokeblockMenuInput(u8 taskId) { if (gMain.newKeys & SELECT_BUTTON) { - sub_81AE860(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + ListMenuGetScrollAndRow(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); if (sSavedPokeblockData.lastItemPage + sSavedPokeblockData.lastItemPos != sPokeblockMenu->itemsNo - 1) { PlaySE(SE_SELECT); @@ -908,7 +908,7 @@ static void Task_HandlePokeblockMenuInput(u8 taskId) u16 oldPosition = sSavedPokeblockData.lastItemPos; s32 itemId = ListMenuHandleInputGetItemId(data[0]); - sub_81AE860(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + ListMenuGetScrollAndRow(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); if (oldPosition != sSavedPokeblockData.lastItemPos) { HandlePokeblockMenuCursor(oldPosition, 5); @@ -945,7 +945,7 @@ static void Task_HandlePokeblocksSwapInput(u8 taskId) if (gMain.newKeys & SELECT_BUTTON) { PlaySE(SE_SELECT); - sub_81AE860(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + ListMenuGetScrollAndRow(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); HandlePokeblocksSwap(taskId, FALSE); } else @@ -954,7 +954,7 @@ static void Task_HandlePokeblocksSwapInput(u8 taskId) u16 var = sSavedPokeblockData.lastItemPos; s32 itemId = ListMenuHandleInputGetItemId(data[0]); - sub_81AE860(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + ListMenuGetScrollAndRow(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); if (i != sSavedPokeblockData.lastItemPage || var != sSavedPokeblockData.lastItemPos) { for (i = 0; i < 9; i++) @@ -996,7 +996,7 @@ static void HandlePokeblocksSwap(u8 taskId, bool8 noSwap) u16 swappedFromId = sSavedPokeblockData.lastItemPage + sSavedPokeblockData.lastItemPos; sPokeblockMenu->isSwapping = FALSE; - sub_81AE6C8(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); + DestroyListMenuTask(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); if (!noSwap && data[2] != swappedFromId && data[2] != swappedFromId - 1) { @@ -1112,7 +1112,7 @@ static void HandleErasePokeblock(u8 taskId) lastPos = &sSavedPokeblockData.lastItemPos; data = gTasks[taskId].data; - sub_81AE6C8(data[0], lastPage, lastPos); + DestroyListMenuTask(data[0], lastPage, lastPos); HandlePokeblockMenuCursor(*lastPos, 5); SetMenuItemsCountAndMaxShowed(); sub_81362E0(); diff --git a/src/pokeblock_feed.c b/src/pokeblock_feed.c index 2039808cb..db92d56a8 100644 --- a/src/pokeblock_feed.c +++ b/src/pokeblock_feed.c @@ -50,7 +50,6 @@ struct PokeblockFeedStruct extern u16 gSpecialVar_ItemId; extern struct MusicPlayerInfo gMPlayInfo_BGM; -extern struct SpriteTemplate gUnknown_0202499C; extern const u8 gBattleTerrainPalette_Frontier[]; extern const u8 gBattleTerrainTiles_Building[]; @@ -837,7 +836,7 @@ static u8 CreateMonSprite(struct Pokemon* mon) gSprites[spriteId].callback = SpriteCallbackDummy; sPokeblockFeed->noMonFlip = TRUE; - if (!IsPokeSpriteNotFlipped(species)) + if (!IsMonSpriteNotFlipped(species)) { gSprites[spriteId].affineAnims = sSpriteAffineAnimTable_MonNoFlip; gSprites[spriteId].oam.affineMode = 3; diff --git a/src/pokemon.c b/src/pokemon.c new file mode 100644 index 000000000..800b7c0cd --- /dev/null +++ b/src/pokemon.c @@ -0,0 +1,6096 @@ +#include "global.h" +#include "pokemon.h" +#include "battle.h" +#include "battle_setup.h" +#include "battle_message.h" +#include "random.h" +#include "main.h" +#include "constants/species.h" +#include "constants/abilities.h" +#include "constants/items.h" +#include "constants/trainers.h" +#include "constants/moves.h" +#include "constants/hold_effects.h" +#include "constants/battle_move_effects.h" +#include "constants/songs.h" +#include "string_util.h" +#include "text.h" +#include "link.h" +#include "event_data.h" +#include "item.h" +#include "battle_controllers.h" +#include "battle_message.h" +#include "evolution_scene.h" +#include "pokemon_animation.h" +#include "pokedex.h" +#include "pokeblock.h" +#include "sound.h" +#include "task.h" +#include "rtc.h" +#include "m4a.h" +#include "malloc.h" +#include "util.h" +#include "strings.h" +#include "pokenav.h" +#include "pokemon_storage_system.h" +#include "recorded_battle.h" + +struct SpeciesItem +{ + u16 species; + u16 item; +}; + +// Extracts the upper 16 bits of a 32-bit number +#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) + +// Extracts the lower 16 bits of a 32-bit number +#define LOHALF(n) ((n) & 0xFFFF) + +extern const struct OamData gUnknown_0831ACB0; +extern const struct OamData gUnknown_0831ACA8; +extern const struct SpriteFrameImage gUnknown_082FF3A8[]; +extern const struct SpriteFrameImage gUnknown_082FF3C8[]; +extern const struct SpriteFrameImage gUnknown_082FF3E8[]; +extern const struct SpriteFrameImage gUnknown_082FF408[]; +extern const struct SpriteFrameImage gUnknown_082FF428[]; +extern const struct SpriteFrameImage gUnknown_082FF448[]; +extern const struct SpriteFrameImage gUnknown_082FF468[]; +extern const struct SpriteFrameImage gUnknown_082FF490[]; +extern const struct SpriteFrameImage gUnknown_082FF4B8[]; +extern const struct SpriteFrameImage gUnknown_082FF4D8[]; +extern const struct SpriteFrameImage gUnknown_082FF4F8[]; +extern const struct SpriteFrameImage gUnknown_082FF518[]; +extern const union AffineAnimCmd *const gUnknown_082FF618[]; +extern const union AffineAnimCmd *const gUnknown_082FF694[]; +extern const union AnimCmd *gUnknown_082FF70C[]; +extern const union AnimCmd *const *const gMonAnimationsSpriteAnimsPtrTable[]; +extern const union AnimCmd *const *const gUnknown_08305D0C[]; +extern const union AnimCmd *const *const gUnknown_0830536C[]; +extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1]; +extern const struct UnknownPokemonStruct3 gUnknown_08610970[]; +extern const struct CompressedSpritePalette gMonPaletteTable[]; +extern const struct CompressedSpritePalette gMonShinyPaletteTable[]; +extern const u8 gTrainerClassNames[][13]; + +extern u8 pokemon_order_func(u8); +extern u16 get_unknown_box_id(void); +extern u8 StorageGetCurrentBox(void); +extern void set_unknown_box_id(u8); +extern void sub_803FA70(u8 battlerId); +extern u8 sav1_map_get_name(void); +extern const u8 *sub_81A1650(u8, u8 language); +extern u8 BattleFrontierGetOpponentLvl(u8); +extern u16 FacilityClassToPicIndex(u16); +extern bool8 InBattlePyramid(void); +extern bool8 InBattlePike(void); +extern bool8 sub_806F104(void); +extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId); +extern u8 sub_81D63C8(u16 trainerOpponentId); +extern u8 GetFrontierOpponentClass(u16 trainerId); +extern void GetFrontierTrainerName(u8* dest, u16 trainerId); +extern void sub_81C488C(u8); + +// this file's functions +static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon); +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType); +static void EncryptBoxMon(struct BoxPokemon *boxMon); +static void DecryptBoxMon(struct BoxPokemon *boxMon); +static void sub_806E6CC(u8 taskId); +static bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 battlerId); + +// EWRAM vars +EWRAM_DATA static u8 sLearningMoveTableID = 0; +EWRAM_DATA u8 gPlayerPartyCount = 0; +EWRAM_DATA u8 gEnemyPartyCount = 0; +EWRAM_DATA struct Pokemon gPlayerParty[PARTY_SIZE] = {0}; +EWRAM_DATA struct Pokemon gEnemyParty[PARTY_SIZE] = {0}; +EWRAM_DATA struct SpriteTemplate gUnknown_0202499C = {0}; +EWRAM_DATA struct Unknown_806F160_Struct *gUnknown_020249B4[2] = {NULL}; + +// const rom data +#include "data/battle_moves.h" +static const u8 sUnreferencedData[] = {0x34, 0x00, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}; + +const u16 gSpeciesToHoennPokedexNum[] = {203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 156, 157, 112, 113, 227, 228, 229, 230, 231, 232, 233, 234, 153, 154, 138, 139, 63, 64, 88, 89, 90, 235, 236, 237, 238, 239, 240, 241, 242, 158, 159, 243, 244, 245, 246, 247, 248, 249, 39, 40, 41, 73, 74, 75, 250, 251, 252, 66, 67, 57, 58, 59, 253, 254, 255, 256, 82, 83, 257, 92, 93, 258, 259, 106, 107, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 84, 85, 270, 271, 272, 273, 274, 275, 276, 108, 109, 169, 170, 277, 278, 279, 184, 185, 50, 51, 143, 144, 280, 281, 282, 283, 284, 167, 285, 52, 53, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 65, 181, 182, 155, 324, 137, 325, 326, 162, 163, 327, 328, 329, 91, 55, 56, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 161, 164, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 168, 357, 358, 359, 103, 104, 360, 361, 180, 362, 363, 364, 365, 115, 366, 367, 186, 165, 166, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43, 44, 25, 26, 34, 35, 114, 27, 28, 32, 33, 99, 100, 61, 62, 145, 131, 132, 60, 105, 68, 127, 128, 183, 129, 130, 140, 141, 97, 98, 116, 117, 118, 48, 49, 78, 79, 101, 102, 173, 174, 175, 119, 120, 171, 172, 125, 126, 54, 110, 111, 80, 81, 69, 76, 77, 121, 122, 160, 148, 149, 94, 36, 37, 38, 95, 96, 150, 45, 46, 47, 176, 177, 178, 152, 146, 147, 124, 123, 179, 70, 71, 72, 142, 86, 87, 133, 134, 135, 136, 29, 30, 31, 187, 188, 189, 190, 191, 192, 193, 194, 195, 198, 199, 200, 196, 197, 201, 202, 151}; +const u16 gSpeciesToNationalPokedexNum[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 290, 291, 292, 276, 277, 285, 286, 327, 278, 279, 283, 284, 320, 321, 300, 301, 352, 343, 344, 299, 324, 302, 339, 340, 370, 341, 342, 349, 350, 318, 319, 328, 329, 330, 296, 297, 309, 310, 322, 323, 363, 364, 365, 331, 332, 361, 362, 337, 338, 298, 325, 326, 311, 312, 303, 307, 308, 333, 334, 360, 355, 356, 315, 287, 288, 289, 316, 317, 357, 293, 294, 295, 366, 367, 368, 359, 353, 354, 336, 335, 369, 304, 305, 306, 351, 313, 314, 345, 346, 347, 348, 280, 281, 282, 371, 372, 373, 374, 375, 376, 377, 378, 379, 382, 383, 384, 380, 381, 385, 386, 358}; +const u16 gHoennToNationalOrder[] = {252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 63, 64, 65, 290, 291, 292, 293, 294, 295, 296, 297, 118, 119, 129, 130, 298, 183, 184, 74, 75, 76, 299, 300, 301, 41, 42, 169, 72, 73, 302, 303, 304, 305, 306, 66, 67, 68, 307, 308, 309, 310, 311, 312, 81, 82, 100, 101, 313, 314, 43, 44, 45, 182, 84, 85, 315, 316, 317, 318, 319, 320, 321, 322, 323, 218, 219, 324, 88, 89, 109, 110, 325, 326, 27, 28, 327, 227, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 174, 39, 40, 349, 350, 351, 120, 121, 352, 353, 354, 355, 356, 357, 358, 359, 37, 38, 172, 25, 26, 54, 55, 360, 202, 177, 178, 203, 231, 232, 127, 214, 111, 112, 361, 362, 363, 364, 365, 366, 367, 368, 369, 222, 170, 171, 370, 116, 117, 230, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 36, 46, 47, 48, 49, 50, 51, 52, 53, 56, 57, 58, 59, 60, 61, 62, 69, 70, 71, 77, 78, 79, 80, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 102, 103, 104, 105, 106, 107, 108, 113, 114, 115, 122, 123, 124, 125, 126, 128, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 173, 175, 176, 179, 180, 181, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 220, 221, 223, 224, 225, 226, 228, 229, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411}; + +const struct SpindaSpot gSpindaSpotGraphics[] = +{ + {16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")}, + {40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")}, + {22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")}, + {34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")} +}; + +#include "data/pokemon/item_effects.h" + +const s8 gNatureStatTable[][5] = +{ + // Atk Def Spd Sp.Atk Sp.Def + { 0, 0, 0, 0, 0}, // Hardy + { +1, -1, 0, 0, 0}, // Lonely + { +1, 0, -1, 0, 0}, // Brave + { +1, 0, 0, -1, 0}, // Adamant + { +1, 0, 0, 0, -1}, // Naughty + { -1, +1, 0, 0, 0}, // Bold + { 0, 0, 0, 0, 0}, // Docile + { 0, +1, -1, 0, 0}, // Relaxed + { 0, +1, 0, -1, 0}, // Impish + { 0, +1, 0, 0, -1}, // Lax + { -1, 0, +1, 0, 0}, // Timid + { 0, -1, +1, 0, 0}, // Hasty + { 0, 0, 0, 0, 0}, // Serious + { 0, 0, +1, -1, 0}, // Jolly + { 0, 0, +1, 0, -1}, // Naive + { -1, 0, 0, +1, 0}, // Modest + { 0, -1, 0, +1, 0}, // Mild + { 0, 0, -1, +1, 0}, // Quiet + { 0, 0, 0, 0, 0}, // Bashful + { 0, 0, 0, +1, -1}, // Rash + { -1, 0, 0, 0, +1}, // Calm + { 0, -1, 0, 0, +1}, // Gentle + { 0, 0, -1, 0, +1}, // Sassy + { 0, 0, 0, -1, +1}, // Careful + { 0, 0, 0, 0, 0}, // Quirky +}; + +#include "data/pokemon/tmhm_learnsets.h" +#include "data/pokemon/trainer_class_lookups.h" +#include "data/pokemon/cry_ids.h" +#include "data/pokemon/experience_tables.h" +#include "data/pokemon/base_stats.h" +#include "data/pokemon/level_up_learnsets.h" +#include "data/pokemon/evolution.h" +#include "data/pokemon/level_up_learnset_pointers.h" + +static const u8 sMonFrontAnimIdsTable[] = +{ + 0x06, // SPECIES_BULBASAUR + 0x17, // SPECIES_IVYSAUR + 0x2f, // SPECIES_VENUSAUR + 0x52, // SPECIES_CHARMANDER + 0x25, // SPECIES_CHARMELEON + 0x10, // SPECIES_CHARIZARD + 0x0b, // SPECIES_SQUIRTLE + 0x13, // SPECIES_WARTORTLE + 0x19, // SPECIES_BLASTOISE + 0x0b, // SPECIES_CATERPIE + 0x0b, // SPECIES_METAPOD + 0x1d, // SPECIES_BUTTERFREE + 0x46, // SPECIES_WEEDLE + 0x20, // SPECIES_KAKUNA + 0x02, // SPECIES_BEEDRILL + 0x47, // SPECIES_PIDGEY + 0x17, // SPECIES_PIDGEOTTO + 0x29, // SPECIES_PIDGEOT + 0x43, // SPECIES_RATTATA + 0x2b, // SPECIES_RATICATE + 0x18, // SPECIES_SPEAROW + 0x2b, // SPECIES_FEAROW + 0x16, // SPECIES_EKANS + 0x17, // SPECIES_ARBOK + 0x2c, // SPECIES_PIKACHU + 0x17, // SPECIES_RAICHU + 0x2d, // SPECIES_SANDSHREW + 0x17, // SPECIES_SANDSLASH + 0x00, // SPECIES_NIDORAN_F + 0x17, // SPECIES_NIDORINA + 0x0f, // SPECIES_NIDOQUEEN + 0x09, // SPECIES_NIDORAN_M + 0x13, // SPECIES_NIDORINO + 0x0f, // SPECIES_NIDOKING + 0x00, // SPECIES_CLEFAIRY + 0x4a, // SPECIES_CLEFABLE + 0x17, // SPECIES_VULPIX + 0x10, // SPECIES_NINETALES + 0x48, // SPECIES_JIGGLYPUFF + 0x31, // SPECIES_WIGGLYTUFF + 0x00, // SPECIES_ZUBAT + 0x1d, // SPECIES_GOLBAT + 0x00, // SPECIES_ODDISH + 0x45, // SPECIES_GLOOM + 0x49, // SPECIES_VILEPLUME + 0x46, // SPECIES_PARAS + 0x0f, // SPECIES_PARASECT + 0x06, // SPECIES_VENONAT + 0x4b, // SPECIES_VENOMOTH + 0x10, // SPECIES_DIGLETT + 0x4c, // SPECIES_DUGTRIO + 0x52, // SPECIES_MEOWTH + 0x17, // SPECIES_PERSIAN + 0x06, // SPECIES_PSYDUCK + 0x4c, // SPECIES_GOLDUCK + 0x32, // SPECIES_MANKEY + 0x48, // SPECIES_PRIMEAPE + 0x25, // SPECIES_GROWLITHE + 0x02, // SPECIES_ARCANINE + 0x00, // SPECIES_POLIWAG + 0x32, // SPECIES_POLIWHIRL + 0x19, // SPECIES_POLIWRATH + 0x31, // SPECIES_ABRA + 0x09, // SPECIES_KADABRA + 0x17, // SPECIES_ALAKAZAM + 0x00, // SPECIES_MACHOP + 0x10, // SPECIES_MACHOKE + 0x31, // SPECIES_MACHAMP + 0x17, // SPECIES_BELLSPROUT + 0x0d, // SPECIES_WEEPINBELL + 0x32, // SPECIES_VICTREEBEL + 0x00, // SPECIES_TENTACOOL + 0x00, // SPECIES_TENTACRUEL + 0x48, // SPECIES_GEODUDE + 0x48, // SPECIES_GRAVELER + 0x2f, // SPECIES_GOLEM + 0x20, // SPECIES_PONYTA + 0x11, // SPECIES_RAPIDASH + 0x45, // SPECIES_SLOWPOKE + 0x0b, // SPECIES_SLOWBRO + 0x54, // SPECIES_MAGNEMITE + 0x2c, // SPECIES_MAGNETON + 0x48, // SPECIES_FARFETCHD + 0x4c, // SPECIES_DODUO + 0x41, // SPECIES_DODRIO + 0x0b, // SPECIES_SEEL + 0x45, // SPECIES_DEWGONG + 0x46, // SPECIES_GRIMER + 0x30, // SPECIES_MUK + 0x12, // SPECIES_SHELLDER + 0x1d, // SPECIES_CLOYSTER + 0x15, // SPECIES_GASTLY + 0x35, // SPECIES_HAUNTER + 0x3a, // SPECIES_GENGAR + 0x43, // SPECIES_ONIX + 0x4f, // SPECIES_DROWZEE + 0x09, // SPECIES_HYPNO + 0x03, // SPECIES_KRABBY + 0x4b, // SPECIES_KINGLER + 0x00, // SPECIES_VOLTORB + 0x00, // SPECIES_ELECTRODE + 0x46, // SPECIES_EXEGGCUTE + 0x32, // SPECIES_EXEGGUTOR + 0x48, // SPECIES_CUBONE + 0x05, // SPECIES_MAROWAK + 0x16, // SPECIES_HITMONLEE + 0x09, // SPECIES_HITMONCHAN + 0x45, // SPECIES_LICKITUNG + 0x13, // SPECIES_KOFFING + 0x04, // SPECIES_WEEZING + 0x10, // SPECIES_RHYHORN + 0x13, // SPECIES_RHYDON + 0x45, // SPECIES_CHANSEY + 0x48, // SPECIES_TANGELA + 0x17, // SPECIES_KANGASKHAN + 0x12, // SPECIES_HORSEA + 0x04, // SPECIES_SEADRA + 0x0d, // SPECIES_GOLDEEN + 0x1c, // SPECIES_SEAKING + 0x4e, // SPECIES_STARYU + 0x12, // SPECIES_STARMIE + 0x46, // SPECIES_MR_MIME + 0x02, // SPECIES_SCYTHER + 0x17, // SPECIES_JYNX + 0x2c, // SPECIES_ELECTABUZZ + 0x0f, // SPECIES_MAGMAR + 0x09, // SPECIES_PINSIR + 0x19, // SPECIES_TAUROS + 0x05, // SPECIES_MAGIKARP + 0x48, // SPECIES_GYARADOS + 0x17, // SPECIES_LAPRAS + 0x01, // SPECIES_DITTO + 0x17, // SPECIES_EEVEE + 0x17, // SPECIES_VAPOREON + 0x00, // SPECIES_JOLTEON + 0x17, // SPECIES_FLAREON + 0x52, // SPECIES_PORYGON + 0x51, // SPECIES_OMANYTE + 0x09, // SPECIES_OMASTAR + 0x1d, // SPECIES_KABUTO + 0x0f, // SPECIES_KABUTOPS + 0x47, // SPECIES_AERODACTYL + 0x0b, // SPECIES_SNORLAX + 0x09, // SPECIES_ARTICUNO + 0x2c, // SPECIES_ZAPDOS + 0x45, // SPECIES_MOLTRES + 0x00, // SPECIES_DRATINI + 0x10, // SPECIES_DRAGONAIR + 0x47, // SPECIES_DRAGONITE + 0x09, // SPECIES_MEWTWO + 0x0d, // SPECIES_MEW + 0x00, // SPECIES_CHIKORITA + 0x00, // SPECIES_BAYLEEF + 0x17, // SPECIES_MEGANIUM + 0x52, // SPECIES_CYNDAQUIL + 0x17, // SPECIES_QUILAVA + 0x10, // SPECIES_TYPHLOSION + 0x31, // SPECIES_TOTODILE + 0x0f, // SPECIES_CROCONAW + 0x0f, // SPECIES_FERALIGATR + 0x00, // SPECIES_SENTRET + 0x32, // SPECIES_FURRET + 0x47, // SPECIES_HOOTHOOT + 0x17, // SPECIES_NOCTOWL + 0x52, // SPECIES_LEDYBA + 0x47, // SPECIES_LEDIAN + 0x4f, // SPECIES_SPINARAK + 0x0f, // SPECIES_ARIADOS + 0x00, // SPECIES_CROBAT + 0x45, // SPECIES_CHINCHOU + 0x51, // SPECIES_LANTURN + 0x1e, // SPECIES_PICHU + 0x52, // SPECIES_CLEFFA + 0x0c, // SPECIES_IGGLYBUFF + 0x0b, // SPECIES_TOGEPI + 0x00, // SPECIES_TOGETIC + 0x31, // SPECIES_NATU + 0x09, // SPECIES_XATU + 0x00, // SPECIES_MAREEP + 0x1e, // SPECIES_FLAAFFY + 0x2c, // SPECIES_AMPHAROS + 0x0b, // SPECIES_BELLOSSOM + 0x00, // SPECIES_MARILL + 0x4a, // SPECIES_AZUMARILL + 0x46, // SPECIES_SUDOWOODO + 0x32, // SPECIES_POLITOED + 0x1c, // SPECIES_HOPPIP + 0x18, // SPECIES_SKIPLOOM + 0x51, // SPECIES_JUMPLUFF + 0x32, // SPECIES_AIPOM + 0x52, // SPECIES_SUNKERN + 0x00, // SPECIES_SUNFLORA + 0x2b, // SPECIES_YANMA + 0x00, // SPECIES_WOOPER + 0x16, // SPECIES_QUAGSIRE + 0x09, // SPECIES_ESPEON + 0x10, // SPECIES_UMBREON + 0x00, // SPECIES_MURKROW + 0x13, // SPECIES_SLOWKING + 0x1c, // SPECIES_MISDREAVUS + 0x0a, // SPECIES_UNOWN + 0x30, // SPECIES_WOBBUFFET + 0x1e, // SPECIES_GIRAFARIG + 0x0b, // SPECIES_PINECO + 0x10, // SPECIES_FORRETRESS + 0x00, // SPECIES_DUNSPARCE + 0x13, // SPECIES_GLIGAR + 0x0f, // SPECIES_STEELIX + 0x17, // SPECIES_SNUBBULL + 0x10, // SPECIES_GRANBULL + 0x3a, // SPECIES_QWILFISH + 0x02, // SPECIES_SCIZOR + 0x0b, // SPECIES_SHUCKLE + 0x41, // SPECIES_HERACROSS + 0x16, // SPECIES_SNEASEL + 0x17, // SPECIES_TEDDIURSA + 0x10, // SPECIES_URSARING + 0x17, // SPECIES_SLUGMA + 0x17, // SPECIES_MAGCARGO + 0x00, // SPECIES_SWINUB + 0x0f, // SPECIES_PILOSWINE + 0x03, // SPECIES_CORSOLA + 0x52, // SPECIES_REMORAID + 0x17, // SPECIES_OCTILLERY + 0x52, // SPECIES_DELIBIRD + 0x0d, // SPECIES_MANTINE + 0x17, // SPECIES_SKARMORY + 0x17, // SPECIES_HOUNDOUR + 0x10, // SPECIES_HOUNDOOM + 0x42, // SPECIES_KINGDRA + 0x32, // SPECIES_PHANPY + 0x19, // SPECIES_DONPHAN + 0x00, // SPECIES_PORYGON2 + 0x00, // SPECIES_STANTLER + 0x31, // SPECIES_SMEARGLE + 0x16, // SPECIES_TYROGUE + 0x02, // SPECIES_HITMONTOP + 0x09, // SPECIES_SMOOCHUM + 0x2c, // SPECIES_ELEKID + 0x00, // SPECIES_MAGBY + 0x45, // SPECIES_MILTANK + 0x00, // SPECIES_BLISSEY + 0x2c, // SPECIES_RAIKOU + 0x09, // SPECIES_ENTEI + 0x10, // SPECIES_SUICUNE + 0x52, // SPECIES_LARVITAR + 0x10, // SPECIES_PUPITAR + 0x0f, // SPECIES_TYRANITAR + 0x3a, // SPECIES_LUGIA + 0x09, // SPECIES_HO_OH + 0x18, // SPECIES_CELEBI + 0x00, // 252 + 0x00, // 253 + 0x00, // 254 + 0x00, // 255 + 0x00, // 256 + 0x00, // 257 + 0x00, // 258 + 0x00, // 259 + 0x00, // 260 + 0x00, // 261 + 0x00, // 262 + 0x00, // 263 + 0x00, // 264 + 0x00, // 265 + 0x00, // 266 + 0x00, // 267 + 0x00, // 268 + 0x00, // 269 + 0x00, // 270 + 0x00, // 271 + 0x00, // 272 + 0x00, // 273 + 0x00, // 274 + 0x00, // 275 + 0x00, // 276 + 0x00, // SPECIES_TREECKO + 0x17, // SPECIES_GROVYLE + 0x10, // SPECIES_SCEPTILE + 0x16, // SPECIES_TORCHIC + 0x06, // SPECIES_COMBUSKEN + 0x0f, // SPECIES_BLAZIKEN + 0x01, // SPECIES_MUDKIP + 0x04, // SPECIES_MARSHTOMP + 0x1e, // SPECIES_SWAMPERT + 0x10, // SPECIES_POOCHYENA + 0x10, // SPECIES_MIGHTYENA + 0x03, // SPECIES_ZIGZAGOON + 0x09, // SPECIES_LINOONE + 0x00, // SPECIES_WURMPLE + 0x00, // SPECIES_SILCOON + 0x04, // SPECIES_BEAUTIFLY + 0x04, // SPECIES_CASCOON + 0x06, // SPECIES_DUSTOX + 0x00, // SPECIES_LOTAD + 0x00, // SPECIES_LOMBRE + 0x49, // SPECIES_LUDICOLO + 0x05, // SPECIES_SEEDOT + 0x00, // SPECIES_NUZLEAF + 0x02, // SPECIES_SHIFTRY + 0x00, // SPECIES_NINCADA + 0x46, // SPECIES_NINJASK + 0x1c, // SPECIES_SHEDINJA + 0x1e, // SPECIES_TAILLOW + 0x01, // SPECIES_SWELLOW + 0x00, // SPECIES_SHROOMISH + 0x00, // SPECIES_BRELOOM + 0x31, // SPECIES_SPINDA + 0x1b, // SPECIES_WINGULL + 0x1c, // SPECIES_PELIPPER + 0x00, // SPECIES_SURSKIT + 0x00, // SPECIES_MASQUERAIN + 0x01, // SPECIES_WAILMER + 0x1c, // SPECIES_WAILORD + 0x00, // SPECIES_SKITTY + 0x17, // SPECIES_DELCATTY + 0x35, // SPECIES_KECLEON + 0x1d, // SPECIES_BALTOY + 0x51, // SPECIES_CLAYDOL + 0x49, // SPECIES_NOSEPASS + 0x17, // SPECIES_TORKOAL + 0x15, // SPECIES_SABLEYE + 0x49, // SPECIES_BARBOACH + 0x49, // SPECIES_WHISCASH + 0x1d, // SPECIES_LUVDISC + 0x10, // SPECIES_CORPHISH + 0x09, // SPECIES_CRAWDAUNT + 0x49, // SPECIES_FEEBAS + 0x22, // SPECIES_MILOTIC + 0x49, // SPECIES_CARVANHA + 0x56, // SPECIES_SHARPEDO + 0x10, // SPECIES_TRAPINCH + 0x0f, // SPECIES_VIBRAVA + 0x4b, // SPECIES_FLYGON + 0x0b, // SPECIES_MAKUHITA + 0x34, // SPECIES_HARIYAMA + 0x00, // SPECIES_ELECTRIKE + 0x00, // SPECIES_MANECTRIC + 0x04, // SPECIES_NUMEL + 0x10, // SPECIES_CAMERUPT + 0x53, // SPECIES_SPHEAL + 0x17, // SPECIES_SEALEO + 0x0f, // SPECIES_WALREIN + 0x49, // SPECIES_CACNEA + 0x04, // SPECIES_CACTURNE + 0x45, // SPECIES_SNORUNT + 0x0a, // SPECIES_GLALIE + 0x0e, // SPECIES_LUNATONE + 0x08, // SPECIES_SOLROCK + 0x00, // SPECIES_AZURILL + 0x56, // SPECIES_SPOINK + 0x32, // SPECIES_GRUMPIG + 0x00, // SPECIES_PLUSLE + 0x01, // SPECIES_MINUN + 0x00, // SPECIES_MAWILE + 0x05, // SPECIES_MEDITITE + 0x45, // SPECIES_MEDICHAM + 0x04, // SPECIES_SWABLU + 0x16, // SPECIES_ALTARIA + 0x32, // SPECIES_WYNAUT + 0x0a, // SPECIES_DUSKULL + 0x02, // SPECIES_DUSCLOPS + 0x45, // SPECIES_ROSELIA + 0x45, // SPECIES_SLAKOTH + 0x31, // SPECIES_VIGOROTH + 0x45, // SPECIES_SLAKING + 0x00, // SPECIES_GULPIN + 0x45, // SPECIES_SWALOT + 0x10, // SPECIES_TROPIUS + 0x03, // SPECIES_WHISMUR + 0x49, // SPECIES_LOUDRED + 0x19, // SPECIES_EXPLOUD + 0x12, // SPECIES_CLAMPERL + 0x09, // SPECIES_HUNTAIL + 0x1c, // SPECIES_GOREBYSS + 0x11, // SPECIES_ABSOL + 0x1c, // SPECIES_SHUPPET + 0x0d, // SPECIES_BANETTE + 0x17, // SPECIES_SEVIPER + 0x09, // SPECIES_ZANGOOSE + 0x1a, // SPECIES_RELICANTH + 0x45, // SPECIES_ARON + 0x00, // SPECIES_LAIRON + 0x19, // SPECIES_AGGRON + 0x1d, // SPECIES_CASTFORM + 0x00, // SPECIES_VOLBEAT + 0x05, // SPECIES_ILLUMISE + 0x17, // SPECIES_LILEEP + 0x19, // SPECIES_CRADILY + 0x12, // SPECIES_ANORITH + 0x10, // SPECIES_ARMALDO + 0x45, // SPECIES_RALTS + 0x00, // SPECIES_KIRLIA + 0x00, // SPECIES_GARDEVOIR + 0x19, // SPECIES_BAGON + 0x04, // SPECIES_SHELGON + 0x0f, // SPECIES_SALAMENCE + 0x0f, // SPECIES_BELDUM + 0x04, // SPECIES_METANG + 0x10, // SPECIES_METAGROSS + 0x01, // SPECIES_REGIROCK + 0x44, // SPECIES_REGICE + 0x09, // SPECIES_REGISTEEL + 0x2d, // SPECIES_KYOGRE + 0x10, // SPECIES_GROUDON + 0x0f, // SPECIES_RAYQUAZA + 0x2d, // SPECIES_LATIAS + 0x10, // SPECIES_LATIOS + 0x0d, // SPECIES_JIRACHI + 0x1b, // SPECIES_DEOXYS + 0x1d, // SPECIES_CHIMECHO +}; + +static const u8 sMonAnimationDelayTable[] = +{ + 0x00, // SPECIES_BULBASAUR + 0x00, // SPECIES_IVYSAUR + 0x00, // SPECIES_VENUSAUR + 0x00, // SPECIES_CHARMANDER + 0x00, // SPECIES_CHARMELEON + 0x00, // SPECIES_CHARIZARD + 0x00, // SPECIES_SQUIRTLE + 0x00, // SPECIES_WARTORTLE + 0x32, // SPECIES_BLASTOISE + 0x00, // SPECIES_CATERPIE + 0x00, // SPECIES_METAPOD + 0x00, // SPECIES_BUTTERFREE + 0x0a, // SPECIES_WEEDLE + 0x14, // SPECIES_KAKUNA + 0x23, // SPECIES_BEEDRILL + 0x00, // SPECIES_PIDGEY + 0x19, // SPECIES_PIDGEOTTO + 0x00, // SPECIES_PIDGEOT + 0x00, // SPECIES_RATTATA + 0x00, // SPECIES_RATICATE + 0x00, // SPECIES_SPEAROW + 0x02, // SPECIES_FEAROW + 0x1e, // SPECIES_EKANS + 0x00, // SPECIES_ARBOK + 0x00, // SPECIES_PIKACHU + 0x00, // SPECIES_RAICHU + 0x00, // SPECIES_SANDSHREW + 0x00, // SPECIES_SANDSLASH + 0x1c, // SPECIES_NIDORAN_F + 0x00, // SPECIES_NIDORINA + 0x00, // SPECIES_NIDOQUEEN + 0x00, // SPECIES_NIDORAN_M + 0x00, // SPECIES_NIDORINO + 0x19, // SPECIES_NIDOKING + 0x00, // SPECIES_CLEFAIRY + 0x00, // SPECIES_CLEFABLE + 0x00, // SPECIES_VULPIX + 0x00, // SPECIES_NINETALES + 0x00, // SPECIES_JIGGLYPUFF + 0x00, // SPECIES_WIGGLYTUFF + 0x00, // SPECIES_ZUBAT + 0x00, // SPECIES_GOLBAT + 0x00, // SPECIES_ODDISH + 0x00, // SPECIES_GLOOM + 0x00, // SPECIES_VILEPLUME + 0x0a, // SPECIES_PARAS + 0x2d, // SPECIES_PARASECT + 0x14, // SPECIES_VENONAT + 0x00, // SPECIES_VENOMOTH + 0x19, // SPECIES_DIGLETT + 0x23, // SPECIES_DUGTRIO + 0x28, // SPECIES_MEOWTH + 0x14, // SPECIES_PERSIAN + 0x00, // SPECIES_PSYDUCK + 0x00, // SPECIES_GOLDUCK + 0x14, // SPECIES_MANKEY + 0x00, // SPECIES_PRIMEAPE + 0x1e, // SPECIES_GROWLITHE + 0x28, // SPECIES_ARCANINE + 0x00, // SPECIES_POLIWAG + 0x05, // SPECIES_POLIWHIRL + 0x00, // SPECIES_POLIWRATH + 0x00, // SPECIES_ABRA + 0x00, // SPECIES_KADABRA + 0x00, // SPECIES_ALAKAZAM + 0x00, // SPECIES_MACHOP + 0x00, // SPECIES_MACHOKE + 0x00, // SPECIES_MACHAMP + 0x00, // SPECIES_BELLSPROUT + 0x03, // SPECIES_WEEPINBELL + 0x00, // SPECIES_VICTREEBEL + 0x00, // SPECIES_TENTACOOL + 0x00, // SPECIES_TENTACRUEL + 0x00, // SPECIES_GEODUDE + 0x00, // SPECIES_GRAVELER + 0x00, // SPECIES_GOLEM + 0x00, // SPECIES_PONYTA + 0x00, // SPECIES_RAPIDASH + 0x00, // SPECIES_SLOWPOKE + 0x00, // SPECIES_SLOWBRO + 0x00, // SPECIES_MAGNEMITE + 0x00, // SPECIES_MAGNETON + 0x00, // SPECIES_FARFETCHD + 0x00, // SPECIES_DODUO + 0x00, // SPECIES_DODRIO + 0x00, // SPECIES_SEEL + 0x00, // SPECIES_DEWGONG + 0x00, // SPECIES_GRIMER + 0x2d, // SPECIES_MUK + 0x14, // SPECIES_SHELLDER + 0x00, // SPECIES_CLOYSTER + 0x00, // SPECIES_GASTLY + 0x17, // SPECIES_HAUNTER + 0x00, // SPECIES_GENGAR + 0x00, // SPECIES_ONIX + 0x30, // SPECIES_DROWZEE + 0x28, // SPECIES_HYPNO + 0x00, // SPECIES_KRABBY + 0x00, // SPECIES_KINGLER + 0x00, // SPECIES_VOLTORB + 0x00, // SPECIES_ELECTRODE + 0x00, // SPECIES_EXEGGCUTE + 0x00, // SPECIES_EXEGGUTOR + 0x00, // SPECIES_CUBONE + 0x00, // SPECIES_MAROWAK + 0x00, // SPECIES_HITMONLEE + 0x19, // SPECIES_HITMONCHAN + 0x00, // SPECIES_LICKITUNG + 0x00, // SPECIES_KOFFING + 0x00, // SPECIES_WEEZING + 0x00, // SPECIES_RHYHORN + 0x00, // SPECIES_RHYDON + 0x00, // SPECIES_CHANSEY + 0x00, // SPECIES_TANGELA + 0x00, // SPECIES_KANGASKHAN + 0x00, // SPECIES_HORSEA + 0x00, // SPECIES_SEADRA + 0x00, // SPECIES_GOLDEEN + 0x00, // SPECIES_SEAKING + 0x00, // SPECIES_STARYU + 0x00, // SPECIES_STARMIE + 0x00, // SPECIES_MR_MIME + 0x0a, // SPECIES_SCYTHER + 0x00, // SPECIES_JYNX + 0x00, // SPECIES_ELECTABUZZ + 0x00, // SPECIES_MAGMAR + 0x00, // SPECIES_PINSIR + 0x0a, // SPECIES_TAUROS + 0x00, // SPECIES_MAGIKARP + 0x00, // SPECIES_GYARADOS + 0x00, // SPECIES_LAPRAS + 0x00, // SPECIES_DITTO + 0x00, // SPECIES_EEVEE + 0x00, // SPECIES_VAPOREON + 0x00, // SPECIES_JOLTEON + 0x00, // SPECIES_FLAREON + 0x00, // SPECIES_PORYGON + 0x00, // SPECIES_OMANYTE + 0x00, // SPECIES_OMASTAR + 0x00, // SPECIES_KABUTO + 0x00, // SPECIES_KABUTOPS + 0x00, // SPECIES_AERODACTYL + 0x00, // SPECIES_SNORLAX + 0x00, // SPECIES_ARTICUNO + 0x00, // SPECIES_ZAPDOS + 0x00, // SPECIES_MOLTRES + 0x00, // SPECIES_DRATINI + 0x00, // SPECIES_DRAGONAIR + 0x00, // SPECIES_DRAGONITE + 0x00, // SPECIES_MEWTWO + 0x00, // SPECIES_MEW + 0x00, // SPECIES_CHIKORITA + 0x00, // SPECIES_BAYLEEF + 0x00, // SPECIES_MEGANIUM + 0x00, // SPECIES_CYNDAQUIL + 0x00, // SPECIES_QUILAVA + 0x14, // SPECIES_TYPHLOSION + 0x00, // SPECIES_TOTODILE + 0x00, // SPECIES_CROCONAW + 0x05, // SPECIES_FERALIGATR + 0x00, // SPECIES_SENTRET + 0x00, // SPECIES_FURRET + 0x00, // SPECIES_HOOTHOOT + 0x00, // SPECIES_NOCTOWL + 0x00, // SPECIES_LEDYBA + 0x00, // SPECIES_LEDIAN + 0x00, // SPECIES_SPINARAK + 0x00, // SPECIES_ARIADOS + 0x00, // SPECIES_CROBAT + 0x00, // SPECIES_CHINCHOU + 0x00, // SPECIES_LANTURN + 0x00, // SPECIES_PICHU + 0x00, // SPECIES_CLEFFA + 0x00, // SPECIES_IGGLYBUFF + 0x00, // SPECIES_TOGEPI + 0x00, // SPECIES_TOGETIC + 0x1e, // SPECIES_NATU + 0x00, // SPECIES_XATU + 0x32, // SPECIES_MAREEP + 0x00, // SPECIES_FLAAFFY + 0x0a, // SPECIES_AMPHAROS + 0x00, // SPECIES_BELLOSSOM + 0x00, // SPECIES_MARILL + 0x00, // SPECIES_AZUMARILL + 0x00, // SPECIES_SUDOWOODO + 0x28, // SPECIES_POLITOED + 0x00, // SPECIES_HOPPIP + 0x00, // SPECIES_SKIPLOOM + 0x00, // SPECIES_JUMPLUFF + 0x00, // SPECIES_AIPOM + 0x00, // SPECIES_SUNKERN + 0x00, // SPECIES_SUNFLORA + 0x00, // SPECIES_YANMA + 0x00, // SPECIES_WOOPER + 0x00, // SPECIES_QUAGSIRE + 0x00, // SPECIES_ESPEON + 0x00, // SPECIES_UMBREON + 0x00, // SPECIES_MURKROW + 0x00, // SPECIES_SLOWKING + 0x00, // SPECIES_MISDREAVUS + 0x00, // SPECIES_UNOWN + 0x00, // SPECIES_WOBBUFFET + 0x00, // SPECIES_GIRAFARIG + 0x00, // SPECIES_PINECO + 0x00, // SPECIES_FORRETRESS + 0x0a, // SPECIES_DUNSPARCE + 0x00, // SPECIES_GLIGAR + 0x2d, // SPECIES_STEELIX + 0x00, // SPECIES_SNUBBULL + 0x00, // SPECIES_GRANBULL + 0x27, // SPECIES_QWILFISH + 0x13, // SPECIES_SCIZOR + 0x00, // SPECIES_SHUCKLE + 0x00, // SPECIES_HERACROSS + 0x00, // SPECIES_SNEASEL + 0x00, // SPECIES_TEDDIURSA + 0x00, // SPECIES_URSARING + 0x00, // SPECIES_SLUGMA + 0x00, // SPECIES_MAGCARGO + 0x00, // SPECIES_SWINUB + 0x00, // SPECIES_PILOSWINE + 0x00, // SPECIES_CORSOLA + 0x00, // SPECIES_REMORAID + 0x14, // SPECIES_OCTILLERY + 0x00, // SPECIES_DELIBIRD + 0x00, // SPECIES_MANTINE + 0x00, // SPECIES_SKARMORY + 0x00, // SPECIES_HOUNDOUR + 0x00, // SPECIES_HOUNDOOM + 0x00, // SPECIES_KINGDRA + 0x00, // SPECIES_PHANPY + 0x00, // SPECIES_DONPHAN + 0x00, // SPECIES_PORYGON2 + 0x00, // SPECIES_STANTLER + 0x00, // SPECIES_SMEARGLE + 0x00, // SPECIES_TYROGUE + 0x00, // SPECIES_HITMONTOP + 0x28, // SPECIES_SMOOCHUM + 0x00, // SPECIES_ELEKID + 0x00, // SPECIES_MAGBY + 0x00, // SPECIES_MILTANK + 0x00, // SPECIES_BLISSEY + 0x00, // SPECIES_RAIKOU + 0x00, // SPECIES_ENTEI + 0x00, // SPECIES_SUICUNE + 0x00, // SPECIES_LARVITAR + 0x00, // SPECIES_PUPITAR + 0x0a, // SPECIES_TYRANITAR + 0x14, // SPECIES_LUGIA + 0x00, // SPECIES_HO_OH + 0x00, // SPECIES_CELEBI + 0x00, // 252 + 0x00, // 253 + 0x00, // 254 + 0x00, // 255 + 0x00, // 256 + 0x00, // 257 + 0x00, // 258 + 0x00, // 259 + 0x00, // 260 + 0x00, // 261 + 0x00, // 262 + 0x00, // 263 + 0x00, // 264 + 0x00, // 265 + 0x00, // 266 + 0x00, // 267 + 0x00, // 268 + 0x00, // 269 + 0x00, // 270 + 0x00, // 271 + 0x00, // 272 + 0x00, // 273 + 0x00, // 274 + 0x00, // 275 + 0x00, // 276 + 0x00, // SPECIES_TREECKO + 0x00, // SPECIES_GROVYLE + 0x00, // SPECIES_SCEPTILE + 0x00, // SPECIES_TORCHIC + 0x00, // SPECIES_COMBUSKEN + 0x00, // SPECIES_BLAZIKEN + 0x00, // SPECIES_MUDKIP + 0x00, // SPECIES_MARSHTOMP + 0x00, // SPECIES_SWAMPERT + 0x00, // SPECIES_POOCHYENA + 0x00, // SPECIES_MIGHTYENA + 0x00, // SPECIES_ZIGZAGOON + 0x00, // SPECIES_LINOONE + 0x00, // SPECIES_WURMPLE + 0x00, // SPECIES_SILCOON + 0x00, // SPECIES_BEAUTIFLY + 0x00, // SPECIES_CASCOON + 0x00, // SPECIES_DUSTOX + 0x00, // SPECIES_LOTAD + 0x00, // SPECIES_LOMBRE + 0x00, // SPECIES_LUDICOLO + 0x00, // SPECIES_SEEDOT + 0x00, // SPECIES_NUZLEAF + 0x00, // SPECIES_SHIFTRY + 0x00, // SPECIES_NINCADA + 0x00, // SPECIES_NINJASK + 0x00, // SPECIES_SHEDINJA + 0x00, // SPECIES_TAILLOW + 0x00, // SPECIES_SWELLOW + 0x00, // SPECIES_SHROOMISH + 0x00, // SPECIES_BRELOOM + 0x00, // SPECIES_SPINDA + 0x00, // SPECIES_WINGULL + 0x00, // SPECIES_PELIPPER + 0x00, // SPECIES_SURSKIT + 0x00, // SPECIES_MASQUERAIN + 0x00, // SPECIES_WAILMER + 0x0a, // SPECIES_WAILORD + 0x00, // SPECIES_SKITTY + 0x00, // SPECIES_DELCATTY + 0x1e, // SPECIES_KECLEON + 0x00, // SPECIES_BALTOY + 0x00, // SPECIES_CLAYDOL + 0x00, // SPECIES_NOSEPASS + 0x00, // SPECIES_TORKOAL + 0x00, // SPECIES_SABLEYE + 0x00, // SPECIES_BARBOACH + 0x00, // SPECIES_WHISCASH + 0x00, // SPECIES_LUVDISC + 0x00, // SPECIES_CORPHISH + 0x00, // SPECIES_CRAWDAUNT + 0x00, // SPECIES_FEEBAS + 0x2d, // SPECIES_MILOTIC + 0x00, // SPECIES_CARVANHA + 0x00, // SPECIES_SHARPEDO + 0x00, // SPECIES_TRAPINCH + 0x00, // SPECIES_VIBRAVA + 0x00, // SPECIES_FLYGON + 0x00, // SPECIES_MAKUHITA + 0x00, // SPECIES_HARIYAMA + 0x00, // SPECIES_ELECTRIKE + 0x00, // SPECIES_MANECTRIC + 0x00, // SPECIES_NUMEL + 0x00, // SPECIES_CAMERUPT + 0x0f, // SPECIES_SPHEAL + 0x00, // SPECIES_SEALEO + 0x00, // SPECIES_WALREIN + 0x00, // SPECIES_CACNEA + 0x00, // SPECIES_CACTURNE + 0x14, // SPECIES_SNORUNT + 0x00, // SPECIES_GLALIE + 0x00, // SPECIES_LUNATONE + 0x00, // SPECIES_SOLROCK + 0x00, // SPECIES_AZURILL + 0x00, // SPECIES_SPOINK + 0x0f, // SPECIES_GRUMPIG + 0x00, // SPECIES_PLUSLE + 0x00, // SPECIES_MINUN + 0x00, // SPECIES_MAWILE + 0x00, // SPECIES_MEDITITE + 0x00, // SPECIES_MEDICHAM + 0x00, // SPECIES_SWABLU + 0x00, // SPECIES_ALTARIA + 0x0f, // SPECIES_WYNAUT + 0x00, // SPECIES_DUSKULL + 0x1e, // SPECIES_DUSCLOPS + 0x00, // SPECIES_ROSELIA + 0x00, // SPECIES_SLAKOTH + 0x00, // SPECIES_VIGOROTH + 0x00, // SPECIES_SLAKING + 0x00, // SPECIES_GULPIN + 0x00, // SPECIES_SWALOT + 0x00, // SPECIES_TROPIUS + 0x00, // SPECIES_WHISMUR + 0x00, // SPECIES_LOUDRED + 0x00, // SPECIES_EXPLOUD + 0x00, // SPECIES_CLAMPERL + 0x00, // SPECIES_HUNTAIL + 0x00, // SPECIES_GOREBYSS + 0x2d, // SPECIES_ABSOL + 0x00, // SPECIES_SHUPPET + 0x00, // SPECIES_BANETTE + 0x00, // SPECIES_SEVIPER + 0x00, // SPECIES_ZANGOOSE + 0x00, // SPECIES_RELICANTH + 0x00, // SPECIES_ARON + 0x00, // SPECIES_LAIRON + 0x00, // SPECIES_AGGRON + 0x00, // SPECIES_CASTFORM + 0x00, // SPECIES_VOLBEAT + 0x00, // SPECIES_ILLUMISE + 0x00, // SPECIES_LILEEP + 0x00, // SPECIES_CRADILY + 0x00, // SPECIES_ANORITH + 0x00, // SPECIES_ARMALDO + 0x00, // SPECIES_RALTS + 0x00, // SPECIES_KIRLIA + 0x00, // SPECIES_GARDEVOIR + 0x00, // SPECIES_BAGON + 0x00, // SPECIES_SHELGON + 0x46, // SPECIES_SALAMENCE + 0x00, // SPECIES_BELDUM + 0x00, // SPECIES_METANG + 0x00, // SPECIES_METAGROSS + 0x00, // SPECIES_REGIROCK + 0x00, // SPECIES_REGICE + 0x00, // SPECIES_REGISTEEL + 0x3c, // SPECIES_KYOGRE + 0x00, // SPECIES_GROUDON + 0x3c, // SPECIES_RAYQUAZA + 0x00, // SPECIES_LATIAS + 0x00, // SPECIES_LATIOS + 0x00, // SPECIES_JIRACHI + 0x00, // SPECIES_DEOXYS + 0x00, // SPECIES_CHIMECHO +}; + +const u8 gUnknown_08329D22[] = {0x03, 0x0c, 0x30, 0xc0}; // Masks for getting PP Up count, also PP Max values +const u8 gUnknown_08329D26[] = {0xfc, 0xf3, 0xcf, 0x3f}; // Masks for setting PP Up count +const u8 gUnknown_08329D2A[] = {0x01, 0x04, 0x10, 0x40}; // Values added to PP Up count + +const u8 gStatStageRatios[][2] = +{ + {10, 40}, // -6 + {10, 35}, // -5 + {10, 30}, // -4 + {10, 25}, // -3 + {10, 20}, // -2 + {10, 15}, // -1 + {10, 10}, // 0 + {15, 10}, // +1 + {20, 10}, // +2 + {25, 10}, // +3 + {30, 10}, // +4 + {35, 10}, // +5 + {40, 10}, // +6 +}; + +static const u16 sDeoxysBaseStats[] = +{ + 50, // Hp + 95, // Attack + 90, // Defense + 180, // Speed + 95, // Sp.Attack + 90, // Sp.Defense +}; + +const u16 gUnknown_08329D54[] = +{ + FACILITY_CLASS_COOLTRAINER_M, FACILITY_CLASS_BLACK_BELT, FACILITY_CLASS_CAMPER, + FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_PSYCHIC_M, FACILITY_CLASS_BUG_CATCHER, + FACILITY_CLASS_PKMN_BREEDER_2, FACILITY_CLASS_GUITARIST, FACILITY_CLASS_COOLTRAINER_F, + FACILITY_CLASS_HEX_MANIAC, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_LASS, + FACILITY_CLASS_PSYCHIC_F, FACILITY_CLASS_BATTLE_GIRL, FACILITY_CLASS_PKMN_BREEDER_1, + FACILITY_CLASS_BEAUTY +}; + +static const u8 sHoldEffectToType[][2] = +{ + {HOLD_EFFECT_BUG_POWER, TYPE_BUG}, + {HOLD_EFFECT_STEEL_POWER, TYPE_STEEL}, + {HOLD_EFFECT_GROUND_POWER, TYPE_GROUND}, + {HOLD_EFFECT_ROCK_POWER, TYPE_ROCK}, + {HOLD_EFFECT_GRASS_POWER, TYPE_GRASS}, + {HOLD_EFFECT_DARK_POWER, TYPE_DARK}, + {HOLD_EFFECT_FIGHTING_POWER, TYPE_FIGHTING}, + {HOLD_EFFECT_ELECTRIC_POWER, TYPE_ELECTRIC}, + {HOLD_EFFECT_WATER_POWER, TYPE_WATER}, + {HOLD_EFFECT_FLYING_POWER, TYPE_FLYING}, + {HOLD_EFFECT_POISON_POWER, TYPE_POISON}, + {HOLD_EFFECT_ICE_POWER, TYPE_ICE}, + {HOLD_EFFECT_GHOST_POWER, TYPE_GHOST}, + {HOLD_EFFECT_PSYCHIC_POWER, TYPE_PSYCHIC}, + {HOLD_EFFECT_FIRE_POWER, TYPE_FIRE}, + {HOLD_EFFECT_DRAGON_POWER, TYPE_DRAGON}, + {HOLD_EFFECT_NORMAL_POWER, TYPE_NORMAL}, +}; + +const struct SpriteTemplate gUnknown_08329D98[MAX_BATTLERS_COUNT] = +{ + { // B_POSITION_PLAYER_LEFT + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF3A8, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { // B_POSITION_OPPONENT_LEFT + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACA8, + .anims = NULL, + .images = gUnknown_082FF3C8, + .affineAnims = gUnknown_082FF694, + .callback = oac_poke_opponent, + }, + { // B_POSITION_PLAYER_RIGHT + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF3E8, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { // B_POSITION_OPPONENT_RIGHT + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACA8, + .anims = NULL, + .images = gUnknown_082FF408, + .affineAnims = gUnknown_082FF694, + .callback = oac_poke_opponent + }, +}; + +static const struct SpriteTemplate gUnknown_08329DF8[] = +{ + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF428, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF448, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF468, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF490, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF4B8, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF4D8, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF4F8, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, + { + .tileTag = 0xFFFF, + .paletteTag = 0, + .oam = &gUnknown_0831ACB0, + .anims = NULL, + .images = gUnknown_082FF518, + .affineAnims = gUnknown_082FF618, + .callback = sub_8039BB4, + }, +}; + +static const u8 sSecretBaseFacilityClasses[2][5] = +{ + {FACILITY_CLASS_YOUNGSTER, FACILITY_CLASS_BUG_CATCHER, FACILITY_CLASS_RICH_BOY, FACILITY_CLASS_CAMPER, FACILITY_CLASS_COOLTRAINER_M}, + {FACILITY_CLASS_LASS, FACILITY_CLASS_SCHOOL_KID_F, FACILITY_CLASS_LADY, FACILITY_CLASS_PICNICKER, FACILITY_CLASS_COOLTRAINER_F} +}; + +static const u8 sGetMonDataEVConstants[] = +{ + MON_DATA_HP_EV, + MON_DATA_ATK_EV, + MON_DATA_DEF_EV, + MON_DATA_SPEED_EV, + MON_DATA_SPDEF_EV, + MON_DATA_SPATK_EV +}; + +static const u8 gUnknown_08329EC8[] = +{ + STAT_ATK, STAT_ATK, STAT_SPEED, STAT_DEF, STAT_SPATK, STAT_ACC +}; + +static const s8 gUnknown_08329ECE[][3] = +{ + { 5, 3, 2}, + { 5, 3, 2}, + { 1, 1, 0}, + { 3, 2, 1}, + { 1, 1, 0}, + { 1, 1, 1}, + {-1, -1, -1}, + {-5, -5, -10}, + {-5, -5, -10}, +}; + +static const u16 sHMMoves[] = +{ + MOVE_CUT, MOVE_FLY, MOVE_SURF, MOVE_STRENGTH, MOVE_FLASH, + MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, 0xFFFF +}; + +static const struct SpeciesItem sAlteringCaveWildMonHeldItems[] = +{ + {SPECIES_NONE, ITEM_NONE}, + {SPECIES_MAREEP, ITEM_GANLON_BERRY}, + {SPECIES_PINECO, ITEM_APICOT_BERRY}, + {SPECIES_HOUNDOUR, ITEM_BIG_MUSHROOM}, + {SPECIES_TEDDIURSA, ITEM_PETAYA_BERRY}, + {SPECIES_AIPOM, ITEM_BERRY_JUICE}, + {SPECIES_SHUCKLE, ITEM_BERRY_JUICE}, + {SPECIES_STANTLER, ITEM_PETAYA_BERRY}, + {SPECIES_SMEARGLE, ITEM_SALAC_BERRY}, +}; + +static const struct OamData sOamData_8329F20 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0 +}; + +static const struct SpriteTemplate gUnknown_08329F28 = +{ + .tileTag = 0xFFFF, + .paletteTag = 0xFFFF, + .oam = &sOamData_8329F20, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +// code +void ZeroBoxMonData(struct BoxPokemon *boxMon) +{ + u8 *raw = (u8 *)boxMon; + u32 i; + for (i = 0; i < sizeof(struct BoxPokemon); i++) + raw[i] = 0; +} + +void ZeroMonData(struct Pokemon *mon) +{ + u32 arg; + ZeroBoxMonData(&mon->box); + arg = 0; + SetMonData(mon, MON_DATA_STATUS, &arg); + SetMonData(mon, MON_DATA_LEVEL, &arg); + SetMonData(mon, MON_DATA_HP, &arg); + SetMonData(mon, MON_DATA_MAX_HP, &arg); + SetMonData(mon, MON_DATA_ATK, &arg); + SetMonData(mon, MON_DATA_DEF, &arg); + SetMonData(mon, MON_DATA_SPEED, &arg); + SetMonData(mon, MON_DATA_SPATK, &arg); + SetMonData(mon, MON_DATA_SPDEF, &arg); + arg = 255; + SetMonData(mon, MON_DATA_MAIL, &arg); +} + +void ZeroPlayerPartyMons(void) +{ + s32 i; + for (i = 0; i < PARTY_SIZE; i++) + ZeroMonData(&gPlayerParty[i]); +} + +void ZeroEnemyPartyMons(void) +{ + s32 i; + for (i = 0; i < PARTY_SIZE; i++) + ZeroMonData(&gEnemyParty[i]); +} + +void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +{ + u32 arg; + ZeroMonData(mon); + CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId); + SetMonData(mon, MON_DATA_LEVEL, &level); + arg = 255; + SetMonData(mon, MON_DATA_MAIL, &arg); + CalculateMonStats(mon); +} + +void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +{ + u8 speciesName[POKEMON_NAME_LENGTH + 1]; + u32 personality; + u32 value; + u16 checksum; + + ZeroBoxMonData(boxMon); + + if (hasFixedPersonality) + personality = fixedPersonality; + else + personality = Random32(); + + SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality); + + //Determine original trainer ID + if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny + { + u32 shinyValue; + do + { + value = Random32(); + shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality); + } while (shinyValue < 8); + } + else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID + { + value = fixedOtId; + } + else //Player is the OT + { + value = gSaveBlock2Ptr->playerTrainerId[0] + | (gSaveBlock2Ptr->playerTrainerId[1] << 8) + | (gSaveBlock2Ptr->playerTrainerId[2] << 16) + | (gSaveBlock2Ptr->playerTrainerId[3] << 24); + } + + SetBoxMonData(boxMon, MON_DATA_OT_ID, &value); + + checksum = CalculateBoxMonChecksum(boxMon); + SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum); + EncryptBoxMon(boxMon); + GetSpeciesName(speciesName, species); + SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName); + SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage); + SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); + SetBoxMonData(boxMon, MON_DATA_SPECIES, &species); + SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]); + SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship); + value = sav1_map_get_name(); + SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value); + SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level); + SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion); + value = ITEM_POKE_BALL; + SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value); + SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); + + if (fixedIV < 32) + { + SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV); + SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV); + SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV); + SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &fixedIV); + SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV); + SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV); + } + else + { + u32 iv; + value = Random(); + + iv = value & 0x1F; + SetBoxMonData(boxMon, MON_DATA_HP_IV, &iv); + iv = (value & 0x3E0) >> 5; + SetBoxMonData(boxMon, MON_DATA_ATK_IV, &iv); + iv = (value & 0x7C00) >> 10; + SetBoxMonData(boxMon, MON_DATA_DEF_IV, &iv); + + value = Random(); + + iv = value & 0x1F; + SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &iv); + iv = (value & 0x3E0) >> 5; + SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv); + iv = (value & 0x7C00) >> 10; + SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv); + } + + if (gBaseStats[species].ability2) + { + value = personality & 1; + SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value); + } + + GiveBoxMonInitialMoveset(boxMon); +} + +void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature) +{ + u32 personality; + + do + { + personality = Random32(); + } + while (nature != GetNatureFromPersonality(personality)); + + CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); +} + +void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter) +{ + u32 personality; + + if ((u8)(unownLetter - 1) < 28) + { + u16 actualLetter; + + do + { + personality = Random32(); + actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28); + } + while (nature != GetNatureFromPersonality(personality) + || gender != GetGenderFromSpeciesAndPersonality(species, personality) + || actualLetter != unownLetter - 1); + } + else + { + do + { + personality = Random32(); + } + while (nature != GetNatureFromPersonality(personality) + || gender != GetGenderFromSpeciesAndPersonality(species, personality)); + } + + CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); +} + +// This is only used to create Wally's Ralts. +void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level) +{ + u32 personality; + u32 otId; + + do + { + otId = Random32(); + personality = Random32(); + } + while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE); + CreateMon(mon, species, level, 32, 1, personality, OT_ID_PRESET, otId); +} + +void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality) +{ + CreateMon(mon, species, level, 0, 1, personality, OT_ID_PLAYER_ID, 0); + SetMonData(mon, MON_DATA_IVS, &ivs); + CalculateMonStats(mon); +} + +void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId) +{ + CreateMon(mon, species, level, 0, 0, 0, OT_ID_PRESET, otId); + SetMonData(mon, MON_DATA_HP_IV, &ivs[0]); + SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]); + SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]); + SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]); + SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]); + SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]); + CalculateMonStats(mon); +} + +void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread) +{ + s32 i; + s32 statCount = 0; + u16 evAmount; + u8 evsBits; + + CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0); + + evsBits = evSpread; + + for (i = 0; i < NUM_STATS; i++) + { + if (evsBits & 1) + statCount++; + evsBits >>= 1; + } + + evAmount = MAX_TOTAL_EVS / statCount; + + evsBits = 1; + + for (i = 0; i < NUM_STATS; i++) + { + if (evSpread & evsBits) + SetMonData(mon, MON_DATA_HP_EV + i, &evAmount); + evsBits <<= 1; + } + + CalculateMonStats(mon); +} + +void sub_806819C(struct Pokemon *mon, struct UnknownPokemonStruct *src) +{ + s32 i; + u8 nickname[30]; + u8 language; + u8 value; + + CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId); + + for (i = 0; i < 4; i++) + SetMonMoveSlot(mon, src->moves[i], i); + + SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses); + SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem); + SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship); + + StringCopy(nickname, src->nickname); + + if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN) + { + language = LANGUAGE_JAPANESE; + StripExtCtrlCodes(nickname); + } + else + { + language = GAME_LANGUAGE; + } + + SetMonData(mon, MON_DATA_LANGUAGE, &language); + SetMonData(mon, MON_DATA_NICKNAME, nickname); + SetMonData(mon, MON_DATA_HP_EV, &src->hpEV); + SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV); + SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV); + SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV); + SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV); + SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV); + value = src->altAbility; + SetMonData(mon, MON_DATA_ALT_ABILITY, &value); + value = src->hpIV; + SetMonData(mon, MON_DATA_HP_IV, &value); + value = src->attackIV; + SetMonData(mon, MON_DATA_ATK_IV, &value); + value = src->defenseIV; + SetMonData(mon, MON_DATA_DEF_IV, &value); + value = src->speedIV; + SetMonData(mon, MON_DATA_SPEED_IV, &value); + value = src->spAttackIV; + SetMonData(mon, MON_DATA_SPATK_IV, &value); + value = src->spDefenseIV; + SetMonData(mon, MON_DATA_SPDEF_IV, &value); + MonRestorePP(mon); + CalculateMonStats(mon); +} + +void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lvl50) +{ + s32 i; + u8 nickname[30]; + u8 level; + u8 language; + u8 value; + + if (gSaveBlock2Ptr->frontierChosenLvl != 0) + level = BattleFrontierGetOpponentLvl(gSaveBlock2Ptr->frontierChosenLvl); + else if (lvl50) + level = 50; + else + level = src->level; + + CreateMon(mon, src->species, level, 0, 1, src->personality, 1, src->otId); + + for (i = 0; i < 4; i++) + SetMonMoveSlot(mon, src->moves[i], i); + + SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses); + SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem); + SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship); + + StringCopy(nickname, src->nickname); + + if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN) + { + language = LANGUAGE_JAPANESE; + StripExtCtrlCodes(nickname); + } + else + { + language = GAME_LANGUAGE; + } + + SetMonData(mon, MON_DATA_LANGUAGE, &language); + SetMonData(mon, MON_DATA_NICKNAME, nickname); + SetMonData(mon, MON_DATA_HP_EV, &src->hpEV); + SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV); + SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV); + SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV); + SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV); + SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV); + value = src->altAbility; + SetMonData(mon, MON_DATA_ALT_ABILITY, &value); + value = src->hpIV; + SetMonData(mon, MON_DATA_HP_IV, &value); + value = src->attackIV; + SetMonData(mon, MON_DATA_ATK_IV, &value); + value = src->defenseIV; + SetMonData(mon, MON_DATA_DEF_IV, &value); + value = src->speedIV; + SetMonData(mon, MON_DATA_SPEED_IV, &value); + value = src->spAttackIV; + SetMonData(mon, MON_DATA_SPATK_IV, &value); + value = src->spDefenseIV; + SetMonData(mon, MON_DATA_SPDEF_IV, &value); + MonRestorePP(mon); + CalculateMonStats(mon); +} + +void sub_8068528(struct Pokemon *mon, const struct UnknownPokemonStruct2 *src, u8 monId) +{ + s32 i; + u16 evAmount; + u8 language; + u32 otId = gUnknown_08610970[src->field_0_0].field_30; + u32 personality = ((gUnknown_08610970[src->field_0_0].field_30 >> 8) | ((gUnknown_08610970[src->field_0_0].field_30 & 0xFF) << 8)) + + src->mons[monId].species + src->field_2; + + CreateMon(mon, + src->mons[monId].species, + BattleFrontierGetOpponentLvl(src->field_0_1 - 1), + 0x1F, + TRUE, + personality, + TRUE, + otId); + + SetMonData(mon, MON_DATA_HELD_ITEM, &src->mons[monId].item); + for (i = 0; i < 4; i++) + SetMonMoveSlot(mon, src->mons[monId].moves[i], i); + + evAmount = MAX_TOTAL_EVS / NUM_STATS; + for (i = 0; i < NUM_STATS; i++) + SetMonData(mon, MON_DATA_HP_EV + i, &evAmount); + + language = src->language; + SetMonData(mon, MON_DATA_LANGUAGE, &language); + SetMonData(mon, MON_DATA_OT_NAME, sub_81A1650(src->field_0_0, language)); + CalculateMonStats(mon); +} + +void CreateMonWithEVSpreadPersonalityOTID(struct Pokemon *mon, u16 species, u8 level, u8 nature, u8 fixedIV, u8 evSpread, u32 otId) +{ + s32 i; + s32 statCount = 0; + u8 evsBits; + u16 evAmount; + + // i is reused as personality value + do + { + i = Random32(); + } while (nature != GetNatureFromPersonality(i)); + + CreateMon(mon, species, level, fixedIV, TRUE, i, TRUE, otId); + evsBits = evSpread; + for (i = 0; i < NUM_STATS; i++) + { + if (evsBits & 1) + statCount++; + evsBits >>= 1; + } + + evAmount = MAX_TOTAL_EVS / statCount; + evsBits = 1; + for (i = 0; i < NUM_STATS; i++) + { + if (evSpread & evsBits) + SetMonData(mon, MON_DATA_HP_EV + i, &evAmount); + evsBits <<= 1; + } + + CalculateMonStats(mon); +} + +void sub_80686FC(struct Pokemon *mon, struct UnknownPokemonStruct *dest) +{ + s32 i; + u16 heldItem; + + dest->species = GetMonData(mon, MON_DATA_SPECIES, NULL); + heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL); + + if (heldItem == ITEM_ENIGMA_BERRY) + heldItem = 0; + + dest->heldItem = heldItem; + + for (i = 0; i < 4; i++) + dest->moves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, NULL); + + dest->level = GetMonData(mon, MON_DATA_LEVEL, NULL); + dest->ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + dest->otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + dest->hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL); + dest->attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL); + dest->defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL); + dest->speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL); + dest->spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL); + dest->spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL); + dest->friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); + dest->hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL); + dest->attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL); + dest->defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL); + dest->speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL); + dest->spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL); + dest->spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL); + dest->altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL); + dest->personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); + GetMonData(mon, MON_DATA_NICKNAME, dest->nickname); +} + +void CreateObedientMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) +{ + bool32 obedient = TRUE; + + CreateMon(mon, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId); + SetMonData(mon, MON_DATA_OBEDIENCE, &obedient); +} + +bool8 sub_80688F8(u8 caseId, u8 battlerId) +{ + switch (caseId) + { + case 0: + default: + return FALSE; + case 1: + if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + return FALSE; + if (!gMain.inBattle) + return FALSE; + if (gLinkPlayers[GetMultiplayerId()].lp_field_18 == battlerId) + return FALSE; + break; + case 2: + break; + case 3: + if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + return FALSE; + if (!gMain.inBattle) + return FALSE; + if (battlerId == 1 || battlerId == 4 || battlerId == 5) + return TRUE; + return FALSE; + case 4: + break; + case 5: + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + if (!gMain.inBattle) + return FALSE; + if (gBattleTypeFlags & BATTLE_TYPE_MULTI) + { + if (gLinkPlayers[GetMultiplayerId()].lp_field_18 == battlerId) + return FALSE; + } + else + { + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + return FALSE; + } + } + else + { + if (!gMain.inBattle) + return FALSE; + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + return FALSE; + } + break; + } + + return TRUE; +} + +static s32 GetDeoxysStat(struct Pokemon *mon, s32 statId) +{ + s32 ivVal, evVal; + s32 statValue; + u8 nature, statId_; + + if (gBattleTypeFlags & BATTLE_TYPE_20) + return 0; + if (GetMonData(mon, MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS) + return 0; + + ivVal = GetMonData(mon, MON_DATA_HP_IV + statId, NULL); + evVal = GetMonData(mon, MON_DATA_HP_EV + statId, NULL); + statValue = (u16)(((sDeoxysBaseStats[statId] * 2 + ivVal + evVal / 4) * mon->level) / 100 + 5); + + nature = GetNature(mon); + statId_ = statId; // needed to match + statValue = ModifyStatByNature(nature, statValue, statId_); + + return statValue; +} + +void SetDeoxysStats(void) +{ + s32 i, value; + + for (i = 0; i < PARTY_SIZE; i++) + { + struct Pokemon *mon = &gPlayerParty[i]; + + if (GetMonData(mon, MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS) + continue; + + value = GetMonData(mon, MON_DATA_ATK, NULL); + SetMonData(mon, MON_DATA_ATK, &value); + + value = GetMonData(mon, MON_DATA_DEF, NULL); + SetMonData(mon, MON_DATA_DEF, &value); + + value = GetMonData(mon, MON_DATA_SPEED, NULL); + SetMonData(mon, MON_DATA_SPEED, &value); + + value = GetMonData(mon, MON_DATA_SPATK, NULL); + SetMonData(mon, MON_DATA_SPATK, &value); + + value = GetMonData(mon, MON_DATA_SPDEF, NULL); + SetMonData(mon, MON_DATA_SPDEF, &value); + } +} + +u16 sub_8068B48(void) +{ + u8 linkId; + u32 arrId; + + if (gBattleTypeFlags & BATTLE_TYPE_x2000000) + linkId = gUnknown_0203C7B4 ^ 1; + else + linkId = GetMultiplayerId() ^ 1; + + arrId = gLinkPlayers[linkId].trainerId & 7; + arrId |= gLinkPlayers[linkId].gender << 3; + return FacilityClassToPicIndex(gUnknown_08329D54[arrId]); +} + +u16 sub_8068BB0(void) +{ + u8 linkId; + u32 arrId; + + if (gBattleTypeFlags & BATTLE_TYPE_x2000000) + linkId = gUnknown_0203C7B4 ^ 1; + else + linkId = GetMultiplayerId() ^ 1; + + arrId = gLinkPlayers[linkId].trainerId & 7; + arrId |= gLinkPlayers[linkId].gender << 3; + return gFacilityClassToTrainerClass[gUnknown_08329D54[arrId]]; +} + +void CreateObedientEnemyMon(void) +{ + s32 species = gSpecialVar_0x8004; + s32 level = gSpecialVar_0x8005; + s32 itemId = gSpecialVar_0x8006; + + ZeroEnemyPartyMons(); + CreateObedientMon(&gEnemyParty[0], species, level, 32, 0, 0, 0, 0); + if (itemId) + { + u8 heldItem[2]; + heldItem[0] = itemId; + heldItem[1] = itemId >> 8; + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem); + } +} + +static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) +{ + u16 checksum = 0; + union PokemonSubstruct *substruct0 = GetSubstruct(boxMon, boxMon->personality, 0); + union PokemonSubstruct *substruct1 = GetSubstruct(boxMon, boxMon->personality, 1); + union PokemonSubstruct *substruct2 = GetSubstruct(boxMon, boxMon->personality, 2); + union PokemonSubstruct *substruct3 = GetSubstruct(boxMon, boxMon->personality, 3); + s32 i; + + for (i = 0; i < 6; i++) + checksum += substruct0->raw[i]; + + for (i = 0; i < 6; i++) + checksum += substruct1->raw[i]; + + for (i = 0; i < 6; i++) + checksum += substruct2->raw[i]; + + for (i = 0; i < 6; i++) + checksum += substruct3->raw[i]; + + return checksum; +} + +#define CALC_STAT(base, iv, ev, statIndex, field) \ +{ \ + u8 baseStat = gBaseStats[species].base; \ + s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \ + u8 nature = GetNature(mon); \ + n = ModifyStatByNature(nature, n, statIndex); \ + SetMonData(mon, field, &n); \ +} + +void CalculateMonStats(struct Pokemon *mon) +{ + s32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL); + s32 currentHP = GetMonData(mon, MON_DATA_HP, NULL); + s32 hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL); + s32 hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL); + s32 attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL); + s32 attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL); + s32 defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL); + s32 defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL); + s32 speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL); + s32 speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL); + s32 spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL); + s32 spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL); + s32 spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL); + s32 spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL); + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + s32 level = GetLevelFromMonExp(mon); + s32 newMaxHP; + + SetMonData(mon, MON_DATA_LEVEL, &level); + + if (species == SPECIES_SHEDINJA) + { + newMaxHP = 1; + } + else + { + s32 n = 2 * gBaseStats[species].baseHP + hpIV; + newMaxHP = (((n + hpEV / 4) * level) / 100) + level + 10; + } + + gBattleScripting.field_23 = newMaxHP - oldMaxHP; + if (gBattleScripting.field_23 == 0) + gBattleScripting.field_23 = 1; + + SetMonData(mon, MON_DATA_MAX_HP, &newMaxHP); + + CALC_STAT(baseAttack, attackIV, attackEV, 1, MON_DATA_ATK) + CALC_STAT(baseDefense, defenseIV, defenseEV, 2, MON_DATA_DEF) + CALC_STAT(baseSpeed, speedIV, speedEV, 3, MON_DATA_SPEED) + CALC_STAT(baseSpAttack, spAttackIV, spAttackEV, 4, MON_DATA_SPATK) + CALC_STAT(baseSpDefense, spDefenseIV, spDefenseEV, 5, MON_DATA_SPDEF) + + if (species == SPECIES_SHEDINJA) + { + if (currentHP != 0 || oldMaxHP == 0) + currentHP = 1; + else + return; + } + else + { + if (currentHP == 0 && oldMaxHP == 0) + currentHP = newMaxHP; + else if (currentHP != 0) + currentHP += newMaxHP - oldMaxHP; + else + return; + } + + SetMonData(mon, MON_DATA_HP, ¤tHP); +} + +void BoxMonToMon(const struct BoxPokemon *src, struct Pokemon *dest) +{ + u32 value = 0; + dest->box = *src; + SetMonData(dest, MON_DATA_STATUS, &value); + SetMonData(dest, MON_DATA_HP, &value); + SetMonData(dest, MON_DATA_MAX_HP, &value); + value = 255; + SetMonData(dest, MON_DATA_MAIL, &value); + CalculateMonStats(dest); +} + +u8 GetLevelFromMonExp(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + u32 exp = GetMonData(mon, MON_DATA_EXP, NULL); + s32 level = 1; + + while (level <= MAX_MON_LEVEL && gExperienceTables[gBaseStats[species].growthRate][level] <= exp) + level++; + + return level - 1; +} + +u8 GetLevelFromBoxMonExp(struct BoxPokemon *boxMon) +{ + u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + u32 exp = GetBoxMonData(boxMon, MON_DATA_EXP, NULL); + s32 level = 1; + + while (level <= MAX_MON_LEVEL && gExperienceTables[gBaseStats[species].growthRate][level] <= exp) + level++; + + return level - 1; +} + +u16 GiveMoveToMon(struct Pokemon *mon, u16 move) +{ + return GiveMoveToBoxMon(&mon->box, move); +} + +u16 GiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) +{ + s32 i; + for (i = 0; i < 4; i++) + { + u16 existingMove = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, NULL); + if (!existingMove) + { + SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &move); + SetBoxMonData(boxMon, MON_DATA_PP1 + i, &gBattleMoves[move].pp); + return move; + } + if (existingMove == move) + return -2; + } + return -1; +} + +u16 GiveMoveToBattleMon(struct BattlePokemon *mon, u16 move) +{ + s32 i; + + for (i = 0; i < 4; i++) + { + if (!mon->moves[i]) + { + mon->moves[i] = move; + mon->pp[i] = gBattleMoves[move].pp; + return move; + } + } + + return -1; +} + +void SetMonMoveSlot(struct Pokemon *mon, u16 move, u8 slot) +{ + SetMonData(mon, MON_DATA_MOVE1 + slot, &move); + SetMonData(mon, MON_DATA_PP1 + slot, &gBattleMoves[move].pp); +} + +void SetBattleMonMoveSlot(struct BattlePokemon *mon, u16 move, u8 slot) +{ + mon->moves[slot] = move; + mon->pp[slot] = gBattleMoves[move].pp; +} + +void GiveMonInitialMoveset(struct Pokemon *mon) +{ + GiveBoxMonInitialMoveset(&mon->box); +} + +void GiveBoxMonInitialMoveset(struct BoxPokemon *boxMon) +{ + u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + s32 level = GetLevelFromBoxMonExp(boxMon); + s32 i; + + for (i = 0; gLevelUpLearnsets[species][i] != (u16)-1; i++) + { + u16 moveLevel; + u16 move; + + moveLevel = (gLevelUpLearnsets[species][i] & 0xFE00); + + if (moveLevel > (level << 9)) + break; + + move = (gLevelUpLearnsets[species][i] & 0x1FF); + + if (GiveMoveToBoxMon(boxMon, move) == (u16)-1) + DeleteFirstMoveAndGiveMoveToBoxMon(boxMon, move); + } +} + +u16 MonTryLearningNewMove(struct Pokemon *mon, bool8 firstMove) +{ + u32 retVal = 0; + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + u8 level = GetMonData(mon, MON_DATA_LEVEL, NULL); + + // since you can learn more than one move per level + // the game needs to know whether you decided to + // learn it or keep the old set to avoid asking + // you to learn the same move over and over again + if (firstMove) + { + sLearningMoveTableID = 0; + + while ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) != (level << 9)) + { + sLearningMoveTableID++; + if (gLevelUpLearnsets[species][sLearningMoveTableID] == 0xFFFF) + return 0; + } + } + + if ((gLevelUpLearnsets[species][sLearningMoveTableID] & 0xFE00) == (level << 9)) + { + gMoveToLearn = (gLevelUpLearnsets[species][sLearningMoveTableID] & 0x1FF); + sLearningMoveTableID++; + retVal = GiveMoveToMon(mon, gMoveToLearn); + } + + return retVal; +} + +void DeleteFirstMoveAndGiveMoveToMon(struct Pokemon *mon, u16 move) +{ + s32 i; + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; + + for (i = 0; i < 3; i++) + { + moves[i] = GetMonData(mon, MON_DATA_MOVE2 + i, NULL); + pp[i] = GetMonData(mon, MON_DATA_PP2 + i, NULL); + } + + ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + ppBonuses >>= 2; + moves[3] = move; + pp[3] = gBattleMoves[move].pp; + + for (i = 0; i < 4; i++) + { + SetMonData(mon, MON_DATA_MOVE1 + i, &moves[i]); + SetMonData(mon, MON_DATA_PP1 + i, &pp[i]); + } + + SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); +} + +void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 move) +{ + s32 i; + u16 moves[4]; + u8 pp[4]; + u8 ppBonuses; + + for (i = 0; i < 3; i++) + { + moves[i] = GetBoxMonData(boxMon, MON_DATA_MOVE2 + i, NULL); + pp[i] = GetBoxMonData(boxMon, MON_DATA_PP2 + i, NULL); + } + + ppBonuses = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, NULL); + ppBonuses >>= 2; + moves[3] = move; + pp[3] = gBattleMoves[move].pp; + + for (i = 0; i < 4; i++) + { + SetBoxMonData(boxMon, MON_DATA_MOVE1 + i, &moves[i]); + SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp[i]); + } + + SetBoxMonData(boxMon, MON_DATA_PP_BONUSES, &ppBonuses); +} + +#define APPLY_STAT_MOD(var, mon, stat, statIndex) \ +{ \ + (var) = (stat) * (gStatStageRatios)[(mon)->statStages[(statIndex)]][0]; \ + (var) /= (gStatStageRatios)[(mon)->statStages[(statIndex)]][1]; \ +} + +s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 battlerIdAtk, u8 battlerIdDef) +{ + u32 i; + s32 damage = 0; + s32 damageHelper; + u8 type; + u16 attack, defense; + u16 spAttack, spDefense; + u8 defenderHoldEffect; + u8 defenderHoldEffectParam; + u8 attackerHoldEffect; + u8 attackerHoldEffectParam; + + if (!powerOverride) + gBattleMovePower = gBattleMoves[move].power; + else + gBattleMovePower = powerOverride; + + if (!typeOverride) + type = gBattleMoves[move].type; + else + type = typeOverride & 0x3F; + + attack = attacker->attack; + defense = defender->defense; + spAttack = attacker->spAttack; + spDefense = defender->spDefense; + + if (attacker->item == ITEM_ENIGMA_BERRY) + { + attackerHoldEffect = gEnigmaBerries[battlerIdAtk].holdEffect; + attackerHoldEffectParam = gEnigmaBerries[battlerIdAtk].holdEffectParam; + } + else + { + attackerHoldEffect = ItemId_GetHoldEffect(attacker->item); + attackerHoldEffectParam = ItemId_GetHoldEffectParam(attacker->item); + } + + if (defender->item == ITEM_ENIGMA_BERRY) + { + defenderHoldEffect = gEnigmaBerries[battlerIdDef].holdEffect; + defenderHoldEffectParam = gEnigmaBerries[battlerIdDef].holdEffectParam; + } + else + { + defenderHoldEffect = ItemId_GetHoldEffect(defender->item); + defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item); + } + + if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER) + attack *= 2; + + if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, battlerIdAtk)) + attack = (110 * attack) / 100; + if (ShouldGetStatBadgeBoost(FLAG_BADGE05_GET, battlerIdDef)) + defense = (110 * defense) / 100; + if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerIdAtk)) + spAttack = (110 * spAttack) / 100; + if (ShouldGetStatBadgeBoost(FLAG_BADGE07_GET, battlerIdDef)) + spDefense = (110 * spDefense) / 100; + + for (i = 0; i < ARRAY_COUNT(sHoldEffectToType); i++) + { + if (attackerHoldEffect == sHoldEffectToType[i][0] + && type == sHoldEffectToType[i][1]) + { + if (type <= 8) + attack = (attack * (attackerHoldEffectParam + 100)) / 100; + else + spAttack = (spAttack * (attackerHoldEffectParam + 100)) / 100; + break; + } + } + + if (attackerHoldEffect == HOLD_EFFECT_CHOICE_BAND) + attack = (150 * attack) / 100; + if (attackerHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (attacker->species == SPECIES_LATIAS || attacker->species == SPECIES_LATIOS)) + spAttack = (150 * spAttack) / 100; + if (defenderHoldEffect == HOLD_EFFECT_SOUL_DEW && !(gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) && (defender->species == SPECIES_LATIAS || defender->species == SPECIES_LATIOS)) + spDefense = (150 * spDefense) / 100; + if (attackerHoldEffect == HOLD_EFFECT_DEEP_SEA_TOOTH && attacker->species == SPECIES_CLAMPERL) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_DEEP_SEA_SCALE && defender->species == SPECIES_CLAMPERL) + spDefense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_LIGHT_BALL && attacker->species == SPECIES_PIKACHU) + spAttack *= 2; + if (defenderHoldEffect == HOLD_EFFECT_METAL_POWDER && defender->species == SPECIES_DITTO) + defense *= 2; + if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK)) + attack *= 2; + if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE)) + spAttack /= 2; + if (attacker->ability == ABILITY_HUSTLE) + attack = (150 * attack) / 100; + if (attacker->ability == ABILITY_PLUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MINUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_MINUS && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_PLUS, 0, 0)) + spAttack = (150 * spAttack) / 100; + if (attacker->ability == ABILITY_GUTS && attacker->status1) + attack = (150 * attack) / 100; + if (defender->ability == ABILITY_MARVEL_SCALE && defender->status1) + defense = (150 * defense) / 100; + if (type == TYPE_ELECTRIC && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFD, 0)) + gBattleMovePower /= 2; + if (type == TYPE_FIRE && AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, 0, 0xFE, 0)) + gBattleMovePower /= 2; + if (type == TYPE_GRASS && attacker->ability == ABILITY_OVERGROW && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_FIRE && attacker->ability == ABILITY_BLAZE && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_WATER && attacker->ability == ABILITY_TORRENT && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3)) + gBattleMovePower = (150 * gBattleMovePower) / 100; + if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION) + defense /= 2; + + if (type < TYPE_MYSTERY) // is physical + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_ATK] > 6) + APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK) + else + damage = attack; + } + else + APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_DEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF) + else + damageHelper = defense; + } + else + APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF) + + damage = damage / damageHelper; + damage /= 50; + + if ((attacker->status1 & STATUS1_BURN) && attacker->ability != ABILITY_GUTS) + damage /= 2; + + if ((sideStatus & SIDE_STATUS_REFLECT) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) + damage /= 2; + + // moves always do at least 1 damage. + if (damage == 0) + damage = 1; + } + + if (type == TYPE_MYSTERY) + damage = 0; // is ??? type. does 0 damage. + + if (type > TYPE_MYSTERY) // is special? + { + if (gCritMultiplier == 2) + { + if (attacker->statStages[STAT_SPATK] > 6) + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK) + else + damage = spAttack; + } + else + APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK) + + damage = damage * gBattleMovePower; + damage *= (2 * attacker->level / 5 + 2); + + if (gCritMultiplier == 2) + { + if (defender->statStages[STAT_SPDEF] < 6) + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF) + else + damageHelper = spDefense; + } + else + APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF) + + damage = (damage / damageHelper); + damage /= 50; + + if ((sideStatus & SIDE_STATUS_LIGHTSCREEN) && gCritMultiplier == 1) + { + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && CountAliveMonsInBattle(2) == 2) + damage = 2 * (damage / 3); + else + damage /= 2; + } + + if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && gBattleMoves[move].target == 8 && CountAliveMonsInBattle(2) == 2) + damage /= 2; + + // are effects of weather negated with cloud nine or air lock + if (!AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_CLOUD_NINE, 0, 0) + && !AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_AIR_LOCK, 0, 0)) + { + if (gBattleWeather & WEATHER_RAIN_TEMPORARY) + { + switch (type) + { + case TYPE_FIRE: + damage /= 2; + break; + case TYPE_WATER: + damage = (15 * damage) / 10; + break; + } + } + + // any weather except sun weakens solar beam + if ((gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SANDSTORM_ANY | WEATHER_HAIL)) && gCurrentMove == MOVE_SOLAR_BEAM) + damage /= 2; + + // sunny + if (gBattleWeather & WEATHER_SUN_ANY) + { + switch (type) + { + case TYPE_FIRE: + damage = (15 * damage) / 10; + break; + case TYPE_WATER: + damage /= 2; + break; + } + } + } + + // flash fire triggered + if ((gBattleResources->flags->flags[battlerIdAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE) + damage = (15 * damage) / 10; + } + + return damage + 2; +} + +u8 CountAliveMonsInBattle(u8 caseId) +{ + s32 i; + u8 retVal = 0; + + switch (caseId) + { + case BATTLE_ALIVE_EXCEPT_ACTIVE: + for (i = 0; i < 4; i++) + { + if (i != gActiveBattler && !(gAbsentBattlerFlags & gBitTable[i])) + retVal++; + } + break; + case BATTLE_ALIVE_ATK_SIDE: + for (i = 0; i < 4; i++) + { + if (GetBattlerSide(i) == GetBattlerSide(gBattlerAttacker) && !(gAbsentBattlerFlags & gBitTable[i])) + retVal++; + } + break; + case BATTLE_ALIVE_DEF_SIDE: + for (i = 0; i < 4; i++) + { + if (GetBattlerSide(i) == GetBattlerSide(gBattlerTarget) && !(gAbsentBattlerFlags & gBitTable[i])) + retVal++; + } + break; + } + + return retVal; +} + +static bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 battlerId) +{ + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER)) + return FALSE; + if (GetBattlerSide(battlerId) != B_SIDE_PLAYER) + return FALSE; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT) + return FALSE; + if (FlagGet(badgeFlag)) + return TRUE; + return FALSE; +} + +u8 GetDefaultMoveTarget(u8 battlerId) +{ + u8 opposing = BATTLE_OPPOSITE(GetBattlerPosition(battlerId) & BIT_SIDE); + + if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) + return GetBattlerAtPosition(opposing); + if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1) + { + u8 position; + + if ((Random() & 1) == 0) + position = BATTLE_PARTNER(opposing); + else + position = opposing; + + return GetBattlerAtPosition(position); + } + else + { + if ((gAbsentBattlerFlags & gBitTable[opposing])) + return GetBattlerAtPosition(BATTLE_PARTNER(opposing)); + else + return GetBattlerAtPosition(opposing); + } +} + +u8 GetMonGender(struct Pokemon *mon) +{ + return GetBoxMonGender(&mon->box); +} + +u8 GetBoxMonGender(struct BoxPokemon *boxMon) +{ + u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL); + + switch (gBaseStats[species].genderRatio) + { + case MON_MALE: + case MON_FEMALE: + case MON_GENDERLESS: + return gBaseStats[species].genderRatio; + } + + if (gBaseStats[species].genderRatio > (personality & 0xFF)) + return MON_FEMALE; + else + return MON_MALE; +} + +u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality) +{ + switch (gBaseStats[species].genderRatio) + { + case MON_MALE: + case MON_FEMALE: + case MON_GENDERLESS: + return gBaseStats[species].genderRatio; + } + + if (gBaseStats[species].genderRatio > (personality & 0xFF)) + return MON_FEMALE; + else + return MON_MALE; +} + +void sub_806A068(u16 species, u8 battlerPosition) +{ + if (gMonSpritesGfxPtr != NULL) + gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition]; + else if (gUnknown_020249B4[0]) + gUnknown_0202499C = gUnknown_020249B4[0]->templates[battlerPosition]; + else if (gUnknown_020249B4[1]) + gUnknown_0202499C = gUnknown_020249B4[1]->templates[battlerPosition]; + else + gUnknown_0202499C = gUnknown_08329D98[battlerPosition]; + + gUnknown_0202499C.paletteTag = species; + if (battlerPosition == 0 || battlerPosition == 2) + gUnknown_0202499C.anims = gUnknown_082FF70C; + else if (species > 500) + gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species - 500]; + else + gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species]; +} + +void sub_806A12C(u16 trainerSpriteId, u8 battlerPosition) +{ + gUnknown_0202499C.paletteTag = trainerSpriteId; + if (battlerPosition == B_POSITION_PLAYER_LEFT || battlerPosition == B_POSITION_PLAYER_RIGHT) + { + gUnknown_0202499C = gUnknown_08329DF8[trainerSpriteId]; + gUnknown_0202499C.anims = gUnknown_08305D0C[trainerSpriteId]; + } + else + { + if (gMonSpritesGfxPtr != NULL) + gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition]; + else + gUnknown_0202499C = gUnknown_08329D98[battlerPosition]; + gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId]; + } +} + +void sub_806A1C0(u16 arg0, u8 battlerPosition) +{ + if (gMonSpritesGfxPtr != NULL) + gUnknown_0202499C = gMonSpritesGfxPtr->templates[battlerPosition]; + else + gUnknown_0202499C = gUnknown_08329D98[battlerPosition]; + + gUnknown_0202499C.paletteTag = arg0; + gUnknown_0202499C.anims = gUnknown_0830536C[arg0]; +} + +static void EncryptBoxMon(struct BoxPokemon *boxMon) +{ + u32 i; + for (i = 0; i < 12; i++) + { + boxMon->secure.raw[i] ^= boxMon->personality; + boxMon->secure.raw[i] ^= boxMon->otId; + } +} + +static void DecryptBoxMon(struct BoxPokemon *boxMon) +{ + u32 i; + for (i = 0; i < 12; i++) + { + boxMon->secure.raw[i] ^= boxMon->otId; + boxMon->secure.raw[i] ^= boxMon->personality; + } +} + +#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \ +case n: \ + { \ + union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \ + union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \ + \ + switch (substructType) \ + { \ + case 0: \ + substruct = &substructs ## n [v1]; \ + break; \ + case 1: \ + substruct = &substructs ## n [v2]; \ + break; \ + case 2: \ + substruct = &substructs ## n [v3]; \ + break; \ + case 3: \ + substruct = &substructs ## n [v4]; \ + break; \ + } \ + break; \ + } \ + + +static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) +{ + union PokemonSubstruct *substruct = NULL; + + switch (personality % 24) + { + SUBSTRUCT_CASE( 0,0,1,2,3) + SUBSTRUCT_CASE( 1,0,1,3,2) + SUBSTRUCT_CASE( 2,0,2,1,3) + SUBSTRUCT_CASE( 3,0,3,1,2) + SUBSTRUCT_CASE( 4,0,2,3,1) + SUBSTRUCT_CASE( 5,0,3,2,1) + SUBSTRUCT_CASE( 6,1,0,2,3) + SUBSTRUCT_CASE( 7,1,0,3,2) + SUBSTRUCT_CASE( 8,2,0,1,3) + SUBSTRUCT_CASE( 9,3,0,1,2) + SUBSTRUCT_CASE(10,2,0,3,1) + SUBSTRUCT_CASE(11,3,0,2,1) + SUBSTRUCT_CASE(12,1,2,0,3) + SUBSTRUCT_CASE(13,1,3,0,2) + SUBSTRUCT_CASE(14,2,1,0,3) + SUBSTRUCT_CASE(15,3,1,0,2) + SUBSTRUCT_CASE(16,2,3,0,1) + SUBSTRUCT_CASE(17,3,2,0,1) + SUBSTRUCT_CASE(18,1,2,3,0) + SUBSTRUCT_CASE(19,1,3,2,0) + SUBSTRUCT_CASE(20,2,1,3,0) + SUBSTRUCT_CASE(21,3,1,2,0) + SUBSTRUCT_CASE(22,2,3,1,0) + SUBSTRUCT_CASE(23,3,2,1,0) + } + + return substruct; +} + +u32 GetMonData(struct Pokemon *mon, s32 field, u8* data) +{ + u32 ret; + + switch (field) + { + case MON_DATA_STATUS: + ret = mon->status; + break; + case MON_DATA_LEVEL: + ret = mon->level; + break; + case MON_DATA_HP: + ret = mon->hp; + break; + case MON_DATA_MAX_HP: + ret = mon->maxHP; + break; + case MON_DATA_ATK: + ret = (u16)GetDeoxysStat(mon, STAT_ATK); + if (!ret) + ret = mon->attack; + break; + case MON_DATA_DEF: + ret = (u16)GetDeoxysStat(mon, STAT_DEF); + if (!ret) + ret = mon->defense; + break; + case MON_DATA_SPEED: + ret = (u16)GetDeoxysStat(mon, STAT_SPEED); + if (!ret) + ret = mon->speed; + break; + case MON_DATA_SPATK: + ret = (u16)GetDeoxysStat(mon, STAT_SPATK); + if (!ret) + ret = mon->spAttack; + break; + case MON_DATA_SPDEF: + ret = (u16)GetDeoxysStat(mon, STAT_SPDEF); + if (!ret) + ret = mon->spDefense; + break; + case MON_DATA_ATK2: + ret = mon->attack; + break; + case MON_DATA_DEF2: + ret = mon->defense; + break; + case MON_DATA_SPEED2: + ret = mon->speed; + break; + case MON_DATA_SPATK2: + ret = mon->spAttack; + break; + case MON_DATA_SPDEF2: + ret = mon->spDefense; + break; + case MON_DATA_MAIL: + ret = mon->mail; + break; + default: + ret = GetBoxMonData(&mon->box, field, data); + break; + } + return ret; +} + +u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) +{ + s32 i; + u32 retVal = 0; + struct PokemonSubstruct0 *substruct0 = NULL; + struct PokemonSubstruct1 *substruct1 = NULL; + struct PokemonSubstruct2 *substruct2 = NULL; + struct PokemonSubstruct3 *substruct3 = NULL; + + if (field > MON_DATA_10) + { + substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); + substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); + substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); + substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); + + DecryptBoxMon(boxMon); + + if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + { + boxMon->isBadEgg = 1; + boxMon->isEgg = 1; + substruct3->isEgg = 1; + } + } + + switch (field) + { + case MON_DATA_PERSONALITY: + retVal = boxMon->personality; + break; + case MON_DATA_OT_ID: + retVal = boxMon->otId; + break; + case MON_DATA_NICKNAME: + { + if (boxMon->isBadEgg) + { + for (retVal = 0; + retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; + data[retVal] = gText_BadEgg[retVal], retVal++) {} + + data[retVal] = EOS; + } + else if (boxMon->isEgg) + { + StringCopy(data, gText_EggNickname); + retVal = StringLength(data); + } + else if (boxMon->language == LANGUAGE_JAPANESE) + { + data[0] = EXT_CTRL_CODE_BEGIN; + data[1] = EXT_CTRL_CODE_JPN; + + for (retVal = 2, i = 0; + i < 5 && boxMon->nickname[i] != EOS; + data[retVal] = boxMon->nickname[i], retVal++, i++) {} + + data[retVal++] = EXT_CTRL_CODE_BEGIN; + data[retVal++] = EXT_CTRL_CODE_ENG; + data[retVal] = EOS; + } + else + { + for (retVal = 0; + retVal < POKEMON_NAME_LENGTH; + data[retVal] = boxMon->nickname[retVal], retVal++){} + + data[retVal] = EOS; + } + break; + } + case MON_DATA_LANGUAGE: + retVal = boxMon->language; + break; + case MON_DATA_SANITY_BIT1: + retVal = boxMon->isBadEgg; + break; + case MON_DATA_SANITY_BIT2: + retVal = boxMon->hasSpecies; + break; + case MON_DATA_SANITY_BIT3: + retVal = boxMon->isEgg; + break; + case MON_DATA_OT_NAME: + { + retVal = 0; + + while (retVal < OT_NAME_LENGTH) + { + data[retVal] = boxMon->otName[retVal]; + retVal++; + } + + data[retVal] = EOS; + break; + } + case MON_DATA_MARKINGS: + retVal = boxMon->markings; + break; + case MON_DATA_CHECKSUM: + retVal = boxMon->checksum; + break; + case MON_DATA_10: + retVal = boxMon->unknown; + break; + case MON_DATA_SPECIES: + retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species; + break; + case MON_DATA_HELD_ITEM: + retVal = substruct0->heldItem; + break; + case MON_DATA_EXP: + retVal = substruct0->experience; + break; + case MON_DATA_PP_BONUSES: + retVal = substruct0->ppBonuses; + break; + case MON_DATA_FRIENDSHIP: + retVal = substruct0->friendship; + break; + case MON_DATA_MOVE1: + case MON_DATA_MOVE2: + case MON_DATA_MOVE3: + case MON_DATA_MOVE4: + retVal = substruct1->moves[field - MON_DATA_MOVE1]; + break; + case MON_DATA_PP1: + case MON_DATA_PP2: + case MON_DATA_PP3: + case MON_DATA_PP4: + retVal = substruct1->pp[field - MON_DATA_PP1]; + break; + case MON_DATA_HP_EV: + retVal = substruct2->hpEV; + break; + case MON_DATA_ATK_EV: + retVal = substruct2->attackEV; + break; + case MON_DATA_DEF_EV: + retVal = substruct2->defenseEV; + break; + case MON_DATA_SPEED_EV: + retVal = substruct2->speedEV; + break; + case MON_DATA_SPATK_EV: + retVal = substruct2->spAttackEV; + break; + case MON_DATA_SPDEF_EV: + retVal = substruct2->spDefenseEV; + break; + case MON_DATA_COOL: + retVal = substruct2->cool; + break; + case MON_DATA_BEAUTY: + retVal = substruct2->beauty; + break; + case MON_DATA_CUTE: + retVal = substruct2->cute; + break; + case MON_DATA_SMART: + retVal = substruct2->smart; + break; + case MON_DATA_TOUGH: + retVal = substruct2->tough; + break; + case MON_DATA_SHEEN: + retVal = substruct2->sheen; + break; + case MON_DATA_POKERUS: + retVal = substruct3->pokerus; + break; + case MON_DATA_MET_LOCATION: + retVal = substruct3->metLocation; + break; + case MON_DATA_MET_LEVEL: + retVal = substruct3->metLevel; + break; + case MON_DATA_MET_GAME: + retVal = substruct3->metGame; + break; + case MON_DATA_POKEBALL: + retVal = substruct3->pokeball; + break; + case MON_DATA_OT_GENDER: + retVal = substruct3->otGender; + break; + case MON_DATA_HP_IV: + retVal = substruct3->hpIV; + break; + case MON_DATA_ATK_IV: + retVal = substruct3->attackIV; + break; + case MON_DATA_DEF_IV: + retVal = substruct3->defenseIV; + break; + case MON_DATA_SPEED_IV: + retVal = substruct3->speedIV; + break; + case MON_DATA_SPATK_IV: + retVal = substruct3->spAttackIV; + break; + case MON_DATA_SPDEF_IV: + retVal = substruct3->spDefenseIV; + break; + case MON_DATA_IS_EGG: + retVal = substruct3->isEgg; + break; + case MON_DATA_ALT_ABILITY: + retVal = substruct3->altAbility; + break; + case MON_DATA_COOL_RIBBON: + retVal = substruct3->coolRibbon; + break; + case MON_DATA_BEAUTY_RIBBON: + retVal = substruct3->beautyRibbon; + break; + case MON_DATA_CUTE_RIBBON: + retVal = substruct3->cuteRibbon; + break; + case MON_DATA_SMART_RIBBON: + retVal = substruct3->smartRibbon; + break; + case MON_DATA_TOUGH_RIBBON: + retVal = substruct3->toughRibbon; + break; + case MON_DATA_CHAMPION_RIBBON: + retVal = substruct3->championRibbon; + break; + case MON_DATA_WINNING_RIBBON: + retVal = substruct3->winningRibbon; + break; + case MON_DATA_VICTORY_RIBBON: + retVal = substruct3->victoryRibbon; + break; + case MON_DATA_ARTIST_RIBBON: + retVal = substruct3->artistRibbon; + break; + case MON_DATA_EFFORT_RIBBON: + retVal = substruct3->effortRibbon; + break; + case MON_DATA_GIFT_RIBBON_1: + retVal = substruct3->giftRibbon1; + break; + case MON_DATA_GIFT_RIBBON_2: + retVal = substruct3->giftRibbon2; + break; + case MON_DATA_GIFT_RIBBON_3: + retVal = substruct3->giftRibbon3; + break; + case MON_DATA_GIFT_RIBBON_4: + retVal = substruct3->giftRibbon4; + break; + case MON_DATA_GIFT_RIBBON_5: + retVal = substruct3->giftRibbon5; + break; + case MON_DATA_GIFT_RIBBON_6: + retVal = substruct3->giftRibbon6; + break; + case MON_DATA_GIFT_RIBBON_7: + retVal = substruct3->giftRibbon7; + break; + case MON_DATA_FATEFUL_ENCOUNTER: + retVal = substruct3->fatefulEncounter; + break; + case MON_DATA_OBEDIENCE: + retVal = substruct3->obedient; + break; + case MON_DATA_SPECIES2: + retVal = substruct0->species; + if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg)) + retVal = SPECIES_EGG; + break; + case MON_DATA_IVS: + retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); + break; + case MON_DATA_KNOWN_MOVES: + if (substruct0->species && !substruct3->isEgg) + { + u16 *moves = (u16 *)data; + s32 i = 0; + + while (moves[i] != 355) + { + u16 move = moves[i]; + if (substruct1->moves[0] == move + || substruct1->moves[1] == move + || substruct1->moves[2] == move + || substruct1->moves[3] == move) + retVal |= gBitTable[i]; + i++; + } + } + break; + case MON_DATA_RIBBON_COUNT: + retVal = 0; + if (substruct0->species && !substruct3->isEgg) + { + retVal += substruct3->coolRibbon; + retVal += substruct3->beautyRibbon; + retVal += substruct3->cuteRibbon; + retVal += substruct3->smartRibbon; + retVal += substruct3->toughRibbon; + retVal += substruct3->championRibbon; + retVal += substruct3->winningRibbon; + retVal += substruct3->victoryRibbon; + retVal += substruct3->artistRibbon; + retVal += substruct3->effortRibbon; + retVal += substruct3->giftRibbon1; + retVal += substruct3->giftRibbon2; + retVal += substruct3->giftRibbon3; + retVal += substruct3->giftRibbon4; + retVal += substruct3->giftRibbon5; + retVal += substruct3->giftRibbon6; + retVal += substruct3->giftRibbon7; + } + break; + case MON_DATA_RIBBONS: + retVal = 0; + if (substruct0->species && !substruct3->isEgg) + { + retVal = substruct3->championRibbon + | (substruct3->coolRibbon << 1) + | (substruct3->beautyRibbon << 4) + | (substruct3->cuteRibbon << 7) + | (substruct3->smartRibbon << 10) + | (substruct3->toughRibbon << 13) + | (substruct3->winningRibbon << 16) + | (substruct3->victoryRibbon << 17) + | (substruct3->artistRibbon << 18) + | (substruct3->effortRibbon << 19) + | (substruct3->giftRibbon1 << 20) + | (substruct3->giftRibbon2 << 21) + | (substruct3->giftRibbon3 << 22) + | (substruct3->giftRibbon4 << 23) + | (substruct3->giftRibbon5 << 24) + | (substruct3->giftRibbon6 << 25) + | (substruct3->giftRibbon7 << 26); + } + break; + default: + break; + } + + if (field > MON_DATA_10) + EncryptBoxMon(boxMon); + + return retVal; +} + +#define SET8(lhs) (lhs) = *data +#define SET16(lhs) (lhs) = data[0] + (data[1] << 8) +#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) + +void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg) +{ + const u8* data = dataArg; + switch (field) + { + case MON_DATA_STATUS: + SET32(mon->status); + break; + case MON_DATA_LEVEL: + SET8(mon->level); + break; + case MON_DATA_HP: + SET16(mon->hp); + break; + case MON_DATA_MAX_HP: + SET16(mon->maxHP); + break; + case MON_DATA_ATK: + SET16(mon->attack); + break; + case MON_DATA_DEF: + SET16(mon->defense); + break; + case MON_DATA_SPEED: + SET16(mon->speed); + break; + case MON_DATA_SPATK: + SET16(mon->spAttack); + break; + case MON_DATA_SPDEF: + SET16(mon->spDefense); + break; + case MON_DATA_MAIL: + SET8(mon->mail); + break; + case MON_DATA_SPECIES2: + break; + default: + SetBoxMonData(&mon->box, field, data); + break; + } +} + +void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) +{ + const u8* data = dataArg; + + struct PokemonSubstruct0 *substruct0 = NULL; + struct PokemonSubstruct1 *substruct1 = NULL; + struct PokemonSubstruct2 *substruct2 = NULL; + struct PokemonSubstruct3 *substruct3 = NULL; + + if (field > MON_DATA_10) + { + substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); + substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); + substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); + substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); + + DecryptBoxMon(boxMon); + + if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) + { + boxMon->isBadEgg = 1; + boxMon->isEgg = 1; + substruct3->isEgg = 1; + EncryptBoxMon(boxMon); + return; + } + } + + switch (field) + { + case MON_DATA_PERSONALITY: + SET32(boxMon->personality); + break; + case MON_DATA_OT_ID: + SET32(boxMon->otId); + break; + case MON_DATA_NICKNAME: + { + s32 i; + for (i = 0; i < POKEMON_NAME_LENGTH; i++) + boxMon->nickname[i] = data[i]; + break; + } + case MON_DATA_LANGUAGE: + SET8(boxMon->language); + break; + case MON_DATA_SANITY_BIT1: + SET8(boxMon->isBadEgg); + break; + case MON_DATA_SANITY_BIT2: + SET8(boxMon->hasSpecies); + break; + case MON_DATA_SANITY_BIT3: + SET8(boxMon->isEgg); + break; + case MON_DATA_OT_NAME: + { + s32 i; + for (i = 0; i < OT_NAME_LENGTH; i++) + boxMon->otName[i] = data[i]; + break; + } + case MON_DATA_MARKINGS: + SET8(boxMon->markings); + break; + case MON_DATA_CHECKSUM: + SET16(boxMon->checksum); + break; + case MON_DATA_10: + SET16(boxMon->unknown); + break; + case MON_DATA_SPECIES: + { + SET16(substruct0->species); + if (substruct0->species) + boxMon->hasSpecies = 1; + else + boxMon->hasSpecies = 0; + break; + } + case MON_DATA_HELD_ITEM: + SET16(substruct0->heldItem); + break; + case MON_DATA_EXP: + SET32(substruct0->experience); + break; + case MON_DATA_PP_BONUSES: + SET8(substruct0->ppBonuses); + break; + case MON_DATA_FRIENDSHIP: + SET8(substruct0->friendship); + break; + case MON_DATA_MOVE1: + case MON_DATA_MOVE2: + case MON_DATA_MOVE3: + case MON_DATA_MOVE4: + SET16(substruct1->moves[field - MON_DATA_MOVE1]); + break; + case MON_DATA_PP1: + case MON_DATA_PP2: + case MON_DATA_PP3: + case MON_DATA_PP4: + SET8(substruct1->pp[field - MON_DATA_PP1]); + break; + case MON_DATA_HP_EV: + SET8(substruct2->hpEV); + break; + case MON_DATA_ATK_EV: + SET8(substruct2->attackEV); + break; + case MON_DATA_DEF_EV: + SET8(substruct2->defenseEV); + break; + case MON_DATA_SPEED_EV: + SET8(substruct2->speedEV); + break; + case MON_DATA_SPATK_EV: + SET8(substruct2->spAttackEV); + break; + case MON_DATA_SPDEF_EV: + SET8(substruct2->spDefenseEV); + break; + case MON_DATA_COOL: + SET8(substruct2->cool); + break; + case MON_DATA_BEAUTY: + SET8(substruct2->beauty); + break; + case MON_DATA_CUTE: + SET8(substruct2->cute); + break; + case MON_DATA_SMART: + SET8(substruct2->smart); + break; + case MON_DATA_TOUGH: + SET8(substruct2->tough); + break; + case MON_DATA_SHEEN: + SET8(substruct2->sheen); + break; + case MON_DATA_POKERUS: + SET8(substruct3->pokerus); + break; + case MON_DATA_MET_LOCATION: + SET8(substruct3->metLocation); + break; + case MON_DATA_MET_LEVEL: + { + u8 metLevel = *data; + substruct3->metLevel = metLevel; + break; + } + case MON_DATA_MET_GAME: + SET8(substruct3->metGame); + break; + case MON_DATA_POKEBALL: + { + u8 pokeball = *data; + substruct3->pokeball = pokeball; + break; + } + case MON_DATA_OT_GENDER: + SET8(substruct3->otGender); + break; + case MON_DATA_HP_IV: + SET8(substruct3->hpIV); + break; + case MON_DATA_ATK_IV: + SET8(substruct3->attackIV); + break; + case MON_DATA_DEF_IV: + SET8(substruct3->defenseIV); + break; + case MON_DATA_SPEED_IV: + SET8(substruct3->speedIV); + break; + case MON_DATA_SPATK_IV: + SET8(substruct3->spAttackIV); + break; + case MON_DATA_SPDEF_IV: + SET8(substruct3->spDefenseIV); + break; + case MON_DATA_IS_EGG: + SET8(substruct3->isEgg); + if (substruct3->isEgg) + boxMon->isEgg = 1; + else + boxMon->isEgg = 0; + break; + case MON_DATA_ALT_ABILITY: + SET8(substruct3->altAbility); + break; + case MON_DATA_COOL_RIBBON: + SET8(substruct3->coolRibbon); + break; + case MON_DATA_BEAUTY_RIBBON: + SET8(substruct3->beautyRibbon); + break; + case MON_DATA_CUTE_RIBBON: + SET8(substruct3->cuteRibbon); + break; + case MON_DATA_SMART_RIBBON: + SET8(substruct3->smartRibbon); + break; + case MON_DATA_TOUGH_RIBBON: + SET8(substruct3->toughRibbon); + break; + case MON_DATA_CHAMPION_RIBBON: + SET8(substruct3->championRibbon); + break; + case MON_DATA_WINNING_RIBBON: + SET8(substruct3->winningRibbon); + break; + case MON_DATA_VICTORY_RIBBON: + SET8(substruct3->victoryRibbon); + break; + case MON_DATA_ARTIST_RIBBON: + SET8(substruct3->artistRibbon); + break; + case MON_DATA_EFFORT_RIBBON: + SET8(substruct3->effortRibbon); + break; + case MON_DATA_GIFT_RIBBON_1: + SET8(substruct3->giftRibbon1); + break; + case MON_DATA_GIFT_RIBBON_2: + SET8(substruct3->giftRibbon2); + break; + case MON_DATA_GIFT_RIBBON_3: + SET8(substruct3->giftRibbon3); + break; + case MON_DATA_GIFT_RIBBON_4: + SET8(substruct3->giftRibbon4); + break; + case MON_DATA_GIFT_RIBBON_5: + SET8(substruct3->giftRibbon5); + break; + case MON_DATA_GIFT_RIBBON_6: + SET8(substruct3->giftRibbon6); + break; + case MON_DATA_GIFT_RIBBON_7: + SET8(substruct3->giftRibbon7); + break; + case MON_DATA_FATEFUL_ENCOUNTER: + SET8(substruct3->fatefulEncounter); + break; + case MON_DATA_OBEDIENCE: + SET8(substruct3->obedient); + break; + case MON_DATA_IVS: + { + u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + substruct3->hpIV = ivs & 0x1F; + substruct3->attackIV = (ivs >> 5) & 0x1F; + substruct3->defenseIV = (ivs >> 10) & 0x1F; + substruct3->speedIV = (ivs >> 15) & 0x1F; + substruct3->spAttackIV = (ivs >> 20) & 0x1F; + substruct3->spDefenseIV = (ivs >> 25) & 0x1F; + break; + } + default: + break; + } + + if (field > MON_DATA_10) + { + boxMon->checksum = CalculateBoxMonChecksum(boxMon); + EncryptBoxMon(boxMon); + } +} + +void CopyMon(void *dest, void *src, size_t size) +{ + memcpy(dest, src, size); +} + +u8 GiveMonToPlayer(struct Pokemon *mon) +{ + s32 i; + + SetMonData(mon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); + SetMonData(mon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); + SetMonData(mon, MON_DATA_OT_ID, gSaveBlock2Ptr->playerTrainerId); + + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE) + break; + } + + if (i >= PARTY_SIZE) + return SendMonToPC(mon); + + CopyMon(&gPlayerParty[i], mon, sizeof(*mon)); + gPlayerPartyCount = i + 1; + return MON_GIVEN_TO_PARTY; +} + +u8 SendMonToPC(struct Pokemon* mon) +{ + s32 boxNo, boxPos; + + set_unknown_box_id(VarGet(VAR_STORAGE_UNKNOWN)); + + boxNo = StorageGetCurrentBox(); + + do + { + for (boxPos = 0; boxPos < 30; boxPos++) + { + struct BoxPokemon* checkingMon = GetBoxedMonPtr(boxNo, boxPos); + if (GetBoxMonData(checkingMon, MON_DATA_SPECIES, NULL) == SPECIES_NONE) + { + MonRestorePP(mon); + CopyMon(checkingMon, &mon->box, sizeof(mon->box)); + gSpecialVar_MonBoxId = boxNo; + gSpecialVar_MonBoxPos = boxPos; + if (get_unknown_box_id() != boxNo) + FlagClear(FLAG_SYS_STORAGE_UNKNOWN_FLAG); + VarSet(VAR_STORAGE_UNKNOWN, boxNo); + return MON_GIVEN_TO_PC; + } + } + + boxNo++; + if (boxNo == 14) + boxNo = 0; + } while (boxNo != StorageGetCurrentBox()); + + return MON_CANT_GIVE; +} + +u8 CalculatePlayerPartyCount(void) +{ + gPlayerPartyCount = 0; + + while (gPlayerPartyCount < 6 + && GetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + { + gPlayerPartyCount++; + } + + return gPlayerPartyCount; +} + +u8 CalculateEnemyPartyCount(void) +{ + gEnemyPartyCount = 0; + + while (gEnemyPartyCount < 6 + && GetMonData(&gEnemyParty[gEnemyPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE) + { + gEnemyPartyCount++; + } + + return gEnemyPartyCount; +} + +u8 GetMonsStateToDoubles(void) +{ + s32 aliveCount = 0; + s32 i; + CalculatePlayerPartyCount(); + + if (gPlayerPartyCount == 1) + return gPlayerPartyCount; // PLAYER_HAS_ONE_MON + + for (i = 0; i < gPlayerPartyCount; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG + && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0 + && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_NONE) + aliveCount++; + } + + return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; +} + +u8 GetMonsStateToDoubles_2(void) +{ + s32 aliveCount = 0; + s32 i; + + for (i = 0; i < PARTY_SIZE; i++) + { + u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL); + if (species != SPECIES_EGG && species != SPECIES_NONE + && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) + aliveCount++; + } + + if (aliveCount == 1) + return PLAYER_HAS_ONE_MON; // may have more than one, but only one is alive + + return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; +} + +u8 GetAbilityBySpecies(u16 species, bool8 altAbility) +{ + if (altAbility) + gLastUsedAbility = gBaseStats[species].ability2; + else + gLastUsedAbility = gBaseStats[species].ability1; + + return gLastUsedAbility; +} + +u8 GetMonAbility(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); + u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL); + return GetAbilityBySpecies(species, altAbility); +} + +void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord) +{ + s32 i, j; + + ZeroEnemyPartyMons(); + *gBattleResources->secretBase = *secretBaseRecord; + + for (i = 0; i < PARTY_SIZE; i++) + { + if (gBattleResources->secretBase->party.species[i]) + { + CreateMon(&gEnemyParty[i], + gBattleResources->secretBase->party.species[i], + gBattleResources->secretBase->party.levels[i], + 15, + 1, + gBattleResources->secretBase->party.personality[i], + 2, + 0); + + SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gBattleResources->secretBase->party.heldItems[i]); + + for (j = 0; j < 6; j++) + SetMonData(&gEnemyParty[i], MON_DATA_HP_EV + j, &gBattleResources->secretBase->party.EVs[i]); + + for (j = 0; j < 4; j++) + { + SetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j, &gBattleResources->secretBase->party.moves[i * 4 + j]); + SetMonData(&gEnemyParty[i], MON_DATA_PP1 + j, &gBattleMoves[gBattleResources->secretBase->party.moves[i * 4 + j]].pp); + } + } + } +} + +u8 GetSecretBaseTrainerPicIndex(void) +{ + u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; + return gFacilityClassToPicIndex[facilityClass]; +} + +u8 GetSecretBaseTrainerClass(void) +{ + u8 facilityClass = sSecretBaseFacilityClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; + return gFacilityClassToTrainerClass[facilityClass]; +} + +bool8 IsPlayerPartyAndPokemonStorageFull(void) +{ + s32 i; + + for (i = 0; i < PARTY_SIZE; i++) + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE) + return FALSE; + + return IsPokemonStorageFull(); +} + +bool8 IsPokemonStorageFull(void) +{ + s32 i, j; + + for (i = 0; i < 14; i++) + for (j = 0; j < 30; j++) + if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE) + return FALSE; + + return TRUE; +} + +void GetSpeciesName(u8 *name, u16 species) +{ + s32 i; + + for (i = 0; i <= POKEMON_NAME_LENGTH; i++) + { + if (species > NUM_SPECIES) + name[i] = gSpeciesNames[0][i]; + else + name[i] = gSpeciesNames[species][i]; + + if (name[i] == EOS) + break; + } + + name[i] = EOS; +} + +u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex) +{ + u8 basePP = gBattleMoves[move].pp; + return basePP + ((basePP * 20 * ((gUnknown_08329D22[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100); +} + +void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex) +{ + u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + ppBonuses &= gUnknown_08329D26[moveIndex]; + SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); +} + +void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex) +{ + mon->ppBonuses &= gUnknown_08329D26[moveIndex]; +} + +void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex) +{ + u16* hpSwitchout; + s32 i; + u8 nickname[POKEMON_NAME_LENGTH * 2]; + + gBattleMons[battlerId].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL); + gBattleMons[battlerId].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL); + + for (i = 0; i < 4; i++) + { + gBattleMons[battlerId].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL); + gBattleMons[battlerId].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL); + } + + gBattleMons[battlerId].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL); + gBattleMons[battlerId].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL); + gBattleMons[battlerId].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL); + gBattleMons[battlerId].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL); + gBattleMons[battlerId].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL); + gBattleMons[battlerId].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL); + gBattleMons[battlerId].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED_IV, NULL); + gBattleMons[battlerId].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL); + gBattleMons[battlerId].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL); + gBattleMons[battlerId].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL); + gBattleMons[battlerId].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL); + gBattleMons[battlerId].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL); + gBattleMons[battlerId].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL); + gBattleMons[battlerId].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL); + gBattleMons[battlerId].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL); + gBattleMons[battlerId].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL); + gBattleMons[battlerId].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED, NULL); + gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL); + gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL); + gBattleMons[battlerId].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL); + gBattleMons[battlerId].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL); + gBattleMons[battlerId].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL); + gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1; + gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2; + gBattleMons[battlerId].ability = GetAbilityBySpecies(gBattleMons[battlerId].species, gBattleMons[battlerId].altAbility); + GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname); + StringCopy10(gBattleMons[battlerId].nickname, nickname); + GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[battlerId].otName); + + hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(battlerId)]; + *hpSwitchout = gBattleMons[battlerId].hp; + + for (i = 0; i < 8; i++) + gBattleMons[battlerId].statStages[i] = 6; + + gBattleMons[battlerId].status2 = 0; + sub_803FA70(battlerId); + ClearTemporarySpeciesSpriteData(battlerId, FALSE); +} + +bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex) +{ + return PokemonUseItemEffects(mon, item, partyIndex, moveIndex, 0); +} + +bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex, u8 e) +{ + u32 dataUnsigned; + s32 dataSigned; + s32 friendship; + s32 cmdIndex; + bool8 retVal = TRUE; + const u8 *itemEffect; + u8 var_3C = 6; + u32 var_38; + s8 var_34 = 0; + u8 holdEffect; + u8 battlerId = 4; + u32 var_28 = 0; + u16 heldItem; + u8 r10; + u32 r4; + u32 r5; + s8 r2; + u16 evCount; + + heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, NULL); + if (heldItem == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + holdEffect = gEnigmaBerries[gBattlerInMenuId].holdEffect; + else + holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + } + else + { + holdEffect = ItemId_GetHoldEffect(heldItem); + } + + gPotentialItemEffectBattler = gBattlerInMenuId; + if (gMain.inBattle) + { + gActiveBattler = gBattlerInMenuId; + cmdIndex = (GetBattlerSide(gActiveBattler) != B_SIDE_PLAYER); + while (cmdIndex < gBattlersCount) + { + if (gBattlerPartyIndexes[cmdIndex] == partyIndex) + { + battlerId = cmdIndex; + break; + } + cmdIndex += 2; + } + } + else + { + gActiveBattler = 0; + battlerId = MAX_BATTLERS_COUNT; + } + + if (!IS_POKEMON_ITEM(item)) + return TRUE; + if (gItemEffectTable[item - 13] == NULL && item != ITEM_ENIGMA_BERRY) + return TRUE; + + if (item == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + itemEffect = gEnigmaBerries[gActiveBattler].itemEffect; + else + itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; + } + else + { + itemEffect = gItemEffectTable[item - 13]; + } + + for (cmdIndex = 0; cmdIndex < 6; cmdIndex++) + { + switch (cmdIndex) + { + // status healing effects + case 0: + if ((itemEffect[cmdIndex] & 0x80) + && gMain.inBattle && battlerId != 4 && (gBattleMons[battlerId].status2 & STATUS2_INFATUATION)) + { + gBattleMons[battlerId].status2 &= ~STATUS2_INFATUATION; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0x30) + && !(gBattleMons[gActiveBattler].status2 & STATUS2_FOCUS_ENERGY)) + { + gBattleMons[gActiveBattler].status2 |= STATUS2_FOCUS_ENERGY; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0xF) + && gBattleMons[gActiveBattler].statStages[STAT_ATK] < 12) + { + gBattleMons[gActiveBattler].statStages[STAT_ATK] += itemEffect[cmdIndex] & 0xF; + if (gBattleMons[gActiveBattler].statStages[STAT_ATK] > 12) + gBattleMons[gActiveBattler].statStages[STAT_ATK] = 12; + retVal = FALSE; + } + break; + // in-battle stat boosting effects? + case 1: + if ((itemEffect[cmdIndex] & 0xF0) + && gBattleMons[gActiveBattler].statStages[STAT_DEF] < 12) + { + gBattleMons[gActiveBattler].statStages[STAT_DEF] += (itemEffect[cmdIndex] & 0xF0) >> 4; + if (gBattleMons[gActiveBattler].statStages[STAT_DEF] > 12) + gBattleMons[gActiveBattler].statStages[STAT_DEF] = 12; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0xF) + && gBattleMons[gActiveBattler].statStages[STAT_SPEED] < 12) + { + gBattleMons[gActiveBattler].statStages[STAT_SPEED] += itemEffect[cmdIndex] & 0xF; + if (gBattleMons[gActiveBattler].statStages[STAT_SPEED] > 12) + gBattleMons[gActiveBattler].statStages[STAT_SPEED] = 12; + retVal = FALSE; + } + break; + // more stat boosting effects? + case 2: + if ((itemEffect[cmdIndex] & 0xF0) + && gBattleMons[gActiveBattler].statStages[STAT_ACC] < 12) + { + gBattleMons[gActiveBattler].statStages[STAT_ACC] += (itemEffect[cmdIndex] & 0xF0) >> 4; + if (gBattleMons[gActiveBattler].statStages[STAT_ACC] > 12) + gBattleMons[gActiveBattler].statStages[STAT_ACC] = 12; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0xF) + && gBattleMons[gActiveBattler].statStages[STAT_SPATK] < 12) + { + gBattleMons[gActiveBattler].statStages[STAT_SPATK] += itemEffect[cmdIndex] & 0xF; + if (gBattleMons[gActiveBattler].statStages[STAT_SPATK] > 12) + gBattleMons[gActiveBattler].statStages[STAT_SPATK] = 12; + retVal = FALSE; + } + break; + case 3: + if ((itemEffect[cmdIndex] & 0x80) + && gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer == 0) + { + gSideTimers[GetBattlerSide(gActiveBattler)].mistTimer = 5; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0x40) // raise level + && GetMonData(mon, MON_DATA_LEVEL, NULL) != MAX_MON_LEVEL) + { + dataUnsigned = gExperienceTables[gBaseStats[GetMonData(mon, MON_DATA_SPECIES, NULL)].growthRate][GetMonData(mon, MON_DATA_LEVEL, NULL) + 1]; + SetMonData(mon, MON_DATA_EXP, &dataUnsigned); + CalculateMonStats(mon); + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0x20) + && HealStatusConditions(mon, partyIndex, 7, battlerId) == 0) + { + if (battlerId != 4) + gBattleMons[battlerId].status2 &= ~STATUS2_NIGHTMARE; + retVal = FALSE; + } + if ((itemEffect[cmdIndex] & 0x10) && HealStatusConditions(mon, partyIndex, STATUS1_PSN_ANY | STATUS1_TOXIC_COUNTER, battlerId) == 0) + retVal = FALSE; + if ((itemEffect[cmdIndex] & 8) && HealStatusConditions(mon, partyIndex, STATUS1_BURN, battlerId) == 0) + retVal = FALSE; + if ((itemEffect[cmdIndex] & 4) && HealStatusConditions(mon, partyIndex, STATUS1_FREEZE, battlerId) == 0) + retVal = FALSE; + if ((itemEffect[cmdIndex] & 2) && HealStatusConditions(mon, partyIndex, STATUS1_PARALYSIS, battlerId) == 0) + retVal = FALSE; + if ((itemEffect[cmdIndex] & 1) // heal confusion + && gMain.inBattle && battlerId != 4 && (gBattleMons[battlerId].status2 & STATUS2_CONFUSION)) + { + gBattleMons[battlerId].status2 &= ~STATUS2_CONFUSION; + retVal = FALSE; + } + break; + // EV, HP, and PP raising effects + case 4: + r10 = itemEffect[cmdIndex]; + if (r10 & 0x20) + { + r10 &= ~0x20; + dataUnsigned = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & gUnknown_08329D22[moveIndex]) >> (moveIndex * 2); + var_38 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); + if (dataUnsigned <= 2 && var_38 > 4) + { + dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL) + gUnknown_08329D2A[moveIndex]; + SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned); + + dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - var_38; + dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL) + dataUnsigned; + SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned); + retVal = FALSE; + } + } + var_38 = 0; + while (r10 != 0) + { + if (r10 & 1) + { + switch (var_38) + { + case 0: + case 1: + evCount = GetMonEVCount(mon); + r5 = itemEffect[var_3C]; + dataSigned = GetMonData(mon, sGetMonDataEVConstants[var_38], NULL); + r2 = r5; + if (r2 > 0) + { + if (evCount >= MAX_TOTAL_EVS) + return TRUE; + if (dataSigned >= 100) + break; + + if (dataSigned + r2 > 100) + r5 = 100 - (dataSigned + r2) + r2; + else + r5 = r2; + + if (evCount + r5 > MAX_TOTAL_EVS) + r5 += MAX_TOTAL_EVS - (evCount + r5); + dataSigned += r5; + } + else + { + if (dataSigned == 0) + { + var_28 = 1; + var_3C++; + break; + } + dataSigned += r2; + if (dataSigned < 0) + dataSigned = 0; + } + SetMonData(mon, sGetMonDataEVConstants[var_38], &dataSigned); + CalculateMonStats(mon); + var_3C++; + retVal = FALSE; + break; + case 2: + // revive? + if (r10 & 0x10) + { + if (GetMonData(mon, MON_DATA_HP, NULL) != 0) + { + var_3C++; + break; + } + if (gMain.inBattle) + { + if (battlerId != 4) + { + gAbsentBattlerFlags &= ~gBitTable[battlerId]; + CopyPlayerPartyMonToBattleData(battlerId, pokemon_order_func(gBattlerPartyIndexes[battlerId])); + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.unk4 < 255) + gBattleResults.unk4++; + } + else + { + gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2]; + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.unk4 < 255) + gBattleResults.unk4++; + } + } + } + else + { + if (GetMonData(mon, MON_DATA_HP, NULL) == 0) + { + var_3C++; + break; + } + } + dataUnsigned = itemEffect[var_3C++]; + switch (dataUnsigned) + { + case 0xFF: + dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL) - GetMonData(mon, MON_DATA_HP, NULL); + break; + case 0xFE: + dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL) / 2; + if (dataUnsigned == 0) + dataUnsigned = 1; + break; + case 0xFD: + dataUnsigned = gBattleScripting.field_23; + break; + } + if (GetMonData(mon, MON_DATA_MAX_HP, NULL) != GetMonData(mon, MON_DATA_HP, NULL)) + { + if (e == 0) + { + dataUnsigned = GetMonData(mon, MON_DATA_HP, NULL) + dataUnsigned; + if (dataUnsigned > GetMonData(mon, MON_DATA_MAX_HP, NULL)) + dataUnsigned = GetMonData(mon, MON_DATA_MAX_HP, NULL); + SetMonData(mon, MON_DATA_HP, &dataUnsigned); + if (gMain.inBattle && battlerId != 4) + { + gBattleMons[battlerId].hp = dataUnsigned; + if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + if (gBattleResults.unk3 < 255) + gBattleResults.unk3++; + // I have to re-use this variable to match. + r5 = gActiveBattler; + gActiveBattler = battlerId; + BtlController_EmitGetMonData(0, 0, 0); + MarkBattlerForControllerExec(gActiveBattler); + gActiveBattler = r5; + } + } + } + else + { + gBattleMoveDamage = -dataUnsigned; + } + retVal = FALSE; + } + r10 &= 0xEF; + break; + case 3: + if (!(r10 & 2)) + { + for (r5 = 0; (signed)(r5) < (signed)(4); r5++) + { + u16 moveId; + + dataUnsigned = GetMonData(mon, MON_DATA_PP1 + r5, NULL); + moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL); + if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5)) + { + dataUnsigned += itemEffect[var_3C]; + moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL); + if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5)) + { + moveId = GetMonData(mon, MON_DATA_MOVE1 + r5, NULL); + dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), r5); + } + SetMonData(mon, MON_DATA_PP1 + r5, &dataUnsigned); + if (gMain.inBattle + && battlerId != 4 && !(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[battlerId].unk18_b & gBitTable[r5])) + gBattleMons[battlerId].pp[r5] = dataUnsigned; + retVal = FALSE; + } + } + var_3C++; + } + else + { + u16 moveId; + + dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL); + moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL); + if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex)) + { + dataUnsigned += itemEffect[var_3C++]; + moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL); + if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex)) + { + moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL); + dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); + } + SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned); + if (gMain.inBattle + && battlerId != 4 && !(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED) + && !(gDisableStructs[battlerId].unk18_b & gBitTable[moveIndex])) + gBattleMons[battlerId].pp[moveIndex] = dataUnsigned; + retVal = FALSE; + } + } + break; + case 7: + { + u16 targetSpecies = GetEvolutionTargetSpecies(mon, 2, item); + + if (targetSpecies != SPECIES_NONE) + { + BeginEvolutionScene(mon, targetSpecies, 0, partyIndex); + return FALSE; + } + } + break; + } + } + var_38++; + r10 >>= 1; + } + break; + case 5: + r10 = itemEffect[cmdIndex]; + var_38 = 0; + while (r10 != 0) + { + if (r10 & 1) + { + switch (var_38) + { + case 0: + case 1: + case 2: + case 3: + evCount = GetMonEVCount(mon); + r5 = itemEffect[var_3C]; + dataSigned = GetMonData(mon, sGetMonDataEVConstants[var_38 + 2], NULL); + r2 = r5; + if (r2 > 0) + { + if (evCount >= MAX_TOTAL_EVS) + return TRUE; + if (dataSigned >= 100) + break; + + if (dataSigned + r2 > 100) + r5 = 100 - (dataSigned + r2) + r2; + else + r5 = r2; + + if (evCount + r5 > MAX_TOTAL_EVS) + r5 += MAX_TOTAL_EVS - (evCount + r5); + dataSigned += r5; + } + else + { + if (dataSigned == 0) + { + var_28 = 1; + var_3C++; + break; + } + dataSigned += r2; + if (dataSigned < 0) + dataSigned = 0; + } + SetMonData(mon, sGetMonDataEVConstants[var_38 + 2], &dataSigned); + CalculateMonStats(mon); + retVal = FALSE; + var_3C++; + break; + case 4: + dataUnsigned = (GetMonData(mon, MON_DATA_PP_BONUSES, NULL) & gUnknown_08329D22[moveIndex]) >> (moveIndex * 2); + r5 = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); + if (dataUnsigned < 3 && r5 > 4) + { + dataUnsigned = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); + dataUnsigned &= gUnknown_08329D26[moveIndex]; + dataUnsigned += gUnknown_08329D2A[moveIndex] * 3; + + SetMonData(mon, MON_DATA_PP_BONUSES, &dataUnsigned); + dataUnsigned = CalculatePPWithBonus(GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL), dataUnsigned, moveIndex) - r5; + dataUnsigned = GetMonData(mon, MON_DATA_PP1 + moveIndex, NULL) + dataUnsigned; + SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned); + retVal = FALSE; + } + break; + case 5: + if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 100 && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0) + { + var_34 = itemEffect[var_3C]; + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); + if (var_34 > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) + friendship += 150 * var_34 / 100; + else + friendship += var_34; + if (var_34 > 0) + { + if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11) + friendship++; + if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name()) + friendship++; + } + if (friendship < 0) + friendship = 0; + if (friendship > 255) + friendship = 255; + SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship); + retVal = FALSE; + } + var_3C++; + break; + case 6: + if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 100 && GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) < 200 + && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0) + { + var_34 = itemEffect[var_3C]; + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); + if ((s8)(var_34) > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) + friendship += 150 * var_34 / 100; + else + friendship += var_34; + if (var_34 > 0) + { + if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11) + friendship++; + if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name()) + friendship++; + } + if (friendship < 0) + friendship = 0; + if (friendship > 255) + friendship = 255; + SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship); + retVal = FALSE; + } + var_3C++; + break; + case 7: + if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 200 && (retVal == 0 || var_28 != 0) && !sub_806F104() && var_34 == 0) + { + var_34 = itemEffect[var_3C]; + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); + if ((s8)(var_34) > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) + friendship += 150 * var_34 / 100; + else + friendship += var_34; + if (var_34 > 0) + { + if (GetMonData(mon, MON_DATA_POKEBALL, NULL) == 11) + friendship++; + if (GetMonData(mon, MON_DATA_MET_LOCATION, NULL) == sav1_map_get_name()) + friendship++; + } + if (friendship < 0) + friendship = 0; + if (friendship > 255) + friendship = 255; + SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship); + retVal = FALSE; + } + var_3C++; + break; + } + } + var_38++; + r10 >>= 1; + } + break; + } + } + return retVal; +} + +bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battlerId) +{ + u32 status = GetMonData(mon, MON_DATA_STATUS, 0); + + if (status & healMask) + { + status &= ~healMask; + SetMonData(mon, MON_DATA_STATUS, &status); + if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT) + gBattleMons[battlerId].status1 &= ~healMask; + return FALSE; + } + else + { + return TRUE; + } +} + +u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit) +{ + const u8 *temp; + const u8 *itemEffect; + u8 offset; + int i; + u8 j; + u8 val; + + offset = 6; + + temp = gItemEffectTable[itemId - 13]; + + if (!temp && itemId != ITEM_ENIGMA_BERRY) + return 0; + + if (itemId == ITEM_ENIGMA_BERRY) + { + temp = gEnigmaBerries[gActiveBattler].itemEffect; + } + + itemEffect = temp; + + for (i = 0; i < 6; i++) + { + switch (i) + { + case 0: + case 1: + case 2: + case 3: + if (i == effectByte) + return 0; + break; + case 4: + val = itemEffect[4]; + if (val & 0x20) + val &= 0xDF; + j = 0; + while (val) + { + if (val & 1) + { + switch (j) + { + case 2: + if (val & 0x10) + val &= 0xEF; + case 0: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 1: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 3: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 7: + if (i == effectByte) + return 0; + break; + } + } + j++; + val >>= 1; + if (i == effectByte) + effectBit >>= 1; + } + break; + case 5: + val = itemEffect[5]; + j = 0; + while (val) + { + if (val & 1) + { + switch (j) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + if (i == effectByte && (val & effectBit)) + return offset; + offset++; + break; + case 7: + if (i == effectByte) + return 0; + break; + } + } + j++; + val >>= 1; + if (i == effectByte) + effectBit >>= 1; + } + break; + } + } + + return offset; +} + +static void sub_806CF24(s32 arg0) +{ + gBattlerTarget = gBattlerInMenuId; + StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[arg0]]); + StringCopy(gBattleTextBuff2, gText_StatRose); + BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2); +} + +u8 *sub_806CF78(u16 itemId) +{ + int i; + const u8 *itemEffect; + + if (itemId == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + itemEffect = gEnigmaBerries[gBattlerInMenuId].itemEffect; + else + itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; + } + else + { + itemEffect = gItemEffectTable[itemId - 13]; + } + + gPotentialItemEffectBattler = gBattlerInMenuId; + + for (i = 0; i < 3; i++) + { + if (itemEffect[i] & 0xF) + sub_806CF24(i * 2); + if (itemEffect[i] & 0xF0) + { + if (i) + { + sub_806CF24(i * 2 + 1); + } + else + { + gBattlerAttacker = gBattlerInMenuId; + BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped); + } + } + } + + if (itemEffect[3] & 0x80) + { + gBattlerAttacker = gBattlerInMenuId; + BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist); + } + + return gDisplayedStringBattle; +} + +u8 GetNature(struct Pokemon *mon) +{ + return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25; +} + +u8 GetNatureFromPersonality(u32 personality) +{ + return personality % 25; +} + +u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem) +{ + int i; + u16 targetSpecies = 0; + u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); + u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); + u8 level; + u16 friendship; + u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0); + u16 upperPersonality = personality >> 16; + u8 holdEffect; + + if (heldItem == ITEM_ENIGMA_BERRY) + holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + else + holdEffect = ItemId_GetHoldEffect(heldItem); + + if (holdEffect == 38 && type != 3) + return 0; + + switch (type) + { + case 0: + level = GetMonData(mon, MON_DATA_LEVEL, 0); + friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); + + for (i = 0; i < 5; i++) + { + switch (gEvolutionTable[species][i].method) + { + case EVO_FRIENDSHIP: + if (friendship >= 220) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_FRIENDSHIP_DAY: + RtcCalcLocalTime(); + if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_FRIENDSHIP_NIGHT: + RtcCalcLocalTime(); + if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL: + if (gEvolutionTable[species][i].param <= level) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_ATK_GT_DEF: + if (gEvolutionTable[species][i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_ATK_EQ_DEF: + if (gEvolutionTable[species][i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_ATK_LT_DEF: + if (gEvolutionTable[species][i].param <= level) + if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0)) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_SILCOON: + if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_CASCOON: + if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_LEVEL_NINJASK: + if (gEvolutionTable[species][i].param <= level) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_BEAUTY: + if (gEvolutionTable[species][i].param <= beauty) + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + } + } + break; + case 1: + for (i = 0; i < 5; i++) + { + switch (gEvolutionTable[species][i].method) + { + case EVO_TRADE: + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + case EVO_TRADE_ITEM: + if (gEvolutionTable[species][i].param == heldItem) + { + heldItem = 0; + SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem); + targetSpecies = gEvolutionTable[species][i].targetSpecies; + } + break; + } + } + break; + case 2: + case 3: + for (i = 0; i < 5; i++) + { + if (gEvolutionTable[species][i].method == EVO_ITEM + && gEvolutionTable[species][i].param == evolutionItem) + { + targetSpecies = gEvolutionTable[species][i].targetSpecies; + break; + } + } + break; + } + + return targetSpecies; +} + +u16 HoennPokedexNumToSpecies(u16 hoennNum) +{ + u16 species; + + if (!hoennNum) + return 0; + + species = 0; + + while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum) + species++; + + if (species == 411) + return 0; + + return species + 1; +} + +u16 NationalPokedexNumToSpecies(u16 nationalNum) +{ + u16 species; + + if (!nationalNum) + return 0; + + species = 0; + + while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum) + species++; + + if (species == 411) + return 0; + + return species + 1; +} + +u16 NationalToHoennOrder(u16 nationalNum) +{ + u16 hoennNum; + + if (!nationalNum) + return 0; + + hoennNum = 0; + + while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum) + hoennNum++; + + if (hoennNum == 411) + return 0; + + return hoennNum + 1; +} + +u16 SpeciesToNationalPokedexNum(u16 species) +{ + if (!species) + return 0; + + return gSpeciesToNationalPokedexNum[species - 1]; +} + +u16 SpeciesToHoennPokedexNum(u16 species) +{ + if (!species) + return 0; + + return gSpeciesToHoennPokedexNum[species - 1]; +} + +u16 HoennToNationalOrder(u16 hoennNum) +{ + if (!hoennNum) + return 0; + + return gHoennToNationalOrder[hoennNum - 1]; +} + +u16 SpeciesToCryId(u16 species) +{ + if (species <= 250) + return species; + + if (species < 276) + return 200; + + return gSpeciesIdToCryId[species - 276]; +} + +void sub_806D544(u16 species, u32 personality, u8 *dest) +{ + if (species == SPECIES_SPINDA + && dest != gMonSpritesGfxPtr->sprites[0] + && dest != gMonSpritesGfxPtr->sprites[2]) + { + int i; + for (i = 0; i < 4; i++) + { + int j; + u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); + u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); + + for (j = 0; j < 16; j++) + { + int k; + s32 row = gSpindaSpotGraphics[i].image[j]; + + for (k = x; k < x + 16; k++) + { + u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2); + + if (row & 1) + { + if (k & 1) + { + if ((u8)((*val & 0xF0) - 0x10) <= 0x20) + *val += 0x40; + } + else + { + if ((u8)((*val & 0xF) - 0x01) <= 0x02) + *val += 0x04; + } + } + + row >>= 1; + } + + y++; + } + + personality >>= 8; + } + } +} + +void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4) +{ + if (species == SPECIES_SPINDA && a4) + { + int i; + for (i = 0; i < 4; i++) + { + int j; + u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); + u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); + + for (j = 0; j < 16; j++) + { + int k; + s32 row = gSpindaSpotGraphics[i].image[j]; + + for (k = x; k < x + 16; k++) + { + u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2); + + if (row & 1) + { + if (k & 1) + { + if ((u8)((*val & 0xF0) - 0x10) <= 0x20) + *val += 0x40; + } + else + { + if ((u8)((*val & 0xF) - 0x01) <= 0x02) + *val += 0x04; + } + } + + row >>= 1; + } + + y++; + } + + personality >>= 8; + } + } +} + +void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies) +{ + u8 language; + GetMonData(mon, MON_DATA_NICKNAME, gStringVar1); + language = GetMonData(mon, MON_DATA_LANGUAGE, &language); + if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1)) + SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]); +} + +bool8 sub_806D7EC(void) +{ + bool8 retVal = FALSE; + switch (gLinkPlayers[GetMultiplayerId()].lp_field_18) + { + case 0: + case 3: + retVal = FALSE; + break; + case 1: + case 2: + retVal = TRUE; + break; + } + return retVal; +} + +bool16 sub_806D82C(u8 id) +{ + bool16 retVal = FALSE; + switch (gLinkPlayers[id].lp_field_18) + { + case 0: + case 3: + retVal = FALSE; + break; + case 1: + case 2: + retVal = TRUE; + break; + } + return retVal; +} + +s32 GetBattlerMultiplayerId(u16 a1) +{ + s32 id; + for (id = 0; id < MAX_LINK_PLAYERS; id++) + if (gLinkPlayers[id].lp_field_18 == a1) + break; + return id; +} + +u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) +{ + if (InBattlePyramid()) + return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId); + if (sub_81D5C18()) + return sub_81D63C8(trainerOpponentId); + return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId); +} + +u16 ModifyStatByNature(u8 nature, u16 n, u8 statIndex) +{ + if (statIndex < 1 || statIndex > 5) + { + // should just be "return n", but it wouldn't match without this + u16 retVal = n; + retVal++; + retVal--; + return retVal; + } + + switch (gNatureStatTable[nature][statIndex - 1]) + { + case 1: + return (u16)(n * 110) / 100; + case -1: + return (u16)(n * 90) / 100; + } + + return n; +} + +void AdjustFriendship(struct Pokemon *mon, u8 event) +{ + u16 species, heldItem; + u8 holdEffect; + + if (sub_806F104()) + return; + + species = GetMonData(mon, MON_DATA_SPECIES2, 0); + heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); + + if (heldItem == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + holdEffect = gEnigmaBerries[0].holdEffect; + else + holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + } + else + { + holdEffect = ItemId_GetHoldEffect(heldItem); + } + + if (species && species != SPECIES_EGG) + { + u8 friendshipLevel = 0; + s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); + if (friendship > 99) + friendshipLevel++; + if (friendship > 199) + friendshipLevel++; + if ((event != 5 || !(Random() & 1)) + && (event != 3 + || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) + && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR + || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER + || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION)))) + { + s8 mod = gUnknown_08329ECE[event][friendshipLevel]; + if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) + mod = (150 * mod) / 100; + friendship += mod; + if (mod > 0) + { + if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL) + friendship++; + if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name()) + friendship++; + } + if (friendship < 0) + friendship = 0; + if (friendship > 255) + friendship = 255; + SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship); + } + } +} + +void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies) +{ + u8 evs[NUM_STATS]; + u16 evIncrease = 0; + u16 totalEVs = 0; + u16 heldItem; + u8 holdEffect; + int i; + + for (i = 0; i < NUM_STATS; i++) + { + evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0); + totalEVs += evs[i]; + } + + for (i = 0; i < NUM_STATS; i++) + { + u8 hasHadPokerus; + int multiplier; + + if (totalEVs >= MAX_TOTAL_EVS) + break; + + hasHadPokerus = CheckPartyHasHadPokerus(mon, 0); + + if (hasHadPokerus) + multiplier = 2; + else + multiplier = 1; + + switch (i) + { + case 0: + evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier; + break; + case 1: + evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier; + break; + case 2: + evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier; + break; + case 3: + evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier; + break; + case 4: + evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier; + break; + case 5: + evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier; + break; + } + + heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); + + if (heldItem == ITEM_ENIGMA_BERRY) + { + if (gMain.inBattle) + holdEffect = gEnigmaBerries[0].holdEffect; + else + holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; + } + else + { + holdEffect = ItemId_GetHoldEffect(heldItem); + } + + if (holdEffect == HOLD_EFFECT_MACHO_BRACE) + evIncrease *= 2; + + if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS) + evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease); + + if (evs[i] + (s16)evIncrease > 255) + { + int val1 = (s16)evIncrease + 255; + int val2 = evs[i] + evIncrease; + evIncrease = val1 - val2; + } + + evs[i] += evIncrease; + totalEVs += evIncrease; + SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]); + } +} + +u16 GetMonEVCount(struct Pokemon *mon) +{ + int i; + u16 count = 0; + + for (i = 0; i < NUM_STATS; i++) + count += GetMonData(mon, MON_DATA_HP_EV + i, 0); + + return count; +} + +void RandomlyGivePartyPokerus(struct Pokemon *party) +{ + u16 rnd = Random(); + if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000) + { + struct Pokemon *mon; + + do + { + do + { + rnd = Random() % PARTY_SIZE; + mon = &party[rnd]; + } + while (!GetMonData(mon, MON_DATA_SPECIES, 0)); + } + while (GetMonData(mon, MON_DATA_IS_EGG, 0)); + + if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd]))) + { + u8 rnd2; + + do + { + rnd2 = Random(); + } + while ((rnd2 & 0x7) == 0); + + if (rnd2 & 0xF0) + rnd2 &= 0x7; + + rnd2 |= (rnd2 << 4); + rnd2 &= 0xF3; + rnd2++; + + SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2); + } + } +} + +u8 CheckPartyPokerus(struct Pokemon *party, u8 selection) +{ + u8 retVal; + + int partyIndex = 0; + unsigned curBit = 1; + retVal = 0; + + if (selection) + { + do + { + if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF)) + retVal |= curBit; + partyIndex++; + curBit <<= 1; + selection >>= 1; + } + while (selection); + } + else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF) + { + retVal = 1; + } + + return retVal; +} + +u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection) +{ + u8 retVal; + + int partyIndex = 0; + unsigned curBit = 1; + retVal = 0; + + if (selection) + { + do + { + if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0)) + retVal |= curBit; + partyIndex++; + curBit <<= 1; + selection >>= 1; + } + while (selection); + } + else if (GetMonData(&party[0], MON_DATA_POKERUS, 0)) + { + retVal = 1; + } + + return retVal; +} + +void UpdatePartyPokerusTime(u16 days) +{ + int i; + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0)) + { + u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0); + if (pokerus & 0xF) + { + if ((pokerus & 0xF) < days || days > 4) + pokerus &= 0xF0; + else + pokerus -= days; + + if (pokerus == 0) + pokerus = 0x10; + + SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus); + } + } + } +} + +void PartySpreadPokerus(struct Pokemon *party) +{ + if ((Random() % 3) == 0) + { + int i; + for (i = 0; i < PARTY_SIZE; i++) + { + if (GetMonData(&party[i], MON_DATA_SPECIES, 0)) + { + u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0); + u8 curPokerus = pokerus; + if (pokerus) + { + if (pokerus & 0xF) + { + // spread to adjacent party members + if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0)) + SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus); + if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0)) + { + SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus); + i++; + } + } + } + } + } + } +} + +bool8 TryIncrementMonLevel(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); + u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1; + u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0); + if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL]) + { + expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL]; + SetMonData(mon, MON_DATA_EXP, &expPoints); + } + if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel]) + { + return FALSE; + } + else + { + SetMonData(mon, MON_DATA_LEVEL, &nextLevel); + return TRUE; + } +} + +u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); + if (species == SPECIES_EGG) + { + return 0; + } + else if (tm < 32) + { + u32 mask = 1 << tm; + return gTMHMLearnsets[species][0] & mask; + } + else + { + u32 mask = 1 << (tm - 32); + return gTMHMLearnsets[species][1] & mask; + } +} + +u32 CanSpeciesLearnTMHM(u16 species, u8 tm) +{ + if (species == SPECIES_EGG) + { + return 0; + } + else if (tm < 32) + { + u32 mask = 1 << tm; + return gTMHMLearnsets[species][0] & mask; + } + else + { + u32 mask = 1 << (tm - 32); + return gTMHMLearnsets[species][1] & mask; + } +} + +u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves) +{ + u16 learnedMoves[4]; + u8 numMoves = 0; + u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); + u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); + int i, j, k; + + for (i = 0; i < 4; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (i = 0; i < 20; i++) + { + u16 moveLevel; + + if (gLevelUpLearnsets[species][i] == 0xFFFF) + break; + + moveLevel = gLevelUpLearnsets[species][i] & 0xFE00; + + if (moveLevel <= (level << 9)) + { + for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++) + ; + + if (j == 4) + { + for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++) + ; + + if (k == numMoves) + moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; + } + } + } + + return numMoves; +} + +u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) +{ + u8 numMoves = 0; + int i; + + for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++) + moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; + + return numMoves; +} + +u8 GetNumberOfRelearnableMoves(struct Pokemon *mon) +{ + u16 learnedMoves[4]; + u16 moves[20]; + u8 numMoves = 0; + u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); + u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); + int i, j, k; + + if (species == SPECIES_EGG) + return 0; + + for (i = 0; i < 4; i++) + learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); + + for (i = 0; i < 20; i++) + { + u16 moveLevel; + + if (gLevelUpLearnsets[species][i] == 0xFFFF) + break; + + moveLevel = gLevelUpLearnsets[species][i] & 0xFE00; + + if (moveLevel <= (level << 9)) + { + for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++) + ; + + if (j == 4) + { + for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++) + ; + + if (k == numMoves) + moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; + } + } + } + + return numMoves; +} + +u16 SpeciesToPokedexNum(u16 species) +{ + if (IsNationalPokedexEnabled()) + { + return SpeciesToNationalPokedexNum(species); + } + else + { + species = SpeciesToHoennPokedexNum(species); + if (species <= 202) + return species; + return 0xFFFF; + } +} + +bool32 sub_806E3F8(u16 species) +{ + if (SpeciesToHoennPokedexNum(species) > 202) + return FALSE; + else + return TRUE; +} + +void ClearBattleMonForms(void) +{ + int i; + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + gBattleMonForms[i] = 0; +} + +u16 GetBattleBGM(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON) + return MUS_BATTLE34; + if (gBattleTypeFlags & BATTLE_TYPE_REGI) + return MUS_BATTLE36; + if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) + return MUS_BATTLE20; + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) + { + u8 trainerClass; + + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) + trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A); + else if (gBattleTypeFlags & BATTLE_TYPE_x4000000) + trainerClass = TRAINER_CLASS_EXPERT; + else + trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; + + switch (trainerClass) + { + case TRAINER_CLASS_AQUA_LEADER: + case TRAINER_CLASS_MAGMA_LEADER: + return MUS_BATTLE30; + case TRAINER_CLASS_TEAM_AQUA: + case TRAINER_CLASS_TEAM_MAGMA: + case TRAINER_CLASS_AQUA_ADMIN: + case TRAINER_CLASS_MAGMA_ADMIN: + return MUS_BATTLE31; + case TRAINER_CLASS_LEADER: + return MUS_BATTLE32; + case TRAINER_CLASS_CHAMPION: + return MUS_BATTLE33; + case TRAINER_CLASS_PKMN_TRAINER_3: + if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) + return MUS_BATTLE35; + if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName)) + return MUS_BATTLE20; + return MUS_BATTLE35; + case TRAINER_CLASS_ELITE_FOUR: + return MUS_BATTLE38; + case TRAINER_CLASS_SALON_MAIDEN: + case TRAINER_CLASS_DOME_ACE: + case TRAINER_CLASS_PALACE_MAVEN: + case TRAINER_CLASS_ARENA_TYCOON: + case TRAINER_CLASS_FACTORY_HEAD: + case TRAINER_CLASS_PIKE_QUEEN: + case TRAINER_CLASS_PYRAMID_KING: + return MUS_VS_FRONT; + default: + return MUS_BATTLE20; + } + } + return MUS_BATTLE27; +} + +void PlayBattleBGM(void) +{ + ResetMapMusic(); + m4aMPlayAllStop(); + PlayBGM(GetBattleBGM()); +} + +void PlayMapChosenOrBattleBGM(u16 songId) +{ + ResetMapMusic(); + m4aMPlayAllStop(); + if (songId) + PlayNewMapMusic(songId); + else + PlayNewMapMusic(GetBattleBGM()); +} + +void sub_806E694(u16 songId) +{ + u8 taskId; + + ResetMapMusic(); + m4aMPlayAllStop(); + + taskId = CreateTask(sub_806E6CC, 0); + gTasks[taskId].data[0] = songId; +} + +static void sub_806E6CC(u8 taskId) +{ + if (gTasks[taskId].data[0]) + PlayNewMapMusic(gTasks[taskId].data[0]); + else + PlayNewMapMusic(GetBattleBGM()); + DestroyTask(taskId); +} + +const u8 *GetMonFrontSpritePal(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); + u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); + return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality); +} + +// Extracts the upper 16 bits of a 32-bit number +#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) + +// Extracts the lower 16 bits of a 32-bit number +#define LOHALF(n) ((n) & 0xFFFF) + +const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality) +{ + u32 shinyValue; + + if (species > SPECIES_EGG) + return gMonPaletteTable[0].data; + + shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + if (shinyValue < 8) + return gMonShinyPaletteTable[species].data; + else + return gMonPaletteTable[species].data; +} + +const struct CompressedSpritePalette *GetMonSpritePalStruct(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); + u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); + return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality); +} + +const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality) +{ + u32 shinyValue; + + shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + if (shinyValue < 8) + return &gMonShinyPaletteTable[species]; + else + return &gMonPaletteTable[species]; +} + +bool32 IsHMMove2(u16 move) +{ + int i = 0; + while (sHMMoves[i] != 0xFFFF) + { + if (sHMMoves[i++] == move) + return TRUE; + } + return FALSE; +} + +bool8 IsMonSpriteNotFlipped(u16 species) +{ + return gBaseStats[species].noFlip; +} + +s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor) +{ + u8 nature = GetNature(mon); + return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor]; +} + +s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor) +{ + u8 nature = GetNatureFromPersonality(personality); + return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor]; +} + +bool8 IsTradedMon(struct Pokemon *mon) +{ + u8 otName[OT_NAME_LENGTH + 1]; + u32 otId; + GetMonData(mon, MON_DATA_OT_NAME, otName); + otId = GetMonData(mon, MON_DATA_OT_ID, 0); + return IsOtherTrainer(otId, otName); +} + +bool8 IsOtherTrainer(u32 otId, u8 *otName) +{ + if (otId == + (gSaveBlock2Ptr->playerTrainerId[0] + | (gSaveBlock2Ptr->playerTrainerId[1] << 8) + | (gSaveBlock2Ptr->playerTrainerId[2] << 16) + | (gSaveBlock2Ptr->playerTrainerId[3] << 24))) + { + int i; + + for (i = 0; otName[i] != EOS; i++) + if (otName[i] != gSaveBlock2Ptr->playerName[i]) + return TRUE; + return FALSE; + } + + return TRUE; +} + +void MonRestorePP(struct Pokemon *mon) +{ + BoxMonRestorePP(&mon->box); +} + +void BoxMonRestorePP(struct BoxPokemon *boxMon) +{ + int i; + + for (i = 0; i < 4; i++) + { + if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0)) + { + u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0); + u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0); + u8 pp = CalculatePPWithBonus(move, bonus, i); + SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp); + } + } +} + +void sub_806E994(void) +{ + gLastUsedAbility = gBattleStruct->field_B0; + + gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN; + gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX; + gBattleTextBuff1[2] = gBattleStruct->field_49; + gBattleTextBuff1[4] = B_BUFF_EOS; + + if (!GetBattlerSide(gBattleStruct->field_49)) + gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]); + else + gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49]; + + PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, pokemon_order_func(gBattlerPartyIndexes[gBattlerInMenuId])) + + BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4); +} + +static s32 GetWildMonTableIdInAlteringCave(u16 species) +{ + s32 i; + for (i = 0; i < (s32) ARRAY_COUNT(sAlteringCaveWildMonHeldItems); i++) + if (sAlteringCaveWildMonHeldItems[i].species == species) + return i; + return 0; +} + +void SetWildMonHeldItem(void) +{ + if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE))) + { + u16 rnd = Random() % 100; + u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0); + u16 var1 = 45; + u16 var2 = 95; + if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0) + && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES) + { + var1 = 20; + var2 = 80; + } + if (gMapHeader.mapDataId == 0x1A4) + { + s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species); + if (alteringCaveId != 0) + { + if (rnd < var2) + return; + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &sAlteringCaveWildMonHeldItems[alteringCaveId].item); + } + else + { + if (rnd < var1) + return; + if (rnd < var2) + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); + else + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); + } + } + else + { + if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0) + { + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); + } + else + { + if (rnd < var1) + return; + if (rnd < var2) + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); + else + SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); + } + } + } +} + +bool8 IsMonShiny(struct Pokemon *mon) +{ + u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); + return IsShinyOtIdPersonality(otId, personality); +} + +bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) +{ + bool8 retVal = FALSE; + u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); + if (shinyValue < 8) + retVal = TRUE; + return retVal; +} + +const u8 *GetTrainerPartnerName(void) +{ + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + { + if (gPartnerTrainerId == STEVEN_PARTNER_ID) + { + return gTrainers[TRAINER_STEVEN].trainerName; + } + else + { + GetFrontierTrainerName(gStringVar1, gPartnerTrainerId); + return gStringVar1; + } + } + else + { + u8 id = GetMultiplayerId(); + return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name; + } +} + +#define READ_PTR_FROM_TASK(taskId, dataId) \ + (void*)( \ + ((u16)(gTasks[taskId].data[dataId]) | \ + ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10))) + +#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \ +{ \ + gTasks[taskId].data[dataId] = (u32)(ptr); \ + gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \ +} + +static void Task_AnimateAfterDelay(u8 taskId) +{ + if (--gTasks[taskId].data[3] == 0) + { + LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); + DestroyTask(taskId); + } +} + +static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId) +{ + if (--gTasks[taskId].data[3] == 0) + { + StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); + sub_81C488C(0xFF); + DestroyTask(taskId); + } +} + +void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) +{ + if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) + DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80); + else + DoMonFrontSpriteAnimation(sprite, species, noCry, arg3); +} + +void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) +{ + s8 pan; + switch (arg3 & 0x7F) + { + case 0: + pan = -25; + break; + case 1: + pan = 25; + break; + default: + pan = 0; + break; + } + if (arg3 & 0x80) + { + if (!noCry) + PlayCry1(species, pan); + sprite->callback = SpriteCallbackDummy; + } + else + { + if (!noCry) + { + PlayCry1(species, pan); + if (HasTwoFramesAnimation(species)) + StartSpriteAnim(sprite, 1); + } + if (sMonAnimationDelayTable[species - 1] != 0) + { + u8 taskId = CreateTask(Task_AnimateAfterDelay, 0); + STORE_PTR_IN_TASK(sprite, taskId, 0); + gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1]; + gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1]; + } + else + { + LaunchAnimationTaskForFrontSprite(sprite, sMonFrontAnimIdsTable[species - 1]); + } + sprite->callback = SpriteCallbackDummy_2; + } +} + +void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame) +{ + if (!oneFrame && HasTwoFramesAnimation(species)) + StartSpriteAnim(sprite, 1); + if (sMonAnimationDelayTable[species - 1] != 0) + { + u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0); + STORE_PTR_IN_TASK(sprite, taskId, 0); + gTasks[taskId].data[2] = sMonFrontAnimIdsTable[species - 1]; + gTasks[taskId].data[3] = sMonAnimationDelayTable[species - 1]; + sub_81C488C(taskId); + SetSpriteCB_MonAnimDummy(sprite); + } + else + { + StartMonSummaryAnimation(sprite, sMonFrontAnimIdsTable[species - 1]); + } +} + +void sub_806EE98(void) +{ + u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay); + if (delayTaskId != 0xFF) + DestroyTask(delayTaskId); +} + +void BattleAnimateBackSprite(struct Sprite* sprite, u16 species) +{ + if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) + { + sprite->callback = SpriteCallbackDummy; + } + else + { + LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species)); + sprite->callback = SpriteCallbackDummy_2; + } +} + +u8 sub_806EF08(u8 arg0) +{ + s32 i; + s32 var = 0; + u8 multiplayerId = GetMultiplayerId(); + switch (gLinkPlayers[multiplayerId].lp_field_18) + { + case 0: + case 2: + var = (arg0 != 0) ? 1 : 3; + break; + case 1: + case 3: + var = (arg0 != 0) ? 2 : 0; + break; + } + for (i = 0; i < 4; i++) + { + if (gLinkPlayers[i].lp_field_18 == (s16)(var)) + break; + } + return i; +} + +u8 sub_806EF84(u8 arg0, u8 arg1) +{ + s32 i; + s32 var = 0; + switch (gLinkPlayers[arg1].lp_field_18) + { + case 0: + case 2: + var = (arg0 != 0) ? 1 : 3; + break; + case 1: + case 3: + var = (arg0 != 0) ? 2 : 0; + break; + } + for (i = 0; i < 4; i++) + { + if (gLinkPlayers[i].lp_field_18 == (s16)(var)) + break; + } + return i; +} + +u16 FacilityClassToPicIndex(u16 facilityClass) +{ + return gFacilityClassToPicIndex[facilityClass]; +} + +u16 PlayerGenderToFrontTrainerPicId(u8 playerGender) +{ + if (playerGender != MALE) + return FacilityClassToPicIndex(FACILITY_CLASS_PKMN_TRAINER_BRENDAN); + else + return FacilityClassToPicIndex(FACILITY_CLASS_PKMN_TRAINER_MAY); +} + +void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality) +{ + u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT; + if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set + { + GetSetPokedexFlag(nationalNum, caseId); + if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN) + gSaveBlock2Ptr->pokedex.unownPersonality = personality; + if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA) + gSaveBlock2Ptr->pokedex.spindaPersonality = personality; + } +} + +const u8 *GetTrainerClassNameFromId(u16 trainerId) +{ + if (trainerId > NO_OF_TRAINERS) + trainerId = 0; + return gTrainerClassNames[gTrainers[trainerId].trainerClass]; +} + +const u8 *GetTrainerNameFromId(u16 trainerId) +{ + if (trainerId > NO_OF_TRAINERS) + trainerId = 0; + return gTrainers[trainerId].trainerName; +} + +bool8 HasTwoFramesAnimation(u16 species) +{ + return (species != SPECIES_CASTFORM + && species != SPECIES_DEOXYS + && species != SPECIES_SPINDA + && species != SPECIES_UNOWN); +} + +bool8 sub_806F104(void) +{ + if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) + return TRUE; + if (!gMain.inBattle && (InBattlePike() || InBattlePyramid())) + return TRUE; + return FALSE; +} + +#define FORCE_SIGNED(x)(-(x * (-1))) + +static void sub_806F160(struct Unknown_806F160_Struct* structPtr) +{ + u16 i, j; + for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++) + { + structPtr->templates[i] = gUnknown_08329D98[i]; + for (j = 0; j < structPtr->field_1; j++) + { + asm(""); + structPtr->frameImages[i * structPtr->field_1 + j].data = &structPtr->byteArrays[i][j * 0x800]; + } + structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_1]; + } +} + +static void sub_806F1FC(struct Unknown_806F160_Struct* structPtr) +{ + u16 i, j; + for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++) + { + structPtr->templates[i] = gUnknown_08329F28; + for (j = 0; j < structPtr->field_1; j++) + { + structPtr->frameImages[i * structPtr->field_0_0 + j].data = &structPtr->byteArrays[i][j * 0x800]; + } + structPtr->templates[i].images = &structPtr->frameImages[i * structPtr->field_0_0]; + structPtr->templates[i].anims = gUnknown_082FF70C; + structPtr->templates[i].paletteTag = i; + } +} + +struct Unknown_806F160_Struct *sub_806F2AC(u8 id, u8 arg1) +{ + u8 i; + u8 flags; + struct Unknown_806F160_Struct *structPtr; + + flags = 0; + id %= 2; + structPtr = AllocZeroed(sizeof(*structPtr)); + if (structPtr == NULL) + return NULL; + + switch (arg1) + { + case 2: + structPtr->field_0_0 = 7; + structPtr->field_0_1 = 7; + structPtr->field_1 = 4; + structPtr->field_3_0 = 1; + structPtr->field_3_1 = 2; + break; + case 0: + default: + structPtr->field_0_0 = 4; + structPtr->field_0_1 = 4; + structPtr->field_1 = 4; + structPtr->field_3_0 = 1; + structPtr->field_3_1 = 0; + break; + } + + structPtr->bytes = AllocZeroed(structPtr->field_3_0 * 0x800 * 4 * structPtr->field_0_0); + structPtr->byteArrays = AllocZeroed(structPtr->field_0_0 * 32); + if (structPtr->bytes == NULL || structPtr->byteArrays == NULL) + { + flags |= 1; + } + else + { + for (i = 0; i < FORCE_SIGNED(structPtr->field_0_0); i++) + structPtr->byteArrays[i] = structPtr->bytes + (structPtr->field_3_0 * (i << 0xD)); + } + + structPtr->templates = AllocZeroed(sizeof(struct SpriteTemplate) * structPtr->field_0_0); + structPtr->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * structPtr->field_0_0 * structPtr->field_1); + if (structPtr->templates == NULL || structPtr->frameImages == NULL) + { + flags |= 2; + } + else + { + for (i = 0; i < structPtr->field_1 * structPtr->field_0_0; i++) + structPtr->frameImages[i].size = 0x800; + + switch (structPtr->field_3_1) + { + case 2: + sub_806F1FC(structPtr); + break; + case 0: + case 1: + default: + sub_806F160(structPtr); + break; + } + } + + if (flags & 2) + { + if (structPtr->frameImages != NULL) + FREE_AND_SET_NULL(structPtr->frameImages); + if (structPtr->templates != NULL) + FREE_AND_SET_NULL(structPtr->templates); + } + if (flags & 1) + { + if (structPtr->byteArrays != NULL) + FREE_AND_SET_NULL(structPtr->byteArrays); + if (structPtr->bytes != NULL) + FREE_AND_SET_NULL(structPtr->bytes); + } + + if (flags) + { + memset(structPtr, 0, sizeof(*structPtr)); + Free(structPtr); + } + else + { + structPtr->magic = 0xA3; + gUnknown_020249B4[id] = structPtr; + } + + return gUnknown_020249B4[id]; +} + +void sub_806F47C(u8 id) +{ + struct Unknown_806F160_Struct *structPtr; + + id %= 2; + structPtr = gUnknown_020249B4[id]; + if (structPtr == NULL) + return; + + if (structPtr->magic != 0xA3) + { + memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct)); + } + else + { + + if (structPtr->frameImages != NULL) + FREE_AND_SET_NULL(structPtr->frameImages); + if (structPtr->templates != NULL) + FREE_AND_SET_NULL(structPtr->templates); + if (structPtr->byteArrays != NULL) + FREE_AND_SET_NULL(structPtr->byteArrays); + if (structPtr->bytes != NULL) + FREE_AND_SET_NULL(structPtr->bytes); + + memset(structPtr, 0, sizeof(struct Unknown_806F160_Struct)); + Free(structPtr); + } +} + +u8 *sub_806F4F8(u8 id, u8 arg1) +{ + struct Unknown_806F160_Struct *structPtr = gUnknown_020249B4[id % 2]; + if (structPtr->magic != 0xA3) + { + return NULL; + } + else + { + if (arg1 >= FORCE_SIGNED(structPtr->field_0_0)) + arg1 = 0; + + return structPtr->byteArrays[arg1]; + } +} diff --git a/src/pokemon_1.c b/src/pokemon_1.c deleted file mode 100644 index cafd86c07..000000000 --- a/src/pokemon_1.c +++ /dev/null @@ -1,457 +0,0 @@ -#include "global.h" -#include "pokemon.h" -#include "random.h" -#include "main.h" -#include "constants/species.h" -#include "constants/abilities.h" -#include "constants/items.h" -#include "constants/trainers.h" -#include "constants/moves.h" -#include "string_util.h" -#include "text.h" - -//Extracts the upper 16 bits of a 32-bit number -#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) - -//Extracts the lower 16 bits of a 32-bit number -#define LOHALF(n) ((n) & 0xFFFF) - -extern u8 sav1_map_get_name(void); - -// EWRAM vars -EWRAM_DATA u8 sLearningMoveTableID = 0; -EWRAM_DATA u8 gPlayerPartyCount = 0; -EWRAM_DATA u8 gEnemyPartyCount = 0; -EWRAM_DATA struct Pokemon gPlayerParty[PARTY_SIZE] = {0}; -EWRAM_DATA struct Pokemon gEnemyParty[PARTY_SIZE] = {0}; - -// const rom data -const u16 gSpeciesToHoennPokedexNum[] = {203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 156, 157, 112, 113, 227, 228, 229, 230, 231, 232, 233, 234, 153, 154, 138, 139, 63, 64, 88, 89, 90, 235, 236, 237, 238, 239, 240, 241, 242, 158, 159, 243, 244, 245, 246, 247, 248, 249, 39, 40, 41, 73, 74, 75, 250, 251, 252, 66, 67, 57, 58, 59, 253, 254, 255, 256, 82, 83, 257, 92, 93, 258, 259, 106, 107, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 84, 85, 270, 271, 272, 273, 274, 275, 276, 108, 109, 169, 170, 277, 278, 279, 184, 185, 50, 51, 143, 144, 280, 281, 282, 283, 284, 167, 285, 52, 53, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 65, 181, 182, 155, 324, 137, 325, 326, 162, 163, 327, 328, 329, 91, 55, 56, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 161, 164, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 168, 357, 358, 359, 103, 104, 360, 361, 180, 362, 363, 364, 365, 115, 366, 367, 186, 165, 166, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 42, 43, 44, 25, 26, 34, 35, 114, 27, 28, 32, 33, 99, 100, 61, 62, 145, 131, 132, 60, 105, 68, 127, 128, 183, 129, 130, 140, 141, 97, 98, 116, 117, 118, 48, 49, 78, 79, 101, 102, 173, 174, 175, 119, 120, 171, 172, 125, 126, 54, 110, 111, 80, 81, 69, 76, 77, 121, 122, 160, 148, 149, 94, 36, 37, 38, 95, 96, 150, 45, 46, 47, 176, 177, 178, 152, 146, 147, 124, 123, 179, 70, 71, 72, 142, 86, 87, 133, 134, 135, 136, 29, 30, 31, 187, 188, 189, 190, 191, 192, 193, 194, 195, 198, 199, 200, 196, 197, 201, 202, 151}; -const u16 gSpeciesToNationalPokedexNum[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 290, 291, 292, 276, 277, 285, 286, 327, 278, 279, 283, 284, 320, 321, 300, 301, 352, 343, 344, 299, 324, 302, 339, 340, 370, 341, 342, 349, 350, 318, 319, 328, 329, 330, 296, 297, 309, 310, 322, 323, 363, 364, 365, 331, 332, 361, 362, 337, 338, 298, 325, 326, 311, 312, 303, 307, 308, 333, 334, 360, 355, 356, 315, 287, 288, 289, 316, 317, 357, 293, 294, 295, 366, 367, 368, 359, 353, 354, 336, 335, 369, 304, 305, 306, 351, 313, 314, 345, 346, 347, 348, 280, 281, 282, 371, 372, 373, 374, 375, 376, 377, 378, 379, 382, 383, 384, 380, 381, 385, 386, 358}; -const u16 gHoennToNationalOrder[] = {252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 63, 64, 65, 290, 291, 292, 293, 294, 295, 296, 297, 118, 119, 129, 130, 298, 183, 184, 74, 75, 76, 299, 300, 301, 41, 42, 169, 72, 73, 302, 303, 304, 305, 306, 66, 67, 68, 307, 308, 309, 310, 311, 312, 81, 82, 100, 101, 313, 314, 43, 44, 45, 182, 84, 85, 315, 316, 317, 318, 319, 320, 321, 322, 323, 218, 219, 324, 88, 89, 109, 110, 325, 326, 27, 28, 327, 227, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 174, 39, 40, 349, 350, 351, 120, 121, 352, 353, 354, 355, 356, 357, 358, 359, 37, 38, 172, 25, 26, 54, 55, 360, 202, 177, 178, 203, 231, 232, 127, 214, 111, 112, 361, 362, 363, 364, 365, 366, 367, 368, 369, 222, 170, 171, 370, 116, 117, 230, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 34, 35, 36, 46, 47, 48, 49, 50, 51, 52, 53, 56, 57, 58, 59, 60, 61, 62, 69, 70, 71, 77, 78, 79, 80, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 102, 103, 104, 105, 106, 107, 108, 113, 114, 115, 122, 123, 124, 125, 126, 128, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 173, 175, 176, 179, 180, 181, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 220, 221, 223, 224, 225, 226, 228, 229, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411}; - -const struct SpindaSpot gSpindaSpotGraphics[] = -{ - {16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")}, - {40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")}, - {22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")}, - {34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")} -}; - -#include "data/pokemon/item_effects.h" - -const s8 gNatureStatTable[][5] = -{ - // Atk Def Spd Sp.Atk Sp.Def - { 0, 0, 0, 0, 0}, // Hardy - { +1, -1, 0, 0, 0}, // Lonely - { +1, 0, -1, 0, 0}, // Brave - { +1, 0, 0, -1, 0}, // Adamant - { +1, 0, 0, 0, -1}, // Naughty - { -1, +1, 0, 0, 0}, // Bold - { 0, 0, 0, 0, 0}, // Docile - { 0, +1, -1, 0, 0}, // Relaxed - { 0, +1, 0, -1, 0}, // Impish - { 0, +1, 0, 0, -1}, // Lax - { -1, 0, +1, 0, 0}, // Timid - { 0, -1, +1, 0, 0}, // Hasty - { 0, 0, 0, 0, 0}, // Serious - { 0, 0, +1, -1, 0}, // Jolly - { 0, 0, +1, 0, -1}, // Naive - { -1, 0, 0, +1, 0}, // Modest - { 0, -1, 0, +1, 0}, // Mild - { 0, 0, -1, +1, 0}, // Quiet - { 0, 0, 0, 0, 0}, // Bashful - { 0, 0, 0, +1, -1}, // Rash - { -1, 0, 0, 0, +1}, // Calm - { 0, -1, 0, 0, +1}, // Gentle - { 0, 0, -1, 0, +1}, // Sassy - { 0, 0, 0, -1, +1}, // Careful - { 0, 0, 0, 0, 0}, // Quirky -}; - -#include "data/pokemon/tmhm_learnsets.h" -#include "data/pokemon/trainer_class_lookups.h" -#include "data/pokemon/cry_ids.h" -#include "data/pokemon/experience_tables.h" -#include "data/pokemon/base_stats.h" -#include "data/pokemon/level_up_learnsets.h" -#include "data/pokemon/evolution.h" -#include "data/pokemon/level_up_learnset_pointers.h" - -// code -void ZeroBoxMonData(struct BoxPokemon *boxMon) -{ - u8 *raw = (u8 *)boxMon; - u32 i; - for (i = 0; i < sizeof(struct BoxPokemon); i++) - raw[i] = 0; -} - -void ZeroMonData(struct Pokemon *mon) -{ - u32 arg; - ZeroBoxMonData(&mon->box); - arg = 0; - SetMonData(mon, MON_DATA_STATUS, &arg); - SetMonData(mon, MON_DATA_LEVEL, &arg); - SetMonData(mon, MON_DATA_HP, &arg); - SetMonData(mon, MON_DATA_MAX_HP, &arg); - SetMonData(mon, MON_DATA_ATK, &arg); - SetMonData(mon, MON_DATA_DEF, &arg); - SetMonData(mon, MON_DATA_SPEED, &arg); - SetMonData(mon, MON_DATA_SPATK, &arg); - SetMonData(mon, MON_DATA_SPDEF, &arg); - arg = 255; - SetMonData(mon, MON_DATA_MAIL, &arg); -} - -void ZeroPlayerPartyMons(void) -{ - s32 i; - for (i = 0; i < PARTY_SIZE; i++) - ZeroMonData(&gPlayerParty[i]); -} - -void ZeroEnemyPartyMons(void) -{ - s32 i; - for (i = 0; i < PARTY_SIZE; i++) - ZeroMonData(&gEnemyParty[i]); -} - -void CreateMon(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) -{ - u32 arg; - ZeroMonData(mon); - CreateBoxMon(&mon->box, species, level, fixedIV, hasFixedPersonality, fixedPersonality, otIdType, fixedOtId); - SetMonData(mon, MON_DATA_LEVEL, &level); - arg = 255; - SetMonData(mon, MON_DATA_MAIL, &arg); - CalculateMonStats(mon); -} - -void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 hasFixedPersonality, u32 fixedPersonality, u8 otIdType, u32 fixedOtId) -{ - u8 speciesName[POKEMON_NAME_LENGTH + 1]; - u32 personality; - u32 value; - u16 checksum; - - ZeroBoxMonData(boxMon); - - if (hasFixedPersonality) - personality = fixedPersonality; - else - personality = Random32(); - - SetBoxMonData(boxMon, MON_DATA_PERSONALITY, &personality); - - //Determine original trainer ID - if (otIdType == OT_ID_RANDOM_NO_SHINY) //Pokemon cannot be shiny - { - u32 shinyValue; - do - { - value = Random32(); - shinyValue = HIHALF(value) ^ LOHALF(value) ^ HIHALF(personality) ^ LOHALF(personality); - } while (shinyValue < 8); - } - else if (otIdType == OT_ID_PRESET) //Pokemon has a preset OT ID - { - value = fixedOtId; - } - else //Player is the OT - { - value = gSaveBlock2Ptr->playerTrainerId[0] - | (gSaveBlock2Ptr->playerTrainerId[1] << 8) - | (gSaveBlock2Ptr->playerTrainerId[2] << 16) - | (gSaveBlock2Ptr->playerTrainerId[3] << 24); - } - - SetBoxMonData(boxMon, MON_DATA_OT_ID, &value); - - checksum = CalculateBoxMonChecksum(boxMon); - SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum); - EncryptBoxMon(boxMon); - GetSpeciesName(speciesName, species); - SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName); - SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage); - SetBoxMonData(boxMon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); - SetBoxMonData(boxMon, MON_DATA_SPECIES, &species); - SetBoxMonData(boxMon, MON_DATA_EXP, &gExperienceTables[gBaseStats[species].growthRate][level]); - SetBoxMonData(boxMon, MON_DATA_FRIENDSHIP, &gBaseStats[species].friendship); - value = sav1_map_get_name(); - SetBoxMonData(boxMon, MON_DATA_MET_LOCATION, &value); - SetBoxMonData(boxMon, MON_DATA_MET_LEVEL, &level); - SetBoxMonData(boxMon, MON_DATA_MET_GAME, &gGameVersion); - value = ITEM_POKE_BALL; - SetBoxMonData(boxMon, MON_DATA_POKEBALL, &value); - SetBoxMonData(boxMon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); - - if (fixedIV < 32) - { - SetBoxMonData(boxMon, MON_DATA_HP_IV, &fixedIV); - SetBoxMonData(boxMon, MON_DATA_ATK_IV, &fixedIV); - SetBoxMonData(boxMon, MON_DATA_DEF_IV, &fixedIV); - SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &fixedIV); - SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &fixedIV); - SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &fixedIV); - } - else - { - u32 iv; - value = Random(); - - iv = value & 0x1F; - SetBoxMonData(boxMon, MON_DATA_HP_IV, &iv); - iv = (value & 0x3E0) >> 5; - SetBoxMonData(boxMon, MON_DATA_ATK_IV, &iv); - iv = (value & 0x7C00) >> 10; - SetBoxMonData(boxMon, MON_DATA_DEF_IV, &iv); - - value = Random(); - - iv = value & 0x1F; - SetBoxMonData(boxMon, MON_DATA_SPEED_IV, &iv); - iv = (value & 0x3E0) >> 5; - SetBoxMonData(boxMon, MON_DATA_SPATK_IV, &iv); - iv = (value & 0x7C00) >> 10; - SetBoxMonData(boxMon, MON_DATA_SPDEF_IV, &iv); - } - - if (gBaseStats[species].ability2) - { - value = personality & 1; - SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value); - } - - GiveBoxMonInitialMoveset(boxMon); -} - -void CreateMonWithNature(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 nature) -{ - u32 personality; - - do - { - personality = Random32(); - } - while (nature != GetNatureFromPersonality(personality)); - - CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); -} - -void CreateMonWithGenderNatureLetter(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 gender, u8 nature, u8 unownLetter) -{ - u32 personality; - - if ((u8)(unownLetter - 1) < 28) - { - u16 actualLetter; - - do - { - personality = Random32(); - actualLetter = ((((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 28); - } - while (nature != GetNatureFromPersonality(personality) - || gender != GetGenderFromSpeciesAndPersonality(species, personality) - || actualLetter != unownLetter - 1); - } - else - { - do - { - personality = Random32(); - } - while (nature != GetNatureFromPersonality(personality) - || gender != GetGenderFromSpeciesAndPersonality(species, personality)); - } - - CreateMon(mon, species, level, fixedIV, 1, personality, OT_ID_PLAYER_ID, 0); -} - -// This is only used to create Wally's Ralts. -void CreateMaleMon(struct Pokemon *mon, u16 species, u8 level) -{ - u32 personality; - u32 otId; - - do - { - otId = Random32(); - personality = Random32(); - } - while (GetGenderFromSpeciesAndPersonality(species, personality) != MON_MALE); - CreateMon(mon, species, level, 32, 1, personality, OT_ID_PRESET, otId); -} - -void CreateMonWithIVsPersonality(struct Pokemon *mon, u16 species, u8 level, u32 ivs, u32 personality) -{ - CreateMon(mon, species, level, 0, 1, personality, OT_ID_PLAYER_ID, 0); - SetMonData(mon, MON_DATA_IVS, &ivs); - CalculateMonStats(mon); -} - -void CreateMonWithIVsOTID(struct Pokemon *mon, u16 species, u8 level, u8 *ivs, u32 otId) -{ - CreateMon(mon, species, level, 0, 0, 0, OT_ID_PRESET, otId); - SetMonData(mon, MON_DATA_HP_IV, &ivs[0]); - SetMonData(mon, MON_DATA_ATK_IV, &ivs[1]); - SetMonData(mon, MON_DATA_DEF_IV, &ivs[2]); - SetMonData(mon, MON_DATA_SPEED_IV, &ivs[3]); - SetMonData(mon, MON_DATA_SPATK_IV, &ivs[4]); - SetMonData(mon, MON_DATA_SPDEF_IV, &ivs[5]); - CalculateMonStats(mon); -} - -void CreateMonWithEVSpread(struct Pokemon *mon, u16 species, u8 level, u8 fixedIV, u8 evSpread) -{ - s32 i; - s32 statCount = 0; - u16 evAmount; - u8 temp; - - CreateMon(mon, species, level, fixedIV, 0, 0, 0, 0); - - temp = evSpread; - - for (i = 0; i < 6; i++) - { - if (temp & 1) - statCount++; - temp >>= 1; - } - - evAmount = 510 / statCount; - - temp = 1; - - for (i = 0; i < 6; i++) - { - if (evSpread & temp) - SetMonData(mon, MON_DATA_HP_EV + i, &evAmount); - temp <<= 1; - } - - CalculateMonStats(mon); -} - -void sub_806819C(struct Pokemon *mon, struct UnknownPokemonStruct *src) -{ - s32 i; - u8 nickname[30]; - u8 language; - u8 value; - - CreateMon(mon, src->species, src->level, 0, 1, src->personality, 1, src->otId); - - for (i = 0; i < 4; i++) - SetMonMoveSlot(mon, src->moves[i], i); - - SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses); - SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem); - SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship); - - StringCopy(nickname, src->nickname); - - if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN) - { - language = LANGUAGE_JAPANESE; - StripExtCtrlCodes(nickname); - } - else - { - language = GAME_LANGUAGE; - } - - SetMonData(mon, MON_DATA_LANGUAGE, &language); - SetMonData(mon, MON_DATA_NICKNAME, nickname); - SetMonData(mon, MON_DATA_HP_EV, &src->hpEV); - SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV); - SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV); - SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV); - SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV); - SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV); - value = src->altAbility; - SetMonData(mon, MON_DATA_ALT_ABILITY, &value); - value = src->hpIV; - SetMonData(mon, MON_DATA_HP_IV, &value); - value = src->attackIV; - SetMonData(mon, MON_DATA_ATK_IV, &value); - value = src->defenseIV; - SetMonData(mon, MON_DATA_DEF_IV, &value); - value = src->speedIV; - SetMonData(mon, MON_DATA_SPEED_IV, &value); - value = src->spAttackIV; - SetMonData(mon, MON_DATA_SPATK_IV, &value); - value = src->spDefenseIV; - SetMonData(mon, MON_DATA_SPDEF_IV, &value); - MonRestorePP(mon); - CalculateMonStats(mon); -} - -u8 BattleFrontierGetOpponentLvl(u8); - -void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lvl50) -{ - s32 i; - u8 nickname[30]; - u8 level; - u8 language; - u8 value; - - if (gSaveBlock2Ptr->frontierChosenLvl != 0) - level = BattleFrontierGetOpponentLvl(gSaveBlock2Ptr->frontierChosenLvl); - else if (lvl50) - level = 50; - else - level = src->level; - - CreateMon(mon, src->species, level, 0, 1, src->personality, 1, src->otId); - - for (i = 0; i < 4; i++) - SetMonMoveSlot(mon, src->moves[i], i); - - SetMonData(mon, MON_DATA_PP_BONUSES, &src->ppBonuses); - SetMonData(mon, MON_DATA_HELD_ITEM, &src->heldItem); - SetMonData(mon, MON_DATA_FRIENDSHIP, &src->friendship); - - StringCopy(nickname, src->nickname); - - if (nickname[0] == EXT_CTRL_CODE_BEGIN && nickname[1] == EXT_CTRL_CODE_JPN) - { - language = LANGUAGE_JAPANESE; - StripExtCtrlCodes(nickname); - } - else - { - language = GAME_LANGUAGE; - } - - SetMonData(mon, MON_DATA_LANGUAGE, &language); - SetMonData(mon, MON_DATA_NICKNAME, nickname); - SetMonData(mon, MON_DATA_HP_EV, &src->hpEV); - SetMonData(mon, MON_DATA_ATK_EV, &src->attackEV); - SetMonData(mon, MON_DATA_DEF_EV, &src->defenseEV); - SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV); - SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV); - SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV); - value = src->altAbility; - SetMonData(mon, MON_DATA_ALT_ABILITY, &value); - value = src->hpIV; - SetMonData(mon, MON_DATA_HP_IV, &value); - value = src->attackIV; - SetMonData(mon, MON_DATA_ATK_IV, &value); - value = src->defenseIV; - SetMonData(mon, MON_DATA_DEF_IV, &value); - value = src->speedIV; - SetMonData(mon, MON_DATA_SPEED_IV, &value); - value = src->spAttackIV; - SetMonData(mon, MON_DATA_SPATK_IV, &value); - value = src->spDefenseIV; - SetMonData(mon, MON_DATA_SPDEF_IV, &value); - MonRestorePP(mon); - CalculateMonStats(mon); -} diff --git a/src/pokemon_2.c b/src/pokemon_2.c deleted file mode 100644 index 3f37381c3..000000000 --- a/src/pokemon_2.c +++ /dev/null @@ -1,1365 +0,0 @@ -#include "global.h" -#include "pokemon.h" -#include "battle.h" -#include "event_data.h" -#include "random.h" -#include "sprite.h" -#include "constants/species.h" -#include "text.h" -#include "string_util.h" - -struct Unknown_020249B4 -{ - u8 unk0[0xC]; - struct SpriteTemplate* templates; -}; - -extern u8 gAbsentBattlerFlags; -extern u8 gActiveBattler; -extern u8 gBattlerAttacker; -extern u8 gBattlerTarget; -extern u8 gLastUsedAbility; -extern u16 gTrainerBattleOpponent_A; -extern u32 gBattleTypeFlags; -extern struct SpriteTemplate gUnknown_0202499C; -extern struct Unknown_020249B4* gUnknown_020249B4[2]; - -extern const u32 gBitTable[]; -extern const struct SpriteTemplate gUnknown_08329D98[]; -extern const struct SpriteTemplate gUnknown_08329DF8[]; -extern const union AnimCmd* gUnknown_082FF70C[]; -extern const union AnimCmd* const * const gMonAnimationsSpriteAnimsPtrTable[]; -extern const union AnimCmd* const * const gUnknown_08305D0C[]; -extern const union AnimCmd* const * const gUnknown_0830536C[]; -extern const u8 gText_BadEgg[]; -extern const u8 gText_EggNickname[]; - -extern u8 GetBattlerSide(u8 bank); -extern u8 GetBattlerAtPosition(u8 bank); -extern u8 GetBattlerPosition(u8 bank); - -u8 CountAliveMonsInBattle(u8 caseId) -{ - s32 i; - u8 retVal = 0; - - switch (caseId) - { - case BATTLE_ALIVE_EXCEPT_ACTIVE: - for (i = 0; i < 4; i++) - { - if (i != gActiveBattler && !(gAbsentBattlerFlags & gBitTable[i])) - retVal++; - } - break; - case BATTLE_ALIVE_ATK_SIDE: - for (i = 0; i < 4; i++) - { - if (GetBattlerSide(i) == GetBattlerSide(gBattlerAttacker) && !(gAbsentBattlerFlags & gBitTable[i])) - retVal++; - } - break; - case BATTLE_ALIVE_DEF_SIDE: - for (i = 0; i < 4; i++) - { - if (GetBattlerSide(i) == GetBattlerSide(gBattlerTarget) && !(gAbsentBattlerFlags & gBitTable[i])) - retVal++; - } - break; - } - - return retVal; -} - -bool8 ShouldGetStatBadgeBoost(u16 badgeFlag, u8 bank) -{ - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_x2000000 | BATTLE_TYPE_FRONTIER)) - return FALSE; - if (GetBattlerSide(bank) != B_SIDE_PLAYER) - return FALSE; - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gTrainerBattleOpponent_A == SECRET_BASE_OPPONENT) - return FALSE; - if (FlagGet(badgeFlag)) - return TRUE; - return FALSE; -} - -u8 GetDefaultMoveTarget(u8 bank) -{ - u8 status = GetBattlerPosition(bank) & 1; - - status ^= 1; - if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) - return GetBattlerAtPosition(status); - if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1) - { - u8 val; - - if ((Random() & 1) == 0) - val = status ^ 2; - else - val = status; - return GetBattlerAtPosition(val); - } - else - { - if ((gAbsentBattlerFlags & gBitTable[status])) - return GetBattlerAtPosition(status ^ 2); - else - return GetBattlerAtPosition(status); - } -} - -u8 GetMonGender(struct Pokemon *mon) -{ - return GetBoxMonGender(&mon->box); -} - -u8 GetBoxMonGender(struct BoxPokemon *boxMon) -{ - u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); - u32 personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY, NULL); - - switch (gBaseStats[species].genderRatio) - { - case MON_MALE: - case MON_FEMALE: - case MON_GENDERLESS: - return gBaseStats[species].genderRatio; - } - - if (gBaseStats[species].genderRatio > (personality & 0xFF)) - return MON_FEMALE; - else - return MON_MALE; -} - -u8 GetGenderFromSpeciesAndPersonality(u16 species, u32 personality) -{ - switch (gBaseStats[species].genderRatio) - { - case MON_MALE: - case MON_FEMALE: - case MON_GENDERLESS: - return gBaseStats[species].genderRatio; - } - - if (gBaseStats[species].genderRatio > (personality & 0xFF)) - return MON_FEMALE; - else - return MON_MALE; -} - -void sub_806A068(u16 species, u8 bankIdentity) -{ - if (gMonSpritesGfxPtr != NULL) - gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity]; - else if (gUnknown_020249B4[0]) - gUnknown_0202499C = gUnknown_020249B4[0]->templates[bankIdentity]; - else if (gUnknown_020249B4[1]) - gUnknown_0202499C = gUnknown_020249B4[1]->templates[bankIdentity]; - else - gUnknown_0202499C = gUnknown_08329D98[bankIdentity]; - - gUnknown_0202499C.paletteTag = species; - if (bankIdentity == 0 || bankIdentity == 2) - gUnknown_0202499C.anims = gUnknown_082FF70C; - else if (species > 500) - gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species - 500]; - else - gUnknown_0202499C.anims = gMonAnimationsSpriteAnimsPtrTable[species]; -} - -void sub_806A12C(u16 trainerSpriteId, u8 bankIdentity) -{ - gUnknown_0202499C.paletteTag = trainerSpriteId; - if (bankIdentity == 0 || bankIdentity == 2) - { - gUnknown_0202499C = gUnknown_08329DF8[trainerSpriteId]; - gUnknown_0202499C.anims = gUnknown_08305D0C[trainerSpriteId]; - } - else - { - if (gMonSpritesGfxPtr != NULL) - gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity]; - else - gUnknown_0202499C = gUnknown_08329D98[bankIdentity]; - gUnknown_0202499C.anims = gUnknown_0830536C[trainerSpriteId]; - } -} - -void sub_806A1C0(u16 arg0, u8 bankIdentity) -{ - if (gMonSpritesGfxPtr != NULL) - gUnknown_0202499C = gMonSpritesGfxPtr->templates[bankIdentity]; - else - gUnknown_0202499C = gUnknown_08329D98[bankIdentity]; - - gUnknown_0202499C.paletteTag = arg0; - gUnknown_0202499C.anims = gUnknown_0830536C[arg0]; -} - -void EncryptBoxMon(struct BoxPokemon *boxMon) -{ - u32 i; - for (i = 0; i < 12; i++) - { - boxMon->secure.raw[i] ^= boxMon->personality; - boxMon->secure.raw[i] ^= boxMon->otId; - } -} - -void DecryptBoxMon(struct BoxPokemon *boxMon) -{ - u32 i; - for (i = 0; i < 12; i++) - { - boxMon->secure.raw[i] ^= boxMon->otId; - boxMon->secure.raw[i] ^= boxMon->personality; - } -} - -#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \ -case n: \ - { \ - union PokemonSubstruct *substructs0 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs1 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs2 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs3 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs4 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs5 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs6 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs7 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs8 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs9 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs10 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs11 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs12 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs13 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs14 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs15 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs16 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs17 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs18 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs19 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs20 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs21 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs22 = boxMon->secure.substructs; \ - union PokemonSubstruct *substructs23 = boxMon->secure.substructs; \ - \ - switch (substructType) \ - { \ - case 0: \ - substruct = &substructs ## n [v1]; \ - break; \ - case 1: \ - substruct = &substructs ## n [v2]; \ - break; \ - case 2: \ - substruct = &substructs ## n [v3]; \ - break; \ - case 3: \ - substruct = &substructs ## n [v4]; \ - break; \ - } \ - break; \ - } \ - - -union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 personality, u8 substructType) -{ - union PokemonSubstruct *substruct = NULL; - - switch (personality % 24) - { - SUBSTRUCT_CASE( 0,0,1,2,3) - SUBSTRUCT_CASE( 1,0,1,3,2) - SUBSTRUCT_CASE( 2,0,2,1,3) - SUBSTRUCT_CASE( 3,0,3,1,2) - SUBSTRUCT_CASE( 4,0,2,3,1) - SUBSTRUCT_CASE( 5,0,3,2,1) - SUBSTRUCT_CASE( 6,1,0,2,3) - SUBSTRUCT_CASE( 7,1,0,3,2) - SUBSTRUCT_CASE( 8,2,0,1,3) - SUBSTRUCT_CASE( 9,3,0,1,2) - SUBSTRUCT_CASE(10,2,0,3,1) - SUBSTRUCT_CASE(11,3,0,2,1) - SUBSTRUCT_CASE(12,1,2,0,3) - SUBSTRUCT_CASE(13,1,3,0,2) - SUBSTRUCT_CASE(14,2,1,0,3) - SUBSTRUCT_CASE(15,3,1,0,2) - SUBSTRUCT_CASE(16,2,3,0,1) - SUBSTRUCT_CASE(17,3,2,0,1) - SUBSTRUCT_CASE(18,1,2,3,0) - SUBSTRUCT_CASE(19,1,3,2,0) - SUBSTRUCT_CASE(20,2,1,3,0) - SUBSTRUCT_CASE(21,3,1,2,0) - SUBSTRUCT_CASE(22,2,3,1,0) - SUBSTRUCT_CASE(23,3,2,1,0) - } - - return substruct; -} - -extern u16 GetDeoxysStat(struct Pokemon *mon, s32 statId); - -u32 GetMonData(struct Pokemon *mon, s32 field, u8* data) -{ - u32 ret; - - switch (field) - { - case MON_DATA_STATUS: - ret = mon->status; - break; - case MON_DATA_LEVEL: - ret = mon->level; - break; - case MON_DATA_HP: - ret = mon->hp; - break; - case MON_DATA_MAX_HP: - ret = mon->maxHP; - break; - case MON_DATA_ATK: - ret = GetDeoxysStat(mon, STAT_ATK); - if (!ret) - ret = mon->attack; - break; - case MON_DATA_DEF: - ret = GetDeoxysStat(mon, STAT_DEF); - if (!ret) - ret = mon->defense; - break; - case MON_DATA_SPEED: - ret = GetDeoxysStat(mon, STAT_SPEED); - if (!ret) - ret = mon->speed; - break; - case MON_DATA_SPATK: - ret = GetDeoxysStat(mon, STAT_SPATK); - if (!ret) - ret = mon->spAttack; - break; - case MON_DATA_SPDEF: - ret = GetDeoxysStat(mon, STAT_SPDEF); - if (!ret) - ret = mon->spDefense; - break; - case MON_DATA_ATK2: - ret = mon->attack; - break; - case MON_DATA_DEF2: - ret = mon->defense; - break; - case MON_DATA_SPEED2: - ret = mon->speed; - break; - case MON_DATA_SPATK2: - ret = mon->spAttack; - break; - case MON_DATA_SPDEF2: - ret = mon->spDefense; - break; - case MON_DATA_MAIL: - ret = mon->mail; - break; - default: - ret = GetBoxMonData(&mon->box, field, data); - break; - } - return ret; -} - -u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) -{ - s32 i; - u32 retVal = 0; - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - - if (field > MON_DATA_10) - { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - - DecryptBoxMon(boxMon); - - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) - { - boxMon->isBadEgg = 1; - boxMon->isEgg = 1; - substruct3->isEgg = 1; - } - } - - switch (field) - { - case MON_DATA_PERSONALITY: - retVal = boxMon->personality; - break; - case MON_DATA_OT_ID: - retVal = boxMon->otId; - break; - case MON_DATA_NICKNAME: - { - if (boxMon->isBadEgg) - { - for (retVal = 0; - retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; - data[retVal] = gText_BadEgg[retVal], retVal++) {} - - data[retVal] = EOS; - } - else if (boxMon->isEgg) - { - StringCopy(data, gText_EggNickname); - retVal = StringLength(data); - } - else if (boxMon->language == LANGUAGE_JAPANESE) - { - data[0] = EXT_CTRL_CODE_BEGIN; - data[1] = EXT_CTRL_CODE_JPN; - - for (retVal = 2, i = 0; - i < 5 && boxMon->nickname[i] != EOS; - data[retVal] = boxMon->nickname[i], retVal++, i++) {} - - data[retVal++] = EXT_CTRL_CODE_BEGIN; - data[retVal++] = EXT_CTRL_CODE_ENG; - data[retVal] = EOS; - } - else - { - for (retVal = 0; - retVal < POKEMON_NAME_LENGTH; - data[retVal] = boxMon->nickname[retVal], retVal++){} - - data[retVal] = EOS; - } - break; - } - case MON_DATA_LANGUAGE: - retVal = boxMon->language; - break; - case MON_DATA_SANITY_BIT1: - retVal = boxMon->isBadEgg; - break; - case MON_DATA_SANITY_BIT2: - retVal = boxMon->hasSpecies; - break; - case MON_DATA_SANITY_BIT3: - retVal = boxMon->isEgg; - break; - case MON_DATA_OT_NAME: - { - retVal = 0; - - while (retVal < OT_NAME_LENGTH) - { - data[retVal] = boxMon->otName[retVal]; - retVal++; - } - - data[retVal] = EOS; - break; - } - case MON_DATA_MARKINGS: - retVal = boxMon->markings; - break; - case MON_DATA_CHECKSUM: - retVal = boxMon->checksum; - break; - case MON_DATA_10: - retVal = boxMon->unknown; - break; - case MON_DATA_SPECIES: - retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species; - break; - case MON_DATA_HELD_ITEM: - retVal = substruct0->heldItem; - break; - case MON_DATA_EXP: - retVal = substruct0->experience; - break; - case MON_DATA_PP_BONUSES: - retVal = substruct0->ppBonuses; - break; - case MON_DATA_FRIENDSHIP: - retVal = substruct0->friendship; - break; - case MON_DATA_MOVE1: - case MON_DATA_MOVE2: - case MON_DATA_MOVE3: - case MON_DATA_MOVE4: - retVal = substruct1->moves[field - MON_DATA_MOVE1]; - break; - case MON_DATA_PP1: - case MON_DATA_PP2: - case MON_DATA_PP3: - case MON_DATA_PP4: - retVal = substruct1->pp[field - MON_DATA_PP1]; - break; - case MON_DATA_HP_EV: - retVal = substruct2->hpEV; - break; - case MON_DATA_ATK_EV: - retVal = substruct2->attackEV; - break; - case MON_DATA_DEF_EV: - retVal = substruct2->defenseEV; - break; - case MON_DATA_SPEED_EV: - retVal = substruct2->speedEV; - break; - case MON_DATA_SPATK_EV: - retVal = substruct2->spAttackEV; - break; - case MON_DATA_SPDEF_EV: - retVal = substruct2->spDefenseEV; - break; - case MON_DATA_COOL: - retVal = substruct2->cool; - break; - case MON_DATA_BEAUTY: - retVal = substruct2->beauty; - break; - case MON_DATA_CUTE: - retVal = substruct2->cute; - break; - case MON_DATA_SMART: - retVal = substruct2->smart; - break; - case MON_DATA_TOUGH: - retVal = substruct2->tough; - break; - case MON_DATA_SHEEN: - retVal = substruct2->sheen; - break; - case MON_DATA_POKERUS: - retVal = substruct3->pokerus; - break; - case MON_DATA_MET_LOCATION: - retVal = substruct3->metLocation; - break; - case MON_DATA_MET_LEVEL: - retVal = substruct3->metLevel; - break; - case MON_DATA_MET_GAME: - retVal = substruct3->metGame; - break; - case MON_DATA_POKEBALL: - retVal = substruct3->pokeball; - break; - case MON_DATA_OT_GENDER: - retVal = substruct3->otGender; - break; - case MON_DATA_HP_IV: - retVal = substruct3->hpIV; - break; - case MON_DATA_ATK_IV: - retVal = substruct3->attackIV; - break; - case MON_DATA_DEF_IV: - retVal = substruct3->defenseIV; - break; - case MON_DATA_SPEED_IV: - retVal = substruct3->speedIV; - break; - case MON_DATA_SPATK_IV: - retVal = substruct3->spAttackIV; - break; - case MON_DATA_SPDEF_IV: - retVal = substruct3->spDefenseIV; - break; - case MON_DATA_IS_EGG: - retVal = substruct3->isEgg; - break; - case MON_DATA_ALT_ABILITY: - retVal = substruct3->altAbility; - break; - case MON_DATA_COOL_RIBBON: - retVal = substruct3->coolRibbon; - break; - case MON_DATA_BEAUTY_RIBBON: - retVal = substruct3->beautyRibbon; - break; - case MON_DATA_CUTE_RIBBON: - retVal = substruct3->cuteRibbon; - break; - case MON_DATA_SMART_RIBBON: - retVal = substruct3->smartRibbon; - break; - case MON_DATA_TOUGH_RIBBON: - retVal = substruct3->toughRibbon; - break; - case MON_DATA_CHAMPION_RIBBON: - retVal = substruct3->championRibbon; - break; - case MON_DATA_WINNING_RIBBON: - retVal = substruct3->winningRibbon; - break; - case MON_DATA_VICTORY_RIBBON: - retVal = substruct3->victoryRibbon; - break; - case MON_DATA_ARTIST_RIBBON: - retVal = substruct3->artistRibbon; - break; - case MON_DATA_EFFORT_RIBBON: - retVal = substruct3->effortRibbon; - break; - case MON_DATA_GIFT_RIBBON_1: - retVal = substruct3->giftRibbon1; - break; - case MON_DATA_GIFT_RIBBON_2: - retVal = substruct3->giftRibbon2; - break; - case MON_DATA_GIFT_RIBBON_3: - retVal = substruct3->giftRibbon3; - break; - case MON_DATA_GIFT_RIBBON_4: - retVal = substruct3->giftRibbon4; - break; - case MON_DATA_GIFT_RIBBON_5: - retVal = substruct3->giftRibbon5; - break; - case MON_DATA_GIFT_RIBBON_6: - retVal = substruct3->giftRibbon6; - break; - case MON_DATA_GIFT_RIBBON_7: - retVal = substruct3->giftRibbon7; - break; - case MON_DATA_FATEFUL_ENCOUNTER: - retVal = substruct3->fatefulEncounter; - break; - case MON_DATA_OBEDIENCE: - retVal = substruct3->obedient; - break; - case MON_DATA_SPECIES2: - retVal = substruct0->species; - if (substruct0->species && (substruct3->isEgg || boxMon->isBadEgg)) - retVal = SPECIES_EGG; - break; - case MON_DATA_IVS: - retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25); - break; - case MON_DATA_KNOWN_MOVES: - if (substruct0->species && !substruct3->isEgg) - { - u16 *moves = (u16 *)data; - s32 i = 0; - - while (moves[i] != 355) - { - u16 move = moves[i]; - if (substruct1->moves[0] == move - || substruct1->moves[1] == move - || substruct1->moves[2] == move - || substruct1->moves[3] == move) - retVal |= gBitTable[i]; - i++; - } - } - break; - case MON_DATA_RIBBON_COUNT: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) - { - retVal += substruct3->coolRibbon; - retVal += substruct3->beautyRibbon; - retVal += substruct3->cuteRibbon; - retVal += substruct3->smartRibbon; - retVal += substruct3->toughRibbon; - retVal += substruct3->championRibbon; - retVal += substruct3->winningRibbon; - retVal += substruct3->victoryRibbon; - retVal += substruct3->artistRibbon; - retVal += substruct3->effortRibbon; - retVal += substruct3->giftRibbon1; - retVal += substruct3->giftRibbon2; - retVal += substruct3->giftRibbon3; - retVal += substruct3->giftRibbon4; - retVal += substruct3->giftRibbon5; - retVal += substruct3->giftRibbon6; - retVal += substruct3->giftRibbon7; - } - break; - case MON_DATA_RIBBONS: - retVal = 0; - if (substruct0->species && !substruct3->isEgg) - { - retVal = substruct3->championRibbon - | (substruct3->coolRibbon << 1) - | (substruct3->beautyRibbon << 4) - | (substruct3->cuteRibbon << 7) - | (substruct3->smartRibbon << 10) - | (substruct3->toughRibbon << 13) - | (substruct3->winningRibbon << 16) - | (substruct3->victoryRibbon << 17) - | (substruct3->artistRibbon << 18) - | (substruct3->effortRibbon << 19) - | (substruct3->giftRibbon1 << 20) - | (substruct3->giftRibbon2 << 21) - | (substruct3->giftRibbon3 << 22) - | (substruct3->giftRibbon4 << 23) - | (substruct3->giftRibbon5 << 24) - | (substruct3->giftRibbon6 << 25) - | (substruct3->giftRibbon7 << 26); - } - break; - default: - break; - } - - if (field > MON_DATA_10) - EncryptBoxMon(boxMon); - - return retVal; -} - -#define SET8(lhs) (lhs) = *data -#define SET16(lhs) (lhs) = data[0] + (data[1] << 8) -#define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) - -void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg) -{ - const u8* data = dataArg; - switch (field) - { - case MON_DATA_STATUS: - SET32(mon->status); - break; - case MON_DATA_LEVEL: - SET8(mon->level); - break; - case MON_DATA_HP: - SET16(mon->hp); - break; - case MON_DATA_MAX_HP: - SET16(mon->maxHP); - break; - case MON_DATA_ATK: - SET16(mon->attack); - break; - case MON_DATA_DEF: - SET16(mon->defense); - break; - case MON_DATA_SPEED: - SET16(mon->speed); - break; - case MON_DATA_SPATK: - SET16(mon->spAttack); - break; - case MON_DATA_SPDEF: - SET16(mon->spDefense); - break; - case MON_DATA_MAIL: - SET8(mon->mail); - break; - case MON_DATA_SPECIES2: - break; - default: - SetBoxMonData(&mon->box, field, data); - break; - } -} - -void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) -{ - const u8* data = dataArg; - - struct PokemonSubstruct0 *substruct0 = NULL; - struct PokemonSubstruct1 *substruct1 = NULL; - struct PokemonSubstruct2 *substruct2 = NULL; - struct PokemonSubstruct3 *substruct3 = NULL; - - if (field > MON_DATA_10) - { - substruct0 = &(GetSubstruct(boxMon, boxMon->personality, 0)->type0); - substruct1 = &(GetSubstruct(boxMon, boxMon->personality, 1)->type1); - substruct2 = &(GetSubstruct(boxMon, boxMon->personality, 2)->type2); - substruct3 = &(GetSubstruct(boxMon, boxMon->personality, 3)->type3); - - DecryptBoxMon(boxMon); - - if (CalculateBoxMonChecksum(boxMon) != boxMon->checksum) - { - boxMon->isBadEgg = 1; - boxMon->isEgg = 1; - substruct3->isEgg = 1; - EncryptBoxMon(boxMon); - return; - } - } - - switch (field) - { - case MON_DATA_PERSONALITY: - SET32(boxMon->personality); - break; - case MON_DATA_OT_ID: - SET32(boxMon->otId); - break; - case MON_DATA_NICKNAME: - { - s32 i; - for (i = 0; i < POKEMON_NAME_LENGTH; i++) - boxMon->nickname[i] = data[i]; - break; - } - case MON_DATA_LANGUAGE: - SET8(boxMon->language); - break; - case MON_DATA_SANITY_BIT1: - SET8(boxMon->isBadEgg); - break; - case MON_DATA_SANITY_BIT2: - SET8(boxMon->hasSpecies); - break; - case MON_DATA_SANITY_BIT3: - SET8(boxMon->isEgg); - break; - case MON_DATA_OT_NAME: - { - s32 i; - for (i = 0; i < OT_NAME_LENGTH; i++) - boxMon->otName[i] = data[i]; - break; - } - case MON_DATA_MARKINGS: - SET8(boxMon->markings); - break; - case MON_DATA_CHECKSUM: - SET16(boxMon->checksum); - break; - case MON_DATA_10: - SET16(boxMon->unknown); - break; - case MON_DATA_SPECIES: - { - SET16(substruct0->species); - if (substruct0->species) - boxMon->hasSpecies = 1; - else - boxMon->hasSpecies = 0; - break; - } - case MON_DATA_HELD_ITEM: - SET16(substruct0->heldItem); - break; - case MON_DATA_EXP: - SET32(substruct0->experience); - break; - case MON_DATA_PP_BONUSES: - SET8(substruct0->ppBonuses); - break; - case MON_DATA_FRIENDSHIP: - SET8(substruct0->friendship); - break; - case MON_DATA_MOVE1: - case MON_DATA_MOVE2: - case MON_DATA_MOVE3: - case MON_DATA_MOVE4: - SET16(substruct1->moves[field - MON_DATA_MOVE1]); - break; - case MON_DATA_PP1: - case MON_DATA_PP2: - case MON_DATA_PP3: - case MON_DATA_PP4: - SET8(substruct1->pp[field - MON_DATA_PP1]); - break; - case MON_DATA_HP_EV: - SET8(substruct2->hpEV); - break; - case MON_DATA_ATK_EV: - SET8(substruct2->attackEV); - break; - case MON_DATA_DEF_EV: - SET8(substruct2->defenseEV); - break; - case MON_DATA_SPEED_EV: - SET8(substruct2->speedEV); - break; - case MON_DATA_SPATK_EV: - SET8(substruct2->spAttackEV); - break; - case MON_DATA_SPDEF_EV: - SET8(substruct2->spDefenseEV); - break; - case MON_DATA_COOL: - SET8(substruct2->cool); - break; - case MON_DATA_BEAUTY: - SET8(substruct2->beauty); - break; - case MON_DATA_CUTE: - SET8(substruct2->cute); - break; - case MON_DATA_SMART: - SET8(substruct2->smart); - break; - case MON_DATA_TOUGH: - SET8(substruct2->tough); - break; - case MON_DATA_SHEEN: - SET8(substruct2->sheen); - break; - case MON_DATA_POKERUS: - SET8(substruct3->pokerus); - break; - case MON_DATA_MET_LOCATION: - SET8(substruct3->metLocation); - break; - case MON_DATA_MET_LEVEL: - { - u8 metLevel = *data; - substruct3->metLevel = metLevel; - break; - } - case MON_DATA_MET_GAME: - SET8(substruct3->metGame); - break; - case MON_DATA_POKEBALL: - { - u8 pokeball = *data; - substruct3->pokeball = pokeball; - break; - } - case MON_DATA_OT_GENDER: - SET8(substruct3->otGender); - break; - case MON_DATA_HP_IV: - SET8(substruct3->hpIV); - break; - case MON_DATA_ATK_IV: - SET8(substruct3->attackIV); - break; - case MON_DATA_DEF_IV: - SET8(substruct3->defenseIV); - break; - case MON_DATA_SPEED_IV: - SET8(substruct3->speedIV); - break; - case MON_DATA_SPATK_IV: - SET8(substruct3->spAttackIV); - break; - case MON_DATA_SPDEF_IV: - SET8(substruct3->spDefenseIV); - break; - case MON_DATA_IS_EGG: - SET8(substruct3->isEgg); - if (substruct3->isEgg) - boxMon->isEgg = 1; - else - boxMon->isEgg = 0; - break; - case MON_DATA_ALT_ABILITY: - SET8(substruct3->altAbility); - break; - case MON_DATA_COOL_RIBBON: - SET8(substruct3->coolRibbon); - break; - case MON_DATA_BEAUTY_RIBBON: - SET8(substruct3->beautyRibbon); - break; - case MON_DATA_CUTE_RIBBON: - SET8(substruct3->cuteRibbon); - break; - case MON_DATA_SMART_RIBBON: - SET8(substruct3->smartRibbon); - break; - case MON_DATA_TOUGH_RIBBON: - SET8(substruct3->toughRibbon); - break; - case MON_DATA_CHAMPION_RIBBON: - SET8(substruct3->championRibbon); - break; - case MON_DATA_WINNING_RIBBON: - SET8(substruct3->winningRibbon); - break; - case MON_DATA_VICTORY_RIBBON: - SET8(substruct3->victoryRibbon); - break; - case MON_DATA_ARTIST_RIBBON: - SET8(substruct3->artistRibbon); - break; - case MON_DATA_EFFORT_RIBBON: - SET8(substruct3->effortRibbon); - break; - case MON_DATA_GIFT_RIBBON_1: - SET8(substruct3->giftRibbon1); - break; - case MON_DATA_GIFT_RIBBON_2: - SET8(substruct3->giftRibbon2); - break; - case MON_DATA_GIFT_RIBBON_3: - SET8(substruct3->giftRibbon3); - break; - case MON_DATA_GIFT_RIBBON_4: - SET8(substruct3->giftRibbon4); - break; - case MON_DATA_GIFT_RIBBON_5: - SET8(substruct3->giftRibbon5); - break; - case MON_DATA_GIFT_RIBBON_6: - SET8(substruct3->giftRibbon6); - break; - case MON_DATA_GIFT_RIBBON_7: - SET8(substruct3->giftRibbon7); - break; - case MON_DATA_FATEFUL_ENCOUNTER: - SET8(substruct3->fatefulEncounter); - break; - case MON_DATA_OBEDIENCE: - SET8(substruct3->obedient); - break; - case MON_DATA_IVS: - { - u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - substruct3->hpIV = ivs & 0x1F; - substruct3->attackIV = (ivs >> 5) & 0x1F; - substruct3->defenseIV = (ivs >> 10) & 0x1F; - substruct3->speedIV = (ivs >> 15) & 0x1F; - substruct3->spAttackIV = (ivs >> 20) & 0x1F; - substruct3->spDefenseIV = (ivs >> 25) & 0x1F; - break; - } - default: - break; - } - - if (field > MON_DATA_10) - { - boxMon->checksum = CalculateBoxMonChecksum(boxMon); - EncryptBoxMon(boxMon); - } -} - -void CopyMon(void *dest, void *src, size_t size) -{ - memcpy(dest, src, size); -} - -u8 GiveMonToPlayer(struct Pokemon *mon) -{ - s32 i; - - SetMonData(mon, MON_DATA_OT_NAME, gSaveBlock2Ptr->playerName); - SetMonData(mon, MON_DATA_OT_GENDER, &gSaveBlock2Ptr->playerGender); - SetMonData(mon, MON_DATA_OT_ID, gSaveBlock2Ptr->playerTrainerId); - - i = 0; - - while (i < 6 && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) != SPECIES_NONE) - i++; - - if (i >= 6) - return SendMonToPC(mon); - - CopyMon(&gPlayerParty[i], mon, sizeof(*mon)); - gPlayerPartyCount = i + 1; - return MON_GIVEN_TO_PARTY; -} - -extern u16 get_unknown_box_id(void); -extern u8 StorageGetCurrentBox(void); -extern void set_unknown_box_id(u8); -extern struct BoxPokemon* GetBoxedMonPtr(u8 boxNumber, u8 boxPosition); - -u8 SendMonToPC(struct Pokemon* mon) -{ - s32 boxNo, boxPos; - - set_unknown_box_id(VarGet(VAR_STORAGE_UNKNOWN)); - - boxNo = StorageGetCurrentBox(); - - do - { - for (boxPos = 0; boxPos < 30; boxPos++) - { - struct BoxPokemon* checkingMon = GetBoxedMonPtr(boxNo, boxPos); - if (GetBoxMonData(checkingMon, MON_DATA_SPECIES, NULL) == SPECIES_NONE) - { - MonRestorePP(mon); - CopyMon(checkingMon, &mon->box, sizeof(mon->box)); - gSpecialVar_MonBoxId = boxNo; - gSpecialVar_MonBoxPos = boxPos; - if (get_unknown_box_id() != boxNo) - FlagClear(FLAG_SYS_STORAGE_UNKNOWN_FLAG); - VarSet(VAR_STORAGE_UNKNOWN, boxNo); - return MON_GIVEN_TO_PC; - } - } - - boxNo++; - if (boxNo == 14) - boxNo = 0; - } while (boxNo != StorageGetCurrentBox()); - - return MON_CANT_GIVE; -} - -u8 CalculatePlayerPartyCount(void) -{ - gPlayerPartyCount = 0; - - while (gPlayerPartyCount < 6 - && GetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE) - { - gPlayerPartyCount++; - } - - return gPlayerPartyCount; -} - -u8 CalculateEnemyPartyCount(void) -{ - gEnemyPartyCount = 0; - - while (gEnemyPartyCount < 6 - && GetMonData(&gEnemyParty[gEnemyPartyCount], MON_DATA_SPECIES, NULL) != SPECIES_NONE) - { - gEnemyPartyCount++; - } - - return gEnemyPartyCount; -} - -u8 GetMonsStateToDoubles(void) -{ - s32 aliveCount = 0; - s32 i; - CalculatePlayerPartyCount(); - - if (gPlayerPartyCount == 1) - return gPlayerPartyCount; // PLAYER_HAS_ONE_MON - - for (i = 0; i < gPlayerPartyCount; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG - && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0 - && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_NONE) - aliveCount++; - } - - return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; -} - -u8 GetMonsStateToDoubles_2(void) -{ - s32 aliveCount = 0; - s32 i; - - for (i = 0; i < PARTY_SIZE; i++) - { - u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL); - if (species != SPECIES_EGG && species != SPECIES_NONE - && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0) - aliveCount++; - } - - if (aliveCount == 1) - return PLAYER_HAS_ONE_MON; // may have more than one, but only one is alive - - return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON; -} - -u8 GetAbilityBySpecies(u16 species, bool8 altAbility) -{ - if (altAbility) - gLastUsedAbility = gBaseStats[species].ability2; - else - gLastUsedAbility = gBaseStats[species].ability1; - - return gLastUsedAbility; -} - -u8 GetMonAbility(struct Pokemon *mon) -{ - u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); - u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL); - return GetAbilityBySpecies(species, altAbility); -} - -extern const struct BattleMove gBattleMoves[]; - -void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord) -{ - s32 i, j; - - ZeroEnemyPartyMons(); - *gBattleResources->secretBase = *secretBaseRecord; - - for (i = 0; i < PARTY_SIZE; i++) - { - if (gBattleResources->secretBase->party.species[i]) - { - CreateMon(&gEnemyParty[i], - gBattleResources->secretBase->party.species[i], - gBattleResources->secretBase->party.levels[i], - 15, - 1, - gBattleResources->secretBase->party.personality[i], - 2, - 0); - - SetMonData(&gEnemyParty[i], MON_DATA_HELD_ITEM, &gBattleResources->secretBase->party.heldItems[i]); - - for (j = 0; j < 6; j++) - SetMonData(&gEnemyParty[i], MON_DATA_HP_EV + j, &gBattleResources->secretBase->party.EVs[i]); - - for (j = 0; j < 4; j++) - { - SetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j, &gBattleResources->secretBase->party.moves[i * 4 + j]); - SetMonData(&gEnemyParty[i], MON_DATA_PP1 + j, &gBattleMoves[gBattleResources->secretBase->party.moves[i * 4 + j]].pp); - } - } - } -} - -extern const u8 gFacilityClassToPicIndex[]; -extern const u8 gFacilityClassToTrainerClass[]; -extern const u8 gSecretBaseTrainerClasses[][5]; - -u8 GetSecretBaseTrainerPicIndex(void) -{ - u8 trainerClass = gSecretBaseTrainerClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; - return gFacilityClassToPicIndex[trainerClass]; -} - -u8 GetSecretBaseTrainerNameIndex(void) -{ - u8 trainerClass = gSecretBaseTrainerClasses[gBattleResources->secretBase->gender][gBattleResources->secretBase->trainerId[0] % 5]; - return gFacilityClassToTrainerClass[trainerClass]; -} - -bool8 IsPlayerPartyAndPokemonStorageFull(void) -{ - s32 i; - - for (i = 0; i < 6; i++) - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL) == SPECIES_NONE) - return FALSE; - - return IsPokemonStorageFull(); -} - -extern u32 GetBoxMonDataFromAnyBox(u8 boxNo, u8 boxPos, s32 field); - -bool8 IsPokemonStorageFull(void) -{ - s32 i, j; - - for (i = 0; i < 14; i++) - for (j = 0; j < 30; j++) - if (GetBoxMonDataFromAnyBox(i, j, MON_DATA_SPECIES) == SPECIES_NONE) - return FALSE; - - return TRUE; -} - -extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1]; - -void GetSpeciesName(u8 *name, u16 species) -{ - s32 i; - - for (i = 0; i <= POKEMON_NAME_LENGTH; i++) - { - if (species > NUM_SPECIES) - name[i] = gSpeciesNames[0][i]; - else - name[i] = gSpeciesNames[species][i]; - - if (name[i] == EOS) - break; - } - - name[i] = EOS; -} - -extern const u8 gUnknown_08329D22[]; -extern const u8 gUnknown_08329D26[]; - -u8 CalculatePPWithBonus(u16 move, u8 ppBonuses, u8 moveIndex) -{ - u8 basePP = gBattleMoves[move].pp; - return basePP + ((basePP * 20 * ((gUnknown_08329D22[moveIndex] & ppBonuses) >> (2 * moveIndex))) / 100); -} - -void RemoveMonPPBonus(struct Pokemon *mon, u8 moveIndex) -{ - u8 ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES, NULL); - ppBonuses &= gUnknown_08329D26[moveIndex]; - SetMonData(mon, MON_DATA_PP_BONUSES, &ppBonuses); -} - -void RemoveBattleMonPPBonus(struct BattlePokemon *mon, u8 moveIndex) -{ - mon->ppBonuses &= gUnknown_08329D26[moveIndex]; -} - -void sub_803FA70(u8 bank); -void ClearTemporarySpeciesSpriteData(u8 bank, bool8); - -extern struct BattlePokemon gBattleMons[4]; - -void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex) -{ - u16* hpSwitchout; - s32 i; - u8 nickname[POKEMON_NAME_LENGTH * 2]; - - gBattleMons[bank].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL); - gBattleMons[bank].item = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM, NULL); - - for (i = 0; i < 4; i++) - { - gBattleMons[bank].moves[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1 + i, NULL); - gBattleMons[bank].pp[i] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP1 + i, NULL); - } - - gBattleMons[bank].ppBonuses = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PP_BONUSES, NULL); - gBattleMons[bank].friendship = GetMonData(&gPlayerParty[partyIndex], MON_DATA_FRIENDSHIP, NULL); - gBattleMons[bank].experience = GetMonData(&gPlayerParty[partyIndex], MON_DATA_EXP, NULL); - gBattleMons[bank].hpIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV, NULL); - gBattleMons[bank].attackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK_IV, NULL); - gBattleMons[bank].defenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF_IV, NULL); - gBattleMons[bank].speedIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED_IV, NULL); - gBattleMons[bank].spAttackIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK_IV, NULL); - gBattleMons[bank].spDefenseIV = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF_IV, NULL); - gBattleMons[bank].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY, NULL); - gBattleMons[bank].status1 = GetMonData(&gPlayerParty[partyIndex], MON_DATA_STATUS, NULL); - gBattleMons[bank].level = GetMonData(&gPlayerParty[partyIndex], MON_DATA_LEVEL, NULL); - gBattleMons[bank].hp = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL); - gBattleMons[bank].maxHP = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MAX_HP, NULL); - gBattleMons[bank].attack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ATK, NULL); - gBattleMons[bank].defense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_DEF, NULL); - gBattleMons[bank].speed = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPEED, NULL); - gBattleMons[bank].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL); - gBattleMons[bank].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL); - gBattleMons[bank].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL); - gBattleMons[bank].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL); - gBattleMons[bank].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL); - gBattleMons[bank].type1 = gBaseStats[gBattleMons[bank].species].type1; - gBattleMons[bank].type2 = gBaseStats[gBattleMons[bank].species].type2; - gBattleMons[bank].ability = GetAbilityBySpecies(gBattleMons[bank].species, gBattleMons[bank].altAbility); - GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname); - StringCopy10(gBattleMons[bank].nickname, nickname); - GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[bank].otName); - - hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(bank)]; - *hpSwitchout = gBattleMons[bank].hp; - - for (i = 0; i < 8; i++) - gBattleMons[bank].statStages[i] = 6; - - gBattleMons[bank].status2 = 0; - sub_803FA70(bank); - ClearTemporarySpeciesSpriteData(bank, FALSE); -} diff --git a/src/pokemon_3.c b/src/pokemon_3.c deleted file mode 100644 index 0dd1131de..000000000 --- a/src/pokemon_3.c +++ /dev/null @@ -1,1749 +0,0 @@ -#include "global.h" -#include "pokemon.h" -#include "main.h" -#include "constants/items.h" -#include "string_util.h" -#include "battle_message.h" -#include "rtc.h" -#include "item.h" -#include "battle.h" -#include "constants/species.h" -#include "link.h" -#include "constants/hold_effects.h" -#include "random.h" -#include "constants/trainers.h" -#include "constants/songs.h" -#include "sound.h" -#include "m4a.h" -#include "task.h" -#include "sprite.h" -#include "text.h" -#include "constants/abilities.h" -#include "pokemon_animation.h" -#include "pokedex.h" -#include "pokeblock.h" - -extern struct BattlePokemon gBattleMons[4]; -extern struct BattleEnigmaBerry gEnigmaBerries[4]; -extern u8 gActiveBattler; -extern u8 gBattlerInMenuId; -extern u8 gBattlerTarget; -extern u8 gBattlerAttacker; -extern u8 gPotentialItemEffectBattler; -extern u16 gTrainerBattleOpponent_A; -extern u32 gBattleTypeFlags; -extern u8 gBattleMonForms[4]; -extern u16 gBattlerPartyIndexes[4]; -extern u8 gLastUsedAbility; -extern u16 gPartnerTrainerId; -extern u32 gHitMarker; - -extern const u16 gSpeciesToHoennPokedexNum[]; -extern const u16 gSpeciesToNationalPokedexNum[]; -extern const u16 gHoennToNationalOrder[]; -extern const u16 gSpeciesIdToCryId[]; -extern const struct SpindaSpot gSpindaSpotGraphics[]; -extern const u8* const gStatNamesTable[]; -extern const u8 gSpeciesNames[][11]; -extern const u8 gUnknown_08329EC8[]; -extern const u8 gText_StatRose[]; -extern const u8 gText_PkmnsStatChanged2[]; -extern const u8 gText_PkmnGettingPumped[]; -extern const u8 gText_PkmnShroudedInMist[]; -extern const s8 gNatureStatTable[][5]; -extern const s8 gUnknown_08329ECE[][3]; -extern const u32 gBitTable[]; -extern const u32 gTMHMLearnsets[][2]; -extern const u8 gText_BattleWallyName[]; -extern const u8 gText_PkmnsXPreventsSwitching[]; -extern const struct CompressedSpritePalette gMonPaletteTable[]; -extern const struct CompressedSpritePalette gMonShinyPaletteTable[]; -extern const u16 gHMMoves[]; -extern const u8 gMonAnimationDelayTable[]; -extern const u8 gMonFrontAnimIdsTable[]; - -extern bool8 InBattlePyramid(void); -extern bool8 InBattlePike(void); -extern bool8 sub_81D5C18(void); -extern bool8 sub_806F104(void); -extern bool32 IsNationalPokedexEnabled(void); -extern u8 GetTrainerEncounterMusicIdInBattlePyramind(u16 trainerOpponentId); -extern u8 sub_81D63C8(u16 trainerOpponentId); -extern u8 sav1_map_get_name(void); -extern u8 GetFrontierOpponentClass(u16 trainerId); -extern u8 pokemon_order_func(u8 bankPartyId); -extern void GetFrontierTrainerName(u8* dest, u16 trainerId); -extern void sub_81C488C(u8); - -static void sub_806E6CC(u8 taskId); - -bool8 HealStatusConditions(struct Pokemon *mon, u32 battlePartyId, u32 healMask, u8 battleBank) -{ - u32 status = GetMonData(mon, MON_DATA_STATUS, 0); - - if (status & healMask) - { - status &= ~healMask; - SetMonData(mon, MON_DATA_STATUS, (u8 *)&status); - if (gMain.inBattle && battleBank != 4) - gBattleMons[battleBank].status1 &= ~healMask; - return FALSE; - } - else - { - return TRUE; - } -} - -u8 GetItemEffectParamOffset(u16 itemId, u8 effectByte, u8 effectBit) -{ - const u8 *temp; - const u8 *itemEffect; - u8 offset; - int i; - u8 j; - u8 val; - - offset = 6; - - temp = gItemEffectTable[itemId - 13]; - - if (!temp && itemId != ITEM_ENIGMA_BERRY) - return 0; - - if (itemId == ITEM_ENIGMA_BERRY) - { - temp = gEnigmaBerries[gActiveBattler].itemEffect; - } - - itemEffect = temp; - - for (i = 0; i < 6; i++) - { - switch (i) - { - case 0: - case 1: - case 2: - case 3: - if (i == effectByte) - return 0; - break; - case 4: - val = itemEffect[4]; - if (val & 0x20) - val &= 0xDF; - j = 0; - while (val) - { - if (val & 1) - { - switch (j) - { - case 2: - if (val & 0x10) - val &= 0xEF; - case 0: - if (i == effectByte && (val & effectBit)) - return offset; - offset++; - break; - case 1: - if (i == effectByte && (val & effectBit)) - return offset; - offset++; - break; - case 3: - if (i == effectByte && (val & effectBit)) - return offset; - offset++; - break; - case 7: - if (i == effectByte) - return 0; - break; - } - } - j++; - val >>= 1; - if (i == effectByte) - effectBit >>= 1; - } - break; - case 5: - val = itemEffect[5]; - j = 0; - while (val) - { - if (val & 1) - { - switch (j) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - if (i == effectByte && (val & effectBit)) - return offset; - offset++; - break; - case 7: - if (i == effectByte) - return 0; - break; - } - } - j++; - val >>= 1; - if (i == effectByte) - effectBit >>= 1; - } - break; - } - } - - return offset; -} - -void sub_806CF24(s32 stat) -{ - gBattlerTarget = gBattlerInMenuId; - StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]); - StringCopy(gBattleTextBuff2, gText_StatRose); - BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2); -} - -u8 *sub_806CF78(u16 itemId) -{ - int i; - const u8 *itemEffect; - - if (itemId == ITEM_ENIGMA_BERRY) - { - if (gMain.inBattle) - itemEffect = gEnigmaBerries[gBattlerInMenuId].itemEffect; - else - itemEffect = gSaveBlock1Ptr->enigmaBerry.itemEffect; - } - else - { - itemEffect = gItemEffectTable[itemId - 13]; - } - - gPotentialItemEffectBattler = gBattlerInMenuId; - - for (i = 0; i < 3; i++) - { - if (itemEffect[i] & 0xF) - sub_806CF24(i * 2); - if (itemEffect[i] & 0xF0) - { - if (i) - { - sub_806CF24(i * 2 + 1); - } - else - { - gBattlerAttacker = gBattlerInMenuId; - BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped); - } - } - } - - if (itemEffect[3] & 0x80) - { - gBattlerAttacker = gBattlerInMenuId; - BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist); - } - - return gDisplayedStringBattle; -} - -u8 GetNature(struct Pokemon *mon) -{ - return GetMonData(mon, MON_DATA_PERSONALITY, 0) % 25; -} - -u8 GetNatureFromPersonality(u32 personality) -{ - return personality % 25; -} - -u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 type, u16 evolutionItem) -{ - int i; - u16 targetSpecies = 0; - u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); - u16 heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - u8 level; - u16 friendship; - u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0); - u16 upperPersonality = personality >> 16; - u8 holdEffect; - - if (heldItem == ITEM_ENIGMA_BERRY) - holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; - else - holdEffect = ItemId_GetHoldEffect(heldItem); - - if (holdEffect == 38 && type != 3) - return 0; - - switch (type) - { - case 0: - level = GetMonData(mon, MON_DATA_LEVEL, 0); - friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); - - for (i = 0; i < 5; i++) - { - switch (gEvolutionTable[species][i].method) - { - case EVO_FRIENDSHIP: - if (friendship >= 220) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_FRIENDSHIP_DAY: - RtcCalcLocalTime(); - if (gLocalTime.hours >= 12 && gLocalTime.hours < 24 && friendship >= 220) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_FRIENDSHIP_NIGHT: - RtcCalcLocalTime(); - if (gLocalTime.hours >= 0 && gLocalTime.hours < 12 && friendship >= 220) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL: - if (gEvolutionTable[species][i].param <= level) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_ATK_GT_DEF: - if (gEvolutionTable[species][i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, 0) > GetMonData(mon, MON_DATA_DEF, 0)) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_ATK_EQ_DEF: - if (gEvolutionTable[species][i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, 0) == GetMonData(mon, MON_DATA_DEF, 0)) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_ATK_LT_DEF: - if (gEvolutionTable[species][i].param <= level) - if (GetMonData(mon, MON_DATA_ATK, 0) < GetMonData(mon, MON_DATA_DEF, 0)) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_SILCOON: - if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) <= 4) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_CASCOON: - if (gEvolutionTable[species][i].param <= level && (upperPersonality % 10) > 4) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_LEVEL_NINJASK: - if (gEvolutionTable[species][i].param <= level) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_BEAUTY: - if (gEvolutionTable[species][i].param <= beauty) - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - } - } - break; - case 1: - for (i = 0; i < 5; i++) - { - switch (gEvolutionTable[species][i].method) - { - case EVO_TRADE: - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - case EVO_TRADE_ITEM: - if (gEvolutionTable[species][i].param == heldItem) - { - heldItem = 0; - SetMonData(mon, MON_DATA_HELD_ITEM, (u8 *)&heldItem); - targetSpecies = gEvolutionTable[species][i].targetSpecies; - } - break; - } - } - break; - case 2: - case 3: - for (i = 0; i < 5; i++) - { - if (gEvolutionTable[species][i].method == EVO_ITEM - && gEvolutionTable[species][i].param == evolutionItem) - { - targetSpecies = gEvolutionTable[species][i].targetSpecies; - break; - } - } - break; - } - - return targetSpecies; -} - -u16 HoennPokedexNumToSpecies(u16 hoennNum) -{ - u16 species; - - if (!hoennNum) - return 0; - - species = 0; - - while (species < 411 && gSpeciesToHoennPokedexNum[species] != hoennNum) - species++; - - if (species == 411) - return 0; - - return species + 1; -} - -u16 NationalPokedexNumToSpecies(u16 nationalNum) -{ - u16 species; - - if (!nationalNum) - return 0; - - species = 0; - - while (species < 411 && gSpeciesToNationalPokedexNum[species] != nationalNum) - species++; - - if (species == 411) - return 0; - - return species + 1; -} - -u16 NationalToHoennOrder(u16 nationalNum) -{ - u16 hoennNum; - - if (!nationalNum) - return 0; - - hoennNum = 0; - - while (hoennNum < 411 && gHoennToNationalOrder[hoennNum] != nationalNum) - hoennNum++; - - if (hoennNum == 411) - return 0; - - return hoennNum + 1; -} - -u16 SpeciesToNationalPokedexNum(u16 species) -{ - if (!species) - return 0; - - return gSpeciesToNationalPokedexNum[species - 1]; -} - -u16 SpeciesToHoennPokedexNum(u16 species) -{ - if (!species) - return 0; - - return gSpeciesToHoennPokedexNum[species - 1]; -} - -u16 HoennToNationalOrder(u16 hoennNum) -{ - if (!hoennNum) - return 0; - - return gHoennToNationalOrder[hoennNum - 1]; -} - -u16 SpeciesToCryId(u16 species) -{ - if (species <= 250) - return species; - - if (species < 276) - return 200; - - return gSpeciesIdToCryId[species - 276]; -} - -void sub_806D544(u16 species, u32 personality, u8 *dest) -{ - if (species == SPECIES_SPINDA - && dest != gMonSpritesGfxPtr->sprites[0] - && dest != gMonSpritesGfxPtr->sprites[2]) - { - int i; - for (i = 0; i < 4; i++) - { - int j; - u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); - u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); - - for (j = 0; j < 16; j++) - { - int k; - s32 row = gSpindaSpotGraphics[i].image[j]; - - for (k = x; k < x + 16; k++) - { - u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2); - - if (row & 1) - { - if (k & 1) - { - if ((u8)((*val & 0xF0) - 0x10) <= 0x20) - *val += 0x40; - } - else - { - if ((u8)((*val & 0xF) - 0x01) <= 0x02) - *val += 0x04; - } - } - - row >>= 1; - } - - y++; - } - - personality >>= 8; - } - } -} - -void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, u8 a4) -{ - if (species == SPECIES_SPINDA && a4) - { - int i; - for (i = 0; i < 4; i++) - { - int j; - u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); - u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); - - for (j = 0; j < 16; j++) - { - int k; - s32 row = gSpindaSpotGraphics[i].image[j]; - - for (k = x; k < x + 16; k++) - { - u8 *val = dest + ((k / 8) * 32) + ((k % 8) / 2) + ((y >> 3) << 8) + ((y & 7) << 2); - - if (row & 1) - { - if (k & 1) - { - if ((u8)((*val & 0xF0) - 0x10) <= 0x20) - *val += 0x40; - } - else - { - if ((u8)((*val & 0xF) - 0x01) <= 0x02) - *val += 0x04; - } - } - - row >>= 1; - } - - y++; - } - - personality >>= 8; - } - } -} - -void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies) -{ - u8 language; - GetMonData(mon, MON_DATA_NICKNAME, gStringVar1); - language = GetMonData(mon, MON_DATA_LANGUAGE, &language); - if (language == GAME_LANGUAGE && !StringCompare(gSpeciesNames[oldSpecies], gStringVar1)) - SetMonData(mon, MON_DATA_NICKNAME, gSpeciesNames[newSpecies]); -} - -bool8 sub_806D7EC(void) -{ - bool8 retVal = FALSE; - switch (gLinkPlayers[GetMultiplayerId()].lp_field_18) - { - case 0: - case 3: - retVal = FALSE; - break; - case 1: - case 2: - retVal = TRUE; - break; - } - return retVal; -} - -bool16 sub_806D82C(u8 id) -{ - bool16 retVal = FALSE; - switch (gLinkPlayers[id].lp_field_18) - { - case 0: - case 3: - retVal = FALSE; - break; - case 1: - case 2: - retVal = TRUE; - break; - } - return retVal; -} - -s32 GetBattlerMultiplayerId(u16 a1) -{ - s32 id; - for (id = 0; id < MAX_LINK_PLAYERS; id++) - if (gLinkPlayers[id].lp_field_18 == a1) - break; - return id; -} - -u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) -{ - if (InBattlePyramid()) - return GetTrainerEncounterMusicIdInBattlePyramind(trainerOpponentId); - if (sub_81D5C18()) - return sub_81D63C8(trainerOpponentId); - return TRAINER_ENCOUNTER_MUSIC(trainerOpponentId); -} - -u16 nature_stat_mod(u8 nature, u16 n, u8 statIndex) -{ - if (statIndex < 1 || statIndex > 5) - { - // should just be "return n", but it wouldn't match without this - u16 retVal = n; - retVal++; - retVal--; - return retVal; - } - - switch (gNatureStatTable[nature][statIndex - 1]) - { - case 1: - return (u16)(n * 110) / 100; - case -1: - return (u16)(n * 90) / 100; - } - - return n; -} - -void AdjustFriendship(struct Pokemon *mon, u8 event) -{ - u16 species, heldItem; - u8 holdEffect; - - if (sub_806F104()) - return; - - species = GetMonData(mon, MON_DATA_SPECIES2, 0); - heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); - - if (heldItem == ITEM_ENIGMA_BERRY) - { - if (gMain.inBattle) - holdEffect = gEnigmaBerries[0].holdEffect; - else - holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; - } - else - { - holdEffect = ItemId_GetHoldEffect(heldItem); - } - - if (species && species != SPECIES_EGG) - { - u8 friendshipLevel = 0; - s16 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, 0); - if (friendship > 99) - friendshipLevel++; - if (friendship > 199) - friendshipLevel++; - if ((event != 5 || !(Random() & 1)) - && (event != 3 - || ((gBattleTypeFlags & BATTLE_TYPE_TRAINER) - && (gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_ELITE_FOUR - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_LEADER - || gTrainers[gTrainerBattleOpponent_A].trainerClass == TRAINER_CLASS_CHAMPION)))) - { - s8 mod = gUnknown_08329ECE[event][friendshipLevel]; - if (mod > 0 && holdEffect == HOLD_EFFECT_HAPPINESS_UP) - mod = (150 * mod) / 100; - friendship += mod; - if (mod > 0) - { - if (GetMonData(mon, MON_DATA_POKEBALL, 0) == ITEM_LUXURY_BALL) - friendship++; - if (GetMonData(mon, MON_DATA_MET_LOCATION, 0) == sav1_map_get_name()) - friendship++; - } - if (friendship < 0) - friendship = 0; - if (friendship > 255) - friendship = 255; - SetMonData(mon, MON_DATA_FRIENDSHIP, &friendship); - } - } -} - -void MonGainEVs(struct Pokemon *mon, u16 defeatedSpecies) -{ - u8 evs[NUM_STATS]; - u16 evIncrease = 0; - u16 totalEVs = 0; - u16 heldItem; - u8 holdEffect; - int i; - - for (i = 0; i < NUM_STATS; i++) - { - evs[i] = GetMonData(mon, MON_DATA_HP_EV + i, 0); - totalEVs += evs[i]; - } - - for (i = 0; i < NUM_STATS; i++) - { - u8 hasHadPokerus; - int multiplier; - - if (totalEVs >= MAX_TOTAL_EVS) - break; - - hasHadPokerus = CheckPartyHasHadPokerus(mon, 0); - - if (hasHadPokerus) - multiplier = 2; - else - multiplier = 1; - - switch (i) - { - case 0: - evIncrease = gBaseStats[defeatedSpecies].evYield_HP * multiplier; - break; - case 1: - evIncrease = gBaseStats[defeatedSpecies].evYield_Attack * multiplier; - break; - case 2: - evIncrease = gBaseStats[defeatedSpecies].evYield_Defense * multiplier; - break; - case 3: - evIncrease = gBaseStats[defeatedSpecies].evYield_Speed * multiplier; - break; - case 4: - evIncrease = gBaseStats[defeatedSpecies].evYield_SpAttack * multiplier; - break; - case 5: - evIncrease = gBaseStats[defeatedSpecies].evYield_SpDefense * multiplier; - break; - } - - heldItem = GetMonData(mon, MON_DATA_HELD_ITEM, 0); - - if (heldItem == ITEM_ENIGMA_BERRY) - { - if (gMain.inBattle) - holdEffect = gEnigmaBerries[0].holdEffect; - else - holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect; - } - else - { - holdEffect = ItemId_GetHoldEffect(heldItem); - } - - if (holdEffect == HOLD_EFFECT_MACHO_BRACE) - evIncrease *= 2; - - if (totalEVs + (s16)evIncrease > MAX_TOTAL_EVS) - evIncrease = ((s16)evIncrease + MAX_TOTAL_EVS) - (totalEVs + evIncrease); - - if (evs[i] + (s16)evIncrease > 255) - { - int val1 = (s16)evIncrease + 255; - int val2 = evs[i] + evIncrease; - evIncrease = val1 - val2; - } - - evs[i] += evIncrease; - totalEVs += evIncrease; - SetMonData(mon, MON_DATA_HP_EV + i, &evs[i]); - } -} - -u16 GetMonEVCount(struct Pokemon *mon) -{ - int i; - u16 count = 0; - - for (i = 0; i < NUM_STATS; i++) - count += GetMonData(mon, MON_DATA_HP_EV + i, 0); - - return count; -} - -void RandomlyGivePartyPokerus(struct Pokemon *party) -{ - u16 rnd = Random(); - if (rnd == 0x4000 || rnd == 0x8000 || rnd == 0xC000) - { - struct Pokemon *mon; - - do - { - do - { - rnd = Random() % PARTY_SIZE; - mon = &party[rnd]; - } - while (!GetMonData(mon, MON_DATA_SPECIES, 0)); - } - while (GetMonData(mon, MON_DATA_IS_EGG, 0)); - - if (!(CheckPartyHasHadPokerus(party, gBitTable[rnd]))) - { - u8 rnd2; - - do - { - rnd2 = Random(); - } - while ((rnd2 & 0x7) == 0); - - if (rnd2 & 0xF0) - rnd2 &= 0x7; - - rnd2 |= (rnd2 << 4); - rnd2 &= 0xF3; - rnd2++; - - SetMonData(&party[rnd], MON_DATA_POKERUS, &rnd2); - } - } -} - -u8 CheckPartyPokerus(struct Pokemon *party, u8 selection) -{ - u8 retVal; - - int partyIndex = 0; - unsigned curBit = 1; - retVal = 0; - - if (selection) - { - do - { - if ((selection & 1) && (GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0) & 0xF)) - retVal |= curBit; - partyIndex++; - curBit <<= 1; - selection >>= 1; - } - while (selection); - } - else if (GetMonData(&party[0], MON_DATA_POKERUS, 0) & 0xF) - { - retVal = 1; - } - - return retVal; -} - -u8 CheckPartyHasHadPokerus(struct Pokemon *party, u8 selection) -{ - u8 retVal; - - int partyIndex = 0; - unsigned curBit = 1; - retVal = 0; - - if (selection) - { - do - { - if ((selection & 1) && GetMonData(&party[partyIndex], MON_DATA_POKERUS, 0)) - retVal |= curBit; - partyIndex++; - curBit <<= 1; - selection >>= 1; - } - while (selection); - } - else if (GetMonData(&party[0], MON_DATA_POKERUS, 0)) - { - retVal = 1; - } - - return retVal; -} - -void UpdatePartyPokerusTime(u16 days) -{ - int i; - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, 0)) - { - u8 pokerus = GetMonData(&gPlayerParty[i], MON_DATA_POKERUS, 0); - if (pokerus & 0xF) - { - if ((pokerus & 0xF) < days || days > 4) - pokerus &= 0xF0; - else - pokerus -= days; - - if (pokerus == 0) - pokerus = 0x10; - - SetMonData(&gPlayerParty[i], MON_DATA_POKERUS, &pokerus); - } - } - } -} - -void PartySpreadPokerus(struct Pokemon *party) -{ - if ((Random() % 3) == 0) - { - int i; - for (i = 0; i < PARTY_SIZE; i++) - { - if (GetMonData(&party[i], MON_DATA_SPECIES, 0)) - { - u8 pokerus = GetMonData(&party[i], MON_DATA_POKERUS, 0); - u8 curPokerus = pokerus; - if (pokerus) - { - if (pokerus & 0xF) - { - // spread to adjacent party members - if (i != 0 && !(GetMonData(&party[i - 1], MON_DATA_POKERUS, 0) & 0xF0)) - SetMonData(&party[i - 1], MON_DATA_POKERUS, &curPokerus); - if (i != (PARTY_SIZE - 1) && !(GetMonData(&party[i + 1], MON_DATA_POKERUS, 0) & 0xF0)) - { - SetMonData(&party[i + 1], MON_DATA_POKERUS, &curPokerus); - i++; - } - } - } - } - } - } -} - -bool8 TryIncrementMonLevel(struct Pokemon *mon) -{ - u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); - u8 nextLevel = GetMonData(mon, MON_DATA_LEVEL, 0) + 1; - u32 expPoints = GetMonData(mon, MON_DATA_EXP, 0); - if (expPoints > gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL]) - { - expPoints = gExperienceTables[gBaseStats[species].growthRate][MAX_MON_LEVEL]; - SetMonData(mon, MON_DATA_EXP, &expPoints); - } - if (nextLevel > MAX_MON_LEVEL || expPoints < gExperienceTables[gBaseStats[species].growthRate][nextLevel]) - { - return FALSE; - } - else - { - SetMonData(mon, MON_DATA_LEVEL, &nextLevel); - return TRUE; - } -} - -u32 CanMonLearnTMHM(struct Pokemon *mon, u8 tm) -{ - u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); - if (species == SPECIES_EGG) - { - return 0; - } - else if (tm < 32) - { - u32 mask = 1 << tm; - return gTMHMLearnsets[species][0] & mask; - } - else - { - u32 mask = 1 << (tm - 32); - return gTMHMLearnsets[species][1] & mask; - } -} - -u32 CanSpeciesLearnTMHM(u16 species, u8 tm) -{ - if (species == SPECIES_EGG) - { - return 0; - } - else if (tm < 32) - { - u32 mask = 1 << tm; - return gTMHMLearnsets[species][0] & mask; - } - else - { - u32 mask = 1 << (tm - 32); - return gTMHMLearnsets[species][1] & mask; - } -} - -u8 GetMoveRelearnerMoves(struct Pokemon *mon, u16 *moves) -{ - u16 learnedMoves[4]; - u8 numMoves = 0; - u16 species = GetMonData(mon, MON_DATA_SPECIES, 0); - u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); - int i, j, k; - - for (i = 0; i < 4; i++) - learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); - - for (i = 0; i < 20; i++) - { - u16 moveLevel; - - if (gLevelUpLearnsets[species][i] == 0xFFFF) - break; - - moveLevel = gLevelUpLearnsets[species][i] & 0xFE00; - - if (moveLevel <= (level << 9)) - { - for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++) - ; - - if (j == 4) - { - for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++) - ; - - if (k == numMoves) - moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; - } - } - } - - return numMoves; -} - -u8 GetLevelUpMovesBySpecies(u16 species, u16 *moves) -{ - u8 numMoves = 0; - int i; - - for (i = 0; i < 20 && gLevelUpLearnsets[species][i] != 0xFFFF; i++) - moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; - - return numMoves; -} - -u8 GetNumberOfRelearnableMoves(struct Pokemon *mon) -{ - u16 learnedMoves[4]; - u16 moves[20]; - u8 numMoves = 0; - u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); - u8 level = GetMonData(mon, MON_DATA_LEVEL, 0); - int i, j, k; - - if (species == SPECIES_EGG) - return 0; - - for (i = 0; i < 4; i++) - learnedMoves[i] = GetMonData(mon, MON_DATA_MOVE1 + i, 0); - - for (i = 0; i < 20; i++) - { - u16 moveLevel; - - if (gLevelUpLearnsets[species][i] == 0xFFFF) - break; - - moveLevel = gLevelUpLearnsets[species][i] & 0xFE00; - - if (moveLevel <= (level << 9)) - { - for (j = 0; j < 4 && learnedMoves[j] != (gLevelUpLearnsets[species][i] & 0x1FF); j++) - ; - - if (j == 4) - { - for (k = 0; k < numMoves && moves[k] != (gLevelUpLearnsets[species][i] & 0x1FF); k++) - ; - - if (k == numMoves) - moves[numMoves++] = gLevelUpLearnsets[species][i] & 0x1FF; - } - } - } - - return numMoves; -} - -u16 SpeciesToPokedexNum(u16 species) -{ - if (IsNationalPokedexEnabled()) - { - return SpeciesToNationalPokedexNum(species); - } - else - { - species = SpeciesToHoennPokedexNum(species); - if (species <= 202) - return species; - return 0xFFFF; - } -} - -bool32 sub_806E3F8(u16 species) -{ - if (SpeciesToHoennPokedexNum(species) > 202) - return FALSE; - else - return TRUE; -} - -void ClearBattleMonForms(void) -{ - int i; - for (i = 0; i < 4; i++) - gBattleMonForms[i] = 0; -} - -u16 GetBattleBGM(void) -{ - if (gBattleTypeFlags & BATTLE_TYPE_KYOGRE_GROUDON) - return MUS_BATTLE34; - if (gBattleTypeFlags & BATTLE_TYPE_REGI) - return MUS_BATTLE36; - if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) - return MUS_BATTLE20; - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) - { - u8 trainerClass; - - if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) - trainerClass = GetFrontierOpponentClass(gTrainerBattleOpponent_A); - else if (gBattleTypeFlags & BATTLE_TYPE_x4000000) - trainerClass = TRAINER_CLASS_EXPERT; - else - trainerClass = gTrainers[gTrainerBattleOpponent_A].trainerClass; - - switch (trainerClass) - { - case TRAINER_CLASS_AQUA_LEADER: - case TRAINER_CLASS_MAGMA_LEADER: - return MUS_BATTLE30; - case TRAINER_CLASS_TEAM_AQUA: - case TRAINER_CLASS_TEAM_MAGMA: - case TRAINER_CLASS_AQUA_ADMIN: - case TRAINER_CLASS_MAGMA_ADMIN: - return MUS_BATTLE31; - case TRAINER_CLASS_LEADER: - return MUS_BATTLE32; - case TRAINER_CLASS_CHAMPION: - return MUS_BATTLE33; - case TRAINER_CLASS_PKMN_TRAINER_3: - if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) - return MUS_BATTLE35; - if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName)) - return MUS_BATTLE20; - return MUS_BATTLE35; - case TRAINER_CLASS_ELITE_FOUR: - return MUS_BATTLE38; - case TRAINER_CLASS_SALON_MAIDEN: - case TRAINER_CLASS_DOME_ACE: - case TRAINER_CLASS_PALACE_MAVEN: - case TRAINER_CLASS_ARENA_TYCOON: - case TRAINER_CLASS_FACTORY_HEAD: - case TRAINER_CLASS_PIKE_QUEEN: - case TRAINER_CLASS_PYRAMID_KING: - return MUS_VS_FRONT; - default: - return MUS_BATTLE20; - } - } - return MUS_BATTLE27; -} - -void PlayBattleBGM(void) -{ - ResetMapMusic(); - m4aMPlayAllStop(); - PlayBGM(GetBattleBGM()); -} - -void PlayMapChosenOrBattleBGM(u16 songId) -{ - ResetMapMusic(); - m4aMPlayAllStop(); - if (songId) - PlayNewMapMusic(songId); - else - PlayNewMapMusic(GetBattleBGM()); -} - -void sub_806E694(u16 songId) -{ - u8 taskId; - - ResetMapMusic(); - m4aMPlayAllStop(); - - taskId = CreateTask(sub_806E6CC, 0); - gTasks[taskId].data[0] = songId; -} - -static void sub_806E6CC(u8 taskId) -{ - if (gTasks[taskId].data[0]) - PlayNewMapMusic(gTasks[taskId].data[0]); - else - PlayNewMapMusic(GetBattleBGM()); - DestroyTask(taskId); -} - -const u8 *GetMonFrontSpritePal(struct Pokemon *mon) -{ - u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); - u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality); -} - -// Extracts the upper 16 bits of a 32-bit number -#define HIHALF(n) (((n) & 0xFFFF0000) >> 16) - -// Extracts the lower 16 bits of a 32-bit number -#define LOHALF(n) ((n) & 0xFFFF) - -const u8 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality) -{ - u32 shinyValue; - - if (species > SPECIES_EGG) - return gMonPaletteTable[0].data; - - shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); - if (shinyValue < 8) - return gMonShinyPaletteTable[species].data; - else - return gMonPaletteTable[species].data; -} - -const struct CompressedSpritePalette *sub_806E794(struct Pokemon *mon) -{ - u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0); - u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - return GetMonSpritePalStructFromOtIdPersonality(species, otId, personality); -} - -const struct CompressedSpritePalette *GetMonSpritePalStructFromOtIdPersonality(u16 species, u32 otId , u32 personality) -{ - u32 shinyValue; - - shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); - if (shinyValue < 8) - return &gMonShinyPaletteTable[species]; - else - return &gMonPaletteTable[species]; -} - -bool32 IsHMMove2(u16 move) -{ - int i = 0; - while (gHMMoves[i] != 0xFFFF) - { - if (gHMMoves[i++] == move) - return TRUE; - } - return FALSE; -} - -bool8 IsPokeSpriteNotFlipped(u16 species) -{ - return gBaseStats[species].noFlip; -} - -s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor) -{ - u8 nature = GetNature(mon); - return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor]; -} - -s8 GetFlavorRelationByPersonality(u32 personality, u8 flavor) -{ - u8 nature = GetNatureFromPersonality(personality); - return gPokeblockFlavorCompatibilityTable[nature * 5 + flavor]; -} - -bool8 IsTradedMon(struct Pokemon *mon) -{ - u8 otName[OT_NAME_LENGTH + 1]; - u32 otId; - GetMonData(mon, MON_DATA_OT_NAME, otName); - otId = GetMonData(mon, MON_DATA_OT_ID, 0); - return IsOtherTrainer(otId, otName); -} - -bool8 IsOtherTrainer(u32 otId, u8 *otName) -{ - if (otId == - (gSaveBlock2Ptr->playerTrainerId[0] - | (gSaveBlock2Ptr->playerTrainerId[1] << 8) - | (gSaveBlock2Ptr->playerTrainerId[2] << 16) - | (gSaveBlock2Ptr->playerTrainerId[3] << 24))) - { - int i; - - for (i = 0; otName[i] != EOS; i++) - if (otName[i] != gSaveBlock2Ptr->playerName[i]) - return TRUE; - return FALSE; - } - - return TRUE; -} - -void MonRestorePP(struct Pokemon *mon) -{ - BoxMonRestorePP(&mon->box); -} - -void BoxMonRestorePP(struct BoxPokemon *boxMon) -{ - int i; - - for (i = 0; i < 4; i++) - { - if (GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0)) - { - u16 move = GetBoxMonData(boxMon, MON_DATA_MOVE1 + i, 0); - u16 bonus = GetBoxMonData(boxMon, MON_DATA_PP_BONUSES, 0); - u8 pp = CalculatePPWithBonus(move, bonus, i); - SetBoxMonData(boxMon, MON_DATA_PP1 + i, &pp); - } - } -} - -void sub_806E994(void) -{ - gLastUsedAbility = gBattleStruct->field_B0; - - gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN; - gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX; - gBattleTextBuff1[2] = gBattleStruct->field_49; - gBattleTextBuff1[4] = B_BUFF_EOS; - - if (!GetBattlerSide(gBattleStruct->field_49)) - gBattleTextBuff1[3] = pokemon_order_func(gBattlerPartyIndexes[gBattleStruct->field_49]); - else - gBattleTextBuff1[3] = gBattlerPartyIndexes[gBattleStruct->field_49]; - - PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBattlerInMenuId, pokemon_order_func(gBattlerPartyIndexes[gBattlerInMenuId])) - - BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4); -} - -struct PokeItem -{ - u16 species; - u16 item; -}; - -extern const struct PokeItem gAlteringCaveWildMonHeldItems[9]; - -static s32 GetWildMonTableIdInAlteringCave(u16 species) -{ - s32 i; - for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++) - if (gAlteringCaveWildMonHeldItems[i].species == species) - return i; - return 0; -} - -void SetWildMonHeldItem(void) -{ - if (!(gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_TRAINER | BATTLE_TYPE_PYRAMID | BATTLE_TYPE_PIKE))) - { - u16 rnd = Random() % 100; - u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, 0); - u16 var1 = 45; - u16 var2 = 95; - if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3, 0) - && GetMonAbility(&gPlayerParty[0]) == ABILITY_COMPOUND_EYES) - { - var1 = 20; - var2 = 80; - } - if (gMapHeader.mapDataId == 0x1A4) - { - s32 alteringCaveId = GetWildMonTableIdInAlteringCave(species); - if (alteringCaveId != 0) - { - if (rnd < var2) - return; - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gAlteringCaveWildMonHeldItems[alteringCaveId].item); - } - else - { - if (rnd < var1) - return; - if (rnd < var2) - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); - else - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); - } - } - else - { - if (gBaseStats[species].item1 == gBaseStats[species].item2 && gBaseStats[species].item1 != 0) - { - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); - } - else - { - if (rnd < var1) - return; - if (rnd < var2) - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item1); - else - SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, &gBaseStats[species].item2); - } - } - } -} - -bool8 IsMonShiny(struct Pokemon *mon) -{ - u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - return IsShinyOtIdPersonality(otId, personality); -} - -bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) -{ - bool8 retVal = FALSE; - u32 shinyValue = HIHALF(otId) ^ LOHALF(otId) ^ HIHALF(personality) ^ LOHALF(personality); - if (shinyValue < 8) - retVal = TRUE; - return retVal; -} - -const u8 *GetTrainerPartnerName(void) -{ - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) - { - if (gPartnerTrainerId == STEVEN_PARTNER_ID) - { - return gTrainers[TRAINER_STEVEN].trainerName; - } - else - { - GetFrontierTrainerName(gStringVar1, gPartnerTrainerId); - return gStringVar1; - } - } - else - { - u8 id = GetMultiplayerId(); - return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].lp_field_18 ^ 2)].name; - } -} - -#define READ_PTR_FROM_TASK(taskId, dataId) \ - (void*)( \ - ((u16)(gTasks[taskId].data[dataId]) | \ - ((u16)(gTasks[taskId].data[dataId + 1]) << 0x10))) - -#define STORE_PTR_IN_TASK(ptr, taskId, dataId) \ -{ \ - gTasks[taskId].data[dataId] = (u32)(ptr); \ - gTasks[taskId].data[dataId + 1] = (u32)(ptr) >> 0x10; \ -} - -static void Task_AnimateAfterDelay(u8 taskId) -{ - if (--gTasks[taskId].data[3] == 0) - { - LaunchAnimationTaskForFrontSprite(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); - DestroyTask(taskId); - } -} - -static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId) -{ - if (--gTasks[taskId].data[3] == 0) - { - StartMonSummaryAnimation(READ_PTR_FROM_TASK(taskId, 0), gTasks[taskId].data[2]); - sub_81C488C(0xFF); - DestroyTask(taskId); - } -} - -void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) -{ - if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) - DoMonFrontSpriteAnimation(sprite, species, noCry, arg3 | 0x80); - else - DoMonFrontSpriteAnimation(sprite, species, noCry, arg3); -} - -extern void SpriteCallbackDummy_2(struct Sprite*); - -void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3) -{ - s8 pan; - switch (arg3 & 0x7F) - { - case 0: - pan = -25; - break; - case 1: - pan = 25; - break; - default: - pan = 0; - break; - } - if (arg3 & 0x80) - { - if (!noCry) - PlayCry1(species, pan); - sprite->callback = SpriteCallbackDummy; - } - else - { - if (!noCry) - { - PlayCry1(species, pan); - if (HasTwoFramesAnimation(species)) - StartSpriteAnim(sprite, 1); - } - if (gMonAnimationDelayTable[species - 1] != 0) - { - u8 taskId = CreateTask(Task_AnimateAfterDelay, 0); - STORE_PTR_IN_TASK(sprite, taskId, 0); - gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1]; - gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1]; - } - else - { - LaunchAnimationTaskForFrontSprite(sprite, gMonFrontAnimIdsTable[species - 1]); - } - sprite->callback = SpriteCallbackDummy_2; - } -} - -void PokemonSummaryDoMonAnimation(struct Sprite* sprite, u16 species, bool8 oneFrame) -{ - if (!oneFrame && HasTwoFramesAnimation(species)) - StartSpriteAnim(sprite, 1); - if (gMonAnimationDelayTable[species - 1] != 0) - { - u8 taskId = CreateTask(Task_PokemonSummaryAnimateAfterDelay, 0); - STORE_PTR_IN_TASK(sprite, taskId, 0); - gTasks[taskId].data[2] = gMonFrontAnimIdsTable[species - 1]; - gTasks[taskId].data[3] = gMonAnimationDelayTable[species - 1]; - sub_81C488C(taskId); - SetSpriteCB_MonAnimDummy(sprite); - } - else - { - StartMonSummaryAnimation(sprite, gMonFrontAnimIdsTable[species - 1]); - } -} - -void sub_806EE98(void) -{ - u8 delayTaskId = FindTaskIdByFunc(Task_PokemonSummaryAnimateAfterDelay); - if (delayTaskId != 0xFF) - DestroyTask(delayTaskId); -} - -void BattleAnimateBackSprite(struct Sprite* sprite, u16 species) -{ - if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))) - { - sprite->callback = SpriteCallbackDummy; - } - else - { - LaunchAnimationTaskForBackSprite(sprite, GetSpeciesBackAnimSet(species)); - sprite->callback = SpriteCallbackDummy_2; - } -} - -u8 sub_806EF08(u8 arg0) -{ - s32 i; - s32 var = 0; - u8 multiplayerId = GetMultiplayerId(); - switch (gLinkPlayers[multiplayerId].lp_field_18) - { - case 0: - case 2: - var = (arg0 != 0) ? 1 : 3; - break; - case 1: - case 3: - var = (arg0 != 0) ? 2 : 0; - break; - } - for (i = 0; i < 4; i++) - { - if (gLinkPlayers[i].lp_field_18 == (s16)(var)) - break; - } - return i; -} - -u8 sub_806EF84(u8 arg0, u8 arg1) -{ - s32 i; - s32 var = 0; - switch (gLinkPlayers[arg1].lp_field_18) - { - case 0: - case 2: - var = (arg0 != 0) ? 1 : 3; - break; - case 1: - case 3: - var = (arg0 != 0) ? 2 : 0; - break; - } - for (i = 0; i < 4; i++) - { - if (gLinkPlayers[i].lp_field_18 == (s16)(var)) - break; - } - return i; -} - -extern const u8 gFacilityClassToPicIndex[]; - -u16 sub_806EFF0(u16 arg0) -{ - return gFacilityClassToPicIndex[arg0]; -} - -u16 PlayerGenderToFrontTrainerPicId(u8 playerGender) -{ - if (playerGender) - return sub_806EFF0(0x3F); - else - return sub_806EFF0(0x3C); -} - -extern const u8 gTrainerClassNames[][13]; - -void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality) -{ - u8 getFlagCaseId = (caseId == FLAG_SET_SEEN) ? FLAG_GET_SEEN : FLAG_GET_CAUGHT; - if (!GetSetPokedexFlag(nationalNum, getFlagCaseId)) // don't set if it's already set - { - GetSetPokedexFlag(nationalNum, caseId); - if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_UNOWN) - gSaveBlock2Ptr->pokedex.unownPersonality = personality; - if (NationalPokedexNumToSpecies(nationalNum) == SPECIES_SPINDA) - gSaveBlock2Ptr->pokedex.spindaPersonality = personality; - } -} - -const u8 *GetTrainerClassNameFromId(u16 trainerId) -{ - if (trainerId > NO_OF_TRAINERS) - trainerId = 0; - return gTrainerClassNames[gTrainers[trainerId].trainerClass]; -} - -const u8 *GetTrainerNameFromId(u16 trainerId) -{ - if (trainerId > NO_OF_TRAINERS) - trainerId = 0; - return gTrainers[trainerId].trainerName; -} - -bool8 HasTwoFramesAnimation(u16 species) -{ - return (species != SPECIES_CASTFORM - && species != SPECIES_DEOXYS - && species != SPECIES_SPINDA - && species != SPECIES_UNOWN); -} - -bool8 sub_806F104(void) -{ - if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) - return TRUE; - if (!gMain.inBattle && (InBattlePike() || InBattlePyramid())) - return TRUE; - return FALSE; -} - -/* - -extern const struct SpriteTemplate gUnknown_08329D98[]; - -struct Unknown_806F160_Struct -{ - u8 field_0; - u8 field_1; - u8 field_2; - u8 field_3; - u8 field_4; - u8 field_5; - u8 field_6; - u8 field_7; - u8 field_8; - u8 field_9; - u8 field_A; - u8 field_B; - struct SpriteTemplate* templates; -}; - -void sub_806F160(struct Unknown_806F160_Struct* structPtr) -{ - u16 i, j; - for (i = 0; i < structPtr->field_0; i++) - { - structPtr->templates[i] = gUnknown_08329D98[i]; - for (j = 0; j < structPtr->field_1) - { - // no clue what the pointer in the struct point to :/ - } - } -} */ - diff --git a/src/pokemon_animation.c b/src/pokemon_animation.c index 02755fe40..c50aa4a75 100644 --- a/src/pokemon_animation.c +++ b/src/pokemon_animation.c @@ -1184,7 +1184,7 @@ static void sub_817F9F4(struct Sprite *sprite) } #else -__attribute__((naked)) +NAKED static void sub_817F9F4(struct Sprite *sprite) { asm(".syntax unified\n\ diff --git a/src/pokemon_icon.c b/src/pokemon_icon.c index 4d1cc51c5..253ab2cb4 100644 --- a/src/pokemon_icon.c +++ b/src/pokemon_icon.c @@ -1,9 +1,28 @@ #include "global.h" #include "sprite.h" +#include "mail.h" #include "graphics.h" +#include "constants/species.h" +#include "palette.h" +#include "pokemon_icon.h" #define POKE_ICON_BASE_PAL_TAG 56000 +struct MonIconSpriteTemplate +{ + const struct OamData *oam; + const u8 *image; + const union AnimCmd *const *anims; + const union AffineAnimCmd *const *affineAnims; + void (*callback)(struct Sprite *); + u16 paletteTag; +}; + +// static functions +static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *, s16, s16, u8); + +// .rodata + const u8 * const gMonIconTable[] = { gMonIcon_Bulbasaur, @@ -1012,3 +1031,288 @@ const u16 sSpriteImageSizes[3][4] = 0x400, // 4×8 }, }; + +u8 CreateMonIcon(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, u32 personality, bool32 extra) +{ + u8 spriteId; + struct MonIconSpriteTemplate iconTemplate = + { + .oam = &sMonIconOamData, + .image = GetMonIconPtr(species, personality, extra), + .anims = sMonIconAnims, + .affineAnims = sMonIconAffineAnims, + .callback = callback, + .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species], + }; + + if (species > SPECIES_EGG) + iconTemplate.paletteTag = POKE_ICON_BASE_PAL_TAG; + + spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority); + + UpdateMonIconFrame(&gSprites[spriteId]); + + return spriteId; +} + +u8 sub_80D2D78(u16 species, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority, bool32 extra) +{ + u8 spriteId; + struct MonIconSpriteTemplate iconTemplate = + { + .oam = &sMonIconOamData, + .image = NULL, + .anims = sMonIconAnims, + .affineAnims = sMonIconAffineAnims, + .callback = callback, + .paletteTag = POKE_ICON_BASE_PAL_TAG + gMonIconPaletteIndices[species], + }; + + iconTemplate.image = GetMonIconTiles(species, extra); + spriteId = CreateMonIconSprite(&iconTemplate, x, y, subpriority); + + UpdateMonIconFrame(&gSprites[spriteId]); + + return spriteId; +} + +u16 mon_icon_convert_unown_species_id(u16 species, u32 personality) +{ + u16 result; + + if (species == SPECIES_UNOWN) + { + u16 letter = GetUnownLetterByPersonality(personality); + if (letter == 0) + letter = SPECIES_UNOWN; + else + letter += (SPECIES_UNOWN_B - 1); + result = letter; + } + else + { + if (species > SPECIES_EGG) + result = 260; + else + result = species; + } + + return result; +} + +u16 GetUnownLetterByPersonality(u32 personality) +{ + if (!personality) + return 0; + return (((personality & 0x3000000) >> 18) | ((personality & 0x30000) >> 12) | ((personality & 0x300) >> 6) | (personality & 0x3)) % 0x1C; +} + +u16 sub_80D2E84(u16 species) +{ + u16 value; + + if (MailSpeciesToSpecies(species, &value) == SPECIES_UNOWN) + { + if (value == 0) + value += SPECIES_UNOWN; + else + value += (SPECIES_UNOWN_B - 1); + return value; + } + else + { + if(species > (SPECIES_UNOWN_B - 1)) + species = 260; + return mon_icon_convert_unown_species_id(species, 0); + } +} + +const u8 *GetMonIconPtr(u16 species, u32 personality, bool32 extra) +{ + return GetMonIconTiles(mon_icon_convert_unown_species_id(species, personality), extra); +} + + + +void sub_80D2EF8(struct Sprite *sprite) +{ + sub_80D328C(sprite); +} + +void LoadMonIconPalettes(void) +{ + u8 i; + for (i = 0; i < 6; i++) + LoadSpritePalette(&gMonIconPaletteTable[i]); +} + +// unused +void SafeLoadMonIconPalette(u16 species) +{ + u8 palIndex; + if (species > SPECIES_EGG) + species = 260; + palIndex = gMonIconPaletteIndices[species]; + if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF) + LoadSpritePalette(&gMonIconPaletteTable[palIndex]); +} + +void LoadMonIconPalette(u16 species) +{ + u8 palIndex = gMonIconPaletteIndices[species]; + if (IndexOfSpritePaletteTag(gMonIconPaletteTable[palIndex].tag) == 0xFF) + LoadSpritePalette(&gMonIconPaletteTable[palIndex]); +} + +void FreeMonIconPalettes(void) +{ + u8 i; + for (i = 0; i < 6; i++) + FreeSpritePaletteByTag(gMonIconPaletteTable[i].tag); +} + +// unused +void SafeFreeMonIconPalette(u16 species) +{ + u8 palIndex; + if (species > SPECIES_EGG) + species = 260; + palIndex = gMonIconPaletteIndices[species]; + FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag); +} + +void FreeMonIconPalette(u16 species) +{ + u8 palIndex; + palIndex = gMonIconPaletteIndices[species]; + FreeSpritePaletteByTag(gMonIconPaletteTable[palIndex].tag); +} + +void sub_80D3014(struct Sprite *sprite) +{ + UpdateMonIconFrame(sprite); +} + +const u8* GetMonIconTiles(u16 species, bool32 extra) +{ + const u8* iconSprite = gMonIconTable[species]; + if(species == SPECIES_DEOXYS && extra == TRUE) + { + iconSprite = (const u8*)(0x400 + (u32)iconSprite); //WTF? + } + return iconSprite; +} + +void sub_80D304C(u16 offset) +{ + s32 i; + const struct SpritePalette* monIconPalettePtr; + + if(offset <= 0xA0) + { + monIconPalettePtr = gMonIconPaletteTable; + for(i = 5; i >= 0 ; i--) + { + LoadPalette(monIconPalettePtr->data, offset, 0x20); + offset += 0x10; + monIconPalettePtr++; + } + } +} + +u8 sub_80D3080(u16 species) +{ + if (species > SPECIES_EGG) + species = 260; + return gMonIconPaletteIndices[species]; +} + +u8 sub_80D30A0(u16 species) +{ + return gMonIconPaletteIndices[species]; +} + +const u16* GetValidMonIconPalettePtr(u16 species) +{ + if (species > SPECIES_EGG) + species = 260; + return gMonIconPaletteTable[gMonIconPaletteIndices[species]].data; +} + +// TODO: try to find a way to avoid using asm statement +u8 UpdateMonIconFrame(struct Sprite *sprite) +{ + u8 result = 0; + + if (sprite->animDelayCounter == 0) + { + s16 frame = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.imageValue; + + switch (frame) + { + case -1: + break; + case -2: + sprite->animCmdIndex = 0; + break; + default: + RequestSpriteCopy( + // pointer arithmetic is needed to get the correct pointer to perform the sprite copy on. + // because sprite->images is a struct def, it has to be casted to (u8 *) before any + // arithmetic can be performed. + (u8 *)sprite->images + (sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] * frame), + (u8 *)(OBJ_VRAM0 + sprite->oam.tileNum * TILE_SIZE_4BPP), + sSpriteImageSizes[sprite->oam.shape][sprite->oam.size]); + { + register u8 duration asm("r0") = sprite->anims[sprite->animNum][sprite->animCmdIndex].frame.duration; + sprite->animDelayCounter = duration; + } + sprite->animCmdIndex++; + result = sprite->animCmdIndex; + break; + } + } + else + { + sprite->animDelayCounter--; + } + return result; +} + +static u8 CreateMonIconSprite(struct MonIconSpriteTemplate *iconTemplate, s16 x, s16 y, u8 subpriority) +{ + u8 spriteId; + + struct SpriteFrameImage image = { NULL, sSpriteImageSizes[iconTemplate->oam->shape][iconTemplate->oam->size] }; + + struct SpriteTemplate spriteTemplate = + { + .tileTag = 0xFFFF, + .paletteTag = iconTemplate->paletteTag, + .oam = iconTemplate->oam, + .anims = iconTemplate->anims, + .images = &image, + .affineAnims = iconTemplate->affineAnims, + .callback = iconTemplate->callback, + }; + + spriteId = CreateSprite(&spriteTemplate, x, y, subpriority); + gSprites[spriteId].animPaused = TRUE; + gSprites[spriteId].animBeginning = FALSE; + gSprites[spriteId].images = (const struct SpriteFrameImage *)iconTemplate->image; + return spriteId; +} + +void sub_80D328C(struct Sprite *sprite) +{ + struct SpriteFrameImage image = { NULL, sSpriteImageSizes[sprite->oam.shape][sprite->oam.size] }; + sprite->images = ℑ + DestroySprite(sprite); +} + +void sub_80D32C8(struct Sprite *sprite, u8 animNum) +{ + sprite->animNum = animNum; + sprite->animDelayCounter = 0; + sprite->animCmdIndex = 0; +} diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 8c9e7a8a0..74dc11973 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -21,6 +21,12 @@ #include "text.h" #include "window.h" #include "event_data.h" +#include "gpu_regs.h" +#include "menu.h" +#include "international_string_util.h" +#include "scanline_effect.h" +#include "menu_helpers.h" +#include "daycare.h" struct ContestMove { @@ -42,7 +48,6 @@ extern struct BgTemplate gUnknown_0861CBB4; extern u8 gUnknown_0203CF20; extern struct MusicPlayerInfo gMPlayInfo_BGM; extern s8 gUnknown_0861CC1C[]; -extern u8 gUnknown_08329D22[]; extern u8 gUnknown_0203CF21; extern struct UnkStruct_61CC04 gUnknown_0861CC04; extern struct UnkStruct_61CC04 gUnknown_0861CC10; @@ -65,20 +70,9 @@ extern u8 gUnknown_0861CE7B[]; extern struct WindowTemplate gUnknown_0861CCEC; extern struct WindowTemplate gUnknown_0861CD14; -extern void sub_806F2AC(u8 a, u8 b); void sub_81C488C(u8 a); -extern void do_scheduled_bg_tilemap_copies_to_vram(void); extern u8 sub_81221EC(); extern u8 sub_81221AC(); -extern void SetVBlankHBlankCallbacksToNull(); -extern void ResetVramOamAndBgCntRegs(); -extern void clear_scheduled_bg_copies_to_vram(); -extern void ScanlineEffect_Stop(); -extern void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable); -extern void ShowBg(u8 a); -extern void SetGpuReg(u8 regOffset, u16 value); -extern void schedule_bg_copy_tilemap_to_vram(u8 a); -extern void SetBgTilemapBuffer(u8 bg, void *tilemap); extern u8 gUnknown_08D9862C; extern u8 gUnknown_08D98CC8; extern u8 gUnknown_08D987FC; @@ -93,9 +87,6 @@ extern struct CompressedSpritePalette gUnknown_0861D100; extern struct CompressedSpritePalette gUnknown_0861D07C; extern u8 gMoveTypes_Pal; extern u8 gUnknown_08D97D0C; -extern void reset_temp_tile_data_buffers(); -extern void decompress_and_copy_tile_data_to_vram(u8 a, void* tiledata, u8 b, u8 c, u8 d); -extern u8 free_temp_tile_data_buffers_if_possible(); extern void sub_81C1E20(u8 taskId); extern u8 *GetMonNickname(struct Pokemon *mon, u8 *dest); extern u16 SpeciesToPokedexNum(u16 species); @@ -125,8 +116,6 @@ extern u8 gText_Appeal[]; extern u8 gText_Jam[]; extern u8 gText_OTSlash[]; extern u8 gText_UnkCtrlF907F908[]; -extern u8 gAbilityNames[][13]; -extern u8 *gAbilityDescriptionPointers[]; extern u8 gText_XNature[]; extern u8 gText_XNatureHatchedAtYZ[]; extern u8 gText_XNatureHatchedSomewhereAt[]; @@ -156,13 +145,8 @@ extern u8 gText_OneDash[]; extern u8 gText_TwoDashes[]; extern u8 gText_ThreeDashes[]; extern u8 gUnknown_0861CE97[]; -extern struct BattleMove gBattleMoves[]; -extern u32 ChangeBgX(u8 bg, u32 value, u8 op); extern void sub_8199C30(u8 a, u8 b, u8 c, u8 d, u8 e, u8 f); -extern void AddTextPrinterParameterized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, const u8* colors, s8 speed, u8 *str); -extern s32 GetStringCenterAlignXOffset(u8 fontId, u8 *str, s32 totalWidth); -extern s32 GetStringRightAlignXOffset(u8 fontId, u8 *str, s32 totalWidth); extern bool8 sub_81A6BF4(); extern bool8 sub_81B9E94(); extern void UnkTextUtil_Reset(); @@ -1433,7 +1417,7 @@ void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId) *ppBonusesPtr = localPpBonuses; } #else -__attribute__((naked)) +NAKED void sub_81C14BC(struct Pokemon *mon, u8 swappingFromId, u8 swappingToId) { asm(".syntax unified\n\ @@ -1644,7 +1628,7 @@ void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId) *ppBonusesPtr = localPpBonuses; } #else -__attribute__((naked)) +NAKED void sub_81C15EC(struct BoxPokemon *mon, u8 swappingFromId, u8 swappingToId) { asm(".syntax unified\n\ @@ -1841,7 +1825,7 @@ void sub_81C174C(u8 taskId) } else { - PlaySE(0x20); + PlaySE(SE_HAZURE); sub_81C18F4(taskId); } } @@ -2055,7 +2039,7 @@ void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d) Free(alloced); } #else -__attribute__((naked)) +NAKED void sub_81C1CB0(struct UnkStruct_61CC04 *a, u16 *b, u8 c, u8 d) { asm(".syntax unified\n\ @@ -2357,7 +2341,7 @@ void sub_81C2194(u16 *a, u16 b, u8 c) } } #else -__attribute__((naked)) +NAKED void sub_81C2194(u16 *a, u16 b, u8 c) { asm(".syntax unified\n\ @@ -2553,7 +2537,7 @@ void sub_81C2554() gUnknown_0203CF1C->unk40CB[i] |= 0xFF; } -void sub_81C25A4(u8 a, u8 *b, u8 c, u8 d, u8 e, u8 f) +void sub_81C25A4(u8 a, const u8 *b, u8 c, u8 d, u8 e, u8 f) { AddTextPrinterParameterized2(a, 1, c, d, 0, e, gUnknown_0861CD2C[f], 0, b); } @@ -2792,93 +2776,27 @@ void sub_81C2C38(u8 a) schedule_bg_copy_tilemap_to_vram(0); } - - -#ifdef NONMATCHING u8 sub_81C2D2C(struct WindowTemplate *template, u8 a) { - u8 *r4 = gUnknown_0203CF1C->unk40CB; - if (r4[a] == 0xFF) + u8 *windowIdPtr = &(gUnknown_0203CF1C->unk40CB[a]); + if (*windowIdPtr == 0xFF) { - r4[a] = AddWindow(&template[a]); - FillWindowPixelBuffer(r4[a], 0); + *windowIdPtr = AddWindow(&template[a]); + FillWindowPixelBuffer(*windowIdPtr, 0); } - return r4[a]; + return *windowIdPtr; } -#else -__attribute__((naked)) -u8 sub_81C2D2C(struct WindowTemplate *template, u8 a) -{ - asm(".syntax unified\n\ - push {r4,lr}\n\ - adds r3, r0, 0\n\ - lsls r1, 24\n\ - lsrs r2, r1, 24\n\ - ldr r0, =gUnknown_0203CF1C\n\ - ldr r4, =0x000040cb\n\ - adds r1, r2, r4\n\ - ldr r0, [r0]\n\ - adds r4, r0, r1\n\ - ldrb r0, [r4]\n\ - cmp r0, 0xFF\n\ - bne _081C2D56\n\ - lsls r0, r2, 3\n\ - adds r0, r3, r0\n\ - bl AddWindow\n\ - strb r0, [r4]\n\ - ldrb r0, [r4]\n\ - movs r1, 0\n\ - bl FillWindowPixelBuffer\n\ -_081C2D56:\n\ - ldrb r0, [r4]\n\ - pop {r4}\n\ - pop {r1}\n\ - bx r1\n\ - .pool\n\ - .syntax divided\n"); -} -#endif -#ifdef NONMATCHING void sub_81C2D68(u8 a) { - u8 *r4 = gUnknown_0203CF1C->unk40CB; - if (r4[a] != 0xFF) + u8 *windowIdPtr = &(gUnknown_0203CF1C->unk40CB[a]); + if (*windowIdPtr != 0xFF) { - ClearWindowTilemap(r4[a]); - RemoveWindow(r4[a]); - r4[a] = 0xFF; + ClearWindowTilemap(*windowIdPtr); + RemoveWindow(*windowIdPtr); + *windowIdPtr = 0xFF; } } -#else -__attribute__((naked)) -void sub_81C2D68(u8 a) -{ - asm(".syntax unified\n\ - push {r4,lr}\n\ - lsls r0, 24\n\ - lsrs r0, 24\n\ - ldr r1, =gUnknown_0203CF1C\n\ - ldr r2, =0x000040cb\n\ - adds r0, r2\n\ - ldr r1, [r1]\n\ - adds r4, r1, r0\n\ - ldrb r0, [r4]\n\ - cmp r0, 0xFF\n\ - beq _081C2D8C\n\ - bl ClearWindowTilemap\n\ - ldrb r0, [r4]\n\ - bl RemoveWindow\n\ - movs r0, 0xFF\n\ - strb r0, [r4]\n\ -_081C2D8C:\n\ - pop {r4}\n\ - pop {r0}\n\ - bx r0\n\ - .pool\n\ - .syntax divided\n"); -} -#endif void sub_81C2D9C(u8 a) { @@ -3041,7 +2959,7 @@ void sub_81C31F0(u8 *a) { u8 level = gUnknown_0203CF1C->summary.metLevel; if (level == 0) - level = 5; + level = EGG_HATCH_LEVEL; ConvertIntToDecimalStringN(a, level, 0, 3); UnkTextUtil_SetPtrI(3, a); } @@ -3108,7 +3026,7 @@ void sub_81C335C() sub_81C25A4(r4, gText_FiveMarks, r5, 1, 0, 1); } #else -__attribute__((naked)) +NAKED void sub_81C335C() { asm(".syntax unified\n\ @@ -3255,11 +3173,11 @@ void sub_81C3554(u8 taskId) void sub_81C35E4() { - u8 *text; + const u8 *text; int offset; if (gUnknown_0203CF1C->summary.item == ITEM_ENIGMA_BERRY && sub_81B1250() == 1 && (gUnknown_0203CF1C->unk40BE == 1 || gUnknown_0203CF1C->unk40BE == 4 || gUnknown_0203CF1C->unk40BE == 5)) { - text = (u8*)ItemId_GetItem(ITEM_ENIGMA_BERRY); + text = ItemId_GetName(ITEM_ENIGMA_BERRY); } else if (gUnknown_0203CF1C->summary.item == ITEM_NONE) text = gText_None; @@ -3451,7 +3369,7 @@ void sub_81C3B08(u8 a) sub_81C25A4(sp, text, offset, (a<<4), 0, r5); } #else -__attribute__((naked)) +NAKED void sub_81C3B08(u8 a) { asm(".syntax unified\n\ diff --git a/src/random.c b/src/random.c index f2f0ede58..f0b2d9e5f 100644 --- a/src/random.c +++ b/src/random.c @@ -7,6 +7,10 @@ EWRAM_DATA static u8 sUnknown = 0; EWRAM_DATA static u32 sRandCount = 0; +// IWRAM common +IWRAM_DATA u32 gRngValue; +IWRAM_DATA u32 gRng2Value; + u16 Random(void) { gRngValue = 1103515245 * gRngValue + 24691; diff --git a/src/record_mixing.c b/src/record_mixing.c index 79db07bf0..1a39dfde9 100644 --- a/src/record_mixing.c +++ b/src/record_mixing.c @@ -106,8 +106,6 @@ void sub_80E89F8(void *dest); void sub_80E8A54(void *src); void sub_80E8AC0(union BattleTowerRecord *); void sub_80EAF80(struct SecretBaseRecord *, size_t, u8); -void sub_80F01E8(void *, size_t, u8); -void sub_80F0C7C(PokeNews *, size_t, u8); void sub_812287C(struct EasyChatPair *, size_t, u8); void TaskDummy4(union BattleTowerRecord *src); @@ -299,7 +297,7 @@ static void sub_80E715C(u8 taskId) if (!gTasks[data[10]].isActive) { data[0] = 4; - if (!gLinkVSyncDisabled) + if (gWirelessCommType == 0) { data[10] = sub_80B3050(); } @@ -319,7 +317,7 @@ static void sub_80E715C(u8 taskId) free(gUnknown_0203A014); free(gUnknown_0203A018); sub_808729C(); - if (gLinkVSyncDisabled) + if (gWirelessCommType != 0) { CreateTask(sub_80AF2B4, 10); } @@ -344,7 +342,7 @@ static void sub_80E7324(u8 taskId) sub_80E70F4(gText_MixingRecords); task->data[8] = 0x708; task->data[0] = 400; - sub_8009FAC(); + ClearLinkCallback_2(); break; case 100: if (++ task->data[12] > 20) @@ -546,7 +544,6 @@ static void sub_80E77D4(u8 taskId) gUnknown_03001130 = TRUE; } - static void *sub_80E77FC(const u16 *asShort) { return (void *)(asShort[0] | (asShort[1] << 16)); @@ -618,7 +615,7 @@ static void sub_80E78C4(OldMan *oldMan, size_t recordSize, u8 which) sub_8120CD0(dest, version, language); } memcpy(gUnknown_03001140, (void *)oldMan + recordSize * mixIndices[which], sizeof(OldMan)); - sub_8120670(); + ResetMauvilleOldManFlag(); } static void sub_80E7948(union BattleTowerRecord *battleTowerRecord, size_t recordSize, u8 which) @@ -1427,7 +1424,7 @@ __attribute__((naked)) static void sub_80E7B60(struct UnkStruct_80E7B60 *src, si static void sub_80E7F68(u16 *item, u8 which) { - if (which != 0 && *item != ITEM_NONE && GetPocketByItemId(*item) == BAG_KEYITEMS) + if (which != 0 && *item != ITEM_NONE && GetPocketByItemId(*item) == POCKET_KEY_ITEMS) { if (!CheckBagHasItem(*item, 1) && !CheckPCHasItem(*item, 1) && AddBagItem(*item, 1)) { @@ -1501,7 +1498,7 @@ static void sub_80E7FF8(u8 taskId) case 7: if (!FuncIsActiveTask(sub_8153688)) { - if (gLinkVSyncDisabled) + if (gWirelessCommType) { sub_801048C(1); task->data[0] = 8; diff --git a/src/recorded_battle.c b/src/recorded_battle.c index e60457257..eb48ab15a 100644 --- a/src/recorded_battle.c +++ b/src/recorded_battle.c @@ -100,7 +100,6 @@ EWRAM_DATA static u16 sUnknown_0203CCDC[6] = {0}; EWRAM_DATA static u8 sUnknown_0203CCE8 = 0; extern u32 sub_81A513C(void); -extern void PlayMapChosenOrBattleBGM(bool8); // this file's functions static u8 sub_8185278(u8 *arg0, u8 *arg1, u8 *arg2); @@ -476,7 +475,7 @@ u32 MoveRecordedBattleToSaveData(void) } #else -__attribute__((naked)) +NAKED u32 MoveRecordedBattleToSaveData(void) { asm(".syntax unified\n\ diff --git a/src/region_map.c b/src/region_map.c index 086c0ba68..f16787fc9 100644 --- a/src/region_map.c +++ b/src/region_map.c @@ -881,7 +881,7 @@ static void RegionMap_InitializeStateBasedOnPlayerLocation(void) return; } - switch (get_map_light_level_by_bank_and_number(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)) + switch (GetMapTypeByGroupAndId(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum)) { default: case 1: @@ -904,7 +904,7 @@ static void RegionMap_InitializeStateBasedOnPlayerLocation(void) case 7: if (gMapHeader.flags & 0x02) { - mapHeader = get_mapheader_by_bank_and_number(gSaveBlock1Ptr->warp4.mapGroup, gSaveBlock1Ptr->warp4.mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1Ptr->warp4.mapGroup, gSaveBlock1Ptr->warp4.mapNum); gRegionMap->mapSecId = mapHeader->regionMapSectionId; gRegionMap->playerIsInCave = TRUE; mapWidth = mapHeader->mapData->width; @@ -923,7 +923,7 @@ static void RegionMap_InitializeStateBasedOnPlayerLocation(void) } break; case 9: - mapHeader = get_mapheader_by_bank_and_number((u16)gSaveBlock1Ptr->warp2.mapGroup, (u16)gSaveBlock1Ptr->warp2.mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId((u16)gSaveBlock1Ptr->warp2.mapGroup, (u16)gSaveBlock1Ptr->warp2.mapNum); gRegionMap->mapSecId = mapHeader->regionMapSectionId; gRegionMap->playerIsInCave = TRUE; mapWidth = mapHeader->mapData->width; @@ -937,12 +937,12 @@ static void RegionMap_InitializeStateBasedOnPlayerLocation(void) if (gRegionMap->mapSecId != MAPSEC_DYNAMIC) { storedWarp = &gSaveBlock1Ptr->warp4; - mapHeader = get_mapheader_by_bank_and_number(storedWarp->mapGroup, storedWarp->mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId(storedWarp->mapGroup, storedWarp->mapNum); } else { storedWarp = &gSaveBlock1Ptr->warp2; - mapHeader = get_mapheader_by_bank_and_number(storedWarp->mapGroup, storedWarp->mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId(storedWarp->mapGroup, storedWarp->mapNum); gRegionMap->mapSecId = mapHeader->regionMapSectionId; } if (RegionMap_IsPlayerInCave(gRegionMap->mapSecId)) @@ -1065,7 +1065,7 @@ static void RegionMap_InitializeStateBasedOnSSTidalLocation(void) break; default: case 0: - mapHeader = get_mapheader_by_bank_and_number(mapGroup, mapNum); + mapHeader = Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum); gRegionMap->mapSecId = mapHeader->regionMapSectionId; dimensionScale = mapHeader->mapData->width / gRegionMapEntries[gRegionMap->mapSecId].width; @@ -1581,7 +1581,7 @@ void MCB2_FlyMap(void) gUnknown_0203A148 = malloc(sizeof(*gUnknown_0203A148)); if (gUnknown_0203A148 == NULL) { - SetMainCallback2(sub_8086194); + SetMainCallback2(CB2_ReturnToFieldWithOpenMenu); } else { diff --git a/src/reset_save_heap.c b/src/reset_save_heap.c index 9950f6691..1d90448b2 100644 --- a/src/reset_save_heap.c +++ b/src/reset_save_heap.c @@ -20,11 +20,11 @@ void sub_81700F8(void) gMain.inBattle = FALSE; SetSaveBlocksPointers(sub_815355C()); sub_808447C(); - ResetSaveCounters(); - sub_81534D0(0); + Save_ResetSaveCounters(); + Save_LoadGameData(0); if (gSaveFileStatus == 0 || gSaveFileStatus == 2) Sav2_ClearSetDefault(); SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound); InitHeap(gHeap, HEAP_SIZE); - SetMainCallback2(sub_8086230); + SetMainCallback2(CB2_ContinueSavedGame); } diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c index b12917c61..45f0f5a9e 100644 --- a/src/reshow_battle_screen.c +++ b/src/reshow_battle_screen.c @@ -13,6 +13,7 @@ #include "constants/species.h" #include "battle_interface.h" #include "battle_anim.h" +#include "data2.h" extern u16 gBattle_BG0_X; extern u16 gBattle_BG0_Y; @@ -22,18 +23,17 @@ extern u16 gBattle_BG2_X; extern u16 gBattle_BG2_Y; extern u16 gBattle_BG3_X; extern u16 gBattle_BG3_Y; -extern struct SpriteTemplate gUnknown_0202499C; extern const union AnimCmd * const * const gMonAnimationsSpriteAnimsPtrTable[]; -extern void sub_806A068(u16 species, u8 bankIdentity); -extern void sub_806A12C(u16 backPicId, u8 bankIdentity); +extern void sub_806A068(u16 species, u8 battlerPosition); +extern void sub_806A12C(u16 backPicId, u8 battlerPosition); // this file's functions static void CB2_ReshowBattleScreenAfterMenu(void); -static bool8 LoadBattlerSpriteGfx(u8 bank); -static void CreateBattlerSprite(u8 bank); -static void CreateHealthboxSprite(u8 bank); +static bool8 LoadBattlerSpriteGfx(u8 battlerId); +static void CreateBattlerSprite(u8 battlerId); +static void CreateHealthboxSprite(u8 battlerId); static void sub_80A95F4(void); void nullsub_35(void) @@ -162,10 +162,10 @@ static void CB2_ReshowBattleScreenAfterMenu(void) ActionSelectionCreateCursorAt(gActionSelectionCursor[gBattlerInMenuId], 0); - if (gLinkVSyncDisabled != 0 && gReceivedRemoteLinkPlayers != 0) + if (gWirelessCommType != 0 && gReceivedRemoteLinkPlayers != 0) { sub_800E0E8(); - sub_800DFB4(0, 0); + CreateWirelessStatusIndicatorSprite(0, 0); } } break; @@ -218,16 +218,6 @@ static bool8 LoadBattlerSpriteGfx(u8 battler) return TRUE; } -// todo: get rid of it once the struct is declared in a header -struct MonCoords -{ - // This would use a bitfield, but sub_8079F44 - // uses it as a u8 and casting won't match. - u8 coords; // u8 x:4, y:4; - u8 y_offset; -}; -extern const struct MonCoords gTrainerBackPicCoords[]; - static void CreateBattlerSprite(u8 battler) { if (battler < gBattlersCount) diff --git a/src/rom6.c b/src/rom6.c new file mode 100644 index 000000000..4a5c506b6 --- /dev/null +++ b/src/rom6.c @@ -0,0 +1,209 @@ +#include "global.h" +#include "constants/map_objects.h" +#include "constants/songs.h" +#include "rom6.h" +#include "braille_puzzles.h" +#include "event_data.h" +#include "event_scripts.h" +#include "field_effect.h" +#include "field_map_obj.h" +#include "field_player_avatar.h" +#include "item_use.h" +#include "party_menu.h" +#include "overworld.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +// static functions +static void task08_080C9820(u8 taskId); +static void sub_8135578(u8 taskId); +static void sub_813552C(u8 taskId); +static void sub_813561C(u8 taskId); +static void sub_81356C4(void); +static void sub_8135714(void); +static void hm2_dig(void); +static void sub_8135780(void); + +// extern RAM loc +extern struct MapPosition gUnknown_0203AB40; + +// text +bool8 npc_before_player_of_type(u8 a) +{ + u8 mapObjId; + + GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203AB40.x, &gUnknown_0203AB40.y); + gUnknown_0203AB40.height = PlayerGetZCoord(); + mapObjId = GetFieldObjectIdByXYZ(gUnknown_0203AB40.x, gUnknown_0203AB40.y, gUnknown_0203AB40.height); + if (gMapObjects[mapObjId].graphicsId != a) + { + return FALSE; + } + else + { + gSpecialVar_LastTalked = gMapObjects[mapObjId].localId; + return TRUE; + } +} + +u8 oei_task_add(void) +{ + GetXYCoordsOneStepInFrontOfPlayer(&gUnknown_0203AB40.x, &gUnknown_0203AB40.y); + return CreateTask(task08_080C9820, 8); +} + +static void task08_080C9820(u8 taskId) +{ + u8 mapObjId; + + ScriptContext2_Enable(); + gPlayerAvatar.preventStep = TRUE; + mapObjId = gPlayerAvatar.mapObjectId; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(&gMapObjects[mapObjId]) + || FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId])) + { + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER) + { + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + gTasks[taskId].func = sub_8135578; + } + else + { + sub_808C114(); + FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], 0x39); + gTasks[taskId].func = sub_813552C; + } + } +} + +static void sub_813552C(u8 taskId) +{ + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[gPlayerAvatar.mapObjectId]) == TRUE) + { + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + gTasks[taskId].func = sub_8135578; + } +} + +static void sub_8135578(u8 taskId) +{ + if (!FieldEffectActiveListContains(6)) + { + gFieldEffectArguments[1] = player_get_direction_lower_nybble(); + if (gFieldEffectArguments[1] == 1) + gFieldEffectArguments[2] = 0; + if (gFieldEffectArguments[1] == 2) + gFieldEffectArguments[2] = 1; + if (gFieldEffectArguments[1] == 3) + gFieldEffectArguments[2] = 2; + if (gFieldEffectArguments[1] == 4) + gFieldEffectArguments[2] = 3; + FieldObjectSetGraphicsId(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByCurrentState()); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], gFieldEffectArguments[2]); + FieldEffectActiveListRemove(6); + gTasks[taskId].func = sub_813561C; + } +} + +static void sub_813561C(u8 taskId) +{ + void (*func)(void) = (void (*)(void))(((u16)gTasks[taskId].data[8] << 16) | (u16)gTasks[taskId].data[9]); + + func(); + gPlayerAvatar.preventStep = FALSE; + DestroyTask(taskId); +} + +bool8 SetUpFieldMove_RockSmash(void) +{ + if(ShouldDoBrailleStrengthEffect()) + { + gSpecialVar_Result = GetCursorSelectionMonId(); + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = sub_8179834; + return TRUE; + } + else if (npc_before_player_of_type(0x56) == TRUE) + { + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = sub_81356C4; + return TRUE; + } + else + { + return FALSE; + } +} + +static void sub_81356C4(void) +{ + gFieldEffectArguments[0] = GetCursorSelectionMonId(); + ScriptContext1_SetupScript(Route111_EventScript_2907F0); +} + +bool8 FldEff_UseRockSmash(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_8135714 >> 16; + gTasks[taskId].data[9] = (u32)sub_8135714; + IncrementGameStat(GAME_STAT_USED_ROCK_SMASH); + return FALSE; +} + +static void sub_8135714(void) +{ + PlaySE(SE_W088); + FieldEffectActiveListRemove(FLDEFF_USE_ROCK_SMASH); + EnableBothScriptContexts(); +} + +bool8 SetUpFieldMove_Dig(void) +{ + if (CanUseEscapeRopeOnCurrMap() == TRUE) + { + gUnknown_03005DB0 = FieldCallback_Teleport; + gUnknown_0203CEEC = hm2_dig; + return TRUE; + } + else + { + return FALSE; + } +} + +static void hm2_dig(void) +{ + Overworld_ResetStateAfterDigEscRope(); + FieldEffectStart(FLDEFF_USE_DIG); + gFieldEffectArguments[0] = GetCursorSelectionMonId(); +} + +bool8 FldEff_UseDig(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_8135780 >> 16; + gTasks[taskId].data[9] = (u32)sub_8135780; + if (!ShouldDoBrailleDigEffect()) + SetPlayerAvatarTransitionFlags(1); + return FALSE; +} + +static void sub_8135780(void) +{ + u8 taskId; + + FieldEffectActiveListRemove(FLDEFF_USE_DIG); + if (ShouldDoBrailleDigEffect()) + { + DoBrailleDigEffect(); + } + else + { + taskId = CreateTask(task08_080A1C44, 8); + gTasks[taskId].data[0] = 0; + } +} diff --git a/src/rom_8011DC0.c b/src/rom_8011DC0.c new file mode 100644 index 000000000..9076b611a --- /dev/null +++ b/src/rom_8011DC0.c @@ -0,0 +1,18 @@ + +// Includes +#include "global.h" + +// Static type declarations + +// Static RAM declarations +IWRAM_DATA u32 gUnknown_03000DA0; +IWRAM_DATA u32 gUnknown_03000DA4; +IWRAM_DATA void *gUnknown_03000DA8; +IWRAM_DATA void *gUnknown_03000DAC; +IWRAM_DATA bool32 gUnknown_03000DB0; + +// Static ROM declarations + +// .rodata + +// .text diff --git a/src/rotating_gate.c b/src/rotating_gate.c new file mode 100644 index 000000000..a16401fa2 --- /dev/null +++ b/src/rotating_gate.c @@ -0,0 +1,1188 @@ +#include "global.h" +#include "bike.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "constants/maps.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" + +#define ROTATING_GATE_TILE_TAG 0x1300 +#define ROTATING_GATE_PUZZLE_MAX 12 +#define GATE_ARM_MAX_LENGTH 2 + +#define GATE_ROT(rotationDirection, arm, longArm) \ + ((rotationDirection & 15) << 4) | ((arm & 7) << 1) | (longArm & 1) +#define GATE_ROT_CW(arm, longArm) GATE_ROT(ROTATE_CLOCKWISE, arm, longArm) +#define GATE_ROT_ACW(arm, longArm) GATE_ROT(ROTATE_ANTICLOCKWISE, arm, longArm) +#define GATE_ROT_NONE 255 + +// static functions +static void SpriteCallback_RotatingGate(struct Sprite *sprite); +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY); +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite); + +// enums +enum +{ + /* + * | + * +-- + */ + GATE_SHAPE_L1, + + /* + * | + * | + * +-- + */ + GATE_SHAPE_L2, + + /* + * | + * +---- + */ + GATE_SHAPE_L3, + + /* + * | + * | + * +---- + */ + GATE_SHAPE_L4, + + /* + * | + * +-- + * | + */ + GATE_SHAPE_T1, + + /* + * | + * | + * +-- + * | + */ + GATE_SHAPE_T2, + + /* + * | + * +---- + * | + */ + GATE_SHAPE_T3, + + /* + * An unused T-shape gate + * | + * +-- + * | + * | + */ + GATE_SHAPE_T4, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + */ + GATE_SHAPE_UNUSED_T1, + + /* + * An unused T-shape gate + * | + * | + * +-- + * | + * | + */ + GATE_SHAPE_UNUSED_T2, + + /* + * An unused T-shape gate + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T3, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T4, +}; + +enum +{ + /* + * 0 degrees (clockwise) + * | + * +-- + * | + */ + GATE_ORIENTATION_0, + + /* + * 90 degress (clockwise) + * --+-- + * | + */ + GATE_ORIENTATION_90, + + /* + * 180 degrees (clockwise) + * | + * --+ + * | + */ + GATE_ORIENTATION_180, + + /* + * 270 degrees (clockwise) + * | + * --+-- + */ + GATE_ORIENTATION_270, + + GATE_ORIENTATION_MAX, +}; + +// Describes the location of the gates "arms" when the gate has not +// been rotated (i.e. rotated 0 degrees) +enum +{ + GATE_ARM_NORTH, + GATE_ARM_EAST, + GATE_ARM_SOUTH, + GATE_ARM_WEST, +}; + +enum +{ + ROTATE_NONE, + ROTATE_ANTICLOCKWISE, + ROTATE_CLOCKWISE, +}; + +enum +{ + PUZZLE_NONE, + PUZZLE_FORTREE_CITY_GYM, + PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6, +}; + +// structure +struct RotatingGatePuzzle +{ + s16 x; + s16 y; + u8 shape; + u8 orientation; +}; + +struct Coords8 +{ + s8 deltaX; + s8 deltaY; +}; + +// .rodata +// Fortree +static const struct RotatingGatePuzzle sRotatingGate_FortreePuzzleConfig[] = +{ + { 6, 7, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 9, 15, GATE_SHAPE_T2, GATE_ORIENTATION_180}, + { 3, 19, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 2, 6, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 9, 12, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 23, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + {12, 22, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 3, GATE_SHAPE_L4, GATE_ORIENTATION_180}, +}; + +// Trickhouse +static const struct RotatingGatePuzzle sRotatingGate_TrickHousePuzzleConfig[] = +{ + {14, 5, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + {10, 6, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + { 6, 6, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {14, 8, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 3, 10, GATE_SHAPE_L3, GATE_ORIENTATION_270}, + { 9, 14, GATE_SHAPE_L1, GATE_ORIENTATION_90}, + { 3, 15, GATE_SHAPE_T3, GATE_ORIENTATION_0}, + { 2, 17, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + {12, 18, GATE_SHAPE_T3, GATE_ORIENTATION_270}, + { 5, 18, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {10, 19, GATE_SHAPE_L3, GATE_ORIENTATION_180}, +}; + +static const u8 sRotatingGateTiles_1[] = INCBIN_U8("graphics/misc/rotating_gate_1.4bpp"); +static const u8 sRotatingGateTiles_2[] = INCBIN_U8("graphics/misc/rotating_gate_2.4bpp"); +static const u8 sRotatingGateTiles_3[] = INCBIN_U8("graphics/misc/rotating_gate_3.4bpp"); +static const u8 sRotatingGateTiles_4[] = INCBIN_U8("graphics/misc/rotating_gate_4.4bpp"); +static const u8 sRotatingGateTiles_5[] = INCBIN_U8("graphics/misc/rotating_gate_5.4bpp"); +static const u8 sRotatingGateTiles_6[] = INCBIN_U8("graphics/misc/rotating_gate_6.4bpp"); +static const u8 sRotatingGateTiles_7[] = INCBIN_U8("graphics/misc/rotating_gate_7.4bpp"); +static const u8 sRotatingGateTiles_8[] = INCBIN_U8("graphics/misc/rotating_gate_8.4bpp"); + +static const struct OamData sOamData_RotatingGateLarge = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct OamData sOamData_RotatingGateRegular = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct SpriteSheet sRotatingGatesGraphicsTable[] = +{ + {sRotatingGateTiles_1, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L1}, + {sRotatingGateTiles_2, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L2}, + {sRotatingGateTiles_3, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L3}, + {sRotatingGateTiles_4, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L4}, + {sRotatingGateTiles_5, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T1}, + {sRotatingGateTiles_6, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T2}, + {sRotatingGateTiles_7, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T3}, + {sRotatingGateTiles_8, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T4}, + {NULL}, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateLarge[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateRegular[] = +{ + ANIMCMD_FRAME(0, 0), ANIMCMD_END, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateLarge[] = +{ + sSpriteAnim_RotatingGateLarge, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateRegular[] = +{ + sSpriteAnim_RotatingGateRegular, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotatingGate[] = +{ + sSpriteAffineAnim_Rotated0, + sSpriteAffineAnim_Rotated90, + sSpriteAffineAnim_Rotated180, + sSpriteAffineAnim_Rotated270, + sSpriteAffineAnim_RotatingAnticlockwise360to270, + sSpriteAffineAnim_RotatingAnticlockwise90to0, + sSpriteAffineAnim_RotatingAnticlockwise180to90, + sSpriteAffineAnim_RotatingAnticlockwise270to180, + sSpriteAffineAnim_RotatingClockwise0to90, + sSpriteAffineAnim_RotatingClockwise90to180, + sSpriteAffineAnim_RotatingClockwise180to270, + sSpriteAffineAnim_RotatingClockwise270to360, + sSpriteAffineAnim_RotatingAnticlockwise360to270Faster, + sSpriteAffineAnim_RotatingAnticlockwise90to0Faster, + sSpriteAffineAnim_RotatingAnticlockwise180to90Faster, + sSpriteAffineAnim_RotatingAnticlockwise270to180Faster, + sSpriteAffineAnim_RotatingClockwise0to90Faster, + sSpriteAffineAnim_RotatingClockwise90to180Faster, + sSpriteAffineAnim_RotatingClockwise180to270Faster, + sSpriteAffineAnim_RotatingClockwise270to360Faster, +}; + + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateLarge = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateLarge, + .anims = sSpriteAnimTable_RotatingGateLarge, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateRegular = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateRegular, + .anims = sSpriteAnimTable_RotatingGateRegular, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +// These structures describe what happens to the gate if you hit it at +// a given coordinate in a 4x4 grid when walking in the specified +// direction. Either the gate does not rotate, or it rotates in the +// given direction. This information is compared against the gate +// "arm" layout to see if there is an arm at the position in order to +// produce the final rotation. +static const u8 sRotatingGate_RotationInfoNorth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_CW(GATE_ARM_WEST, 1), GATE_ROT_CW(GATE_ARM_WEST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoSouth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_ACW(GATE_ARM_WEST, 1), GATE_ROT_ACW(GATE_ARM_WEST, 0), GATE_ROT_CW(GATE_ARM_EAST, 0), GATE_ROT_CW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoWest[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoEast[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, +}; + +// These tables describe the relative coordinate positions the arms +// must move through in order to be rotated. +static const struct Coords8 sRotatingGate_ArmPositionsClockwiseRotation[] = { + { 0, -1 }, { 1, -2 }, { 0, 0 }, { 1, 0 }, { -1, 0 }, { -1, 1 }, { -1, -1 }, { -2, -1 }, +}; + +static const struct Coords8 sRotatingGate_ArmPositionsAntiClockwiseRotation[] = { + { -1, -1 }, { -1, -2 }, { 0, -1 }, { 1, -1 }, { 0, 0 }, { 0, 1 }, { -1, 0 }, { -2, 0 }, +}; + +// Describes where the gates "arms" are in the order north, east, south, west. +// These are adjusted using the current orientation to perform collision checking +static const u8 sRotatingGate_ArmLayout[][4 * 2] = +{ + // L-shape gates + { + 1, 0, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 1, + 0, 0, + 0, 0, + }, + + // T-shape gates + { + 1, 0, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 0, + 1, 1, + 0, 0, + }, + + // Unused T-shape gates + // These have 2-3 long arms and cannot actually be used anywhere + // since configuration for them is missing from the other tables. + { + 1, 1, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 1, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 1, + 0, 0, + }, + { + 1, 1, + 1, 1, + 1, 1, + 0, 0, + }, +}; + +// ewram +static EWRAM_DATA u8 gRotatingGate_GateSpriteIds[ROTATING_GATE_PUZZLE_MAX] = {0}; +static EWRAM_DATA const struct RotatingGatePuzzle *gRotatingGate_PuzzleConfig = NULL; +static EWRAM_DATA u8 gRotatingGate_PuzzleCount = 0; + +// text +static s32 GetCurrentMapRotatingGatePuzzleType(void) +{ + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FORTREE_CITY_GYM) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(FORTREE_CITY_GYM)) + { + return PUZZLE_FORTREE_CITY_GYM; + } + + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE110_TRICK_HOUSE_PUZZLE6) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE110_TRICK_HOUSE_PUZZLE6)) + { + return PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6; + } + + return PUZZLE_NONE; +} + +static void RotatingGate_ResetAllGateOrientations(void) +{ + s32 i; + u8 *ptr; + + ptr = (u8 *)GetVarPointer(VAR_0x4000); + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + ptr[i] = gRotatingGate_PuzzleConfig[i].orientation; + } +} + +static s32 RotatingGate_GetGateOrientation(u8 gateId) +{ + return ((u8 *)GetVarPointer(VAR_0x4000))[gateId]; +} + +static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation) +{ + ((u8 *)GetVarPointer(VAR_0x4000))[gateId] = orientation; +} + +static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection) +{ + u8 orientation = RotatingGate_GetGateOrientation(gateId); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + if (orientation) + orientation--; + else + orientation = GATE_ORIENTATION_270; + } + else + { + orientation = ++orientation % GATE_ORIENTATION_MAX; + } + RotatingGate_SetGateOrientation(gateId, orientation); +} + +static void RotatingGate_LoadPuzzleConfig(void) +{ + s32 puzzleType = GetCurrentMapRotatingGatePuzzleType(); + u32 i; + + switch (puzzleType) + { + case PUZZLE_FORTREE_CITY_GYM: + gRotatingGate_PuzzleConfig = sRotatingGate_FortreePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_FortreePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6: + gRotatingGate_PuzzleConfig = sRotatingGate_TrickHousePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_TrickHousePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_NONE: + default: + return; + } + + for (i = 0; i < ROTATING_GATE_PUZZLE_MAX - 1; i++) + { + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } +} + +static void RotatingGate_CreateGatesWithinViewport(s16 deltaX, s16 deltaY) +{ + u8 i; + + // Calculate the bounding box of the camera + // Same as RotatingGate_DestroyGatesOutsideViewport + s16 x = gSaveBlock1Ptr->pos.x - 2; + s16 x2 = gSaveBlock1Ptr->pos.x + 0x11; + s16 y = gSaveBlock1Ptr->pos.y - 2; + s16 y2 = gSaveBlock1Ptr->pos.y + 0xe; + + s16 x3, y3; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + x3 = gRotatingGate_PuzzleConfig[i].x + 7; + y3 = gRotatingGate_PuzzleConfig[i].y + 7; + + if (y <= y3 && y2 >= y3 && x <= x3 && x2 >= x3 && + gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + { + gRotatingGate_GateSpriteIds[i] = RotatingGate_CreateGate(i, deltaX, deltaY); + } + } +} + +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY) +{ + struct Sprite *sprite; + struct SpriteTemplate template; + const struct RotatingGatePuzzle *gate; + u8 spriteId; + s16 x, y; + + gate = &gRotatingGate_PuzzleConfig[gateId]; + + if (gate->shape == GATE_SHAPE_L1 || gate->shape == GATE_SHAPE_T1) + template = sSpriteTemplate_RotatingGateRegular; + else + template = sSpriteTemplate_RotatingGateLarge; + + template.tileTag = gate->shape + ROTATING_GATE_TILE_TAG; + + spriteId = CreateSprite(&template, 0, 0, 0x94); + if (spriteId == MAX_SPRITES) + return MAX_SPRITES; + + x = gate->x + 7; + y = gate->y + 7; + + sprite = &gSprites[spriteId]; + sprite->data[0] = gateId; + sprite->coordOffsetEnabled = 1; + + sub_8092FF0(x + deltaX, y + deltaY, &sprite->pos1.x, &sprite->pos1.y); + RotatingGate_HideGatesOutsideViewport(sprite); + StartSpriteAffineAnim(sprite, RotatingGate_GetGateOrientation(gateId)); + + return spriteId; +} + +static void SpriteCallback_RotatingGate(struct Sprite *sprite) +{ + u8 rotationDirection; + u8 orientation; + u8 affineAnimation; + + rotationDirection = sprite->data[1]; + orientation = sprite->data[2]; + + RotatingGate_HideGatesOutsideViewport(sprite); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + affineAnimation = orientation + 4; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + else if (rotationDirection == ROTATE_CLOCKWISE) + { + affineAnimation = orientation + 8; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + + sprite->data[1] = ROTATE_NONE; +} + +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite) +{ + u16 x; + s16 x2; + u16 y; + s16 y2; + + sprite->invisible = FALSE; + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + + x2 = x + 0x40; // Dimensions of the rotating gate + y2 = y + 0x40; + + if ((s16)x > DISPLAY_WIDTH + 0x10 - 1 || x2 < -0x10) + { + sprite->invisible = TRUE; + } + + if ((s16)y > DISPLAY_HEIGHT + 0x10 - 1 || y2 < -0x10) + { + sprite->invisible = TRUE; + } +} + +static void LoadRotatingGatePics(void) +{ + LoadSpriteSheets(sRotatingGatesGraphicsTable); +} + +/* +static*/ void RotatingGate_DestroyGatesOutsideViewport(void) +{ + s16 x; + s16 x2; + s16 y; + s16 y2; + s16 xGate; + s16 yGate; + s32 i; + struct Sprite *sprite; + + // Same as RotatingGate_CreateGatesWithinViewport + x = gSaveBlock1Ptr->pos.x - 2; + x2 = gSaveBlock1Ptr->pos.x + 0x11; + y = gSaveBlock1Ptr->pos.y - 2; + y2 = gSaveBlock1Ptr->pos.y + 0xe; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + xGate = gRotatingGate_PuzzleConfig[i].x + 7; + yGate = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + continue; + + if (xGate < x || xGate > x2 || yGate < y || yGate > y2) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[i]]; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } + } +} + + +#ifdef NONMATCHING +bool8 MapGridIsImpassableAt(s32, s32); //fool the compiler + +static s32 RotatingGate_CanRotate(u8 gateId, s16 rotationDirection) +{ + const struct Coords8 *armPos; + u8 orientation; + s16 x; + s16 y; + u8 shape; + u32 shape8; + s32 i; + s32 j; + s32 armOrientation; + const u8 *gateArmCollisionData; + u8 armIndex; + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + armPos = sRotatingGate_ArmPositionsAntiClockwiseRotation; + else if (rotationDirection == ROTATE_CLOCKWISE) + armPos = sRotatingGate_ArmPositionsClockwiseRotation; + else + return FALSE; + + orientation = RotatingGate_GetGateOrientation(gateId); + + shape = gRotatingGate_PuzzleConfig[gateId].shape; + x = gRotatingGate_PuzzleConfig[gateId].x + 7; + y = gRotatingGate_PuzzleConfig[gateId].y + 7; + + + // Loop through the gate's "arms" clockwise (north, south, east, west) + for (i = GATE_ARM_NORTH, shape8 = shape* 4*2 ; i <= GATE_ARM_WEST; i++) + { + // Ensure that no part of the arm collides with the map + for (j = 0, armOrientation = orientation + i, gateArmCollisionData = (u8 *)((u32)sRotatingGate_ArmLayout + shape8 + 2*i); j < GATE_ARM_MAX_LENGTH; j++) + { + armIndex = 2 * (armOrientation % 4) + j; + + if (*gateArmCollisionData) + { + if (MapGridIsImpassableAt(x + armPos[armIndex].deltaX, y + armPos[armIndex].deltaY) == TRUE) + return FALSE; + } + gateArmCollisionData++; + } + } + + return TRUE; +} + +#else +NAKED +static s32 RotatingGate_CanRotate(u8 a, s16 rotationDirection) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0xC\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r1, 0x1\n\ + bne _080FBCFC\n\ + ldr r0, =sRotatingGate_ArmPositionsAntiClockwiseRotation\n\ + mov r10, r0\n\ + b _080FBD08\n\ + .pool\n\ +_080FBCFC:\n\ + cmp r1, 0x2\n\ + beq _080FBD04\n\ +_080FBD00:\n\ + movs r0, 0\n\ + b _080FBD98\n\ +_080FBD04:\n\ + ldr r1, =sRotatingGate_ArmPositionsClockwiseRotation\n\ + mov r10, r1\n\ +_080FBD08:\n\ + adds r0, r4, 0\n\ + bl RotatingGate_GetGateOrientation\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp]\n\ + ldr r0, =gRotatingGate_PuzzleConfig\n\ + ldr r1, [r0]\n\ + lsls r0, r4, 3\n\ + adds r0, r1\n\ + ldrb r2, [r0, 0x4]\n\ + ldrh r1, [r0]\n\ + adds r1, 0x7\n\ + ldrh r0, [r0, 0x2]\n\ + adds r0, 0x7\n\ + movs r3, 0\n\ + lsls r2, 3\n\ + str r2, [sp, 0x4]\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + mov r9, r1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + mov r8, r0\n\ +_080FBD38:\n\ + movs r6, 0\n\ + ldr r2, [sp]\n\ + adds r7, r2, r3\n\ + lsls r0, r3, 1\n\ + adds r5, r7, 0\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1\n\ + ldr r2, =sRotatingGate_ArmLayout\n\ + adds r4, r0, r2\n\ +_080FBD4A:\n\ + adds r0, r5, 0\n\ + cmp r5, 0\n\ + bge _080FBD52\n\ + adds r0, r7, 0x3\n\ +_080FBD52:\n\ + asrs r0, 2\n\ + lsls r0, 2\n\ + subs r0, r5, r0\n\ + lsls r0, 1\n\ + adds r0, r6\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + beq _080FBD88\n\ + lsls r1, 2\n\ + add r1, r10\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + add r0, r9\n\ + ldrb r1, [r1, 0x1]\n\ + lsls r1, 24\n\ + asrs r1, 24\n\ + add r1, r8\n\ + str r3, [sp, 0x8]\n\ + bl MapGridIsImpassableAt\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldr r3, [sp, 0x8]\n\ + cmp r0, 0x1\n\ + beq _080FBD00\n\ +_080FBD88:\n\ + adds r4, 0x1\n\ + adds r6, 0x1\n\ + cmp r6, 0x1\n\ + ble _080FBD4A\n\ + adds r3, 0x1\n\ + cmp r3, 0x3\n\ + ble _080FBD38\n\ + movs r0, 0x1\n\ +_080FBD98:\n\ + add sp, 0xC\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool\n\ +.syntax divided\n"); +} +#endif + +static s32 RotatingGate_HasArm(u8 gateId, u8 armInfo) +{ + s32 isLongArm; + s8 armOrientation; + s32 arm; + s32 shape; + + arm = armInfo >> 1; + isLongArm = armInfo & 1; + + armOrientation = (arm - RotatingGate_GetGateOrientation(gateId) + 4) % 4; + shape = gRotatingGate_PuzzleConfig[gateId].shape; + return sRotatingGate_ArmLayout[shape][armOrientation * 2 + isLongArm]; +} + +static void RotatingGate_TriggerRotationAnimation(u8 gateId, s32 rotationDirection) +{ + struct Sprite *sprite; + + if (gRotatingGate_GateSpriteIds[gateId] != MAX_SPRITES) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[gateId]]; + sprite->data[1] = rotationDirection; + sprite->data[2] = RotatingGate_GetGateOrientation(gateId); + } +} + +static u8 RotatingGate_GetRotationInfo(u8 direction, s16 x, s16 y) +{ + register const u8 *ptr; + + if (direction == DIR_NORTH) + ptr = sRotatingGate_RotationInfoNorth; + else if (direction == DIR_SOUTH) + ptr = sRotatingGate_RotationInfoSouth; + else if (direction == DIR_WEST) + ptr = sRotatingGate_RotationInfoWest; + else if (direction == DIR_EAST) + ptr = sRotatingGate_RotationInfoEast; + else + return GATE_ROT_NONE; + + return ptr[y * 4 + x]; +} + +void RotatingGate_InitPuzzle(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_LoadPuzzleConfig(); + RotatingGate_ResetAllGateOrientations(); + } +} + +void RotatingGatePuzzleCameraUpdate(u16 deltaX, u16 deltaY) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_CreateGatesWithinViewport(deltaX, deltaY); + RotatingGate_DestroyGatesOutsideViewport(); + } +} + +void RotatingGate_InitPuzzleAndGraphics(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + LoadRotatingGatePics(); + RotatingGate_LoadPuzzleConfig(); + RotatingGate_CreateGatesWithinViewport(0, 0); + } +} + +bool8 CheckForRotatingGatePuzzleCollision(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (RotatingGate_CanRotate(i, rotationDirection)) + { + RotatingGate_TriggerRotationAnimation(i, rotationDirection); + RotatingGate_RotateInDirection(i, rotationDirection); + return FALSE; + } + return TRUE; + } + } + } + } + return FALSE; +} + +bool8 CheckForRotatingGatePuzzleCollisionWithoutAnimation(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (!RotatingGate_CanRotate(i, rotationDirection)) + { + return TRUE; + } + } + } + } + } + return FALSE; +} diff --git a/src/safari_zone.c b/src/safari_zone.c index dd3cf3733..ab5c38f3a 100644 --- a/src/safari_zone.c +++ b/src/safari_zone.c @@ -30,9 +30,9 @@ extern void sub_80EE44C(u8, u8); extern void IncrementGameStat(u8 index); extern void ScriptContext1_SetupScript(u8*); extern void ScriptContext2_RunNewScript(u8*); -extern void c2_exit_to_overworld_2_switch(void); -extern void c2_exit_to_overworld_1_continue_scripts_restart_music(void); -extern void c2_load_new_map(void); +extern void CB2_ReturnToField(void); +extern void CB2_ReturnToFieldContinueScript(void); +extern void CB2_LoadMap(void); extern void sub_80AF6F0(void); extern void ScriptContext1_Stop(void); extern void warp_in(void); @@ -112,20 +112,20 @@ void CB2_EndSafariBattle(void) sSafariZoneCaughtMons++; if (gNumSafariBalls != 0) { - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); } else if (gBattleOutcome == B_OUTCOME_NO_SAFARI_BALLS) { ScriptContext2_RunNewScript(EventScript_2A4B4C); warp_in(); gFieldCallback = sub_80AF6F0; - SetMainCallback2(c2_load_new_map); + SetMainCallback2(CB2_LoadMap); } else if (gBattleOutcome == B_OUTCOME_CAUGHT) { ScriptContext1_SetupScript(EventScript_2A4B9B); ScriptContext1_Stop(); - SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + SetMainCallback2(CB2_ReturnToFieldContinueScript); } } diff --git a/src/save.c b/src/save.c index 8d77e801a..81731692e 100644 --- a/src/save.c +++ b/src/save.c @@ -3,17 +3,16 @@ #include "save.h" #include "constants/game_stat.h" #include "task.h" +#include "decompress.h" +#include "load_save.h" +#include "overworld.h" // for the chunk declarations -extern struct SaveBlock2 gSaveblock2; -extern struct SaveBlock1 gSaveblock1; -extern struct PokemonStorage gPokemonStorage; extern struct SaveSectionLocation gRamSaveSectionLocations[0xE]; -extern u8 gDecompressionBuffer[]; -extern u32 gFlashMemoryPresent; extern u16 gUnknown_03006294; extern bool8 gSoftResetDisabled; +extern u32 gUnknown_0203CF5C; // Divide save blocks into individual chunks to be written to flash sectors @@ -23,13 +22,13 @@ extern bool8 gSoftResetDisabled; /* * Sector Layout: - * + * * Sectors 0 - 13: Save Slot 1 * Sectors 14 - 27: Save Slot 2 * Sectors 28 - 29: Hall of Fame * Sector 30: e-Reader/Mystery Gift Stuff (note: e-Reader is deprecated in Emerald US) * Sector 31: Recorded Battle - * + * * There are two save slots for saving the player's game data. We alternate between * them each time the game is saved, so that if the current save slot is corrupt, * we can load the previous one. We also rotate the sectors in each save slot @@ -40,7 +39,7 @@ extern bool8 gSoftResetDisabled; // (u8 *)structure was removed from the first statement of the macro in Emerald. // This is because malloc is used to allocate addresses so storing the raw -// addresses should not be done in the offsets information. +// addresses should not be done in the offsets information. #define SAVEBLOCK_CHUNK(structure, chunkNum) \ { \ chunkNum * SECTOR_DATA_SIZE, \ @@ -68,8 +67,10 @@ const struct SaveSectionOffsets gSaveSectionOffsets[] = }; extern void DoSaveFailedScreen(u8); // save_failed_screen -extern void LoadSerializedGame(void); // load_save extern bool32 ProgramFlashSectorAndVerify(u8 sector, u8 *data); +extern void save_serialize_map(void); +extern void sub_800ADF8(void); +extern bool8 sub_800A520(void); // iwram common u16 gLastWrittenSector; @@ -96,7 +97,7 @@ void ClearSaveData(void) } } -void ResetSaveCounters(void) +void Save_ResetSaveCounters(void) { gSaveCounter = 0; gLastWrittenSector = 0; @@ -655,11 +656,6 @@ void UpdateSaveAddresses(void) } } -extern u32 GetGameStat(u8 index); // rom4 -extern void IncrementGameStat(u8 index); // rom4 -extern void SaveSerializedGame(void); // load_save -extern u32 gUnknown_0203CF5C; - u8 HandleSavingData(u8 saveType) { u8 i; @@ -670,25 +666,25 @@ u8 HandleSavingData(u8 saveType) UpdateSaveAddresses(); switch (saveType) { - case HOF_DELETE_SAVE: // deletes HOF before overwriting HOF completely. unused + case SAVE_HALL_OF_FAME_ERASE_BEFORE: // deletes HOF before overwriting HOF completely. unused for (i = 0xE * 2 + 0; i < 32; i++) EraseFlashSector(i); - case HOF_SAVE: // hall of fame. + case SAVE_HALL_OF_FAME: // hall of fame. if (GetGameStat(GAME_STAT_ENTERED_HOF) < 999) IncrementGameStat(GAME_STAT_ENTERED_HOF); SaveSerializedGame(); save_write_to_flash(0xFFFF, gRamSaveSectionLocations); - tempAddr = (u8 *)0x201C000; // FIXME: make this a label. + tempAddr = gDecompressionBuffer; HandleWriteSectorNBytes(0x1C, tempAddr, 0xF80); HandleWriteSectorNBytes(0x1D, tempAddr + 0xF80, 0xF80); break; - case NORMAL_SAVE: // normal save. also called by overwriting your own save. + case SAVE_NORMAL: // normal save. also called by overwriting your own save. default: SaveSerializedGame(); save_write_to_flash(0xFFFF, gRamSaveSectionLocations); break; - case LINK_SAVE: // _081532C4 - case LINK2_SAVE: + case SAVE_LINK: // _081532C4 + case SAVE_LINK2: SaveSerializedGame(); for(i = 0; i < 5; i++) ClearSaveData_2(i, gRamSaveSectionLocations); @@ -702,7 +698,7 @@ u8 HandleSavingData(u8 saveType) save_write_to_flash(0, gRamSaveSectionLocations); break; */ - case DIFFERENT_FILE_SAVE: + case SAVE_OVERWRITE_DIFFERENT_FILE: for (i = (0xE * 2 + 0); i < 32; i++) EraseFlashSector(i); // erase HOF. SaveSerializedGame(); @@ -799,7 +795,7 @@ bool8 sub_8153474(void) return retVal; } -u8 sub_81534D0(u8 a1) +u8 Save_LoadGameData(u8 a1) { u8 result; @@ -835,7 +831,7 @@ u16 sub_815355C(void) struct SaveSection* savSection; savSection = gFastSaveSection = &gSaveDataBuffer; - if (gFlashMemoryPresent != 1) + if (gFlashMemoryPresent != TRUE) return 0; UpdateSaveAddresses(); GetSaveValidStatus(gRamSaveSectionLocations); @@ -896,12 +892,6 @@ u32 sub_8153634(u8 sector, u8* src) return 1; } -extern void save_serialize_map(void); -extern void sub_8076D5C(void); -extern void sav2_gender2_inplace_and_xFE(void); -extern void sub_800ADF8(void); -extern bool8 sub_800A520(void); - void sub_8153688(u8 taskId) { s16* taskData = gTasks[taskId].data; diff --git a/src/scrcmd.c b/src/scrcmd.c index d2e9c13c9..a29e64979 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -31,7 +31,6 @@ #include "mystery_event_script.h" #include "palette.h" #include "party_menu.h" -#include "pokemon_3.h" #include "pokemon_storage_system.h" #include "random.h" #include "overworld.h" @@ -1477,20 +1476,14 @@ bool8 ScrCmd_showcontestwinner(struct ScriptContext *ctx) return TRUE; } -// Lots of math, can't figure it out. -/* bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) { u8 *ptr = (u8 *)ScriptReadWord(ctx); - struct WindowTemplate template1; - struct WindowTemplate template2; - int i; - u8 width; - u8 height; - int temp1; - int temp2; - u8 x; - u8 y; + struct WindowTemplate winTemplate; + s32 i; + u8 width, height; + u8 xWindow, yWindow, xText, yText; + u8 temp; StringExpandPlaceholders(gStringVar4, ptr + 6); @@ -1508,168 +1501,30 @@ bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) if (height > 0x12) height = 0x12; - x = width + 2; - temp1 = (0x1E - x) / 2; - x = temp1 + 1; - temp1 = ((x - temp1 - 1) * 8 + 3); + temp = width + 2; + xWindow = (0x1E - temp) / 2; - y = height + 2; - temp2 = (0x14 - y) / 2; - y = temp2 + 2; - temp2 = ((y - temp2 - 1) * 8); + temp = height + 2; + yText = (0x14 - temp) / 2; - sub_8198A50(&template1, 0, x, y, width, height, 0xF, 0x1); - template2 = template1; - gUnknown_03000F30 = AddWindow(&template2); + xText = xWindow; + xWindow += 1; + + yWindow = yText; + yText += 2; + + xText = (xWindow - xText - 1) * 8 + 3; + yText = (yText - yWindow - 1) * 8; + + winTemplate = sub_8198A50(0, xWindow, yWindow + 1, width, height, 0xF, 0x1); + gUnknown_03000F30 = AddWindow(&winTemplate); sub_809882C(gUnknown_03000F30, 0x214, 0xE0); NewMenuHelpers_DrawStdWindowFrame(gUnknown_03000F30, 0); PutWindowTilemap(gUnknown_03000F30); FillWindowPixelBuffer(gUnknown_03000F30, 0x11); - PrintTextOnWindow(gUnknown_03000F30, 6, gStringVar4, temp1, temp2, 0xFF, 0x0); + PrintTextOnWindow(gUnknown_03000F30, 6, gStringVar4, xText, yText, 0xFF, 0x0); CopyWindowToVram(gUnknown_03000F30, 3); return FALSE; -}*/ -__attribute__((naked)) -bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) -{ - asm("push {r4-r7,lr}\n\ - mov r7, r8\n\ - push {r7}\n\ - sub sp, #0x20\n\ - bl ScriptReadWord\n\ - add r1, r0, #0\n\ - ldr r4, =gStringVar4\n\ - add r1, #0x6\n\ - add r0, r4, #0\n\ - bl StringExpandPlaceholders\n\ - mov r2, #0x1\n\ - neg r2, r2\n\ - mov r0, #0x6\n\ - add r1, r4, #0\n\ - bl GetStringWidth\n\ - lsr r0, #3\n\ - lsl r0, #24\n\ - lsr r7, r0, #24\n\ - cmp r7, #0x1C\n\ - bls _0809AE9C\n\ - mov r7, #0x1C\n\ -_0809AE9C:\n\ - mov r5, #0x4\n\ - ldrb r0, [r4]\n\ - add r2, r7, #0x2\n\ - add r1, sp, #0x18\n\ - mov r8, r1\n\ - cmp r0, #0xFF\n\ - beq _0809AEC0\n\ - add r1, r4, #0\n\ -_0809AEAC:\n\ - ldrb r0, [r1]\n\ - add r1, #0x1\n\ - cmp r0, #0xFE\n\ - bne _0809AEBA\n\ - add r0, r5, #0x3\n\ - lsl r0, #24\n\ - lsr r5, r0, #24\n\ -_0809AEBA:\n\ - ldrb r0, [r1]\n\ - cmp r0, #0xFF\n\ - bne _0809AEAC\n\ -_0809AEC0:\n\ - cmp r5, #0x12\n\ - bls _0809AEC6\n\ - mov r5, #0x12\n\ -_0809AEC6:\n\ - lsl r0, r2, #24\n\ - lsr r0, #24\n\ - mov r2, #0x1E\n\ - sub r2, r0\n\ - lsr r0, r2, #31\n\ - add r2, r0\n\ - asr r2, #1\n\ - lsl r2, #24\n\ - add r0, r5, #0x2\n\ - lsl r0, #24\n\ - lsr r0, #24\n\ - mov r4, #0x14\n\ - sub r4, r0\n\ - lsr r0, r4, #31\n\ - add r4, r0\n\ - asr r4, #1\n\ - lsl r4, #24\n\ - lsr r6, r2, #24\n\ - mov r0, #0x80\n\ - lsl r0, #17\n\ - add r2, r0\n\ - lsr r2, #24\n\ - lsr r3, r4, #24\n\ - mov r1, #0x80\n\ - lsl r1, #18\n\ - add r4, r1\n\ - lsr r4, #24\n\ - sub r6, r2, r6\n\ - sub r6, #0x1\n\ - lsl r6, #3\n\ - add r6, #0x3\n\ - lsl r6, #24\n\ - lsr r6, #24\n\ - sub r4, r3\n\ - sub r4, #0x1\n\ - lsl r4, #27\n\ - lsr r4, #24\n\ - add r3, #0x1\n\ - lsl r3, #24\n\ - lsr r3, #24\n\ - str r7, [sp]\n\ - str r5, [sp, #0x4]\n\ - mov r0, #0xF\n\ - str r0, [sp, #0x8]\n\ - mov r0, #0x1\n\ - str r0, [sp, #0xC]\n\ - add r0, sp, #0x10\n\ - mov r1, #0\n\ - bl sub_8198A50\n\ - ldr r0, [sp, #0x10]\n\ - ldr r1, [sp, #0x14]\n\ - str r0, [sp, #0x18]\n\ - str r1, [sp, #0x1C]\n\ - ldr r5, =gUnknown_03000F30\n\ - mov r0, r8\n\ - bl AddWindow\n\ - strb r0, [r5]\n\ - ldrb r0, [r5]\n\ - mov r1, #0x85\n\ - lsl r1, #2\n\ - mov r2, #0xE0\n\ - bl sub_809882C\n\ - ldrb r0, [r5]\n\ - mov r1, #0\n\ - bl NewMenuHelpers_DrawStdWindowFrame\n\ - ldrb r0, [r5]\n\ - bl PutWindowTilemap\n\ - ldrb r0, [r5]\n\ - mov r1, #0x11\n\ - bl FillWindowPixelBuffer\n\ - ldrb r0, [r5]\n\ - ldr r2, =gStringVar4\n\ - str r4, [sp]\n\ - mov r1, #0xFF\n\ - str r1, [sp, #0x4]\n\ - mov r1, #0\n\ - str r1, [sp, #0x8]\n\ - mov r1, #0x6\n\ - add r3, r6, #0\n\ - bl PrintTextOnWindow\n\ - ldrb r0, [r5]\n\ - mov r1, #0x3\n\ - bl CopyWindowToVram\n\ - mov r0, #0\n\ - add sp, #0x20\n\ - pop {r3}\n\ - mov r8, r3\n\ - pop {r4-r7}\n\ - pop {r1}\n\ - bx r1\n\ - .pool"); } bool8 ScrCmd_cmdDA(struct ScriptContext *ctx) @@ -1757,7 +1612,7 @@ bool8 ScrCmd_buffernumberstring(struct ScriptContext *ctx) { u8 stringVarIndex = ScriptReadByte(ctx); u16 v1 = VarGet(ScriptReadHalfword(ctx)); - u8 v2 = sub_80EF370(v1); + u8 v2 = CountDigits(v1); ConvertIntToDecimalStringN(sScriptStringVars[stringVarIndex], v1, 0, v2); return FALSE; @@ -2055,7 +1910,7 @@ bool8 ScrCmd_playslotmachine(struct ScriptContext *ctx) { u8 slotMachineIndex = VarGet(ScriptReadHalfword(ctx)); - PlaySlotMachine(slotMachineIndex, c2_exit_to_overworld_1_continue_scripts_restart_music); + PlaySlotMachine(slotMachineIndex, CB2_ReturnToFieldContinueScript); ScriptContext1_Stop(); return TRUE; } diff --git a/src/script.c b/src/script.c index 5a1c5daa9..8c868128b 100644 --- a/src/script.c +++ b/src/script.c @@ -243,7 +243,7 @@ void ScriptContext2_RunNewScript(const u8 *ptr) u8 *mapheader_get_tagged_pointer(u8 tag) { - u8 *mapScripts = gMapHeader.mapScripts; + const u8 *mapScripts = gMapHeader.mapScripts; if (!mapScripts) return NULL; diff --git a/src/script_movement.c b/src/script_movement.c new file mode 100644 index 000000000..bbeb0eedc --- /dev/null +++ b/src/script_movement.c @@ -0,0 +1,233 @@ +#include "global.h" +#include "script_movement.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "task.h" +#include "util.h" + +// static functions +static void sub_80D33AC(u8); +static u8 sub_80D33F4(void); +static bool8 sub_80D3408(u8, u8, const u8 *); +static u8 sub_80D3474(u8, u8); +static bool8 sub_80D3584(u8, u8); +static void sub_80D35DC(u8, u8, u8, const u8 *); +static void UnfreezeObjects(u8); +static void sub_80D3660(u8); +static void sub_80A2490(u8, u8, u8, const u8 *); + +// EWRAM_DATA +static EWRAM_DATA const u8 *gUnknown_02039D90[16] = {0}; + +// text +bool8 ScriptMovement_StartObjectMovementScript(u8 localId, u8 mapNum, u8 mapGroup, const u8 *movementScript) +{ + u8 mapObjId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjId)) + return TRUE; + if (!FuncIsActiveTask(sub_80D3660)) + sub_80D33AC(50); + return sub_80D3408(sub_80D33F4(), mapObjId, movementScript); +} + +bool8 ScriptMovement_IsObjectMovementFinished(u8 localId, u8 mapNum, u8 mapBank) +{ + u8 mapObjId; + u8 r4; + u8 r1; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapBank, &mapObjId)) + return TRUE; + r4 = sub_80D33F4(); + r1 = sub_80D3474(r4, mapObjId); + if (r1 == 16) + return TRUE; + return sub_80D3584(r4, r1); +} + +void sub_80D338C(void) +{ + u8 taskId; + + taskId = sub_80D33F4(); + if (taskId != 0xFF) + { + UnfreezeObjects(taskId); + DestroyTask(taskId); + } +} + + +static void sub_80D33AC(u8 priority) +{ + u8 taskId; + u8 i; + + taskId = CreateTask(sub_80D3660, priority); + for (i = 1; i < 16; i++) + gTasks[taskId].data[i] = 0xFFFF; +} + +static u8 sub_80D33F4(void) +{ + return FindTaskIdByFunc(sub_80D3660); +} + +static bool8 sub_80D3408(u8 taskId, u8 mapObjId, const u8 *movementScript) +{ + u8 r4; + + r4 = sub_80D3474(taskId, mapObjId); + if (r4 != 16) + { + if (sub_80D3584(taskId, r4) == 0) + { + return TRUE; + } + else + { + sub_80D35DC(taskId, r4, mapObjId, movementScript); + return FALSE; + } + } + r4 = sub_80D3474(taskId, 0xFF); + if (r4 == 16) + { + return TRUE; + } + else + { + sub_80D35DC(taskId, r4, mapObjId, movementScript); + return FALSE; + } +} + +static u8 sub_80D3474(u8 taskId, u8 b) +{ + u8 *ptr; + u8 i; + + ptr = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, ptr++) + { + if (*ptr == b) + return i; + } + return 16; +} + +static void sub_80D34B0(u8 taskId, u8 b, u8 **c) +{ + u8 i; + + *c = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < b; i++, (*c)++) + ; +} + +static void sub_80D34E4(u8 taskId, u8 b, u8 c) +{ + u8 *ptr; + + sub_80D34B0(taskId, b, &ptr); + *ptr = c; //what is this supposed to do? +} + +static void sub_80D3508(u8 taskId, u8 b, u8 *c) +{ + u8 *ptr; + + sub_80D34B0(taskId, b, &ptr); + *c = *ptr; +} + +static void sub_80D352C(u8 a, u8 b) +{ + u16 var = ~gBitTable[b]; + + gTasks[a].data[0] &= var; +} + +static void sub_80D355C(u8 taskId, u8 b) +{ + gTasks[taskId].data[0] |= gBitTable[b]; +} + +static bool8 sub_80D3584(u8 taskId, u8 b) +{ + u16 var = (u16)gTasks[taskId].data[0] & gBitTable[b]; + + if (var != 0) + return TRUE; + else + return FALSE; +} + +static void npc_obj_offscreen_culling_and_flag_update(u8 a, const u8 *movementScript) +{ + gUnknown_02039D90[a] = movementScript; +} + +static const u8 *sub_80D35CC(u8 a) +{ + return gUnknown_02039D90[a]; +} + +static void sub_80D35DC(u8 taskId, u8 b, u8 mapObjId, const u8 *movementScript) +{ + sub_80D352C(taskId, b); + npc_obj_offscreen_culling_and_flag_update(b, movementScript); + sub_80D34E4(taskId, b, mapObjId); +} + +static void UnfreezeObjects(u8 taskId) +{ + u8 *pMapObjId; + u8 i; + + pMapObjId = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, pMapObjId++) + { + if (*pMapObjId != 0xFF) + npc_sync_anim_pause_bits(&gMapObjects[*pMapObjId]); + } +} + +static void sub_80D3660(u8 taskId) +{ + u8 i; + u8 var; + + for (i = 0; i < 16; i++) + { + sub_80D3508(taskId, i, &var); + if (var != 0xFF) + sub_80A2490(taskId, i, var, sub_80D35CC(i)); + } +} + +static void sub_80A2490(u8 taskId, u8 b, u8 mapObjId, const u8 *d) +{ + u8 var; + + if (FieldObjectIsSpecialAnimActive(&gMapObjects[mapObjId]) + && !FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId])) + return; + + var = *d; + if (var == 0xFE) + { + sub_80D355C(taskId, b); + FreezeMapObject(&gMapObjects[mapObjId]); + } + else + { + if (!FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], var)) + { + d++; + npc_obj_offscreen_culling_and_flag_update(b, d); + } + } +} + diff --git a/src/secret_base.c b/src/secret_base.c index e3c06a75d..e2b7e20f1 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -3,10 +3,11 @@ #include "global.h" #include "constants/decorations.h" #include "malloc.h" +#include "main.h" #include "task.h" #include "palette.h" -#include "list_menu.h" #include "window.h" +#include "list_menu.h" #include "menu.h" #include "menu_helpers.h" #include "menu_indicators.h" @@ -39,6 +40,8 @@ #include "tv.h" #include "secret_base.h" +extern void mapldr_default(void); + // Static type declarations struct SecretBaseListMenuBuffer { @@ -61,7 +64,7 @@ EWRAM_DATA struct SecretBaseListMenuBuffer *gUnknown_0203A020 = NULL; void sub_80E9C9C(u8 taskId); void game_continue(u8 taskId); -void sub_80E9DEC(u32 a0, bool8 flag, struct ListMenu *menu); +void sub_80E9DEC(s32 a0, bool8 flag, struct ListMenu *menu); void sub_80E9E00(u8 taskId); void sub_80E9E44(u8 taskId); void sub_80E9E90(u8 taskId); @@ -244,7 +247,7 @@ void sub_80E8C98(void) void sub_80E8CB0(s16 *xPtr, s16 *yPtr, u16 tile) { - struct MapData *mapData; + const struct MapData *mapData; s16 x; s16 y; @@ -322,7 +325,7 @@ void sub_80E8E18(void) VarSet(VAR_SECRET_BASE_MAP, gMapHeader.regionMapSectionId); } -void sub_80E8EE0(struct MapEvents *events) +void sub_80E8EE0(struct MapEvents const *events) { u16 bgEventIndex; u16 i; @@ -386,7 +389,7 @@ void sub_80E8FD0(u8 taskId) sub_80E8F9C(); warp_in(); gFieldCallback = sub_80AF168; - SetMainCallback2(c2_load_new_map); + SetMainCallback2(CB2_LoadMap); DestroyTask(taskId); break; } @@ -411,7 +414,7 @@ bool8 sub_80E909C(void) void sub_80E90C8(u8 taskId) { FieldObjectTurn(&gMapObjects[gPlayerAvatar.mapObjectId], DIR_NORTH); - if (sub_80ABDFC() == TRUE) + if (IsWeatherNotFadingIn() == TRUE) { EnableBothScriptContexts(); DestroyTask(taskId); @@ -444,7 +447,7 @@ void sub_80E916C(u8 taskId) Overworld_SetWarpDestination(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1, gUnknown_0858CFE8[idx + 2], gUnknown_0858CFE8[idx + 3]); warp_in(); gFieldCallback = sub_80E9108; - SetMainCallback2(c2_load_new_map); + SetMainCallback2(CB2_LoadMap); DestroyTask(taskId); } } @@ -642,7 +645,7 @@ void sub_80E96A4(u8 taskId) copy_saved_warp2_bank_and_enter_x_to_warp1(0x7e); warp_in(); gFieldCallback = mapldr_default; - SetMainCallback2(c2_load_new_map); + SetMainCallback2(CB2_LoadMap); ScriptContext2_Disable(); DestroyTask(taskId); break; @@ -773,7 +776,7 @@ void sub_80E9AD0(void) u16 i; u16 j; s16 tile; - struct MapEvents *events; + const struct MapEvents *events; events = gMapHeader.events; for (i = 0; i < events->bgEventCount; i ++) @@ -908,13 +911,13 @@ void game_continue(u8 taskId) data[3] = 8; } gMultiuseListMenuTemplate = gUnknown_0858D07C; - gMultiuseListMenuTemplate.unk_10 = data[6]; + gMultiuseListMenuTemplate.windowId = data[6]; gMultiuseListMenuTemplate.totalItems = data[0]; gMultiuseListMenuTemplate.items = gUnknown_0203A020->items; gMultiuseListMenuTemplate.maxShowed = data[3]; } -void sub_80E9DEC(u32 a0, bool8 flag, struct ListMenu *menu) +void sub_80E9DEC(s32 a0, bool8 flag, struct ListMenu *menu) { if (flag != TRUE) { @@ -948,14 +951,14 @@ void sub_80E9E90(u8 taskId) data = gTasks[taskId].data; input = ListMenuHandleInputGetItemId(data[5]); - sub_81AE860(data[5], &data[2], &data[1]); + ListMenuGetScrollAndRow(data[5], &data[2], &data[1]); switch (input) { case -1: break; case -2: PlaySE(SE_SELECT); - sub_81AE6C8(data[5], NULL, NULL); + DestroyListMenuTask(data[5], NULL, NULL); RemoveScrollIndicatorArrowPair(data[8]); sub_819746C(data[6], 0); ClearWindowTilemap(data[6]); @@ -1037,7 +1040,7 @@ void sub_80EA08C(u8 taskId) data = gTasks[taskId].data; sub_8197434(0, 0); - sub_81AE6C8(data[5], &data[2], &data[1]); + DestroyListMenuTask(data[5], &data[2], &data[1]); gSaveBlock1Ptr->secretBases[data[4]].sbr_field_1_6 = 0; game_continue(taskId); sub_812225C(&data[2], &data[1], data[3], data[0]); @@ -1056,7 +1059,7 @@ void sub_80EA13C(u8 taskId) data = gTasks[taskId].data; sub_8197434(0, 0); - sub_81AE6C8(data[5], &data[2], &data[1]); + DestroyListMenuTask(data[5], &data[2], &data[1]); sub_80E9E00(taskId); gTasks[taskId].func = sub_80E9E90; } diff --git a/src/smokescreen.c b/src/smokescreen.c new file mode 100644 index 000000000..9b37cd234 --- /dev/null +++ b/src/smokescreen.c @@ -0,0 +1,71 @@ +#include "global.h" +#include "data2.h" +#include "decompress.h" +#include "sprite.h" +#include "util.h" + +static void sub_8075370(struct Sprite *); + +u8 sub_807521C(s16 x, s16 y, u8 a3) +{ + u8 mainSpriteId; + u8 spriteId1, spriteId2, spriteId3, spriteId4; + struct Sprite *mainSprite; + + if (GetSpriteTileStartByTag(gUnknown_0831C620.tag) == 0xFFFF) + { + LoadCompressedObjectPicUsingHeap(&gUnknown_0831C620); + LoadCompressedObjectPaletteUsingHeap(&gUnknown_0831C628); + } + + mainSpriteId = CreateInvisibleSpriteWithCallback(sub_8075370); + mainSprite = &gSprites[mainSpriteId]; + mainSprite->data[1] = a3; + + spriteId1 = CreateSprite(&gUnknown_0831C688, x - 16, y - 16, 2); + gSprites[spriteId1].data[0] = mainSpriteId; + mainSprite->data[0]++; + AnimateSprite(&gSprites[spriteId1]); + + spriteId2 = CreateSprite(&gUnknown_0831C688, x, y - 16, 2); + gSprites[spriteId2].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId2], 1); + AnimateSprite(&gSprites[spriteId2]); + + spriteId3 = CreateSprite(&gUnknown_0831C688, x - 16, y, 2); + gSprites[spriteId3].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId3], 2); + AnimateSprite(&gSprites[spriteId3]); + + spriteId4 = CreateSprite(&gUnknown_0831C688, x, y, 2); + gSprites[spriteId4].data[0] = mainSpriteId; + mainSprite->data[0]++; + StartSpriteAnim(&gSprites[spriteId4], 3); + AnimateSprite(&gSprites[spriteId4]); + + return mainSpriteId; +} + +static void sub_8075370(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + FreeSpriteTilesByTag(gUnknown_0831C620.tag); + FreeSpritePaletteByTag(gUnknown_0831C628.tag); + if (!sprite->data[1]) + DestroySprite(sprite); + else + sprite->callback = SpriteCallbackDummy; + } +} + +void sub_80753B4(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + gSprites[sprite->data[0]].data[0]--; + DestroySprite(sprite); + } +} diff --git a/src/start_menu.c b/src/start_menu.c index d076d307d..c248ca86b 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -8,6 +8,31 @@ #include "text.h" #include "strings.h" #include "bg.h" +#include "field_effect.h" +#include "task.h" +#include "overworld.h" +#include "link.h" +#include "battle_frontier_2.h" +#include "rom_818CFC8.h" +#include "field_specials.h" +#include "field_map_obj_helpers.h" +#include "script.h" +#include "main.h" +#include "sound.h" +#include "pokedex.h" +#include "field_weather.h" +#include "palette.h" +#include "item_menu.h" +#include "option_menu.h" +#include "event_scripts.h" +#include "save.h" +#include "gpu_regs.h" +#include "scanline_effect.h" +#include "text_window.h" +#include "load_save.h" +#include "international_string_util.h" +#include "constants/songs.h" +#include "field_player_avatar.h" // Menu actions enum @@ -27,49 +52,99 @@ enum MENU_ACTION_PYRAMID_BAG }; -extern bool32 is_c1_link_related_active(void); -extern bool32 InUnionRoom(void); -extern bool8 InBattlePike(void); -extern bool8 InBattlePyramid(void); -extern bool8 InMultiBattleRoom(void); -extern void NewMenuHelpers_DrawStdWindowFrame(u8 windowId, u8 a1); -extern void sub_8198070(u8 windowId, u8 a1); - -// this file's functions -static void BuildStartMenuActions_LinkMode(void); -static void BuildStartMenuActions_UnionRoom(void); -static void BuildStartMenuActions_SafariZone(void); -static void BuildStartMenuActions_BattlePike(void); -static void BuildStartMenuActions_BattlePyramid(void); -static void BuildStartMenuActions_MultiBattleRoom(void); -static void BuildStartMenuActions_Normal(void); -bool8 StartMenu_Pokedex(void); -bool8 StartMenu_Pokemon(void); -bool8 StartMenu_Bag(void); -bool8 StartMenu_PokeNav(void); -bool8 StartMenu_PlayerName(void); -bool8 StartMenu_Save(void); -bool8 StartMenu_Option(void); -bool8 StartMenu_Exit(void); -bool8 StartMenu_SafariZoneRetire(void); -bool8 StartMenu_LinkModePlayerName(void); -bool8 StartMenu_BattlePyramidRetire(void); -bool8 StartMenu_BattlePyramidBag(void); - -// EWRAM vars -EWRAM_DATA u8 sSafariBallsWindowId = 0; -EWRAM_DATA u8 sBattlePyramidFloorWindowId = 0; -EWRAM_DATA u8 sStartMenuCursorPos = 0; -EWRAM_DATA u8 sNumStartMenuActions = 0; -EWRAM_DATA u8 sCurrentStartMenuActions[9] = {0}; -EWRAM_DATA u8 gUnknown_02037619[2] = {0}; -EWRAM_DATA bool8 (*gUnknown_0203761C)(void) = NULL; -EWRAM_DATA u8 gUnknown_02037620 = 0; -EWRAM_DATA u8 gUnknown_02037621 = 0; -EWRAM_DATA u8 gUnknown_02037622 = 0; - -// const rom data -static const struct WindowTemplate gSafariBallsWindowTemplate = {0, 1, 1, 9, 4, 0xF, 8}; +// Save status +enum +{ + SAVE_IN_PROGRESS, + SAVE_SUCCESS, + SAVE_CANCELED, + SAVE_ERROR +}; + +EWRAM_DATA static u8 sSafariBallsWindowId = 0; +EWRAM_DATA static u8 sBattlePyramidFloorWindowId = 0; +EWRAM_DATA static u8 sStartMenuCursorPos = 0; +EWRAM_DATA static u8 sNumStartMenuActions = 0; +EWRAM_DATA static u8 sCurrentStartMenuActions[9] = {0}; +EWRAM_DATA static u8 sUnknown_02037619[2] = {0}; + +EWRAM_DATA static u8 (*sSaveDialogCallback)(void) = NULL; +EWRAM_DATA static u8 sSaveDialogTimer = 0; +EWRAM_DATA static bool8 sSavingComplete = FALSE; +EWRAM_DATA static u8 sSaveInfoWindowId = 0; + +// Extern variables +extern u8 gDifferentSaveFile; +extern u16 gSaveFileStatus; +extern u8 gUnknown_03005DB4; + +// Extern functions in uncompiled files +extern void sub_80AF688(void); +extern void var_800D_set_xB(void); +extern void sub_808B864(void); +extern void sub_80BB534(void); +extern void play_some_sound(void); +extern void CB2_PartyMenuFromStartMenu(void); +extern void CB2_PokeNav(void); +extern void sub_80C4DDC(void (*)(void)); +extern void sub_80C51C4(void (*)(void)); +extern void sub_80C4E74(u8, void (*)(void)); +extern void sub_81C4EFC(void); +extern void sub_80984F4(void); +extern void sub_81A9EC8(void); +extern void save_serialize_map(void); +extern void sub_81A9E90(void); + +// Menu action callbacks +static bool8 StartMenuPokedexCallback(void); +static bool8 StartMenuPokemonCallback(void); +static bool8 StartMenuBagCallback(void); +static bool8 StartMenuPokeNavCallback(void); +static bool8 StartMenuPlayerNameCallback(void); +static bool8 StartMenuSaveCallback(void); +static bool8 StartMenuOptionCallback(void); +static bool8 StartMenuExitCallback(void); +static bool8 StartMenuSafariZoneRetireCallback(void); +static bool8 StartMenuLinkModePlayerNameCallback(void); +static bool8 StartMenuBattlePyramidRetireCallback(void); +static bool8 StartMenuBattlePyramidBagCallback(void); + +// Menu callbacks +static bool8 SaveStartCallback(void); +static bool8 SaveCallback(void); +static bool8 BattlePyramidRetireStartCallback(void); +static bool8 BattlePyramidRetireReturnCallback(void); +static bool8 BattlePyramidRetireCallback(void); +static bool8 HandleStartMenuInput(void); + +// Save dialog callbacks +static u8 SaveConfirmSaveCallback(void); +static u8 SaveYesNoCallback(void); +static u8 SaveConfirmInputCallback(void); +static u8 SaveFileExistsCallback(void); +static u8 SaveConfirmOverwriteNoCallback(void); +static u8 SaveConfirmOverwriteCallback(void); +static u8 SaveOverwriteInputCallback(void); +static u8 SaveSavingMessageCallback(void); +static u8 SaveDoSaveCallback(void); +static u8 SaveSuccessCallback(void); +static u8 SaveReturnSuccessCallback(void); +static u8 SaveErrorCallback(void); +static u8 SaveReturnErrorCallback(void); +static u8 BattlePyramidConfirmRetireCallback(void); +static u8 BattlePyramidRetireYesNoCallback(void); +static u8 BattlePyramidRetireInputCallback(void); + +// Task callbacks +static void StartMenuTask(u8 taskId); +static void SaveGameTask(u8 taskId); +static void sub_80A0550(u8 taskId); +static void sub_80A08A4(u8 taskId); + +// Some other callback +static bool8 sub_809FA00(void); + +static const struct WindowTemplate sSafariBallsWindowTemplate = {0, 1, 1, 9, 4, 0xF, 8}; static const u8* const sPyramindFloorNames[] = { @@ -83,27 +158,27 @@ static const u8* const sPyramindFloorNames[] = gText_Peak }; -static const struct WindowTemplate gPyramidFloorWindowTemplate_2 = {0, 1, 1, 0xA, 4, 0xF, 8}; -static const struct WindowTemplate gPyramidFloorWindowTemplate_1 = {0, 1, 1, 0xC, 4, 0xF, 8}; - -const struct MenuAction sStartMenuItems[] = -{ - {gText_MenuPokedex, {.u8_void = StartMenu_Pokedex}}, - {gText_MenuPokemon, {.u8_void = StartMenu_Pokemon}}, - {gText_MenuBag, {.u8_void = StartMenu_Bag}}, - {gText_MenuPokenav, {.u8_void = StartMenu_PokeNav}}, - {gText_MenuPlayer, {.u8_void = StartMenu_PlayerName}}, - {gText_MenuSave, {.u8_void = StartMenu_Save}}, - {gText_MenuOption, {.u8_void = StartMenu_Option}}, - {gText_MenuExit, {.u8_void = StartMenu_Exit}}, - {gText_MenuRetire, {.u8_void = StartMenu_SafariZoneRetire}}, - {gText_MenuPlayer, {.u8_void = StartMenu_LinkModePlayerName}}, - {gText_MenuRest, {.u8_void = StartMenu_Save}}, - {gText_MenuRetire, {.u8_void = StartMenu_BattlePyramidRetire}}, - {gText_MenuBag, {.u8_void = StartMenu_BattlePyramidBag}} +static const struct WindowTemplate sPyramidFloorWindowTemplate_2 = {0, 1, 1, 0xA, 4, 0xF, 8}; +static const struct WindowTemplate sPyramidFloorWindowTemplate_1 = {0, 1, 1, 0xC, 4, 0xF, 8}; + +static const struct MenuAction sStartMenuItems[] = +{ + {gText_MenuPokedex, {.u8_void = StartMenuPokedexCallback}}, + {gText_MenuPokemon, {.u8_void = StartMenuPokemonCallback}}, + {gText_MenuBag, {.u8_void = StartMenuBagCallback}}, + {gText_MenuPokenav, {.u8_void = StartMenuPokeNavCallback}}, + {gText_MenuPlayer, {.u8_void = StartMenuPlayerNameCallback}}, + {gText_MenuSave, {.u8_void = StartMenuSaveCallback}}, + {gText_MenuOption, {.u8_void = StartMenuOptionCallback}}, + {gText_MenuExit, {.u8_void = StartMenuExitCallback}}, + {gText_MenuRetire, {.u8_void = StartMenuSafariZoneRetireCallback}}, + {gText_MenuPlayer, {.u8_void = StartMenuLinkModePlayerNameCallback}}, + {gText_MenuRest, {.u8_void = StartMenuSaveCallback}}, + {gText_MenuRetire, {.u8_void = StartMenuBattlePyramidRetireCallback}}, + {gText_MenuBag, {.u8_void = StartMenuBattlePyramidBagCallback}} }; -const struct BgTemplate gUnknown_085105A8[] = +static const struct BgTemplate sUnknown_085105A8[] = { { .bg = 0, @@ -116,15 +191,47 @@ const struct BgTemplate gUnknown_085105A8[] = } }; -const struct WindowTemplate gUnknown_085105AC[] = +static const struct WindowTemplate sUnknown_085105AC[] = { {0, 2, 0xF, 0x1A, 4, 0xF, 0x194}, DUMMY_WIN_TEMPLATE }; -const struct WindowTemplate gUnknown_085105BC = {0, 1, 1, 0xE, 0xA, 0xF, 8}; +static const struct WindowTemplate sSaveInfoWindowTemplate = {0, 1, 1, 0xE, 0xA, 0xF, 8}; + +// Local functions +static void BuildStartMenuActions(void); +static void AddStartMenuAction(u8 action); +static void BuildNormalStartMenu(void); +static void BuildSafariZoneStartMenu(void); +static void BuildLinkModeStartMenu(void); +static void BuildUnionRoomStartMenu(void); +static void BuildBattlePikeStartMenu(void); +static void BuildBattlePyramidStartMenu(void); +static void BuildMultiBattleRoomStartMenu(void); +static void ShowSafariBallsWindow(void); +static void ShowPyramidFloorWindow(void); +static void RemoveExtraStartMenuWindows(void); +static bool32 PrintStartMenuActions(s8 *pIndex, u32 count); +static bool32 InitStartMenuStep(void); +static void InitStartMenu(void); +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 HideSaveInfoWindow(void); +static void SaveStartTimer(void); +static bool8 SaveSuccesTimer(void); +static bool8 SaveErrorTimer(void); +static void InitBattlePyramidRetire(void); +static void sub_80A03D8(void); +static bool32 sub_80A03E4(u8 *par1); +static void sub_80A0540(void); +static void ShowSaveInfoWindow(void); +static void RemoveSaveInfoWindow(void); +static void HideStartMenuWindow(void); -// code void SetDexPokemonPokenavFlags(void) // unused { FlagSet(FLAG_SYS_POKEDEX_GET); @@ -132,46 +239,70 @@ void SetDexPokemonPokenavFlags(void) // unused FlagSet(FLAG_SYS_POKENAV_GET); } -void BuildStartMenuActions(void) +static void BuildStartMenuActions(void) { sNumStartMenuActions = 0; + if (is_c1_link_related_active() == TRUE) - BuildStartMenuActions_LinkMode(); + { + BuildLinkModeStartMenu(); + } else if (InUnionRoom() == TRUE) - BuildStartMenuActions_UnionRoom(); + { + BuildUnionRoomStartMenu(); + } else if (GetSafariZoneFlag() == TRUE) - BuildStartMenuActions_SafariZone(); + { + BuildSafariZoneStartMenu(); + } else if (InBattlePike()) - BuildStartMenuActions_BattlePike(); + { + BuildBattlePikeStartMenu(); + } else if (InBattlePyramid()) - BuildStartMenuActions_BattlePyramid(); + { + BuildBattlePyramidStartMenu(); + } else if (InMultiBattleRoom()) - BuildStartMenuActions_MultiBattleRoom(); + { + BuildMultiBattleRoomStartMenu(); + } else - BuildStartMenuActions_Normal(); + { + BuildNormalStartMenu(); + } } -void AddStartMenuAction(u8 action) +static void AddStartMenuAction(u8 action) { AppendToList(sCurrentStartMenuActions, &sNumStartMenuActions, action); } -static void BuildStartMenuActions_Normal(void) +static void BuildNormalStartMenu(void) { if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) + { AddStartMenuAction(MENU_ACTION_POKEDEX); + } if (FlagGet(FLAG_SYS_POKEMON_GET) == TRUE) + { AddStartMenuAction(MENU_ACTION_POKEMON); + } + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) + { AddStartMenuAction(MENU_ACTION_POKENAV); + } + AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_SAVE); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_SafariZone(void) +static void BuildSafariZoneStartMenu(void) { AddStartMenuAction(MENU_ACTION_RETIRE_SAFARI); AddStartMenuAction(MENU_ACTION_POKEDEX); @@ -182,29 +313,37 @@ static void BuildStartMenuActions_SafariZone(void) AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_LinkMode(void) +static void BuildLinkModeStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) + { AddStartMenuAction(MENU_ACTION_POKENAV); + } + AddStartMenuAction(MENU_ACTION_PLAYER_LINK); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_UnionRoom(void) +static void BuildUnionRoomStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) + { AddStartMenuAction(MENU_ACTION_POKENAV); + } + AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_BattlePike(void) +static void BuildBattlePikeStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEDEX); AddStartMenuAction(MENU_ACTION_POKEMON); @@ -213,7 +352,7 @@ static void BuildStartMenuActions_BattlePike(void) AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_BattlePyramid(void) +static void BuildBattlePyramidStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_PYRAMID_BAG); @@ -224,7 +363,7 @@ static void BuildStartMenuActions_BattlePyramid(void) AddStartMenuAction(MENU_ACTION_EXIT); } -static void BuildStartMenuActions_MultiBattleRoom(void) +static void BuildMultiBattleRoomStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_PLAYER); @@ -232,74 +371,1056 @@ static void BuildStartMenuActions_MultiBattleRoom(void) AddStartMenuAction(MENU_ACTION_EXIT); } -void DisplaySafariBallsWindow(void) +static void ShowSafariBallsWindow(void) { - sSafariBallsWindowId = AddWindow(&gSafariBallsWindowTemplate); + sSafariBallsWindowId = AddWindow(&sSafariBallsWindowTemplate); PutWindowTilemap(sSafariBallsWindowId); - NewMenuHelpers_DrawStdWindowFrame(sSafariBallsWindowId, 0); + NewMenuHelpers_DrawStdWindowFrame(sSafariBallsWindowId, FALSE); ConvertIntToDecimalStringN(gStringVar1, gNumSafariBalls, STR_CONV_MODE_RIGHT_ALIGN, 2); StringExpandPlaceholders(gStringVar4, gText_SafariBallStock); PrintTextOnWindow(sSafariBallsWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); CopyWindowToVram(sSafariBallsWindowId, 2); } -void DisplayPyramidFloorWindow(void) +static void ShowPyramidFloorWindow(void) { - // TODO: fix location - if (gSaveBlock2Ptr->field_CAA[4] == 7) - sBattlePyramidFloorWindowId = AddWindow(&gPyramidFloorWindowTemplate_1); + if (gSaveBlock2Ptr->field_CAA[4] == 7) // TODO: fix location + { + sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_1); + } else - sBattlePyramidFloorWindowId = AddWindow(&gPyramidFloorWindowTemplate_2); + { + sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_2); + } + PutWindowTilemap(sBattlePyramidFloorWindowId); - NewMenuHelpers_DrawStdWindowFrame(sBattlePyramidFloorWindowId, 0); + NewMenuHelpers_DrawStdWindowFrame(sBattlePyramidFloorWindowId, FALSE); StringCopy(gStringVar1, sPyramindFloorNames[gSaveBlock2Ptr->field_CAA[4]]); StringExpandPlaceholders(gStringVar4, gText_BattlePyramidFloor); PrintTextOnWindow(sBattlePyramidFloorWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); CopyWindowToVram(sBattlePyramidFloorWindowId, 2); } -void RemoveExtraStartMenuWindows(void) +static void RemoveExtraStartMenuWindows(void) { if (GetSafariZoneFlag()) { - sub_8198070(sSafariBallsWindowId, 0); + sub_8198070(sSafariBallsWindowId, FALSE); CopyWindowToVram(sSafariBallsWindowId, 2); RemoveWindow(sSafariBallsWindowId); } if (InBattlePyramid()) { - sub_8198070(sBattlePyramidFloorWindowId, 0); + sub_8198070(sBattlePyramidFloorWindowId, FALSE); RemoveWindow(sBattlePyramidFloorWindowId); } } -/* -// Prints n menu items starting at *index -static bool32 PrintStartMenuItemsMultistep(s16 *index, u32 n) +static bool32 PrintStartMenuActions(s8 *pIndex, u32 count) { - s8 _index = *index; - + s8 index = *pIndex; + do { - if (sStartMenuItems[sCurrentStartMenuActions[_index]].func.u8_void == StartMenu_PlayerName) + if (sStartMenuItems[sCurrentStartMenuActions[index]].func.u8_void == StartMenuPlayerNameCallback) { + PrintPlayerNameOnWindow(GetStartMenuWindowId(), sStartMenuItems[sCurrentStartMenuActions[index]].text, 8, (index << 4) + 9); + } + else { + StringExpandPlaceholders(gStringVar4, sStartMenuItems[sCurrentStartMenuActions[index]].text); + PrintTextOnWindow(GetStartMenuWindowId(), 1, gStringVar4, 8, (index << 4) + 9, 0xFF, NULL); + } + + index++; + if (index >= sNumStartMenuActions) { + *pIndex = index; + return TRUE; + } + + count--; + } + while (count != 0); + + *pIndex = index; + return FALSE; +} + +static bool32 InitStartMenuStep(void) +{ + s8 value = sUnknown_02037619[0]; + + switch (value) + { + case 0: + sUnknown_02037619[0]++; + break; + case 1: + BuildStartMenuActions(); + sUnknown_02037619[0]++; + break; + case 2: + sub_81973A4(); + NewMenuHelpers_DrawStdWindowFrame(sub_81979C4(sNumStartMenuActions), FALSE); + sUnknown_02037619[1] = 0; + sUnknown_02037619[0]++; + break; + case 3: + if (GetSafariZoneFlag() != FALSE) + { + ShowSafariBallsWindow(); + } + if (InBattlePyramid() != FALSE) + { + ShowPyramidFloorWindow(); + } + sUnknown_02037619[0]++; + break; + case 4: + if (PrintStartMenuActions(&sUnknown_02037619[1], 2) == FALSE) { + break; + } + sUnknown_02037619[0]++; + break; + case 5: + sStartMenuCursorPos = sub_81983AC(GetStartMenuWindowId(), 1, 0, 9, 16, sNumStartMenuActions, sStartMenuCursorPos); + CopyWindowToVram(GetStartMenuWindowId(), TRUE); + return TRUE; + } + + return FALSE; +} + +static void InitStartMenu(void) +{ + sUnknown_02037619[0] = 0; + sUnknown_02037619[1] = 0; + while (!InitStartMenuStep()); +} + +static void StartMenuTask(u8 taskId) +{ + if (InitStartMenuStep() == TRUE) + { + SwitchTaskToFollowupFunc(taskId); + } +} + +static void CreateStartMenuTask(TaskFunc followupFunc) +{ + u8 taskId; + + sUnknown_02037619[0] = 0; + sUnknown_02037619[1] = 0; + taskId = CreateTask(StartMenuTask, 0x50); + SetTaskFuncWithFollowupFunc(taskId, StartMenuTask, followupFunc); +} + +static bool8 sub_809FA00(void) +{ + if (InitStartMenuStep() == FALSE) + { + return FALSE; + } + + sub_80AF688(); + return TRUE; +} + +void sub_809FA18(void) // Called from field_screen.s +{ + sUnknown_02037619[0] = 0; + sUnknown_02037619[1] = 0; + gUnknown_03005DB0 = sub_809FA00; +} + +void sub_809FA34(u8 taskId) // Referenced in field_screen.s and rom_8011DC0.s +{ + struct Task* task = &gTasks[taskId]; + switch(task->data[0]) + { + case 0: + if (InUnionRoom() == TRUE) + { + var_800D_set_xB(); } - else + + gMenuCallback = HandleStartMenuInput; + task->data[0]++; + break; + case 1: + if (gMenuCallback() == TRUE) { + DestroyTask(taskId); + } + break; + } +} + +void ShowStartMenu(void) // Called from overworld.c and field_control_avatar.s +{ + if (!is_c1_link_related_active()) + { + FreezeMapObjects(); + sub_808B864(); + sub_808BCF4(); + } + CreateStartMenuTask(sub_809FA34); + ScriptContext2_Enable(); +} +static bool8 HandleStartMenuInput(void) +{ + if (gMain.newKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + sStartMenuCursorPos = MoveMenuCursor(-1); + } + + if (gMain.newKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + sStartMenuCursorPos = MoveMenuCursor(1); + } + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void == StartMenuPokedexCallback) + { + if (GetNationalPokedexCount(0) == 0) { + return FALSE; + } + } + + gMenuCallback = sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void; + + if (gMenuCallback != StartMenuSaveCallback + && gMenuCallback != StartMenuExitCallback + && gMenuCallback != StartMenuSafariZoneRetireCallback + && gMenuCallback != StartMenuBattlePyramidRetireCallback) + { + FadeScreen(1, 0); + } + + return FALSE; + } + + if (gMain.newKeys & (START_BUTTON | B_BUTTON)) + { + RemoveExtraStartMenuWindows(); + HideStartMenu(); + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuPokedexCallback(void) +{ + if (!gPaletteFade.active) + { + IncrementGameStat(GAME_STAT_CHECKED_POKEDEX); + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(sub_80BB534); // Display pokedex + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuPokemonCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(CB2_PartyMenuFromStartMenu); // Display party menu + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuBagCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(CB2_BagMenuFromStartMenu); // Display bag menu + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuPokeNavCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(CB2_PokeNav); // Display PokeNav + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuPlayerNameCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + + if (is_c1_link_related_active() || InUnionRoom()) + { + sub_80C4DDC(CB2_ReturnToFieldWithOpenMenu); // Display trainer card + } + else if (FlagGet(FLAG_SYS_FRONTIER_PASS)) + { + sub_80C51C4(CB2_ReturnToFieldWithOpenMenu); // Display frontier pass + } + else + { + sub_80C4DDC(CB2_ReturnToFieldWithOpenMenu); // Display trainer card } - } while (++_index > sNumStartMenuActions); + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuSaveCallback(void) +{ + if (InBattlePyramid()) + { + RemoveExtraStartMenuWindows(); + } + + gMenuCallback = SaveStartCallback; // Display save menu + + return FALSE; +} + +static bool8 StartMenuOptionCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(CB2_InitOptionMenu); // Display option menu + gMain.savedCallback = CB2_ReturnToFieldWithOpenMenu; + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuExitCallback(void) +{ + RemoveExtraStartMenuWindows(); + HideStartMenu(); // Hide start menu + + return TRUE; +} + +static bool8 StartMenuSafariZoneRetireCallback(void) +{ + RemoveExtraStartMenuWindows(); + HideStartMenu(); + SafariZoneRetirePrompt(); + + return TRUE; +} + +static bool8 StartMenuLinkModePlayerNameCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + overworld_free_bg_tilemaps(); + sub_80C4E74(gUnknown_03005DB4, CB2_ReturnToFieldWithOpenMenu); + + return TRUE; + } + + return FALSE; +} + +static bool8 StartMenuBattlePyramidRetireCallback(void) +{ + gMenuCallback = BattlePyramidRetireStartCallback; // Confirm retire + + return FALSE; +} + +void sub_809FDD4(void) // Called from battle_frontier_2.s +{ + sub_8197DF8(0, FALSE); + sub_80984F4(); + CreateStartMenuTask(sub_809FA34); + ScriptContext2_Enable(); +} + +static bool8 StartMenuBattlePyramidBagCallback(void) +{ + if (!gPaletteFade.active) + { + play_some_sound(); + RemoveExtraStartMenuWindows(); + overworld_free_bg_tilemaps(); + SetMainCallback2(sub_81C4EFC); // Display battle pyramid bag + + return TRUE; + } + + return FALSE; +} + +static bool8 SaveStartCallback(void) +{ + InitSave(); + gMenuCallback = SaveCallback; - if (--n == 0) + return FALSE; +} + +static bool8 SaveCallback(void) +{ + switch (RunSaveCallback()) { - *index = _index; + case SAVE_IN_PROGRESS: + return FALSE; + case SAVE_CANCELED: // Back to start menu + sub_8197DF8(0, FALSE); + InitStartMenu(); + gMenuCallback = HandleStartMenuInput; return FALSE; + case SAVE_SUCCESS: + case SAVE_ERROR: // Close start menu + sub_8197DF8(0, TRUE); + sub_80984F4(); + ScriptContext2_Disable(); + sub_81A9EC8(); + return TRUE; + } + + return FALSE; +} + +static bool8 BattlePyramidRetireStartCallback(void) +{ + InitBattlePyramidRetire(); + gMenuCallback = BattlePyramidRetireCallback; + + return FALSE; +} + +static bool8 BattlePyramidRetireReturnCallback(void) +{ + InitStartMenu(); + gMenuCallback = HandleStartMenuInput; + + return FALSE; +} + +static bool8 BattlePyramidRetireCallback(void) +{ + switch (RunSaveCallback()) + { + case SAVE_SUCCESS: // No (Stay in battle pyramid) + RemoveExtraStartMenuWindows(); + gMenuCallback = BattlePyramidRetireReturnCallback; + return FALSE; + case SAVE_IN_PROGRESS: + return FALSE; + case SAVE_CANCELED: // Yes (Retire from battle pyramid) + sub_8197DF8(0, TRUE); + sub_80984F4(); + ScriptContext2_Disable(); + ScriptContext1_SetupScript(BattleFrontier_BattlePyramidEmptySquare_EventScript_252C88); + return TRUE; + } + + return FALSE; +} + +static void InitSave(void) +{ + save_serialize_map(); + sSaveDialogCallback = SaveConfirmSaveCallback; + sSavingComplete = FALSE; +} + +static u8 RunSaveCallback(void) +{ + // True if text is still printing + if (sub_8197224() == TRUE) + { + return SAVE_IN_PROGRESS; + } + + sSavingComplete = FALSE; + return sSaveDialogCallback(); +} + +void SaveGame(void) // Called from cable_club.s +{ + InitSave(); + CreateTask(SaveGameTask, 0x50); +} + +static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)) +{ + StringExpandPlaceholders(gStringVar4, message); + sub_819786C(0, TRUE); + AddTextPrinterForMessage_2(TRUE); + sSavingComplete = TRUE; + sSaveDialogCallback = saveCallback; +} + +static void SaveGameTask(u8 taskId) +{ + u8 status = RunSaveCallback(); + + switch (status) + { + case SAVE_CANCELED: + case SAVE_ERROR: + gSpecialVar_Result = 0; + break; + case SAVE_SUCCESS: + gSpecialVar_Result = status; + break; + case SAVE_IN_PROGRESS: + return; + } + + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +static void sub_80A0014(void) +{ + sub_8197434(0, TRUE); +} + +static void HideSaveInfoWindow(void) +{ + RemoveSaveInfoWindow(); +} + +static void SaveStartTimer(void) +{ + sSaveDialogTimer = 60; +} + +static bool8 SaveSuccesTimer(void) +{ + sSaveDialogTimer--; + + if (gMain.heldKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + return TRUE; + } + else if (sSaveDialogTimer == 0) + { + return TRUE; + } + + return FALSE; +} + +static bool8 SaveErrorTimer(void) +{ + if (sSaveDialogTimer != 0) + { + sSaveDialogTimer--; + } + else if (gMain.heldKeys & A_BUTTON) + { + return TRUE; + } + + return FALSE; +} + +static u8 SaveConfirmSaveCallback(void) +{ + sub_819746C(GetStartMenuWindowId(), FALSE); + RemoveStartMenuWindow(); + ShowSaveInfoWindow(); + + if (InBattlePyramid()) + { + ShowSaveMessage(gText_BattlePyramidConfirmRest, SaveYesNoCallback); + } + else + { + ShowSaveMessage(gText_ConfirmSave, SaveYesNoCallback); + } + + return SAVE_IN_PROGRESS; +} + +static u8 SaveYesNoCallback(void) +{ + sub_8197930(); // Show Yes/No menu + sSaveDialogCallback = SaveConfirmInputCallback; + return SAVE_IN_PROGRESS; +} + +static u8 SaveConfirmInputCallback(void) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: // Yes + switch (gSaveFileStatus) + { + case 0: + case 2: + if (gDifferentSaveFile == FALSE) + { + sSaveDialogCallback = SaveFileExistsCallback; + return SAVE_IN_PROGRESS; + } + + sSaveDialogCallback = SaveSavingMessageCallback; + return SAVE_IN_PROGRESS; + default: + sSaveDialogCallback = SaveFileExistsCallback; + return SAVE_IN_PROGRESS; + } + case -1: // B Button + case 1: // No + HideSaveInfoWindow(); + sub_80A0014(); + return SAVE_CANCELED; + } + + return SAVE_IN_PROGRESS; +} + +// A different save file exists +static u8 SaveFileExistsCallback(void) +{ + if (gDifferentSaveFile == TRUE) + { + ShowSaveMessage(gText_DifferentSaveFile, SaveConfirmOverwriteNoCallback); + } + else + { + ShowSaveMessage(gText_AlreadySavedFile, SaveConfirmOverwriteCallback); + } + + return SAVE_IN_PROGRESS; +} + +static u8 SaveConfirmOverwriteNoCallback(void) +{ + sub_8197948(1); // Show Yes/No menu (No selected as default) + sSaveDialogCallback = SaveOverwriteInputCallback; + return SAVE_IN_PROGRESS; +} + +static u8 SaveConfirmOverwriteCallback(void) +{ + sub_8197930(); // Show Yes/No menu + sSaveDialogCallback = SaveOverwriteInputCallback; + return SAVE_IN_PROGRESS; +} + +static u8 SaveOverwriteInputCallback(void) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: // Yes + sSaveDialogCallback = SaveSavingMessageCallback; + return SAVE_IN_PROGRESS; + case -1: // B Button + case 1: // No + HideSaveInfoWindow(); + sub_80A0014(); + return SAVE_CANCELED; + } + + return SAVE_IN_PROGRESS; +} + +static u8 SaveSavingMessageCallback(void) +{ + ShowSaveMessage(gText_SavingDontTurnOff, SaveDoSaveCallback); + return SAVE_IN_PROGRESS; +} + +static u8 SaveDoSaveCallback(void) +{ + u8 saveStatus; + + IncrementGameStat(GAME_STAT_SAVED_GAME); + sub_81A9E90(); + + if (gDifferentSaveFile == TRUE) + { + saveStatus = TrySavingData(SAVE_OVERWRITE_DIFFERENT_FILE); + gDifferentSaveFile = FALSE; + } + else + { + saveStatus = TrySavingData(SAVE_NORMAL); + } + + if (saveStatus == 1) // Save succeded + { + ShowSaveMessage(gText_PlayerSavedGame, SaveSuccessCallback); + } + else // Save error + { + ShowSaveMessage(gText_SaveError, SaveErrorCallback); + } + + SaveStartTimer(); + return SAVE_IN_PROGRESS; +} + +static u8 SaveSuccessCallback(void) +{ + if (!IsTextPrinterActive(0)) + { + PlaySE(SE_SAVE); + sSaveDialogCallback = SaveReturnSuccessCallback; + } + + return SAVE_IN_PROGRESS; +} + +static u8 SaveReturnSuccessCallback(void) +{ + if (!IsSEPlaying() && SaveSuccesTimer()) + { + HideSaveInfoWindow(); + return SAVE_SUCCESS; + } + else + { + return SAVE_IN_PROGRESS; + } +} + +static u8 SaveErrorCallback(void) +{ + if (!IsTextPrinterActive(0)) + { + PlaySE(SE_BOO); + sSaveDialogCallback = SaveReturnErrorCallback; + } + + return SAVE_IN_PROGRESS; +} + +static u8 SaveReturnErrorCallback(void) +{ + if (!SaveErrorTimer()) + { + return SAVE_IN_PROGRESS; } else { - *index = _index; + HideSaveInfoWindow(); + return SAVE_ERROR; + } +} + +static void InitBattlePyramidRetire(void) +{ + sSaveDialogCallback = BattlePyramidConfirmRetireCallback; + sSavingComplete = FALSE; +} + +static u8 BattlePyramidConfirmRetireCallback(void) +{ + sub_819746C(GetStartMenuWindowId(), FALSE); + RemoveStartMenuWindow(); + ShowSaveMessage(gText_BattlePyramidConfirmRetire, BattlePyramidRetireYesNoCallback); + + return SAVE_IN_PROGRESS; +} + +static u8 BattlePyramidRetireYesNoCallback(void) +{ + sub_8197948(1); // Show Yes/No menu (No selected as default) + sSaveDialogCallback = BattlePyramidRetireInputCallback; + + return SAVE_IN_PROGRESS; +} + +static u8 BattlePyramidRetireInputCallback(void) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: // Yes + return SAVE_CANCELED; + case -1: // B Button + case 1: // No + sub_80A0014(); + return SAVE_SUCCESS; + } + + return SAVE_IN_PROGRESS; +} + +static void sub_80A03D8(void) +{ + TransferPlttBuffer(); +} + +static bool32 sub_80A03E4(u8 *par1) +{ + switch (*par1) + { + case 0: + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); + SetVBlankCallback(NULL); + ScanlineEffect_Stop(); + DmaClear16(3, PLTT, PLTT_SIZE); + DmaFillLarge16(3, 0, (void *)(VRAM + 0x0), 0x18000, 0x1000); + break; + case 1: + ResetSpriteData(); + ResetTasks(); + ResetPaletteFade(); + ScanlineEffect_Clear(); + break; + case 2: + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sUnknown_085105A8, ARRAY_COUNT(sUnknown_085105A8)); + InitWindows(sUnknown_085105AC); + box_border_load_tiles_and_pal(0, 8, 224); + sub_81978B0(240); + break; + case 3: + ShowBg(0); + BlendPalettes(-1, 16, 0); + SetVBlankCallback(sub_80A03D8); + EnableInterrupts(1); + break; + case 4: return TRUE; } -}*/ + + (*par1)++; + return FALSE; +} + +void sub_80A0514(void) // Called from cable_club.s +{ + if (sub_80A03E4(&gMain.state)) + { + CreateTask(sub_80A0550, 0x50); + SetMainCallback2(sub_80A0540); + } +} + +static void sub_80A0540(void) +{ + RunTasks(); + UpdatePaletteFade(); +} + +static void sub_80A0550(u8 taskId) +{ + s16 *step = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + switch (*step) + { + case 0: + FillWindowPixelBuffer(0, 17); + AddTextPrinterParameterized(0, + 1, + gText_SavingDontTurnOffPower, + 255, + NULL, + 2, + 1, + 3); + sub_8098858(0, 8, 14); + PutWindowTilemap(0); + CopyWindowToVram(0, 3); + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + + if (gWirelessCommType != 0 && InUnionRoom()) + { + if (sub_800A07C()) + { + *step = 1; + } + else + { + *step = 5; + } + } + else + { + gSoftResetDisabled = 1; + *step = 1; + } + break; + case 1: + sub_8076D5C(); + sub_8153430(); + *step = 2; + break; + case 2: + if (sub_8153474()) + { + sav2_gender2_inplace_and_xFE(); + *step = 3; + gSoftResetDisabled = 0; + } + break; + case 3: + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + *step = 4; + break; + case 4: + FreeAllWindowBuffers(); + SetMainCallback2(gMain.savedCallback); + DestroyTask(taskId); + break; + case 5: + CreateTask(sub_8153688, 0x5); + *step = 6; + break; + case 6: + if (!FuncIsActiveTask(sub_8153688)) + { + *step = 3; + } + break; + } + } +} + +static void ShowSaveInfoWindow(void) +{ + struct WindowTemplate saveInfoWindow = sSaveInfoWindowTemplate; + u8 gender; + u8 color; + u32 xOffset; + u32 yOffset; + + if (!FlagGet(FLAG_SYS_POKEDEX_GET)) + { + saveInfoWindow.height -= 2; + } + + sSaveInfoWindowId = AddWindow(&saveInfoWindow); + NewMenuHelpers_DrawStdWindowFrame(sSaveInfoWindowId, FALSE); + + gender = gSaveBlock2Ptr->playerGender; + color = TEXT_COLOR_RED; // Red when female, blue when male. + + if (gender == MALE) + { + color = TEXT_COLOR_BLUE; + } + + // Print region name + yOffset = 1; + sub_819A344(3, gStringVar4, TEXT_COLOR_GREEN); + PrintTextOnWindow(sSaveInfoWindowId, 1, gStringVar4, 0, yOffset, 0xFF, NULL); + + // Print player name + yOffset = 0x11; + PrintTextOnWindow(sSaveInfoWindowId, 1, gText_SavingPlayer, 0, yOffset, 0xFF, NULL); + sub_819A344(0, gStringVar4, color); + xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); + PrintPlayerNameOnWindow(sSaveInfoWindowId, gStringVar4, xOffset, yOffset); + + // Print badge count + yOffset = 0x21; + PrintTextOnWindow(sSaveInfoWindowId, 1, gText_SavingBadges, 0, yOffset, 0xFF, NULL); + sub_819A344(4, gStringVar4, color); + xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); + PrintTextOnWindow(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); + + if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) + { + // Print pokedex count + yOffset = 0x31; + PrintTextOnWindow(sSaveInfoWindowId, 1, gText_SavingPokedex, 0, yOffset, 0xFF, NULL); + sub_819A344(1, gStringVar4, color); + xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); + PrintTextOnWindow(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); + } + + // Print play time + yOffset += 0x10; + PrintTextOnWindow(sSaveInfoWindowId, 1, gText_SavingTime, 0, yOffset, 0xFF, NULL); + sub_819A344(2, gStringVar4, color); + xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); + PrintTextOnWindow(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); + + CopyWindowToVram(sSaveInfoWindowId, 2); +} + +static void RemoveSaveInfoWindow(void) +{ + sub_819746C(sSaveInfoWindowId, FALSE); + RemoveWindow(sSaveInfoWindowId); +} + +static void sub_80A08A4(u8 taskId) +{ + if (!FuncIsActiveTask(sub_8153688)) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} + +void sub_80A08CC(void) // Referenced in data/specials.inc and data/scripts/maps/BattleFrontier_BattleTowerLobby.inc +{ + u8 taskId = CreateTask(sub_8153688, 0x5); + gTasks[taskId].data[2] = 1; + gTasks[CreateTask(sub_80A08A4, 0x6)].data[1] = taskId; +} + +static void HideStartMenuWindow(void) +{ + sub_819746C(GetStartMenuWindowId(), TRUE); + RemoveStartMenuWindow(); + sub_80984F4(); + ScriptContext2_Disable(); +} + +void HideStartMenu(void) // Called from map_name_popup.s +{ + PlaySE(SE_SELECT); + HideStartMenuWindow(); +} + +void AppendToList(u8 *list, u8 *pos, u8 newEntry) +{ + list[*pos] = newEntry; + (*pos)++; +}
\ No newline at end of file diff --git a/src/starter_choose.c b/src/starter_choose.c index 83a7b8112..480edbcb7 100644 --- a/src/starter_choose.c +++ b/src/starter_choose.c @@ -25,12 +25,6 @@ #define STARTER_PKMN_POS_X 120 #define STARTER_PKMN_POS_Y 64 -// graphics -extern const u32 gBirchHelpGfx[]; -extern const u32 gBirchBagTilemap[]; -extern const u32 gBirchGrassTilemap[]; -extern const u16 gBirchBagGrassPal[]; - // text extern const u8 gText_BirchInTrouble[]; extern const u8 gText_ConfirmStarterChoice[]; diff --git a/src/text.c b/src/text.c index 6a83d5d15..f7c68f549 100644 --- a/src/text.c +++ b/src/text.c @@ -4,18 +4,15 @@ #include "m4a.h" #include "palette.h" #include "sound.h" +#include "constants/songs.h" #include "string_util.h" #include "window.h" #include "text.h" +#include "blit.h" -extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue); -extern void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height); -extern void BlitBitmapRectToWindow(u8 windowId, const u8 *pixels, u16 srcX, u16 srcY, u16 srcWidth, int srcHeight, u16 destX, u16 destY, u16 rectWidth, u16 rectHeight); extern u8 GetKeypadIconWidth(u8 keypadIconId); -extern void CopyWindowToVram(u8 windowId, u8 mode); extern u16 Font6Func(struct TextPrinter *textPrinter); extern u32 GetGlyphWidthFont6(u16 glyphId, bool32 isJapanese); -extern void PlaySE(u16 songNum); extern u8* UnkTextUtil_GetPtrI(u8 a1); extern int sub_8197964(); @@ -27,7 +24,6 @@ static u16 gLastTextBgColor; static u16 gLastTextFgColor; static u16 gLastTextShadowColor; -extern struct Main gMain; extern struct MusicPlayerInfo gMPlayInfo_BGM; const struct FontInfo *gFonts; @@ -379,7 +375,7 @@ void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor) *(current++) = (shadowColor << 12) | (shadowColor << 8) | (shadowColor << 4) | shadowColor; } #else -__attribute__((naked)) +NAKED void GenerateFontHalfRowLookupTable(u8 fgColor, u8 bgColor, u8 shadowColor) { asm("push {r4-r7,lr}\n\ @@ -875,7 +871,7 @@ void DecompressGlyphTile(const u16 *src, u16 *dest) *(dest) = (gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] & 0xFF]] << 16) | gFontHalfRowLookupTable[gFontHalfRowOffsets[src[1] >> 8]]; } #else -__attribute__((naked)) +NAKED void DecompressGlyphTile(const u16 *src, u16 *dest) { asm("push {r4-r7,lr}\n\ @@ -1056,7 +1052,7 @@ u8 GetLastTextColor(u8 colorType) } } -__attribute__((naked)) +NAKED void CopyGlyphToWindow(struct TextPrinter *x) { asm("push {r4-r7,lr}\n\ @@ -1986,7 +1982,7 @@ bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter) if (gMain.newKeys & (A_BUTTON | B_BUTTON)) { result = TRUE; - PlaySE(5); + PlaySE(SE_SELECT); } } return result; @@ -2004,7 +2000,7 @@ bool16 TextPrinterWait(struct TextPrinter *textPrinter) if (gMain.newKeys & (A_BUTTON | B_BUTTON)) { result = TRUE; - PlaySE(5); + PlaySE(SE_SELECT); } } return result; @@ -2285,7 +2281,6 @@ u16 RenderText(struct TextPrinter *textPrinter) else textPrinter->subPrinter.currentX += gUnknown_03002F90[0x80]; } - return 0; case 1: // _08005C78 if (TextPrinterWait(textPrinter)) @@ -2346,7 +2341,7 @@ u16 RenderText(struct TextPrinter *textPrinter) return 1; } #else -__attribute__((naked)) +NAKED u16 RenderText(struct TextPrinter *textPrinter) { asm("push {r4-r6,lr}\n\ diff --git a/src/text_window.c b/src/text_window.c index 33cd7cffe..c3b9f7197 100644 --- a/src/text_window.c +++ b/src/text_window.c @@ -7,26 +7,26 @@ #include "graphics.h" // const rom data -const u32 gTextWindowFrame1_Gfx[] = INCBIN_U32("graphics/text_window/1.4bpp"); -static const u32 sTextWindowFrame2_Gfx[] = INCBIN_U32("graphics/text_window/2.4bpp"); -static const u32 sTextWindowFrame3_Gfx[] = INCBIN_U32("graphics/text_window/3.4bpp"); -static const u32 sTextWindowFrame4_Gfx[] = INCBIN_U32("graphics/text_window/4.4bpp"); -static const u32 sTextWindowFrame5_Gfx[] = INCBIN_U32("graphics/text_window/5.4bpp"); -static const u32 sTextWindowFrame6_Gfx[] = INCBIN_U32("graphics/text_window/6.4bpp"); -static const u32 sTextWindowFrame7_Gfx[] = INCBIN_U32("graphics/text_window/7.4bpp"); -static const u32 sTextWindowFrame8_Gfx[] = INCBIN_U32("graphics/text_window/8.4bpp"); -static const u32 sTextWindowFrame9_Gfx[] = INCBIN_U32("graphics/text_window/9.4bpp"); -static const u32 sTextWindowFrame10_Gfx[] = INCBIN_U32("graphics/text_window/10.4bpp"); -static const u32 sTextWindowFrame11_Gfx[] = INCBIN_U32("graphics/text_window/11.4bpp"); -static const u32 sTextWindowFrame12_Gfx[] = INCBIN_U32("graphics/text_window/12.4bpp"); -static const u32 sTextWindowFrame13_Gfx[] = INCBIN_U32("graphics/text_window/13.4bpp"); -static const u32 sTextWindowFrame14_Gfx[] = INCBIN_U32("graphics/text_window/14.4bpp"); -static const u32 sTextWindowFrame15_Gfx[] = INCBIN_U32("graphics/text_window/15.4bpp"); -static const u32 sTextWindowFrame16_Gfx[] = INCBIN_U32("graphics/text_window/16.4bpp"); -static const u32 sTextWindowFrame17_Gfx[] = INCBIN_U32("graphics/text_window/17.4bpp"); -static const u32 sTextWindowFrame18_Gfx[] = INCBIN_U32("graphics/text_window/18.4bpp"); -static const u32 sTextWindowFrame19_Gfx[] = INCBIN_U32("graphics/text_window/19.4bpp"); -static const u32 sTextWindowFrame20_Gfx[] = INCBIN_U32("graphics/text_window/20.4bpp"); +const u8 gTextWindowFrame1_Gfx[] = INCBIN_U8("graphics/text_window/1.4bpp"); +static const u8 sTextWindowFrame2_Gfx[] = INCBIN_U8("graphics/text_window/2.4bpp"); +static const u8 sTextWindowFrame3_Gfx[] = INCBIN_U8("graphics/text_window/3.4bpp"); +static const u8 sTextWindowFrame4_Gfx[] = INCBIN_U8("graphics/text_window/4.4bpp"); +static const u8 sTextWindowFrame5_Gfx[] = INCBIN_U8("graphics/text_window/5.4bpp"); +static const u8 sTextWindowFrame6_Gfx[] = INCBIN_U8("graphics/text_window/6.4bpp"); +static const u8 sTextWindowFrame7_Gfx[] = INCBIN_U8("graphics/text_window/7.4bpp"); +static const u8 sTextWindowFrame8_Gfx[] = INCBIN_U8("graphics/text_window/8.4bpp"); +static const u8 sTextWindowFrame9_Gfx[] = INCBIN_U8("graphics/text_window/9.4bpp"); +static const u8 sTextWindowFrame10_Gfx[] = INCBIN_U8("graphics/text_window/10.4bpp"); +static const u8 sTextWindowFrame11_Gfx[] = INCBIN_U8("graphics/text_window/11.4bpp"); +static const u8 sTextWindowFrame12_Gfx[] = INCBIN_U8("graphics/text_window/12.4bpp"); +static const u8 sTextWindowFrame13_Gfx[] = INCBIN_U8("graphics/text_window/13.4bpp"); +static const u8 sTextWindowFrame14_Gfx[] = INCBIN_U8("graphics/text_window/14.4bpp"); +static const u8 sTextWindowFrame15_Gfx[] = INCBIN_U8("graphics/text_window/15.4bpp"); +static const u8 sTextWindowFrame16_Gfx[] = INCBIN_U8("graphics/text_window/16.4bpp"); +static const u8 sTextWindowFrame17_Gfx[] = INCBIN_U8("graphics/text_window/17.4bpp"); +static const u8 sTextWindowFrame18_Gfx[] = INCBIN_U8("graphics/text_window/18.4bpp"); +static const u8 sTextWindowFrame19_Gfx[] = INCBIN_U8("graphics/text_window/19.4bpp"); +static const u8 sTextWindowFrame20_Gfx[] = INCBIN_U8("graphics/text_window/20.4bpp"); const u16 gTextWindowFrame1_Pal[] = INCBIN_U16("graphics/text_window/1.gbapal"); static const u16 sTextWindowFrame2_Pal[] = INCBIN_U16("graphics/text_window/2.gbapal"); diff --git a/src/time_events.c b/src/time_events.c index 1f169a5c6..1f46e7705 100644 --- a/src/time_events.c +++ b/src/time_events.c @@ -81,7 +81,7 @@ void UpdateShoalTideFlag(void) 1, // 23 }; - if (is_light_level_1_2_3_5_or_6(get_map_light_from_warp0())) + if (is_map_type_1_2_3_5_or_6(get_map_light_from_warp0())) { RtcCalcLocalTime(); if (tide[gLocalTime.hours]) diff --git a/src/title_screen.c b/src/title_screen.c index 4e25c8152..15a0482dc 100644 --- a/src/title_screen.c +++ b/src/title_screen.c @@ -19,6 +19,7 @@ #include "gpu_regs.h" #include "trig.h" #include "constants/rgb.h" +#include "constants/songs.h" #define VERSION_BANNER_SHAPE 1 #define VERSION_BANNER_RIGHT_TILEOFFSET 64 @@ -574,7 +575,7 @@ void CB2_InitTitleScreen(void) | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_OBJWIN_ON); - m4aSongNumStart(0x19D); + m4aSongNumStart(MUS_TITLE3); gMain.state = 5; break; case 5: diff --git a/src/trader.c b/src/trader.c new file mode 100644 index 000000000..c4d70ac9a --- /dev/null +++ b/src/trader.c @@ -0,0 +1,209 @@ +#include "global.h" +#include "constants/decorations.h" +#include "constants/mauville_man.h" +#include "decoration.h" +#include "decoration_inventory.h" +#include "event_data.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "script.h" +#include "constants/songs.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "script_menu.h" + +static const u8 * const sDefaultTraderNames[] = +{ + gText_Tristan, + gText_Philip, + gText_Dennis, + gText_Roberto, +}; + +static const u8 sDefaultTraderDecorations[] = +{ + DECOR_DUSKULL_DOLL, + DECOR_BALL_CUSHION, + DECOR_TIRE, + DECOR_PRETTY_FLOWERS, +}; + +void TraderSetup(void) +{ + u8 i; + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + + trader->id = MAUVILLE_MAN_TRADER; + trader->alreadyTraded = FALSE; + + for (i = 0; i < 4; i++) + { + StringCopy(trader->playerNames[i], sDefaultTraderNames[i]); + trader->decorIds[i] = sDefaultTraderDecorations[i]; + trader->language[i] = GAME_LANGUAGE; + } +} + +void Trader_ResetFlag(void) +{ + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + trader->alreadyTraded = FALSE; +} + +void CreateAvailableDecorationsMenu(u8 taskId) +{ + u8 i; + s16 * data = gTasks[taskId].data; + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + struct WindowTemplate windowTemplate = {0, 1, 1, 10, 10, 15, 1}; + s32 windowWidth = GetStringWidth(1, gText_Exit, 0); + s32 fiveMarksWidth = GetStringWidth(1, gText_FiveMarks, 0); + for (i = 0; i < 4; i++) + { + s32 curWidth; + if (trader->decorIds[i] > NUM_DECORATIONS) + curWidth = fiveMarksWidth; + else + curWidth = GetStringWidth(1, gDecorations[trader->decorIds[i]].name, 0); + if (curWidth > windowWidth) + windowWidth = curWidth; + } + windowTemplate.width = convert_pixel_width_to_tile_width(windowWidth); + data[3] = AddWindow(&windowTemplate); + SetWindowBorderStyle(data[3], FALSE, 0x214, 14); + for (i = 0; i < 4; i++) + { + if (trader->decorIds[i] > NUM_DECORATIONS) + PrintTextOnWindow(data[3], 1, gText_FiveMarks, 8, 16 * i + 1, 255, NULL); + else + PrintTextOnWindow(data[3], 1, gDecorations[trader->decorIds[i]].name, 8, 16 * i + 1, 255, NULL); + } + PrintTextOnWindow(data[3], 1, gText_Exit, 8, 16 * i + 1, 255, NULL); + InitMenuInUpperLeftCornerPlaySoundWhenAPressed(data[3], 5, 0); + schedule_bg_copy_tilemap_to_vram(0); +} + +void sub_8133BE4(u8 taskId, u8 decorationId) +{ + s16 * data = gTasks[taskId].data; + if (decorationId > NUM_DECORATIONS) + { + gSpecialVar_0x8004 = 0xFFFF; + } + else + { + gSpecialVar_0x8004 = decorationId; + } + + sub_8198070(data[3], FALSE); + ClearWindowTilemap(data[3]); + RemoveWindow(data[3]); + schedule_bg_copy_tilemap_to_vram(0); + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void Task_HandleGetDecorationMenuInput(u8 taskId) +{ + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + s8 input = ProcessMenuInput(); + + switch (input) + { + case -2: + break; + case -1: + case 4: + PlaySE(SE_SELECT); + sub_8133BE4(taskId, 0); + break; + default: + PlaySE(SE_SELECT); + gSpecialVar_0x8005 = input; + StringCopy(gStringVar1, trader->playerNames[input]); + ConvertInternationalString(gStringVar1, trader->language[input]); + sub_8133BE4(taskId, trader->decorIds[input]); + break; + } +} + +void ScrSpecial_GetTraderTradedFlag(void) +{ + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + gSpecialVar_Result = trader->alreadyTraded; +} + +void ScrSpecial_DoesPlayerHaveNoDecorations(void) +{ + u8 i; + + for (i = 0; i < 8; i++) + { + if (CountDecorationCategoryN(i)) + { + gSpecialVar_Result = FALSE; + return; + } + } + gSpecialVar_Result = TRUE; +} + +void ScrSpecial_IsDecorationFull(void) +{ + gSpecialVar_Result = FALSE; + if (gDecorations[gSpecialVar_0x8004].category != gDecorations[gSpecialVar_0x8006].category + && GetFirstEmptyDecorSlot(gDecorations[gSpecialVar_0x8004].category) == -1) + { + sub_8127250(gStringVar2, gDecorations[gSpecialVar_0x8004].category); + gSpecialVar_Result = TRUE; + } +} + +void ScrSpecial_TraderMenuGiveDecoration(void) +{ + CreateTask(sub_8127208, 0); +} + +void sub_8133DA0(u8 taskId) +{ + if (IsSelectedDecorInThePC() == TRUE) + { + gSpecialVar_0x8006 = gCurDecorInventoryItems[gCurDecorationIndex]; + StringCopy(gStringVar3, gDecorations[gSpecialVar_0x8004].name); + StringCopy(gStringVar2, gDecorations[gSpecialVar_0x8006].name); + } + else + { + gSpecialVar_0x8006 = 0xFFFF; + } + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void sub_8133E1C(u8 taskId) +{ + gSpecialVar_0x8006 = 0; + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void ScrSpecial_TraderDoDecorationTrade(void) +{ + struct MauvilleOldManTrader *trader = &gSaveBlock1Ptr->oldMan.trader; + + DecorationRemove(gSpecialVar_0x8006); + DecorationAdd(gSpecialVar_0x8004); + StringCopy(trader->playerNames[gSpecialVar_0x8005], gSaveBlock2Ptr->playerName); + trader->decorIds[gSpecialVar_0x8005] = gSpecialVar_0x8006; + trader->language[gSpecialVar_0x8005] = GAME_LANGUAGE; + trader->alreadyTraded = TRUE; +} + +void ScrSpecial_TraderMenuGetDecoration(void) +{ + u8 taskId = CreateTask(Task_HandleGetDecorationMenuInput, 0); + CreateAvailableDecorationsMenu(taskId); +} @@ -36,9 +36,7 @@ #include "decoration.h" #include "secret_base.h" #include "tv.h" - -extern const u8 gSpeciesNames[][11]; -extern const u8 gMoveNames[][13]; +#include "data2.h" // Static type declarations @@ -87,101 +85,100 @@ void tv_store_id_3x(TVShow *show); void DeleteTVShowInArrayByIdx(TVShow *shows, u8 idx); s8 FindEmptyTVSlotWithinFirstFiveShowsOfArray(TVShow *shows); void FindActiveBroadcastByShowType_SetScriptResult(u8 kind); -void InterviewBefore_BravoTrainerPkmnProfile(void); -void InterviewBefore_NameRater(void); +static void InterviewBefore_BravoTrainerPkmnProfile(void); +static void InterviewBefore_NameRater(void); u16 TV_GetSomeOtherSpeciesAlreadySeenByPlayer(u16 passedSpecies); -void sub_80EFA88(void); -void sub_80EF93C(TVShow *shows); +static void sub_80EFA88(void); +static void sub_80EF93C(TVShow *shows); s8 sub_80EEE30(PokeNews *pokeNews); bool8 sub_80EF0E4(u8 newsKind); void ClearPokemonNewsI(u8 i); -void sub_80F1254(TVShow *shows); -void sub_80F12A4(TVShow *shows); -void sub_80F0358(TVShow *player1, TVShow *player2, TVShow *player3, TVShow *player4); -void sub_80F0C04(void); -void sub_80F0708(void); -void sub_80F0B64(void); -s8 sub_80F06D0(TVShow *tvShows); -bool8 sub_80F049C(TVShow *dest[], TVShow *src[], u8 idx); -bool8 sub_80F0580(TVShow *tv1, TVShow *tv2, u8 idx); -bool8 sub_80F05E8(TVShow *tv1, TVShow *tv2, u8 idx); -bool8 sub_80F0668(TVShow *tv1, TVShow *tv2, u8 idx); -void sub_80F0B00(u8 showIdx); -void sub_80F0B24(u16 species, u8 showIdx); -void sub_80F0D60(PokeNews *player1, PokeNews *player2, PokeNews *player3, PokeNews *player4); -void sub_80F0EEC(void); -void sub_80F0F24(void); -s8 sub_80F0ECC(PokeNews *pokeNews, u8 idx); -void sub_80F0E58(PokeNews *dest[], PokeNews *src[]); -bool8 sub_80F0E84(PokeNews *dest, PokeNews *src, s8 slot); +static void sub_80F1254(TVShow *shows); +static void sub_80F12A4(TVShow *shows); +static void sub_80F0358(TVShow *player1, TVShow *player2, TVShow *player3, TVShow *player4); +static void sub_80F0C04(void); +static void sub_80F0708(void); +static void sub_80F0B64(void); +static s8 sub_80F06D0(TVShow *tvShows); +static bool8 sub_80F049C(TVShow *dest[], TVShow *src[], u8 idx); +static bool8 sub_80F0580(TVShow *tv1, TVShow *tv2, u8 idx); +static bool8 sub_80F05E8(TVShow *tv1, TVShow *tv2, u8 idx); +static bool8 sub_80F0668(TVShow *tv1, TVShow *tv2, u8 idx); +void SetTvShowInactive(u8 showIdx); +static void sub_80F0B24(u16 species, u8 showIdx); +static void sub_80F0D60(PokeNews *player1, PokeNews *player2, PokeNews *player3, PokeNews *player4); +static void sub_80F0EEC(void); +static void sub_80F0F24(void); +static s8 sub_80F0ECC(PokeNews *pokeNews, u8 idx); +static void sub_80F0E58(PokeNews *dest[], PokeNews *src[]); +static bool8 sub_80F0E84(PokeNews *dest, PokeNews *src, s8 slot); void TVShowDone(void); -void InterviewAfter_FanClubLetter(void); -void InterviewAfter_RecentHappenings(void); -void InterviewAfter_PkmnFanClubOpinions(void); -void InterviewAfter_DummyShow4(void); -void InterviewAfter_BravoTrainerPokemonProfile(void); -void InterviewAfter_BravoTrainerBattleTowerProfile(void); -void InterviewAfter_ContestLiveUpdates(void); +static void InterviewAfter_FanClubLetter(void); +static void InterviewAfter_RecentHappenings(void); +static void InterviewAfter_PkmnFanClubOpinions(void); +static void InterviewAfter_DummyShow4(void); +static void InterviewAfter_BravoTrainerPokemonProfile(void); +static void InterviewAfter_BravoTrainerBattleTowerProfile(void); +static void InterviewAfter_ContestLiveUpdates(void); void UpdateWorldOfMastersAndPutItOnTheAir(void); void PutPokemonTodayFailedOnTheAir(void); -void sub_80ED718(void); -void sub_80EED88(void); +static void sub_80ED718(void); +static void sub_80EED88(void); void TV_SortPurchasesByQuantity(void); -void sub_80ED8B4(u16 days); +static void sub_80ED8B4(u16 days); void UpdateMassOutbreakTimeLeft(u16 days); -void sub_80EF120(u16 days); -void sub_80EDA48(u16 days); -void sub_80EEB98(u16 days); +static void sub_80EF120(u16 days); +static void sub_80EDA48(u16 days); +static void sub_80EEB98(u16 days); void PutFishingAdviceShowOnTheAir(void); -void sub_80EDA80(void); u8 TV_MonDataIdxToRibbon(u8 monDataIdx); -void sub_80EEBF4(u8 actionIdx); +static void sub_80EEBF4(u8 actionIdx); bool8 IsPriceDiscounted(u8 newsKind); -void InterviewBefore_FanClubLetter(void); -void InterviewBefore_RecentHappenings(void); -void InterviewBefore_PkmnFanClubOpinions(void); -void InterviewBefore_Dummy(void); -void InterviewBefore_BravoTrainerBTProfile(void); -void InterviewBefore_ContestLiveUpdates(void); -void InterviewBefore_3CheersForPokeblocks(void); -void InterviewBefore_FanClubSpecial(void); +static void InterviewBefore_FanClubLetter(void); +static void InterviewBefore_RecentHappenings(void); +static void InterviewBefore_PkmnFanClubOpinions(void); +static void InterviewBefore_Dummy(void); +static void InterviewBefore_BravoTrainerBTProfile(void); +static void InterviewBefore_ContestLiveUpdates(void); +static void InterviewBefore_3CheersForPokeblocks(void); +static void InterviewBefore_FanClubSpecial(void); void ChangeBoxPokemonNickname_CB(void); -void DoTVShowPokemonFanClubLetter(void); -void DoTVShowRecentHappenings(void); -void DoTVShowPokemonFanClubOpinions(void); -void DoTVShowDummiedOut(void); -void DoTVShowPokemonNewsMassOutbreak(void); -void DoTVShowBravoTrainerPokemonProfile(void); -void DoTVShowBravoTrainerBattleTower(void); -void DoTVShowPokemonTodaySuccessfulCapture(void); -void DoTVShowTodaysSmartShopper(void); -void DoTVShowTheNameRaterShow(void); -void DoTVShowPokemonContestLiveUpdates(void); -void DoTVShowPokemonBattleUpdate(void); -void DoTVShow3CheersForPokeblocks(void); -void DoTVShowPokemonTodayFailedCapture(void); -void DoTVShowPokemonAngler(void); -void DoTVShowTheWorldOfMasters(void); -void DoTVShowTodaysRivalTrainer(void); -void DoTVShowDewfordTrendWatcherNetwork(void); -void DoTVShowHoennTreasureInvestigators(void); -void DoTVShowFindThatGamer(void); -void DoTVShowBreakingNewsTV(void); -void DoTVShowSecretBaseVisit(void); -void DoTVShowPokemonLotteryWinnerFlashReport(void); -void DoTVShowThePokemonBattleSeminar(void); -void DoTVShowTrainerFanClubSpecial(void); -void DoTVShowTrainerFanClub(void); -void DoTVShowSpotTheCuties(void); -void DoTVShowPokemonNewsBattleFrontier(void); -void DoTVShowWhatsNo1InHoennToday(void); -void DoTVShowSecretBaseSecrets(void); -void DoTVShowSafariFanClub(void); -void DoTVShowPokemonContestLiveUpdates2(void); +static void DoTVShowPokemonFanClubLetter(void); +static void DoTVShowRecentHappenings(void); +static void DoTVShowPokemonFanClubOpinions(void); +static void DoTVShowDummiedOut(void); +static void DoTVShowPokemonNewsMassOutbreak(void); +static void DoTVShowBravoTrainerPokemonProfile(void); +static void DoTVShowBravoTrainerBattleTower(void); +static void DoTVShowPokemonTodaySuccessfulCapture(void); +static void DoTVShowTodaysSmartShopper(void); +static void DoTVShowTheNameRaterShow(void); +static void DoTVShowPokemonContestLiveUpdates(void); +static void DoTVShowPokemonBattleUpdate(void); +static void DoTVShow3CheersForPokeblocks(void); +static void DoTVShowPokemonTodayFailedCapture(void); +static void DoTVShowPokemonAngler(void); +static void DoTVShowTheWorldOfMasters(void); +static void DoTVShowTodaysRivalTrainer(void); +static void DoTVShowDewfordTrendWatcherNetwork(void); +static void DoTVShowHoennTreasureInvestigators(void); +static void DoTVShowFindThatGamer(void); +static void DoTVShowBreakingNewsTV(void); +static void DoTVShowSecretBaseVisit(void); +static void DoTVShowPokemonLotteryWinnerFlashReport(void); +static void DoTVShowThePokemonBattleSeminar(void); +static void DoTVShowTrainerFanClubSpecial(void); +static void DoTVShowTrainerFanClub(void); +static void DoTVShowSpotTheCuties(void); +static void DoTVShowPokemonNewsBattleFrontier(void); +static void DoTVShowWhatsNo1InHoennToday(void); +static void DoTVShowSecretBaseSecrets(void); +static void DoTVShowSafariFanClub(void); +static void DoTVShowPokemonContestLiveUpdates2(void); // .rodata -const struct { +static const struct { u16 species; u16 moves[4]; u8 level; @@ -214,8 +211,7 @@ const struct { } }; -// TODO: Figure out what these are, and define constants in include/flags.h -const u16 sGoldSymbolFlags[] = { +static const u16 sGoldSymbolFlags[] = { FLAG_SYS_TOWER_GOLD, FLAG_SYS_DOME_GOLD, FLAG_SYS_PALACE_GOLD, @@ -225,7 +221,7 @@ const u16 sGoldSymbolFlags[] = { FLAG_SYS_PYRAMID_GOLD }; -const u16 sSilverSymbolFlags[] = { +static const u16 sSilverSymbolFlags[] = { FLAG_SYS_TOWER_SILVER, FLAG_SYS_DOME_SILVER, FLAG_SYS_PALACE_SILVER, @@ -235,8 +231,7 @@ const u16 sSilverSymbolFlags[] = { FLAG_SYS_PYRAMID_SILVER }; -// TODO: Figure out what these are, and define constants in include/vars.h -const u16 sNumberOneVarsAndThresholds[][2] = { +static const u16 sNumberOneVarsAndThresholds[][2] = { {VAR_DAILY_SLOTS, 100}, {VAR_DAILY_ROULETTE, 50}, {VAR_DAILY_WILDS, 100}, @@ -246,7 +241,7 @@ const u16 sNumberOneVarsAndThresholds[][2] = { {VAR_DAILY_BP, 30} }; -const u8 *const sPokeNewsTextGroup_Upcoming[] = { +static const u8 *const sPokeNewsTextGroup_Upcoming[] = { NULL, gPokeNewsTextSlateport_Upcoming, gPokeNewsTextGameCorner_Upcoming, @@ -254,7 +249,7 @@ const u8 *const sPokeNewsTextGroup_Upcoming[] = { gPokeNewsTextBlendMaster_Upcoming }; -const u8 *const sPokeNewsTextGroup_Ongoing[] = { +static const u8 *const sPokeNewsTextGroup_Ongoing[] = { NULL, gPokeNewsTextSlateport_Ongoing, gPokeNewsTextGameCorner_Ongoing, @@ -262,7 +257,7 @@ const u8 *const sPokeNewsTextGroup_Ongoing[] = { gPokeNewsTextBlendMaster_Ongoing }; -const u8 *const sPokeNewsTextGroup_Ending[] = { +static const u8 *const sPokeNewsTextGroup_Ending[] = { NULL, gPokeNewsTextSlateport_Ending, gPokeNewsTextGameCorner_Ending, @@ -276,7 +271,7 @@ u8 *const gTVStringVarPtrs[] = { gStringVar3 }; -const u8 *const sTVFanClubTextGroup[] = { +static const u8 *const sTVFanClubTextGroup[] = { gTVFanClubText00, gTVFanClubText01, gTVFanClubText02, @@ -287,7 +282,7 @@ const u8 *const sTVFanClubTextGroup[] = { gTVFanClubText07 }; -const u8 *const sTVRecentHappeninssTextGroup[] = { +static const u8 *const sTVRecentHappeninssTextGroup[] = { gTVRecentHappeningsText00, gTVRecentHappeningsText01, gTVRecentHappeningsText02, @@ -296,7 +291,7 @@ const u8 *const sTVRecentHappeninssTextGroup[] = { gTVRecentHappeningsText05 }; -const u8 *const sTVFanClubOpinionsTextGroup[] = { +static const u8 *const sTVFanClubOpinionsTextGroup[] = { gTVFanClubOpinionsText00, gTVFanClubOpinionsText01, gTVFanClubOpinionsText02, @@ -304,11 +299,11 @@ const u8 *const sTVFanClubOpinionsTextGroup[] = { gTVFanClubOpinionsText04 }; -const u8 *const sTVMassOutbreakTextGroup[] = { +static const u8 *const sTVMassOutbreakTextGroup[] = { gTVMassOutbreakText00 }; -const u8 *const sTVPokemonTodaySuccessfulTextGroup[] = { +static const u8 *const sTVPokemonTodaySuccessfulTextGroup[] = { gTVPokemonTodaySuccessfulText00, gTVPokemonTodaySuccessfulText01, gTVPokemonTodaySuccessfulText02, @@ -323,7 +318,7 @@ const u8 *const sTVPokemonTodaySuccessfulTextGroup[] = { gTVPokemonTodaySuccessfulText11 }; -const u8 *const sTVTodaysSmartShopperTextGroup[] = { +static const u8 *const sTVTodaysSmartShopperTextGroup[] = { gTVTodaysSmartShopperText00, gTVTodaysSmartShopperText01, gTVTodaysSmartShopperText02, @@ -339,7 +334,7 @@ const u8 *const sTVTodaysSmartShopperTextGroup[] = { gTVTodaysSmartShopperText12 }; -const u8 *const sTVBravoTrainerTextGroup[] = { +static const u8 *const sTVBravoTrainerTextGroup[] = { gTVBravoTrainerText00, gTVBravoTrainerText01, gTVBravoTrainerText02, @@ -351,7 +346,7 @@ const u8 *const sTVBravoTrainerTextGroup[] = { gTVBravoTrainerText08 }; -const u8 *const sTV3CheersForPokeblocksTextGroup[] = { +static const u8 *const sTV3CheersForPokeblocksTextGroup[] = { gTV3CheersForPokeblocksText00, gTV3CheersForPokeblocksText01, gTV3CheersForPokeblocksText02, @@ -360,7 +355,7 @@ const u8 *const sTV3CheersForPokeblocksTextGroup[] = { gTV3CheersForPokeblocksText05 }; -const u8 *const sTVBravoTrainerBattleTowerTextGroup[] = { +static const u8 *const sTVBravoTrainerBattleTowerTextGroup[] = { gTVBravoTrainerBattleTowerText00, gTVBravoTrainerBattleTowerText01, gTVBravoTrainerBattleTowerText02, @@ -378,7 +373,7 @@ const u8 *const sTVBravoTrainerBattleTowerTextGroup[] = { gTVBravoTrainerBattleTowerText14 }; -const u8 *const sTVContestLiveUpdatesTextGroup[] = { +static const u8 *const sTVContestLiveUpdatesTextGroup[] = { gTVContestLiveUpdatesText00, gTVContestLiveUpdatesText01, gTVContestLiveUpdatesText02, @@ -414,7 +409,7 @@ const u8 *const sTVContestLiveUpdatesTextGroup[] = { gTVContestLiveUpdatesText32 }; -const u8 *const sTVPokemonBattleUpdateTextGroup[] = { +static const u8 *const sTVPokemonBattleUpdateTextGroup[] = { gTVPokemonBattleUpdateText00, gTVPokemonBattleUpdateText01, gTVPokemonBattleUpdateText02, @@ -425,7 +420,7 @@ const u8 *const sTVPokemonBattleUpdateTextGroup[] = { gTVPokemonBattleUpdateText07 }; -const u8 *const sTVTrainerFanClubSpecialTextGroup[] = { +static const u8 *const sTVTrainerFanClubSpecialTextGroup[] = { gTVTrainerFanClubSpecialText00, gTVTrainerFanClubSpecialText01, gTVTrainerFanClubSpecialText02, @@ -434,7 +429,7 @@ const u8 *const sTVTrainerFanClubSpecialTextGroup[] = { gTVTrainerFanClubSpecialText05 }; -const u8 *const sTVNameRaterTextGroup[] = { +static const u8 *const sTVNameRaterTextGroup[] = { gTVNameRaterText00, gTVNameRaterText01, gTVNameRaterText02, @@ -456,14 +451,14 @@ const u8 *const sTVNameRaterTextGroup[] = { gTVNameRaterText18 }; -const u8 *const sTVPokemonContestLiveUpdates2TextGroup[] = { +static const u8 *const sTVPokemonContestLiveUpdates2TextGroup[] = { gTVPokemonContestLiveUpdates2Text00, gTVPokemonContestLiveUpdates2Text01, gTVPokemonContestLiveUpdates2Text02, gTVPokemonContestLiveUpdates2Text03 }; -const u8 *const sTVPokemonTodayFailedTextGroup[] = { +static const u8 *const sTVPokemonTodayFailedTextGroup[] = { gTVPokemonTodayFailedText00, gTVPokemonTodayFailedText01, gTVPokemonTodayFailedText02, @@ -473,18 +468,18 @@ const u8 *const sTVPokemonTodayFailedTextGroup[] = { gTVPokemonTodayFailedText06 }; -const u8 *const sTVPokemonAnslerTextGroup[] = { +static const u8 *const sTVPokemonAnslerTextGroup[] = { gTVPokemonAnglerText00, gTVPokemonAnglerText01 }; -const u8 *const sTVWorldOfMastersTextGroup[] = { +static const u8 *const sTVWorldOfMastersTextGroup[] = { gTVWorldOfMastersText00, gTVWorldOfMastersText01, gTVWorldOfMastersText02 }; -const u8 *const sTVTodaysRivalTrainerTextGroup[] = { +static const u8 *const sTVTodaysRivalTrainerTextGroup[] = { gTVTodaysRivalTrainerText00, gTVTodaysRivalTrainerText01, gTVTodaysRivalTrainerText02, @@ -498,7 +493,7 @@ const u8 *const sTVTodaysRivalTrainerTextGroup[] = { gTVTodaysRivalTrainerText10 }; -const u8 *const sTVDewfordTrendWatcherNetworkTextGroup[] = { +static const u8 *const sTVDewfordTrendWatcherNetworkTextGroup[] = { gTVDewfordTrendWatcherNetworkText00, gTVDewfordTrendWatcherNetworkText01, gTVDewfordTrendWatcherNetworkText02, @@ -508,20 +503,20 @@ const u8 *const sTVDewfordTrendWatcherNetworkTextGroup[] = { gTVDewfordTrendWatcherNetworkText06 }; -const u8 *const sTVHoennTreasureInvestisatorsTextGroup[] = { +static const u8 *const sTVHoennTreasureInvestisatorsTextGroup[] = { gTVHoennTreasureInvestigatorsText00, gTVHoennTreasureInvestigatorsText01, gTVHoennTreasureInvestigatorsText02 }; -const u8 *const sTVFindThatGamerTextGroup[] = { +static const u8 *const sTVFindThatGamerTextGroup[] = { gTVFindThatGamerText00, gTVFindThatGamerText01, gTVFindThatGamerText02, gTVFindThatGamerText03 }; -const u8 *const sTVBreakinsNewsTextGroup[] = { +static const u8 *const sTVBreakinsNewsTextGroup[] = { gTVBreakingNewsText00, gTVBreakingNewsText01, gTVBreakingNewsText02, @@ -537,7 +532,7 @@ const u8 *const sTVBreakinsNewsTextGroup[] = { gTVBreakingNewsText12 }; -const u8 *const sTVSecretBaseVisitTextGroup[] = { +static const u8 *const sTVSecretBaseVisitTextGroup[] = { gTVSecretBaseVisitText00, gTVSecretBaseVisitText01, gTVSecretBaseVisitText02, @@ -554,11 +549,11 @@ const u8 *const sTVSecretBaseVisitTextGroup[] = { gTVSecretBaseVisitText13 }; -const u8 *const sTVPokemonLotteryWinnerFlashReportTextGroup[] = { +static const u8 *const sTVPokemonLotteryWinnerFlashReportTextGroup[] = { gTVPokemonLotteryWinnerFlashReportText00 }; -const u8 *const sTVThePokemonBattleSeminarTextGroup[] = { +static const u8 *const sTVThePokemonBattleSeminarTextGroup[] = { gTVThePokemonBattleSeminarText00, gTVThePokemonBattleSeminarText01, gTVThePokemonBattleSeminarText02, @@ -568,7 +563,7 @@ const u8 *const sTVThePokemonBattleSeminarTextGroup[] = { gTVThePokemonBattleSeminarText06 }; -const u8 *const sTVTrainerFanClubTextGroup[] = { +static const u8 *const sTVTrainerFanClubTextGroup[] = { gTVTrainerFanClubText00, gTVTrainerFanClubText01, gTVTrainerFanClubText02, @@ -583,7 +578,7 @@ const u8 *const sTVTrainerFanClubTextGroup[] = { gTVTrainerFanClubText11 }; -const u8 *const sTVCutiesTextGroup[] = { +static const u8 *const sTVCutiesTextGroup[] = { gTVCutiesText00, gTVCutiesText01, gTVCutiesText02, @@ -602,7 +597,7 @@ const u8 *const sTVCutiesTextGroup[] = { gTVCutiesText15 }; -const u8 *const sTVPokemonNewsBattleFrontierTextGroup[] = { +static const u8 *const sTVPokemonNewsBattleFrontierTextGroup[] = { gTVPokemonNewsBattleFrontierText00, gTVPokemonNewsBattleFrontierText01, gTVPokemonNewsBattleFrontierText02, @@ -624,7 +619,7 @@ const u8 *const sTVPokemonNewsBattleFrontierTextGroup[] = { gTVPokemonNewsBattleFrontierText18 }; -const u8 *const sTVWhatsNo1InHoennTodayTextGroup[] = { +static const u8 *const sTVWhatsNo1InHoennTodayTextGroup[] = { gTVWhatsNo1InHoennTodayText00, gTVWhatsNo1InHoennTodayText01, gTVWhatsNo1InHoennTodayText02, @@ -636,7 +631,7 @@ const u8 *const sTVWhatsNo1InHoennTodayTextGroup[] = { gTVWhatsNo1InHoennTodayText08 }; -const u8 *const sTVSecretBaseSecretsTextGroup[] = { +static const u8 *const sTVSecretBaseSecretsTextGroup[] = { gTVSecretBaseSecretsText00, gTVSecretBaseSecretsText01, gTVSecretBaseSecretsText02, @@ -682,7 +677,7 @@ const u8 *const sTVSecretBaseSecretsTextGroup[] = { gTVSecretBaseSecretsText42 }; -const u8 *const sTVSafariFanClubTextGroup[] = { +static const u8 *const sTVSafariFanClubTextGroup[] = { gTVSafariFanClubText00, gTVSafariFanClubText01, gTVSafariFanClubText02, @@ -696,7 +691,7 @@ const u8 *const sTVSafariFanClubTextGroup[] = { gTVSafariFanClubText10 }; -const u8 *const sTVInSearchOfTrainersTextGroup[] = { +static const u8 *const sTVInSearchOfTrainersTextGroup[] = { gTVInSearchOfTrainersText00, gTVInSearchOfTrainersText01, gTVInSearchOfTrainersText02, @@ -1253,7 +1248,7 @@ void tv_store_id_2x(TVShow *show) show->common.trainerIdHi = id >> 8; } -void InterviewAfter_ContestLiveUpdates(void) +static void InterviewAfter_ContestLiveUpdates(void) { TVShow *show; TVShow *show2; @@ -1281,7 +1276,7 @@ void InterviewAfter_ContestLiveUpdates(void) } } -void PutBattleUpdateOnTheAir(u8 a0, u16 a1, u16 a2, u16 a3) +void PutBattleUpdateOnTheAir(u8 opponentLinkPlayerId, u16 move, u16 speciesPlayer, u16 speciesOpponent) { TVShow *show; u8 name[32]; @@ -1308,21 +1303,21 @@ void PutBattleUpdateOnTheAir(u8 a0, u16 a1, u16 a2, u16 a3) { show->battleUpdate.battleType = 0; } - show->battleUpdate.move = a1; - show->battleUpdate.species2 = a2; - show->battleUpdate.species = a3; - StringCopy(name, gLinkPlayers[a0].name); + show->battleUpdate.move = move; + show->battleUpdate.speciesPlayer = speciesPlayer; + show->battleUpdate.speciesOpponent = speciesOpponent; + StringCopy(name, gLinkPlayers[opponentLinkPlayerId].name); StripExtCtrlCodes(name); StringCopy(show->battleUpdate.linkOpponentName, name); tv_store_id_2x(show); show->battleUpdate.language = gGameLanguage; - if (show->battleUpdate.language == LANGUAGE_JAPANESE || gLinkPlayers[a0].language == LANGUAGE_JAPANESE) + if (show->battleUpdate.language == LANGUAGE_JAPANESE || gLinkPlayers[opponentLinkPlayerId].language == LANGUAGE_JAPANESE) { show->battleUpdate.linkOpponentLanguage = LANGUAGE_JAPANESE; } else { - show->battleUpdate.linkOpponentLanguage = gLinkPlayers[a0].language; + show->battleUpdate.linkOpponentLanguage = gLinkPlayers[opponentLinkPlayerId].language; } } } @@ -1385,13 +1380,13 @@ void PutFanClubSpecialOnTheAir(void) StringCopy(show->fanClubSpecial.idolName, name); tv_store_id_2x(show); show->fanClubSpecial.language = gGameLanguage; - if (show->fanClubSpecial.language == LANGUAGE_JAPANESE || gSaveBlock1Ptr->unk_31A0 == LANGUAGE_JAPANESE) + if (show->fanClubSpecial.language == LANGUAGE_JAPANESE || gSaveBlock1Ptr->linkBattleRecords.languages[0] == LANGUAGE_JAPANESE) { show->fanClubSpecial.idolNameLanguage = LANGUAGE_JAPANESE; } else { - show->fanClubSpecial.idolNameLanguage = gSaveBlock1Ptr->unk_31A0; + show->fanClubSpecial.idolNameLanguage = gSaveBlock1Ptr->linkBattleRecords.languages[0]; } } @@ -1472,7 +1467,7 @@ void ContestLiveUpdates_BeforeInterview_5(u8 a0, u8 a1) } } -void InterviewAfter_BravoTrainerPokemonProfile(void) +static void InterviewAfter_BravoTrainerPokemonProfile(void) { TVShow *show; TVShow *show2; @@ -1538,7 +1533,7 @@ void BravoTrainerPokemonProfile_BeforeInterview2(u8 a0) } } -void InterviewAfter_BravoTrainerBattleTowerProfile(void) +static void InterviewAfter_BravoTrainerBattleTowerProfile(void) { TVShow *show; @@ -1671,7 +1666,7 @@ void PutLilycoveContestLadyShowOnTheAir(void) } } -void InterviewAfter_FanClubLetter(void) +static void InterviewAfter_FanClubLetter(void) { TVShow *show; @@ -1684,7 +1679,7 @@ void InterviewAfter_FanClubLetter(void) show->fanclubLetter.language = gGameLanguage; } -void InterviewAfter_RecentHappenings(void) +static void InterviewAfter_RecentHappenings(void) { TVShow *show; @@ -1697,7 +1692,7 @@ void InterviewAfter_RecentHappenings(void) show->recentHappenings.language = gGameLanguage; } -void InterviewAfter_PkmnFanClubOpinions(void) +static void InterviewAfter_PkmnFanClubOpinions(void) { TVShow *show; @@ -1722,14 +1717,14 @@ void InterviewAfter_PkmnFanClubOpinions(void) } } -void InterviewAfter_DummyShow4() +static void InterviewAfter_DummyShow4(void) { TVShow *show; show = &gSaveBlock1Ptr->tvShows[sCurTVShowSlot]; } -void sub_80ED718(void) +static void sub_80ED718(void) { u8 i; u16 outbreakIdx; @@ -1794,7 +1789,6 @@ void EndMassOutbreak(void) void UpdateTVShowsPerDay(u16 days) { - sub_80ED8B4(days); UpdateMassOutbreakTimeLeft(days); sub_80EF120(days); @@ -1802,7 +1796,7 @@ void UpdateTVShowsPerDay(u16 days) sub_80EEB98(days); } -void sub_80ED8B4(u16 days) +static void sub_80ED8B4(u16 days) { u8 i; TVShow *show; @@ -1872,7 +1866,7 @@ void PutFishingAdviceShowOnTheAir(void) { TVShow *show; - sCurTVShowSlot = FindEmptyTVSlotBeyondFirstFiveShowsOfArray(gSaveBlock1Ptr->tvShows); + sCurTVShowSlot = FindEmptyTVSlotBeyondFirstFiveShowsOfArray(gSaveBlock1Ptr->tvShows); if (sCurTVShowSlot != -1 && HasMixableShowAlreadyBeenSpawnedWithPlayerID(TVSHOW_FISHING_ADVICE, FALSE) != TRUE) { show = &gSaveBlock1Ptr->tvShows[sCurTVShowSlot]; @@ -1892,7 +1886,7 @@ void SetPokemonAnglerSpecies(u16 species) sPokemonAnglerSpecies = species; } -void sub_80EDA48(u16 days) +static void sub_80EDA48(u16 days) { TVShow *show; @@ -1957,11 +1951,11 @@ void sub_80EDB44(void) show->rivalTrainer.badgeCount = nBadges; if (IsNationalPokedexEnabled()) { - show->rivalTrainer.dexCount = pokedex_count(0x01); + show->rivalTrainer.dexCount = GetNationalPokedexCount(0x01); } else { - show->rivalTrainer.dexCount = sub_80C0844(0x01); + show->rivalTrainer.dexCount = GetHoennPokedexCount(0x01); } show->rivalTrainer.location = gMapHeader.regionMapSectionId; show->rivalTrainer.mapDataId = gMapHeader.mapDataId; @@ -2088,8 +2082,7 @@ void sub_80EDE84(u16 nCoinsSpent) sFindThatGamerCoinsSpent = nCoinsSpent; } -#ifdef NONMATCHING // FIXME: Register allocation shenanigans -void sub_80EDE98(TVShow *show) +static void sub_80EDE98(TVShow *show) { u8 i; u8 j; @@ -2140,11 +2133,11 @@ void sub_80EDE98(TVShow *show) default: for (k = 0; k < n * n; k ++) { - i = Random() % n; + deco = Random() % n; j = Random() % n; - x = sTV_DecorationsBuffer[i]; - sTV_DecorationsBuffer[i] = sTV_DecorationsBuffer[j]; - sTV_DecorationsBuffer[j] = x; + i = sTV_DecorationsBuffer[deco]; + sTV_DecorationsBuffer[deco] = sTV_DecorationsBuffer[j]; + sTV_DecorationsBuffer[j] = i; } for (i = 0; i < show->secretBaseVisit.nDecorations; i ++) { @@ -2153,157 +2146,8 @@ void sub_80EDE98(TVShow *show) break; } } -#else -__attribute__((naked)) -void sub_80EDE98(TVShow *show) -{ - asm_unified("\tpush {r4-r7,lr}\n" - "\tmov r7, r9\n" - "\tmov r6, r8\n" - "\tpush {r6,r7}\n" - "\tmov r8, r0\n" - "\tmovs r3, 0\n" - "\tldr r6, =sTV_DecorationsBuffer\n" - "\tldr r7, =gSaveBlock1Ptr\n" - "\tadds r2, r6, 0\n" - "\tmovs r1, 0\n" - "_080EDEAC:\n" - "\tadds r0, r3, r2\n" - "\tstrb r1, [r0]\n" - "\tadds r0, r3, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r3, r0, 24\n" - "\tcmp r3, 0xF\n" - "\tbls _080EDEAC\n" - "\tmovs r3, 0\n" - "\tmovs r5, 0\n" - "_080EDEBE:\n" - "\tldr r0, [r7]\n" - "\tldr r1, =0x00001aae\n" - "\tadds r0, r1\n" - "\tadds r0, r3\n" - "\tldrb r4, [r0]\n" - "\tadds r3, 0x1\n" - "\tcmp r4, 0\n" - "\tbeq _080EDF0A\n" - "\tmovs r1, 0\n" - "\tldrb r0, [r6]\n" - "\tcmp r0, 0\n" - "\tbne _080EDEE8\n" - "\tstrb r4, [r6]\n" - "\tb _080EDF04\n" - "\t.pool\n" - "_080EDEE8:\n" - "\tadds r0, r1, r6\n" - "\tldrb r0, [r0]\n" - "\tcmp r0, r4\n" - "\tbeq _080EDF0A\n" - "\tadds r0, r1, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r1, r0, 24\n" - "\tcmp r1, 0xF\n" - "\tbhi _080EDF0A\n" - "\tadds r2, r1, r6\n" - "\tldrb r0, [r2]\n" - "\tcmp r0, 0\n" - "\tbne _080EDEE8\n" - "\tstrb r4, [r2]\n" - "_080EDF04:\n" - "\tadds r0, r5, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r5, r0, 24\n" - "_080EDF0A:\n" - "\tlsls r0, r3, 24\n" - "\tlsrs r3, r0, 24\n" - "\tcmp r3, 0xF\n" - "\tbls _080EDEBE\n" - "\tcmp r5, 0x4\n" - "\tbls _080EDF1E\n" - "\tmovs r0, 0x4\n" - "\tmov r1, r8\n" - "\tstrb r0, [r1, 0x3]\n" - "\tb _080EDF22\n" - "_080EDF1E:\n" - "\tmov r0, r8\n" - "\tstrb r5, [r0, 0x3]\n" - "_080EDF22:\n" - "\tmov r1, r8\n" - "\tldrb r0, [r1, 0x3]\n" - "\tcmp r0, 0\n" - "\tbeq _080EDFA4\n" - "\tcmp r0, 0x1\n" - "\tbne _080EDF34\n" - "\tldrb r0, [r6]\n" - "\tstrb r0, [r1, 0x4]\n" - "\tb _080EDFA4\n" - "_080EDF34:\n" - "\tmovs r6, 0\n" - "\tadds r7, r5, 0\n" - "\tmuls r7, r5\n" - "\tcmp r6, r7\n" - "\tbge _080EDF7E\n" - "\tldr r0, =sTV_DecorationsBuffer\n" - "\tmov r9, r0\n" - "_080EDF42:\n" - "\tbl Random\n" - "\tlsls r0, 16\n" - "\tlsrs r0, 16\n" - "\tadds r1, r5, 0\n" - "\tbl __modsi3\n" - "\tlsls r0, 24\n" - "\tlsrs r4, r0, 24\n" - "\tbl Random\n" - "\tlsls r0, 16\n" - "\tlsrs r0, 16\n" - "\tadds r1, r5, 0\n" - "\tbl __modsi3\n" - "\tlsls r0, 24\n" - "\tlsrs r1, r0, 24\n" - "\tmov r0, r9\n" - "\tadds r2, r4, r0\n" - "\tldrb r3, [r2]\n" - "\tadd r1, r9\n" - "\tldrb r0, [r1]\n" - "\tstrb r0, [r2]\n" - "\tstrb r3, [r1]\n" - "\tadds r0, r6, 0x1\n" - "\tlsls r0, 16\n" - "\tlsrs r6, r0, 16\n" - "\tcmp r6, r7\n" - "\tblt _080EDF42\n" - "_080EDF7E:\n" - "\tmovs r3, 0\n" - "\tmov r1, r8\n" - "\tldrb r1, [r1, 0x3]\n" - "\tcmp r3, r1\n" - "\tbcs _080EDFA4\n" - "\tmov r2, r8\n" - "\tadds r2, 0x4\n" - "\tldr r4, =sTV_DecorationsBuffer\n" - "_080EDF8E:\n" - "\tadds r1, r2, r3\n" - "\tadds r0, r3, r4\n" - "\tldrb r0, [r0]\n" - "\tstrb r0, [r1]\n" - "\tadds r0, r3, 0x1\n" - "\tlsls r0, 24\n" - "\tlsrs r3, r0, 24\n" - "\tmov r0, r8\n" - "\tldrb r0, [r0, 0x3]\n" - "\tcmp r3, r0\n" - "\tbcc _080EDF8E\n" - "_080EDFA4:\n" - "\tpop {r3,r4}\n" - "\tmov r8, r3\n" - "\tmov r9, r4\n" - "\tpop {r4-r7}\n" - "\tpop {r0}\n" - "\tbx r0\n" - "\t.pool"); -} -#endif -void sub_80EDFB4(TVShow *show) +static void sub_80EDFB4(TVShow *show) { u8 i; u16 move; @@ -2621,7 +2465,7 @@ bool8 sub_80EE7C0(void) { return TRUE; } - if (gSaveBlock1Ptr->linkBattleRecords[0].name[0] == EOS) + if (gSaveBlock1Ptr->linkBattleRecords.entries[0].name[0] == EOS) { return TRUE; } @@ -2740,7 +2584,7 @@ void sub_80EEA70(void) } } -void sub_80EEB98(u16 days) +static void sub_80EEB98(u16 days) { u8 i; @@ -2758,7 +2602,7 @@ void sub_80EEB98(u16 days) } } -void sub_80EEBF4(u8 actionIdx) +static void sub_80EEBF4(u8 actionIdx) { TVShow *show; @@ -2814,7 +2658,7 @@ void sub_80EED60(u16 delta) // PokeNews -void sub_80EED88(void) +static void sub_80EED88(void) { u8 newsKind; @@ -2865,7 +2709,7 @@ void ClearPokemonNewsI(u8 i) gSaveBlock1Ptr->pokeNews[i].days = 0; } -void sub_80EEEB8(void) +static void sub_80EEEB8(void) { u8 i; u8 j; @@ -2995,7 +2839,7 @@ bool8 sub_80EF0E4(u8 newsKind) return FALSE; } -void sub_80EF120(u16 days) +static void sub_80EF120(u16 days) { u8 i; @@ -3073,48 +2917,25 @@ void TV_PrintIntToStringVar(u8 varIdx, int value) { int nDigits; - nDigits = sub_80EF370(value); + nDigits = CountDigits(value); ConvertIntToDecimalStringN(gTVStringVarPtrs[varIdx], value, STR_CONV_MODE_LEFT_ALIGN, nDigits); } -size_t sub_80EF370(int value) +size_t CountDigits(int value) { - if (value / 10 == 0) - { - return 1; - } - if (value / 100 == 0) - { - return 2; - } - if (value / 1000 == 0) - { - return 3; - } - if (value / 10000 == 0) - { - return 4; - } - if (value / 100000 == 0) - { - return 5; - } - if (value / 1000000 == 0) - { - return 6; - } - if (value / 10000000 == 0) - { - return 7; - } - if (value / 100000000 == 0) - { - return 8; - } + if (value / 10 == 0) return 1; + if (value / 100 == 0) return 2; + if (value / 1000 == 0) return 3; + if (value / 10000 == 0) return 4; + if (value / 100000 == 0) return 5; + if (value / 1000000 == 0) return 6; + if (value / 10000000 == 0) return 7; + if (value / 100000000 == 0) return 8; + return 1; } -void sub_80EF40C(u8 varIdx, TVShow *show) +static void sub_80EF40C(u8 varIdx, TVShow *show) { u8 i; int price; @@ -3124,7 +2945,7 @@ void sub_80EF40C(u8 varIdx, TVShow *show) { if (show->smartshopperShow.itemIds[i] != ITEM_NONE) { - price += itemid_get_market_price(show->smartshopperShow.itemIds[i]) * show->smartshopperShow.itemAmounts[i]; + price += ItemId_GetPrice(show->smartshopperShow.itemIds[i]) * show->smartshopperShow.itemAmounts[i]; } } if (show->smartshopperShow.priceReduced == TRUE) @@ -3245,7 +3066,7 @@ void InterviewBefore(void) } } -void InterviewBefore_FanClubLetter(void) +static void InterviewBefore_FanClubLetter(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_FAN_CLUB_LETTER); if (!gSpecialVar_Result) @@ -3255,7 +3076,7 @@ void InterviewBefore_FanClubLetter(void) } } -void InterviewBefore_RecentHappenings(void) +static void InterviewBefore_RecentHappenings(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_RECENT_HAPPENINGS); if (!gSpecialVar_Result) @@ -3264,7 +3085,7 @@ void InterviewBefore_RecentHappenings(void) } } -void InterviewBefore_PkmnFanClubOpinions(void) +static void InterviewBefore_PkmnFanClubOpinions(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_PKMN_FAN_CLUB_OPINIONS); if (!gSpecialVar_Result) @@ -3276,17 +3097,17 @@ void InterviewBefore_PkmnFanClubOpinions(void) } } -void InterviewBefore_Dummy(void) +static void InterviewBefore_Dummy(void) { gSpecialVar_Result = TRUE; } -void InterviewBefore_NameRater(void) +static void InterviewBefore_NameRater(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_NAME_RATER_SHOW); } -void InterviewBefore_BravoTrainerPkmnProfile(void) +static void InterviewBefore_BravoTrainerPkmnProfile(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE); if (!gSpecialVar_Result) @@ -3295,17 +3116,17 @@ void InterviewBefore_BravoTrainerPkmnProfile(void) } } -void InterviewBefore_ContestLiveUpdates(void) +static void InterviewBefore_ContestLiveUpdates(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_CONTEST_LIVE_UPDATES); } -void InterviewBefore_3CheersForPokeblocks(void) +static void InterviewBefore_3CheersForPokeblocks(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_3_CHEERS_FOR_POKEBLOCKS); } -void InterviewBefore_BravoTrainerBTProfile(void) +static void InterviewBefore_BravoTrainerBTProfile(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE); if (!gSpecialVar_Result) @@ -3314,7 +3135,7 @@ void InterviewBefore_BravoTrainerBTProfile(void) } } -void InterviewBefore_FanClubSpecial(void) +static void InterviewBefore_FanClubSpecial(void) { FindActiveBroadcastByShowType_SetScriptResult(TVSHOW_FAN_CLUB_SPECIAL); if (!gSpecialVar_Result) @@ -3355,7 +3176,7 @@ void DeleteTVShowInArrayByIdx(TVShow *shows, u8 idx) } } -void sub_80EF93C(TVShow *shows) +static void sub_80EF93C(TVShow *shows) { u8 i; u8 j; @@ -3427,7 +3248,7 @@ u16 TV_GetSomeOtherSpeciesAlreadySeenByPlayer(u16 passedSpecies) return species; } -void sub_80EFA88(void) +static void sub_80EFA88(void) { sCurTVShowSlot = FindEmptyTVSlotWithinFirstFiveShowsOfArray(gSaveBlock1Ptr->tvShows); gSpecialVar_0x8006 = sCurTVShowSlot; @@ -3633,7 +3454,7 @@ void ChangePokemonNickname(void) void ChangePokemonNickname_CB(void) { SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar2); - c2_exit_to_overworld_1_continue_scripts_restart_music(); + CB2_ReturnToFieldContinueScript(); } void ChangeBoxPokemonNickname(void) @@ -3649,7 +3470,7 @@ void ChangeBoxPokemonNickname(void) void ChangeBoxPokemonNickname_CB(void) { SetBoxMonNickFromAnyBox(gSpecialVar_MonBoxId, gSpecialVar_MonBoxPos, gStringVar2); - c2_exit_to_overworld_1_continue_scripts_restart_music(); + CB2_ReturnToFieldContinueScript(); } void TV_CopyNicknameToStringVar1AndEnsureTerminated(void) @@ -3836,7 +3657,7 @@ void sub_80F01E8(void *src, u32 size, u8 masterIdx) } } -void sub_80F0358(TVShow player1[25], TVShow player2[25], TVShow player3[25], TVShow player4[25]) +static void sub_80F0358(TVShow player1[25], TVShow player2[25], TVShow player3[25], TVShow player4[25]) { u8 i; u8 j; @@ -3884,7 +3705,7 @@ void sub_80F0358(TVShow player1[25], TVShow player2[25], TVShow player3[25], TVS } } -bool8 sub_80F049C(TVShow *dest[25], TVShow *src[25], u8 idx) +static bool8 sub_80F049C(TVShow *dest[25], TVShow *src[25], u8 idx) { u8 value; u8 switchval; @@ -3915,7 +3736,7 @@ bool8 sub_80F049C(TVShow *dest[25], TVShow *src[25], u8 idx) return FALSE; } -u8 sub_80F0580(TVShow *tv1, TVShow *tv2, u8 idx) +static bool8 sub_80F0580(TVShow *tv1, TVShow *tv2, u8 idx) { u32 linkTrainerId = GetLinkPlayerTrainerId(idx); @@ -3932,7 +3753,7 @@ u8 sub_80F0580(TVShow *tv1, TVShow *tv2, u8 idx) return TRUE; } -u8 sub_80F05E8(TVShow *tv1, TVShow *tv2, u8 idx) +static bool8 sub_80F05E8(TVShow *tv1, TVShow *tv2, u8 idx) { u32 linkTrainerId = GetLinkPlayerTrainerId(idx); if ((linkTrainerId & 0xFF) == tv2->common.srcTrainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.srcTrainerIdHi) @@ -3952,7 +3773,7 @@ u8 sub_80F05E8(TVShow *tv1, TVShow *tv2, u8 idx) return TRUE; } -u8 sub_80F0668(TVShow *tv1, TVShow *tv2, u8 idx) +static bool8 sub_80F0668(TVShow *tv1, TVShow *tv2, u8 idx) { u32 linkTrainerId = GetLinkPlayerTrainerId(idx); if ((linkTrainerId & 0xFF) == tv2->common.trainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.trainerIdHi) @@ -3969,7 +3790,7 @@ u8 sub_80F0668(TVShow *tv1, TVShow *tv2, u8 idx) return TRUE; } -s8 sub_80F06D0(TVShow *tvShows) +static s8 sub_80F06D0(TVShow *tvShows) { u8 i; @@ -3984,7 +3805,7 @@ s8 sub_80F06D0(TVShow *tvShows) } #ifdef NONMATCHING -void sub_80F0708(void) // FIXME: register allocation shenanigans +static void sub_80F0708(void) // FIXME: register allocation shenanigans { u16 i; TVShow *show; @@ -4000,8 +3821,8 @@ void sub_80F0708(void) // FIXME: register allocation shenanigans case TVSHOW_3_CHEERS_FOR_POKEBLOCKS: break; case TVSHOW_BATTLE_UPDATE: - sub_80F0B24((&gSaveBlock1Ptr->tvShows[i])->battleUpdate.species2, i); - sub_80F0B24((&gSaveBlock1Ptr->tvShows[i])->battleUpdate.species, i); + sub_80F0B24((&gSaveBlock1Ptr->tvShows[i])->battleUpdate.speciesPlayer, i); + sub_80F0B24((&gSaveBlock1Ptr->tvShows[i])->battleUpdate.speciesOpponent, i); break; case TVSHOW_FAN_CLUB_SPECIAL: break; @@ -4104,13 +3925,13 @@ void sub_80F0708(void) // FIXME: register allocation shenanigans break; default: - sub_80F0B00(i); + SetTvShowInactive(i); break; } } } #else -__attribute__((naked)) void sub_80F0708(void) +NAKED static void sub_80F0708(void) { asm_unified("\tpush {r4-r7,lr}\n" "\tmov r7, r9\n" @@ -4527,7 +4348,7 @@ __attribute__((naked)) void sub_80F0708(void) "\tmov r2, r9\n" "\tlsls r0, r2, 24\n" "\tlsrs r0, 24\n" - "\tbl sub_80F0B00\n" + "\tbl SetTvShowInactive\n" "_080F0AE2_break:\n" "\tmov r0, r9\n" "\tadds r0, 0x1\n" @@ -4548,12 +4369,12 @@ __attribute__((naked)) void sub_80F0708(void) } #endif -void sub_80F0B00(u8 showIdx) +void SetTvShowInactive(u8 showIdx) { gSaveBlock1Ptr->tvShows[showIdx].common.active = FALSE; } -void sub_80F0B24(u16 species, u8 showIdx) +static void sub_80F0B24(u16 species, u8 showIdx) { if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), 0) == 0) { @@ -4561,7 +4382,7 @@ void sub_80F0B24(u16 species, u8 showIdx) } } -void sub_80F0B64(void) +static void sub_80F0B64(void) { u16 i; @@ -4594,7 +4415,7 @@ void sub_80F0BB8(void) } } -void sub_80F0C04(void) +static void sub_80F0C04(void) { s8 i; s8 ct; @@ -4648,7 +4469,7 @@ void sub_80F0C7C(void *src, u32 size, u8 masterIdx) } } -void sub_80F0D60(PokeNews player1[16], PokeNews player2[16], PokeNews player3[16], PokeNews player4[16]) +static void sub_80F0D60(PokeNews player1[16], PokeNews player2[16], PokeNews player3[16], PokeNews player4[16]) { u8 i; u8 j; @@ -4680,7 +4501,7 @@ void sub_80F0D60(PokeNews player1[16], PokeNews player2[16], PokeNews player3[16 } } -void sub_80F0E58(PokeNews *dest[16], PokeNews *src[16]) +static void sub_80F0E58(PokeNews *dest[16], PokeNews *src[16]) { PokeNews *ptr1; PokeNews *ptr2; @@ -4691,7 +4512,7 @@ void sub_80F0E58(PokeNews *dest[16], PokeNews *src[16]) sub_80F0E84(ptr1, ptr2, sCurTVShowSlot); } -bool8 sub_80F0E84(PokeNews *dest, PokeNews *src, s8 slot) +static bool8 sub_80F0E84(PokeNews *dest, PokeNews *src, s8 slot) { u8 i; u8 kind; @@ -4713,7 +4534,7 @@ bool8 sub_80F0E84(PokeNews *dest, PokeNews *src, s8 slot) return TRUE; } -s8 sub_80F0ECC(PokeNews *pokeNews, u8 idx) +static s8 sub_80F0ECC(PokeNews *pokeNews, u8 idx) { if (pokeNews[idx].kind == POKENEWS_NONE) { @@ -4722,7 +4543,7 @@ s8 sub_80F0ECC(PokeNews *pokeNews, u8 idx) return idx; } -void sub_80F0EEC(void) +static void sub_80F0EEC(void) { u8 i; @@ -4736,7 +4557,7 @@ void sub_80F0EEC(void) sub_80EEEB8(); } -void sub_80F0F24(void) +static void sub_80F0F24(void) { u8 i; @@ -4759,7 +4580,7 @@ else \ (langptr) = langfix; \ } -void sub_80F0F64(TVShow *show, u32 language) +static void sub_80F0F64(TVShow *show, u32 language) { int i; TVShow **r4; @@ -4841,7 +4662,7 @@ void sub_80F1208(TVShow *shows) } } -void sub_80F1254(TVShow *shows) +static void sub_80F1254(TVShow *shows) { TVShow *curShow; @@ -4866,7 +4687,7 @@ u8 TV_GetStringLanguage(u8 *str) return IsStringJapanese(str) ? LANGUAGE_JAPANESE : LANGUAGE_ENGLISH; } -void sub_80F12A4(TVShow *shows) +static void sub_80F12A4(TVShow *shows) { TVShow *curShow; @@ -5106,7 +4927,7 @@ void DoTVShow(void) } } -void DoTVShowBravoTrainerPokemonProfile(void) +static void DoTVShowBravoTrainerPokemonProfile(void) { TVShow *show; u8 state; @@ -5178,7 +4999,7 @@ void DoTVShowBravoTrainerPokemonProfile(void) ShowFieldMessage(sTVBravoTrainerTextGroup[state]); } -void DoTVShowBravoTrainerBattleTower(void) +static void DoTVShowBravoTrainerBattleTower(void) { TVShow *show; u8 state; @@ -5275,7 +5096,7 @@ void DoTVShowBravoTrainerBattleTower(void) ShowFieldMessage(sTVBravoTrainerBattleTowerTextGroup[state]); } -void DoTVShowTodaysSmartShopper(void) +static void DoTVShowTodaysSmartShopper(void) { TVShow *show; u8 state; @@ -5299,7 +5120,7 @@ void DoTVShowTodaysSmartShopper(void) break; case 1: TVShowConvertInternationalString(gStringVar1, show->smartshopperShow.playerName, show->smartshopperShow.language); - StringCopy(gStringVar2, ItemId_GetItem(show->smartshopperShow.itemIds[0])->name); + StringCopy(gStringVar2, ItemId_GetName(show->smartshopperShow.itemIds[0])); TV_PrintIntToStringVar(2, show->smartshopperShow.itemAmounts[0]); sTVShowState += 1 + (Random() % 4); break; @@ -5327,7 +5148,7 @@ void DoTVShowTodaysSmartShopper(void) } break; case 6: - StringCopy(gStringVar2, ItemId_GetItem(show->smartshopperShow.itemIds[1])->name); + StringCopy(gStringVar2, ItemId_GetName(show->smartshopperShow.itemIds[1])); TV_PrintIntToStringVar(2, show->smartshopperShow.itemAmounts[1]); if (show->smartshopperShow.itemIds[2] != ITEM_NONE) { @@ -5343,7 +5164,7 @@ void DoTVShowTodaysSmartShopper(void) } break; case 7: - StringCopy(gStringVar2, ItemId_GetItem(show->smartshopperShow.itemIds[2])->name); + StringCopy(gStringVar2, ItemId_GetName(show->smartshopperShow.itemIds[2])); TV_PrintIntToStringVar(2, show->smartshopperShow.itemAmounts[2]); if (show->smartshopperShow.priceReduced == TRUE) { @@ -5380,7 +5201,7 @@ void DoTVShowTodaysSmartShopper(void) break; case 11: TVShowConvertInternationalString(gStringVar1, show->smartshopperShow.playerName, show->smartshopperShow.language); - StringCopy(gStringVar2, ItemId_GetItem(show->smartshopperShow.itemIds[0])->name); + StringCopy(gStringVar2, ItemId_GetName(show->smartshopperShow.itemIds[0])); if (show->smartshopperShow.priceReduced == TRUE) { sTVShowState = 8; @@ -5398,7 +5219,7 @@ void DoTVShowTodaysSmartShopper(void) ShowFieldMessage(sTVTodaysSmartShopperTextGroup[state]); } -void DoTVShowTheNameRaterShow(void) +static void DoTVShowTheNameRaterShow(void) { TVShow *show; u8 state; @@ -5496,7 +5317,7 @@ void DoTVShowTheNameRaterShow(void) ShowFieldMessage(sTVNameRaterTextGroup[state]); } -void DoTVShowPokemonTodaySuccessfulCapture(void) +static void DoTVShowPokemonTodaySuccessfulCapture(void) { TVShow *show; u8 state; @@ -5523,7 +5344,7 @@ void DoTVShowPokemonTodaySuccessfulCapture(void) sTVShowState = 2; break; case 2: - StringCopy(gStringVar2, ItemId_GetItem(show->pokemonToday.ball)->name); + StringCopy(gStringVar2, ItemId_GetName(show->pokemonToday.ball)); TV_PrintIntToStringVar(2, show->pokemonToday.nBallsUsed); if (show->pokemonToday.nBallsUsed < 4) { @@ -5574,7 +5395,7 @@ void DoTVShowPokemonTodaySuccessfulCapture(void) ShowFieldMessage(sTVPokemonTodaySuccessfulTextGroup[state]); } -void DoTVShowPokemonTodayFailedCapture(void) +static void DoTVShowPokemonTodayFailedCapture(void) { TVShow *show; u8 state; @@ -5627,7 +5448,7 @@ void DoTVShowPokemonTodayFailedCapture(void) ShowFieldMessage(sTVPokemonTodayFailedTextGroup[state]); } -void DoTVShowPokemonFanClubLetter(void) +static void DoTVShowPokemonFanClubLetter(void) { TVShow *show; u8 state; @@ -5681,7 +5502,7 @@ void DoTVShowPokemonFanClubLetter(void) ShowFieldMessage(sTVFanClubTextGroup[state]); } -void DoTVShowRecentHappenings(void) +static void DoTVShowRecentHappenings(void) { TVShow *show; u8 state; @@ -5716,7 +5537,7 @@ void DoTVShowRecentHappenings(void) ShowFieldMessage(sTVRecentHappeninssTextGroup[state]); } -void DoTVShowPokemonFanClubOpinions(void) +static void DoTVShowPokemonFanClubOpinions(void) { TVShow *show; u8 state; @@ -5749,12 +5570,12 @@ void DoTVShowPokemonFanClubOpinions(void) ShowFieldMessage(sTVFanClubOpinionsTextGroup[state]); } -void DoTVShowDummiedOut(void) +static void DoTVShowDummiedOut(void) { } -void DoTVShowPokemonNewsMassOutbreak(void) +static void DoTVShowPokemonNewsMassOutbreak(void) { TVShow *show; @@ -5766,7 +5587,7 @@ void DoTVShowPokemonNewsMassOutbreak(void) ShowFieldMessage(sTVMassOutbreakTextGroup[sTVShowState]); } -void DoTVShowPokemonContestLiveUpdates(void) +static void DoTVShowPokemonContestLiveUpdates(void) { TVShow *show; u8 state; @@ -6113,7 +5934,7 @@ void DoTVShowPokemonContestLiveUpdates(void) ShowFieldMessage(sTVContestLiveUpdatesTextGroup[state]); } -void DoTVShowPokemonBattleUpdate(void) +static void DoTVShowPokemonBattleUpdate(void) { TVShow *show; u8 state; @@ -6150,13 +5971,13 @@ void DoTVShowPokemonBattleUpdate(void) break; case 2: TVShowConvertInternationalString(gStringVar1, show->battleUpdate.playerName, show->battleUpdate.language); - StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.species2]); + StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.speciesPlayer]); StringCopy(gStringVar3, gMoveNames[show->battleUpdate.move]); sTVShowState = 3; break; case 3: TVShowConvertInternationalString(gStringVar1, show->battleUpdate.linkOpponentName, show->battleUpdate.linkOpponentLanguage); - StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.species]); + StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.speciesOpponent]); sTVShowState = 4; break; case 4: @@ -6171,21 +5992,21 @@ void DoTVShowPokemonBattleUpdate(void) break; case 6: TVShowConvertInternationalString(gStringVar1, show->battleUpdate.playerName, show->battleUpdate.language); - StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.species2]); + StringCopy(gStringVar2, gSpeciesNames[show->battleUpdate.speciesPlayer]); StringCopy(gStringVar3, gMoveNames[show->battleUpdate.move]); sTVShowState = 7; break; case 7: TVShowConvertInternationalString(gStringVar1, show->battleUpdate.playerName, show->battleUpdate.language); TVShowConvertInternationalString(gStringVar2, show->battleUpdate.linkOpponentName, show->battleUpdate.linkOpponentLanguage); - StringCopy(gStringVar3, gSpeciesNames[show->battleUpdate.species]); + StringCopy(gStringVar3, gSpeciesNames[show->battleUpdate.speciesOpponent]); TVShowDone(); break; } ShowFieldMessage(sTVPokemonBattleUpdateTextGroup[state]); } -void DoTVShow3CheersForPokeblocks(void) +static void DoTVShow3CheersForPokeblocks(void) { TVShow *show; u8 state; @@ -6356,7 +6177,7 @@ void DoTVShowInSearchOfTrainers(void) ShowFieldMessage(sTVInSearchOfTrainersTextGroup[state]); } -void DoTVShowPokemonAngler(void) +static void DoTVShowPokemonAngler(void) { TVShow *show; u8 state; @@ -6390,7 +6211,7 @@ void DoTVShowPokemonAngler(void) ShowFieldMessage(sTVPokemonAnslerTextGroup[state]); } -void DoTVShowTheWorldOfMasters(void) +static void DoTVShowTheWorldOfMasters(void) { TVShow *show; u8 state; @@ -6420,7 +6241,7 @@ void DoTVShowTheWorldOfMasters(void) ShowFieldMessage(sTVWorldOfMastersTextGroup[state]); } -void DoTVShowTodaysRivalTrainer(void) +static void DoTVShowTodaysRivalTrainer(void) { TVShow *show; u8 state; @@ -6569,7 +6390,7 @@ void DoTVShowTodaysRivalTrainer(void) ShowFieldMessage(sTVTodaysRivalTrainerTextGroup[state]); } -void DoTVShowDewfordTrendWatcherNetwork(void) +static void DoTVShowDewfordTrendWatcherNetwork(void) { TVShow *show; u8 state; @@ -6625,7 +6446,7 @@ void DoTVShowDewfordTrendWatcherNetwork(void) ShowFieldMessage(sTVDewfordTrendWatcherNetworkTextGroup[state]); } -void DoTVShowHoennTreasureInvestigators(void) +static void DoTVShowHoennTreasureInvestigators(void) { TVShow *show; u8 state; @@ -6636,7 +6457,7 @@ void DoTVShowHoennTreasureInvestigators(void) switch (state) { case 0: - StringCopy(gStringVar1, ItemId_GetItem(show->treasureInvestigators.item)->name); + StringCopy(gStringVar1, ItemId_GetName(show->treasureInvestigators.item)); if (show->treasureInvestigators.location == MAPSEC_DYNAMIC) { switch (show->treasureInvestigators.mapDataId) @@ -6655,13 +6476,13 @@ void DoTVShowHoennTreasureInvestigators(void) } break; case 1: - StringCopy(gStringVar1, ItemId_GetItem(show->treasureInvestigators.item)->name); + StringCopy(gStringVar1, ItemId_GetName(show->treasureInvestigators.item)); TVShowConvertInternationalString(gStringVar2, show->treasureInvestigators.playerName, show->treasureInvestigators.language); GetMapName(gStringVar3, show->treasureInvestigators.location, 0); TVShowDone(); break; case 2: - StringCopy(gStringVar1, ItemId_GetItem(show->treasureInvestigators.item)->name); + StringCopy(gStringVar1, ItemId_GetName(show->treasureInvestigators.item)); TVShowConvertInternationalString(gStringVar2, show->treasureInvestigators.playerName, show->treasureInvestigators.language); TVShowDone(); break; @@ -6669,7 +6490,7 @@ void DoTVShowHoennTreasureInvestigators(void) ShowFieldMessage(sTVHoennTreasureInvestisatorsTextGroup[state]); } -void DoTVShowFindThatGamer(void) +static void DoTVShowFindThatGamer(void) { TVShow *show; u8 state; @@ -6743,7 +6564,7 @@ void DoTVShowFindThatGamer(void) ShowFieldMessage(sTVFindThatGamerTextGroup[state]); } -void DoTVShowBreakingNewsTV(void) +static void DoTVShowBreakingNewsTV(void) { TVShow *show; u8 state; @@ -6777,7 +6598,7 @@ void DoTVShowBreakingNewsTV(void) break; case 3: TV_PrintIntToStringVar(0, show->breakingNews.balls); - StringCopy(gStringVar2, ItemId_GetItem(show->breakingNews.caughtMonBall)->name); + StringCopy(gStringVar2, ItemId_GetName(show->breakingNews.caughtMonBall)); sTVShowState = 4; break; case 4: @@ -6846,7 +6667,7 @@ void DoTVShowBreakingNewsTV(void) ShowFieldMessage(sTVBreakinsNewsTextGroup[state]); } -void DoTVShowSecretBaseVisit(void) +static void DoTVShowSecretBaseVisit(void) { TVShow *show; u8 state; @@ -6942,7 +6763,7 @@ void DoTVShowSecretBaseVisit(void) ShowFieldMessage(sTVSecretBaseVisitTextGroup[state]); } -void DoTVShowPokemonLotteryWinnerFlashReport(void) +static void DoTVShowPokemonLotteryWinnerFlashReport(void) { TVShow *show; u8 state; @@ -6967,12 +6788,12 @@ void DoTVShowPokemonLotteryWinnerFlashReport(void) { StringCopy(gStringVar2, gText_Third); } - StringCopy(gStringVar3, ItemId_GetItem(show->lottoWinner.item)->name); + StringCopy(gStringVar3, ItemId_GetName(show->lottoWinner.item)); TVShowDone(); ShowFieldMessage(sTVPokemonLotteryWinnerFlashReportTextGroup[state]); } -void DoTVShowThePokemonBattleSeminar(void) +static void DoTVShowThePokemonBattleSeminar(void) { TVShow *show; u8 state; @@ -7036,7 +6857,7 @@ void DoTVShowThePokemonBattleSeminar(void) ShowFieldMessage(sTVThePokemonBattleSeminarTextGroup[state]); } -void DoTVShowTrainerFanClubSpecial(void) +static void DoTVShowTrainerFanClubSpecial(void) { TVShow *show; u8 state; @@ -7101,7 +6922,7 @@ void DoTVShowTrainerFanClubSpecial(void) ShowFieldMessage(sTVTrainerFanClubSpecialTextGroup[state]); } -void DoTVShowTrainerFanClub(void) +static void DoTVShowTrainerFanClub(void) { TVShow *show; u8 state; @@ -7188,7 +7009,7 @@ void DoTVShowTrainerFanClub(void) ShowFieldMessage(sTVTrainerFanClubTextGroup[state]); } -void DoTVShowSpotTheCuties(void) +static void DoTVShowSpotTheCuties(void) { TVShow *show; u8 state; @@ -7293,7 +7114,7 @@ void DoTVShowSpotTheCuties(void) ShowFieldMessage(sTVCutiesTextGroup[state]); } -void DoTVShowPokemonNewsBattleFrontier(void) +static void DoTVShowPokemonNewsBattleFrontier(void) { TVShow *show; u8 state; @@ -7442,7 +7263,7 @@ void DoTVShowPokemonNewsBattleFrontier(void) ShowFieldMessage(sTVPokemonNewsBattleFrontierTextGroup[state]); } -void DoTVShowWhatsNo1InHoennToday(void) +static void DoTVShowWhatsNo1InHoennToday(void) { TVShow *show; u8 state; @@ -7557,7 +7378,7 @@ u8 sub_80F51AC(TVShow *show, u8 a1) return 0; } -void DoTVShowSecretBaseSecrets(void) +static void DoTVShowSecretBaseSecrets(void) { TVShow *show; u8 state; @@ -7709,7 +7530,7 @@ void DoTVShowSecretBaseSecrets(void) sTVShowState = show->secretBaseSecrets.savedState; break; case 19: - StringCopy(gStringVar2, ItemId_GetItem(show->secretBaseSecrets.item)->name); + StringCopy(gStringVar2, ItemId_GetName(show->secretBaseSecrets.item)); sTVShowState = show->secretBaseSecrets.savedState; break; case 20: @@ -7795,7 +7616,7 @@ void DoTVShowSecretBaseSecrets(void) ShowFieldMessage(sTVSecretBaseSecretsTextGroup[state]); } -void DoTVShowSafariFanClub(void) +static void DoTVShowSafariFanClub(void) { TVShow *show; u8 state; @@ -7882,7 +7703,7 @@ void DoTVShowSafariFanClub(void) ShowFieldMessage(sTVSafariFanClubTextGroup[state]); } -void DoTVShowPokemonContestLiveUpdates2(void) +static void DoTVShowPokemonContestLiveUpdates2(void) { TVShow *show; u8 state; diff --git a/src/util.c b/src/util.c index 58088c3ee..88be4e4a1 100644 --- a/src/util.c +++ b/src/util.c @@ -230,7 +230,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) } #else -__attribute__((naked)) void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) +NAKED void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) { asm("\n\ .syntax unified\n\ diff --git a/src/walda_phrase.c b/src/walda_phrase.c index 59fd3fedb..0aa6f5aca 100644 --- a/src/walda_phrase.c +++ b/src/walda_phrase.c @@ -6,15 +6,14 @@ #include "main.h" #include "text.h" #include "new_game.h" - -extern void (*gFieldCallback)(void); +#include "overworld.h" extern const u8 gText_Peekaboo[]; extern u8 *GetWaldaPhrasePtr(void); extern bool32 IsWaldaPhraseEmpty(void); extern void sub_80AF168(void); -extern void c2_exit_to_overworld_2_switch(void); +extern void CB2_ReturnToField(void); extern void SetWaldaPhrase(const u8 *src); extern void SetWaldaWallpaperPatternId(u8 patternId); extern void SetWaldaWallpaperIconId(u8 iconId); @@ -80,7 +79,7 @@ static void CB2_HandleGivenWaldaPhrase(void) StringCopy(gStringVar1, GetWaldaPhrasePtr()); gFieldCallback = sub_80AF168; - SetMainCallback2(c2_exit_to_overworld_2_switch); + SetMainCallback2(CB2_ReturnToField); } static u32 GetWaldaPhraseInputCase(u8 *inputPtr) diff --git a/src/window.c b/src/window.c index 9a892d079..9a52a5a20 100644 --- a/src/window.c +++ b/src/window.c @@ -1,9 +1,14 @@ #include "global.h" #include "window.h" #include "malloc.h" - -extern u8 gUnknown_03002F60; -extern void* gUnknown_03002F70[]; +#include "bg.h" +#include "blit.h" + +u32 filler_03002F58; +u32 filler_03002F5C; +u8 gUnknown_03002F60; +u32 filler_03002F64; +void *gUnknown_03002F70[4]; extern u32 gUnneededFireRedVariable; #define WINDOWS_MAX 32 @@ -12,19 +17,6 @@ EWRAM_DATA struct Window gWindows[WINDOWS_MAX] = {0}; EWRAM_DATA static struct Window* sWindowPtr = NULL; EWRAM_DATA static u16 sWindowSize = 0; -extern void* GetBgTilemapBuffer(u8 bg); -extern int DummiedOutFireRedLeafGreenTileAllocFunc(int, int, int, int); -extern u16 GetBgAttribute(u8 bg, u8 attributeId); -extern void SetBgTilemapBuffer(u8 bg, void *tilemap); -extern void CopyBgTilemapBufferToVram(u8 bg); -extern u8 LoadBgTiles(u8 bg, void *src, u16 size, u16 destOffset); -extern void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 width, u8 height, u8 paletteSlot, u16 tileNumDelta); -extern void FillBgTilemapBufferRect(u8 bg, u16 tileNum, u8 x, u8 y, u8 width, u8 height, u8 palette); -extern void BlitBitmapRect4Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey); -extern void BlitBitmapRect4BitTo8Bit(struct Bitmap *src, struct Bitmap *dest, u16 srcX, u16 srcY, u16 destX, u16 destY, u16 width, u16 height, u8 colorKey, u8 paletteNum); -extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue); -extern void FillBitmapRect8Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue); - static u8 GetNumActiveWindowsOnBg(u8 bgId); static u8 GetNumActiveWindowsOnBg8Bit(u8 bgId); @@ -127,13 +119,13 @@ u16 AddWindow(const struct WindowTemplate *template) u8 *allocatedTilemapBuffer; int i; - for (win = 0; win < 0x20; ++win) + for (win = 0; win < WINDOWS_MAX; ++win) { if ((bgLayer = gWindows[win].window.priority) == 0xFF) break; } - if (win == 0x20) + if (win == WINDOWS_MAX) return 0xFF; bgLayer = template->priority; @@ -196,13 +188,13 @@ int AddWindowWithoutTileMap(const struct WindowTemplate *template) u8 bgLayer; int allocatedBaseBlock; - for (win = 0; win < 0x20; ++win) + for (win = 0; win < WINDOWS_MAX; ++win) { if (gWindows[win].window.priority == 0xFF) break; } - if (win == 0x20) + if (win == WINDOWS_MAX) return 0xFF; bgLayer = template->priority; |